Spring MVC使用mvc:resources和mvc:default-servlet-handler标签来处理静态资源

Spring MVC中的核心是DispatcherServlet,我们会在web.xml文件中做如下配置:

<!-- Spring MVC配置 -->
<servlet>
	<servlet-name>springmvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/config/springmvc-servlet.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>springmvc</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

如上所示,该servlet对应的url-pattern是/,因此该servlet会匹配上诸如ext4/resources/css/ext-all.css、ext4/ext-all.js等这种静态资源文件,甚至也会包括一些jsp文件,所以会导致错误的拦截。

对于上面这个问题,Spring提供了一种方法,就是使用<mvc:resources />标签,看我下面这样的一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 启用spring mvc 注解 -->
	<context:annotation-config />
	
	<!-- 配置自动扫描 -->
	<context:component-scan base-package="**.controller" />
	
	<!-- 引入静态资源的路径 -->
	<mvc:resources mapping="ext4/**" location="ext4/" />
	<mvc:resources mapping="app/**" location="app/"></mvc:resources>

	<!-- 视图解析 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
	
</beans>

除了上面使用<mvc:resources mapping="ext4/**" location="ext4/" />这种方法以外,还可以使用<mvc:default-servlet-handler />这个配置,如果有需要,可以加上<mvc:annotation-driven />,例如上面的配置文件换成下面这种形式:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 启用spring mvc 注解 -->
	<context:annotation-config />
	
	<!-- 配置自动扫描 -->
	<context:component-scan base-package="**.controller" />
	
	<!-- 配置默认servlet handler -->
	<mvc:default-servlet-handler />
	
	<!-- 引入静态资源的路径 -->
	<!--
	<mvc:resources mapping="ext4/**" location="ext4/" />
	<mvc:resources mapping="app/**" location="app/"></mvc:resources>
 	-->
	<!-- 视图解析 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
	
</beans>

<mvc:default-servlet-handler />会把/** url注册到SimpleUrlHandlerMapping的urlMap中,把对静态资源的访问由HandlerMapping转到org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler处理并返回。DefaultServletHttpRequestHandler使用的就是各个Servlet容器自己默认的Servlet。

<servlet-mapping>
	<servlet-name>default</servlet-name>
	<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
	<servlet-name>default</servlet-name>
	<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
	<servlet-name>default</servlet-name>
	<url-pattern>*.css</url-pattern>
</servlet-mapping>

在Servlet容器中,只有servlet才能处理请求。比如在Tomcat容器中,即使是JSP,也会被编译成servlet,当访问静态资源,比如a.jpg的时候,也是由servlet来处理,在tomcat中,对于这种资源的处理servlet就是default,上面的这段配置,就是tomcat对静态资源的处理配置,该配置要写在DispatcherServlet的前面,让defaultServlet先于DispatcherServlet拦截生效。不同的servlet容器,处理静态资源的servlet的名字不太一样:Tomcat、Jetty、JBoss、GlassFish默认的servlet名字是default,WebLogic默认的servlet名字是FileServlet,WebSphere默认的servlet名字是SimpleFileServlet。对于这么多种类的默认servlet,实在记不住,在Spring MVC中也没必要记,直接使用<mvc:default-servlet-handler />配置即可。

多个HandlerMapping的执行顺序问题:

DefaultAnnotationHandlerMapping的order属性值是:0,<mvc:resources/ >自动注册的SimpleUrlHandlerMapping的order属性值是:2147483646,<mvc:default-servlet-handler/>自动注册的SimpleUrlHandlerMapping 的order属性值是:2147483647。

spring会先执行order值比较小的,当访问一个a.jpg图片文件时,先通过DefaultAnnotationHandlerMapping来找处理器,一定是找不到的,因为我们没有叫a.jpg的Action。然后再按order值升序找,由于最后一个SimpleUrlHandlerMapping是匹配 "/**"的,所以一定会匹配上,就可以响应图片。

DispatcherServlet上面在配置的时候拦截的是/,即全部请求,如果我们只是设置的拦截/*.action或者/*.do的后缀,那么就不会存在上面的问题了,因为,一般来说不会存在后缀为.action、.do的静态资源文件。

本文标题:Spring MVC使用mvc:resources和mvc:default-servlet-handler标签来处理静态资源

本文链接:http://yedward.net/?id=350

本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处。

相关文章