在SpringMVC中,DispatcherServlet的配置是这样的:
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
他默认会覆盖静态资源,比如http://localhost:8080/a2.jpg实际上就是走的controller映射,但controller并没有这个mapping,处理方式是加上:
<mvc:default-servlet-handler/><!-- 静态资源放行 -->
配置了这个就相当于启用了DefaultServletHttpRequestHandler
这个Handler也是用来处理静态文件的,它会尝试映射/。
当DispatcherServelt映射/时,并且没有找到合适的
Handler来处理请求时,就会交给DefaultServletHttpRequestHandler 来处理。
详细请看博主之前写的:SpringMVC - (3)DispatcherServlet在web.xml中的路径映射问题
而在springboot中DefaultServletHttpRequestHandler会被DefaultServletHandlerConfigurer自动启用,而DefaultServletHandlerConfigurer又会被WebMvcConfigurationSupport自动启用:
走到这步,springboot中"/"已经会走tomcat来处理了,那么在Springboot中怎么通过映射路径来访问静态资源呢:
我新创建一个项目,在默认生成的static文件夹下放一张图片,然后运行项目,发现就能直接访问了,springboot肯定是做了相关的映射:
在springboot中,对于springmvc的自动化配置都在WebMvcAutoConfiguration中,相关的简化配置可以在其中一探究竟:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
staticPathPattern 是静态资源url路径匹配:
/**
* Path pattern used for static resources.
*/
private String staticPathPattern = "/**";
getResourceLocations(this.resourceProperties.getStaticLocations())是默认静态资源位置:
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/].
*/
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
这里已经有四个路径了,但是还有第五个:
static String[] getResourceLocations(String[] staticLocations) {
String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length];
System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length);
return locations;
}
这个"/"作用于webapp,但由于我么是springboot项目,基本用不到webapp,所以作用不大
如果默认的静态资源过滤策略不能满足需求,我们可以自定义过滤策略:
- 在配置文件中配置:
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/
- 实现WebMvcConfigurer
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
}
配置了这些就相当于springmvc中如下配置:
<!-- 设置静态资源不过滤 -->
<mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/img/" mapping="/img/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/plugins/" mapping="/plugins/**" />
然后http://localhost:8080/static/a2.jpg就可以成功访问了!