測試
1、靜態資源訪問
官網說明如下:
默認情況下,Spring Boot 從 Classpath 中名為
/static
(或/public
或/resources
或/META-INF/resources
)的目錄或ServletContext
的根目錄中提供靜態內容。它使用 Spring MVC 中的ResourceHttpRequestHandler
,因此您可以通過添加自己的WebMvcConfigurer
並覆蓋addResourceHandlers
方法來修改該行為。在獨立的 Web 應用程序中,還啟用了容器中的默認 servlet,並將其用作后備,如果 Spring 決定不處理
ServletContext
的根,則從ServletContext
的根開始提供內容。在大多數情況下,這不會發生(除非您修改默認的 MVC 配置),因為 Spring 始終可以通過DispatcherServlet
處理請求。默認情況下,資源 Map 在
/**
上,但是您可以使用spring.mvc.static-path-pattern
屬性對其進行調整。例如,將所有資源重定位到/resources/**
可以實現如下:spring.mvc.static-path-pattern=/resources/**
您還可以使用
spring.resources.static-locations
屬性來自定義靜態資源位置(用目錄位置列表替換默認值)。根 Servlet 上下文路徑"/"
也會自動添加為位置。除了前面提到的“標准”靜態資源位置以外,還對Webjars content進行了特殊處理。如果 jar 文件以 Webjars 格式打包,則從 jar 文件提供帶有
/webjars/**
路徑的任何資源。如果您的應用程序打包為 jar,則不要使用
src/main/webapp
目錄。盡管此目錄是一個通用標准,但它僅在 war 打包中有效,並且在生成 jar 時,大多數構建工具都將其忽略。Spring Boot 還支持 Spring MVC 提供的高級資源處理功能,允許使用案例,例如緩存清除靜態資源或對 Webjars 使用版本無關的 URL。
要對 Webjar 使用版本無關的 URL,請添加
webjars-locator-core
依賴項。然后聲明您的 Webjar。以 jQuery 為例,在"/webjars/jquery/x.y.z/jquery.min.js"
中添加"/webjars/jquery/jquery.min.js"
結果。其中x.y.z
是 Webjar 版本。
進行測試:
靜態資源目錄
進行測試的時候,由於之前項目引入了手寫的sarter,里面有個攔截器,對所有資源進行攔截,導致訪問不到靜態資源,需要方向。

由於靜態資源默認的映射是/**
,為了方便攔截器放行,這里可以自定義。
spring:
mvc:
static-path-pattern: /res/**

官網也說明了,可以自定義靜態資源路徑
spring:
mvc:
static-path-pattern: /res/** ##這里是加的請求的路徑
resources:
static-locations: [classpath:/test/] ## 這里是隱射的路徑

注意,這里數組只寫一個的話,會把其他幾個路徑覆蓋掉。
webjar
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.5.1</version>
</dependency>
進行測試
http://localhost:8888/webjars/jquery/3.5.1/webjars-requirejs.js
2、歡迎頁支持
-
靜態資源路徑下 index.html
-
- 可以配置靜態資源路徑
- 但是不可以配置靜態資源的訪問前綴。否則導致 index.html不能被默
要注釋掉下面配置,因為在源碼中,有了判斷,不然不生效
#spring:
# mvc:
# static-path-pattern: /res/**
3、自定義 Favicon
favicon.ico 放在靜態資源目錄下即可。
源碼
-
因為springboot自動配置的原因,引入了很多自動配置類,所以先找到入口WebMvcAutoConfiguration
-
查看這個配置類生效的前提條件,其中發現了 WebMvcConfigurationSupport.class.
@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration {
如果自己全部接管mvc的,可以使用@EnableWebMvc這個注解,它其實會往IOC容器注入DelegatingWebMvcConfiguration,它繼承了WebMvcConfigurationSupport。
-
都是在容器中找WebMvcAutoConfigurationAdapter這個類
//有參構造器所有參數的值都會從容器中確定 //ResourceProperties resourceProperties;獲取和spring.resources綁定的所有的值的對象 //WebMvcProperties mvcProperties 獲取和spring.mvc綁定的所有的值的對象 //ListableBeanFactory beanFactory Spring的beanFactory //HttpMessageConverters 找到所有的HttpMessageConverters //ResourceHandlerRegistrationCustomizer 找到 資源處理器的自定義器。========= //DispatcherServletPath //ServletRegistrationBean 給應用注冊Servlet、Filter.... public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) { this.mvcProperties = mvcProperties; this.beanFactory = beanFactory; this.messageConvertersProvider = messageConvertersProvider; this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); this.dispatcherServletPath = dispatcherServletPath; this.servletRegistrations = servletRegistrations; this.mvcProperties.checkConfiguration(); }
資源處理的默認規則
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
//如果在yaml里面配置的false,則靜態資源全部失效
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
ServletContext servletContext = getServletContext();
//這里配置的就是webjars資源映射
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
//這里配置的就是靜態資源映射,這里可以看下面的圖
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (servletContext != null) {
registration.addResourceLocations(new ServletContextResource(servletContext, SERVLET_LOCATION));
}
});
}
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
addResourceHandler(registry, pattern, (registration) -> registration.addResourceLocations(locations));
}
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern,
Consumer<ResourceHandlerRegistration> customizer) {
if (registry.hasMappingForPattern(pattern)) {
return;
}
ResourceHandlerRegistration registration = registry.addResourceHandler(pattern);
customizer.accept(registration);
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
customizeResourceHandlerRegistration(registration);
}
注:如果請求的靜態資源和請求的接口是同一個路徑,則優先處理接口
3、歡迎頁的處理規則
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
return welcomePageHandlerMapping;
}
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
if (welcomePage != null && "/**".equals(staticPathPattern)) {
logger.info("Adding welcome page: " + welcomePage);
setRootViewName("forward:index.html");
}
else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
logger.info("Adding welcome page template: index");
setRootViewName("index");
}
}
注:如果這里配置了靜態資源路徑,會導致歡迎頁失效,如果沒有失效,則請重定向到Index.html