针对静态文件处理的方法总结
动静分离一直是比较好的提高网站响应速度的方案。从网上搜索的资料来看有三种有关Spring与容器的方式。另外还有一些细节注意,否则会使controller失效。
第一种
SpringMVC 在Web.xml中配置拦截指定请求的方式。这种方式直接过滤掉了非指定请求(包括静态文件等)如 .do 、.shtml等。REST风格的资源URL不希望带 .html 或 .do 等后缀,所以这种情况的程序越来越少了。
<!-- Spring MVC -->
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/spring-mvc*.xml,
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
这种好处是,Spring MVC配置拦截器也只拦截*.do。静态资源不走Spring,也不走拦截器,性能比较好。
第二种
激活Tomcat的defaultServlet来处理静态文件
<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-mapping,同时,要写在 DispatcherServlet 的前面, 让 defaultServlet 先拦截。 让 defaultServlet先拦截,这个就不会进入Spring了 。
同样的指定了default默认Servlet后,指定静态资源不走Spring,也不走拦截器,性能比较好。
由 servlet 处理这些资源那是一定了。不过,不同的 servlet 容器/应用服务器,处理这些静态资源的 servlet 的名字不大一样:
- Tomcat, Jetty, JBoss, and GlassFish:默认 Servlet 名字为 “default”
- Google App Engine:默认 Servlet 名字为 “_ah_default”
- Resin:默认 Servlet 名字为 “resin-file”
- WebLogic:默认 Servlet 名字为 “FileServlet”
- WebSphere:默认 Servlet 名字为 “SimpleFileServlet”
第三种
如果将DispatcherServlet请求映射配置为”/”,则Spring MVC将捕获Web容器所有的请求,包括静态资源的请求,Spring MVC会将它们当成一个普通请求处理.Spring MVC配置的拦截器也将拦截所有的请求(包括静态资源)
1、<mvc:resources/>
Spring 3.0.4 以后版本提供了这个标签。
<mvc:resources/>
由Spring MVC框架自己处理静态资源,并添加一些有用的附加值功能
<mvc:resources location="/resources/" mapping="/resources/**"/>
<mvc:resources location="/,classpath:/META-INF/publicResources/" mapping="/resources/**"/>
/resources/** 映射到 ResourceHttpRequestHandler 进行处理,location 指定静态资源的位置,可以是 web application 根目录下、jar 包里面,这样可以把静态资源压缩到 jar 包中。cache-period 可以使得静态资源进行 web cache。
使用 <mvc:resources/>
元素,会把 mapping 的 URI 注册到 SimpleUrlHandlerMapping 的 urlMap 中,key 为 mapping 的 URI pattern 值,而 value 为 ResourceHttpRequestHandler,这样就巧妙的把对静态资源的访问由 HandlerMapping 转到 ResourceHttpRequestHandler 处理并返回,所以就支持 classpath 目录, jar 包内静态资源的访问。
2、采用<mvc:default-servlet-handler />
必须同时配置
<mvc:annotation-driven>
在springMVC-servlet.xml中配置后,会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。
一般Web应用服务器默认的Servlet名称是”default”,因此DefaultServletHttpRequestHandler可以找到它。如果你所有的Web应用服务器的默认Servlet名称不是”default”,则需要通过default-servlet-name属性显示指定:
PS:第三种方案,不管是采用<mvc:resources>
,还是<mvc:default-servlet-handler>
静态资源都会被Spring拦截然后再分配,同时也会被拦截器拦截。性能不好。
最好的方式依然是第二种方法,激活Web容器的defaultServlet处理静态资源(nginx方式另做讨论)。然后结合第三种方式使用一些附加值的映射。
配置细节不注意的坑
<mvc:default-servlet-handler/>
- 必须与
<mvc:annotation-driven>
结合使用,否则controller将失效。 - 容器默认的DefaultServletHandler处理 所有静态内容与无RequestMapping处理的URL;放到handlerMapping配置后,否则会导致映射失效
容器默认拦截
- 会让“/” 失效
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
参考文章:
http://www.cnblogs.com/fangqi/archive/2012/10/28/2743108.html
http://zachary-guo.iteye.com/blog/1502622
http://www.th7.cn/Program/java/201411/316575.shtml