对于这个问题,我们准备了以下三种解决方案:
1、静态资源统一交由Servlet容器直接处理;
2、静态资源统一交由Spring MVC框架间接处理,再转交给Servlet容器处理;
3、静态资源统一交由Spring MVC框架直接处理;
从这3种解决方案中,处理静态资源的方式可以分为Servlet容器处理和Spring MVC框架处理。在这里要说明的是,只要静态资源的请求经过Spring MVC框架的大门,如果不做额外的配置,就必然会跟拦截器扯上关系。
java注解配置方式:请点击这里
静态资源统一交由Servlet容器直接处理
在web.xml中加入以下配置即可,相关参数改为项目实际参数。一旦静态资源请求匹配后,直接由servlet容器处理。
说明:由于DispatcherServlet配置的映射路径为/,所以导致了Servlet容器全局配置文件中提供处理静态资源的servlet没有匹配的机会,所以要处理这个问题,只要将default Servlet的映射路径以更精确的静态资源匹配路径重新注册到web.xml中即可。
说明:有很多博客中刻意说明该配置必须要放在DispatcherServlet配置的前面,其实不是这样的,只要能保证静态资源匹配路径的优先级高于/即可,与位置无关;(*.)星点带后缀的路径优先级高于/
参考:
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.cssurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.jsurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>defaultservlet-name>
<url-pattern>*.jpgurl-pattern>
servlet-mapping>
结论:
加上以上配置,即可解决静态资源请求失败的问题,此刻与Spring MVC完全没有关系,所以配置Spring MVC拦截器时,不用考虑对静态资源的处理。
静态资源统一交由Spring MVC框架间接处理,再转交给Servlet容器处理
个人理解如下:
源码参考:
在初始化Spring MVC容器的过程中,从容器中检测拦截器,如果在配置文件中进行了拦截器的配置,将获取全部拦截器绑定到处理器映射器中,只要你请求的路径与拦截器的路径四配,你的请求就一定会被拦截。
首先,在springmvc.xml的配置文件中加入以下标签:
<mvc:default-servlet-handler/>
该标签会在Spring MVC容器启动过程中,将 DefaultServletHttpRequestHandler处理器以/**为映射路径,同时还从Spring MVC容器中获取配置文件中注册的拦截器,一起绑定到SimpleUrlHandlerMapping处理器映射器中。所以,只要我们配置的拦截器映射路径能匹配静态资源的路径,那么我们请求的静态资源就一定会被拦截器拦截,至于拦截后放行还是不放行,则依据拦截器的执行逻辑决定,所以拦截器的不同执行逻辑,就有可能导致静态资源访问失败,那要解决这个问题,可以采用在preHandle()方法里首先进行判断是否是静态资源的请求,如果是,则返回true直接放行,也只有返回true,才有机会将静态资源交给Servlet容器来处理,虽然这种方式可以解决静态资源访问失败的问题,但拦截器却参与其中了。还有一种更好的处理方式就是不让拦截器参与工作,即在配置拦截器的时候,把我们不需要拦截的路径排除,这样,由于我们访问的静态资源路径不在拦截器的拦截范围中,自然就不会触发到拦截器了。
说明:如果采用
(参考2选1)
参考1:在拦截器中放行静态资源,拦截器参与了工作
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
//判断静态资源请求
if(requestURI.contains(".js")|| requestURI.contains(".css")|| requestURI.contains(".jpg")){
return true;
}else{
//其它业务逻辑......................................
return false;
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxx.interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
参考2:在配置拦截器中排除静态资源,拦截器没有参与工作,也就不用在拦截器中判断静态资源的请求了.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/**/*.css"/>
<mvc:exclude-mapping path="/**/*.js"/>
<bean class="com.xxx.interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
静态资源统一交由Spring MVC框架直接处理
首先,在springmvc.xml的配置文件中加入以下标签:
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/jpg/**" location="/jpg/"/>
说明:该标签的location属性值可以指定任意目录,包括web-info安全目录。
该标签会在Spring MVC容器启动过程中,将 ResourceHttpRequestHandler处理器以mapping属性的值作为映射路径,同时还从Spring MVC容器中获取配置文件中注册的拦截器,一起绑定到SimpleUrlHandlerMapping处理器映射器中。所以,只要我们配置的拦截器映射路径能匹配静态资源的路径,那么我们请求的静态资源就一定会被拦截器拦截,至于拦截后放行还是不放行,则依据拦截器的执行逻辑决定,所以拦截器的不同执行逻辑,就有可能导致静态资源访问失败,那要解决这个问题,可以采用在拦截方法里首先进行判断是否是静态资源的请求,如果是,则返回true直接放行,也只有返回true,才有机会交给静态资源的处理器来处理,虽然这种方式可以解决静态资源访问失败的问题,但拦截器却参与其中了。还有一种更好的处理方式就是不让拦截器参与工作,即在配置拦截器的时候,把我们不需要拦截的路径排除,这样,由于我们访问的静态资源路径不在拦截器的拦截范围中,自然就不会触发到拦截器了。
说明:如果采用
(参考2选1)
参考1:在拦截器中放行静态资源,拦截器参与了工作
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxx.interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
//判断静态资源请求
if(requestURI.contains(".js")|| requestURI.contains(".css")|| requestURI.contains(".jpg")){
return true;
}else{
//其它业务逻辑......................................
return false;
}
}
参考2:在配置拦截器中排除静态资源,拦截器没有参与工作,也就不用在拦截器中判断静态资源的请求了
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/**/*.css"/>
<mvc:exclude-mapping path="/**/*.js"/>
<bean class="com.xxx.interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
总结:
1、如果采用第一种解决方案,拦截器不用做任何处理静态资源的操作。因为Spring MVC的DispatcherServlet没有匹配静态资源的请求。
2、如果采用第二或三种解决方案,在xml配置文件中配置了全局自定义拦截器,就必须要在拦截器preHandle方法中最开始处判断并放行静态资源的请求或者在配置拦截器的时候直接排除静态资源的路径,这样才能解决静态资源访问失败的问题,建议在配置拦截器中排除静态资源的请求路径,减少了拦截器的执行步骤。
3、至于选择哪种解决方案,建议还是结合实际项目选择,各有优缺点。
以上内容为自己的理解所获,如有误,欢迎留言指正,谢谢!