The static resource distribution function of SpringBoot is a very convenient function, but you can not access it except for the top page unless you specify the file name up to the extension. A general SPA has a routing function that uses the HTML5 History API, and while multiple URLs are assigned to each page, the only HTML file to prepare is index.html. For this reason, if the SPA is delivered as a static resource with the default settings of Spring Boot, the page cannot be displayed correctly when directly accessing other than the top page or when the screen is refreshed.
We will consider a setting method that meets the following requirements.
--The target page is displayed even if you access the top page directly. --The original page should be displayed even when the screen is refreshed. --For access to js and css files, return 404 if the target file does not exist.
The presence or absence of the extension is used to determine whether the access target is a page or a file. Access to a URL without an extension is considered to be a page access and returns index.html.
The easiest way is to use hash mode in the router settings on the SPA side (the following is an example of Nuxt.js).
js:nuxt.config.js
module.exports = {
mode: 'spa',
router: {
mode: 'hash'
},
......
Regardless of the routing on the SPA side, the request to the server will always be the access to the top page. With the default settings of SpringBoot, index.html is returned as a response as WelcomePage, so all page URLs are valid.
If you don't want to give up history mode, you need to configure it on the Spring Boot side.
First of all, let's check how the static resource distribution of Spring Boot is set by default.
The default setting is WebMvcAutoConfiguration.java of the spring-boot-autoconfigure module. -It is described in (autoconfigure / src / main / java / org / springframework / boot / autoconfigure / web / module / WebMvcAutoConfiguration.java). In this class, the mapping for the following static resources is set.
If you set the log level of ʻorg.springframework.web` to DEBUG, you can confirm that it is set as follows in the log output at startup.
app.log
2018-06-05 23:17:29.654 INFO 18345 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-06-05 23:17:29.655 INFO 18345 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-06-05 23:17:29.732 INFO 18345 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html]
2018-06-05 23:17:29.915 DEBUG 18345 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Looking for resource handler mappings
2018-06-05 23:17:29.916 DEBUG 18345 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**/favicon.ico", locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@3b4ef7]
2018-06-05 23:17:29.916 DEBUG 18345 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/webjars/**", locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@1af05b03]
2018-06-05 23:17:29.916 DEBUG 18345 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**", locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@5987e932]
Add a setting in application.yml to return static resources only for paths with extensions. The default mapping pattern to static resources is defined in spring.mvc.static-path-pattern
and will be overridden.
application.yml
spring:
mvc:
static-path-pattern: /**/*.*
With the above settings, access to the page URL will deviate from the default static resource handler mapping settings. Therefore, define the following Configuration with reference to WebMvcAutoConfiguration.java so that index.html is returned when the target resource does not exist for the access to the page URL.
Html5HistoryModeResourceConfig.java
@Configuration
public class Html5HistoryModeResourceConfig implements WebMvcConfigurer {
@Autowired
private ResourceProperties resourceProperties;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/**")
.addResourceLocations(resourceProperties.getStaticLocations())
.resourceChain(false)
.addResolver(new SpaPageResourceResolver());
}
public static class SpaPageResourceResolver extends PathResourceResolver {
@Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
Resource resource = super.getResource(resourcePath, location);
return resource != null ? resource : super.getResource("index.html", location);
}
}
}
Since the default settings take precedence, we have set resource handlers for all other paths.
The storage path of static resources is obtained from the instance of ResourceProperties so that the setting of spring.resources.static-locations
can be used as it is.
The last SpaPageResourceResolver
registered in ʻaddResolver` returns the response of index.html of the root path.
If the above Configuration class is loaded at startup, it should appear in the startup log as shown below.
app.log
2018-06-05 23:42:22.481 INFO 18576 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-06-05 23:42:22.481 INFO 18576 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/*.*] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-06-05 23:42:22.481 INFO 18576 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-06-05 23:42:22.781 DEBUG 18576 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Looking for resource handler mappings
2018-06-05 23:42:22.782 DEBUG 18576 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**/favicon.ico", locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@1af1347d]
2018-06-05 23:42:22.782 DEBUG 18576 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/webjars/**", locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@632aa1a3]
2018-06-05 23:42:22.782 DEBUG 18576 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**/*.*", locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@20765ed5]
2018-06-05 23:42:22.782 DEBUG 18576 --- [ main] o.s.w.s.resource.ResourceUrlProvider : Found resource handler mapping: URL pattern="/**", locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[com.test.spa.Html5HistoryModeResourceConfig$SpaPageResourceResolver@3b582111]
Regarding the deployment of SPA, I think that there is another better way considering full-scale operation and SSR, but if you start the jar file alone like Jenkins, the screen will come with it. If you want to make it, I think this setting is effective.
Spring Boot Reference Guide - 27.1.5 Static Content https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-static-content
Understand access to static resources on Spring MVC (+ Spring Boot)-Qiita https://qiita.com/kazuki43zoo/items/e12a72d4ac4de418ee37
Goslings Development Memo-Part 5: Spring Boot Final (Static Resource Processing) | To Be Decided https://www.kaitoy.xyz/2017/01/24/goslings-development-memo5-spring-boot-static-resources / /
html5 - Spring Boot with AngularJS html5Mode - Stack Overflow https://stackoverflow.com/questions/24837715/spring-boot-with-angularjs-html5mode
spring - Springboot/Angular2 - How to handle HTML5 urls? - Stack Overflow https://stackoverflow.com/questions/38516667/springboot-angular2-how-to-handle-html5-urls
Recommended Posts