springMVC对静态资源访问的处理
在restful 风格下springMVC会进行如下配置
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/conf/spring/mvc-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
很明显,该 servlet 对应的 url-pattern 定义成 /,因此该 servlet 会匹配上诸如 /images/a.jpg, /css/hello.css 等这些静态资源,甚至包括 /jsp/stock/index.jsp 这些 jsp 也会匹配。但是并没有定义相应的 Controller 来处理这些资源,因此这些请求通常是无法完成的。
很麻烦?没有 Struts 方便?此言差矣,因此你在 Struts 定义其核心 filter 的 url-pattern 是 *.action,当然不会对处理 jsp 和静态资源操作影响了。Spring MVC 若也定义类似的 url-pattern,同样不存在问题。
说到这里,我们应该想一个问题。Tomcat 中,只有 servlet 能够处理请求,即使是 jsp,也会被编译成 servlet。我们即便使用 Struts,定义 *.action 的url-pattern,那 .css, *.gfi 等这些静态资源到底是谁来处理了???你可不要想当然的认为我不是输入了图片的路径了吗?如,/images/a/b/c.gif。请注意,servlet 容器中,只有 servlet 采用处理资源!
由 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"
◇ 方案一:激活 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 先拦截。
但是这样还会有个问题,就是无法访问到classpath下的资源文件,看了tomcat的DefaultServlet的配置项,似乎也没有可以指定目录的地方。
◇ 方案二:Spring 3.0.4 以后版本提供了 <mvc:resources />
<!-- 处理静态资源 -->
<!-- 上传的图片缓存1个月,其他js,css,img资源缓存一年 -->
<mvc:resources mapping="/res/**" location="/res/" cache-period="2592000"/>
<mvc:resources mapping="/resources/**" location="/resources/" cache-period="31536000"/>
<mvc:resources mapping="/css/**" location="/css/" cache-period="31536000"/>
<mvc:resources mapping="/js/**" location="/js/" cache-period="31536000"/>
<mvc:resources mapping="/img/**" location="/img/" cache-period="31536000"/>
<mvc:resources mapping="/images/**" location="/images/" cache-period="31536000"/>
mapping 映射到 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 包内静态资源的访问。
报错WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'
◇ 方案三:使用 <mvc:default-servlet-handler />
<mvc:default-servlet-handler /> 会把 "/**" url 注册到 SimpleUrlHandlerMapping 的 urlMap 中,把对静态资源的访问由 HandlerMapping 转到 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler 处理并返回。DefaultServletHttpRequestHandler
使用就是各个 Servlet 容器自己的默认 Servlet。
补充说明下以上提到的 HandlerMapping 的 order 的默认值:
DefaultAnnotationHandlerMapping:0
<mvc:resources /> 自动注册的 SimpleUrlHandlerMapping:2147483646
<mvc:default-servlet-handler/> 自动注册的 SimpleUrlHandlerMapping:2147483647
Spring 会先执行 order 值比较小的。当访问一个 a.jpg 图片文件时,先通过 DefaultAnnotationHandlerMapping 来找处理器,一定是找不到的,我们没有叫 a.jpg 的 Controller。再按 order 值升序找,由于最后一个 SimpleUrlHandlerMapping 是匹配 "/**" 的,所以一定会匹配上,再响应图片。
Spring MVC 中,访问一个图片,还要走层层匹配。性能肯定好不到哪里去。不仅仅是 Spring MVC,即便 Struts,它们毕竟存活于 servlet 容器,只要由 servlet 容器处理这些静态资源,必然要将这些资源读入 JVM 的内存区中。所以,处理静态资源,我们通常会在前端加 apache 或 nginx。
另外,性能最好的应该是直接利用容器的DefaultServlet,让它最先拦截静态资源请求,这样就避免了后续的转发等操作,提高了性能,但是无法访问classpath下的资源文件。而通过mvc:resources标签可以简单配置匹配规则和资源文件路径,应该说是最简单快捷的一种方式,当然这大概也是mvc命名空间设计的初衷。
另外,若想结合两者的话,自己倒是可以尝试写一个Servlet或者filter来处理,不过估计有难度且麻烦。
--- add 2016-04-19
最近又想到一个办法,在java服务器前再增加一个http服务器处理静态资源,java服务器只处理动态资源,这样也可以啊
另一篇好博文:http://www.cnblogs.com/yank/p/4477204.html
springMVC对静态资源访问的处理的更多相关文章
- 【SpringMVC】静态资源访问的问题
在项目中经常会用到一些静态的资源,而一般我们在配置SpringMVC时会让SpringMVC接管所有的请求(包括静态资源的访问), 那么我们怎样才能最简单的来配置静态资源的访问呢? 一,在web.xm ...
- springmvc之静态资源访问不到 -记一次惨痛的经历
springmvc之静态资源访问不到 -记一次惨痛的经历 问题描述:项目正常启动,可以访问页面,但是无法找到静态资源文件,如css,js等文件资源. 控制台: $ 未定义 页面: GET http:/ ...
- springMVC配置静态资源访问的<mvc:resources>标签的使用
在springmvc中,为了引用资源的访问不会类似Controller一样被拦截,区分出关注的资源的访问,一般我们在springMVC里面的拦截都会配置为"/",拦截所有的.但是这 ...
- SSM框架 springMVC对静态资源访问的处理
https://my.oschina.net/hnqingping1255/blog/415575 错误信息 [org.springframework.web.servlet.PageNotFound ...
- SpringMVC REST 风格静态资源访问配置
1 在web.xml中使用默认servlet处理静态资源,缺点是如果静态资源过多,则配置量会比较大,一旦有遗漏,则会造成资源无法正常显示或404错误. <!-- 静态资源访问控制 --> ...
- SpringMVC下关于静态资源访问
SpringMVC静态资源访问 聊一聊关于静态资源的访问问题 首先,我们要对web.xml里面的DispatcherServlet进行设置 <!-- 中央调度器--> <servle ...
- spring mvc官网下最新jar搭建框架-静态资源访问处理-注解-自动扫描
1.从官网下载spring相关jar http://spring.io/projects 点击SPRING FRAMEWORK
- Spring Boot 静态资源访问原理解析
一.前言 springboot配置静态资源方式是多种多样,接下来我会介绍其中几种方式,并解析一下其中的原理. 二.使用properties属性进行配置 应该说 spring.mvc.static-pa ...
- 7.Spring MVC静态资源访问
在SpringMVC中常用的就是Controller与View.但是我们常常会需要访问静态资源,如html,js,css,image等. 默认的访问的URL都会被DispatcherServlet所拦 ...
随机推荐
- 移除手机端a标签点击自动出现的边框和背景
手机端a标签会自动补充出现边框或者背景,使得用户知道a标签的点击状态,但样式很不好看 <!DOCTYPE html> <html> <head> <meta ...
- Spring MVC中防止csrf攻击
Spring MVC中防止csrf攻击的拦截器示例 https://blog.csdn.net/qq_40754259/article/details/80510088 Spring MVC中的CSR ...
- Jenkin远程部署Tomcat8.5总结
tomcat8.5相比之前的tomcat进入manger管理界面需要多一些设置 1. 在 $tomcathome/conf/Catalina/localhost/下创建 manager.xml , 填 ...
- 题解 P4171 【[JSOI2010]满汉全席】
什么,tarjan?那是什么? 码量太大,我选择放弃 为什么不用dfs写2-sat呢?他会伤心的说 这题2-sat的过程大佬们已经讲得非常清楚了,我就略微提一下,主要讲dfs的原理 2_sat原理 我 ...
- 运行SQL文件报错Invalid ON UPDATE clause for 'create_date' column
Invalid ON UPDATE clause for 'create_date' column 原因: 高版本的mysql导数据到低版本出现的问题 日期类型报错 MySQL 5.5 每个表只允 ...
- JavaEE--调用 WSDL -- httpclient 4.x.x
参考:http://aperise.iteye.com/blog/2223454 http://blog.csdn.net/chenleixing/article/details/43456987 ...
- HDU 1257最少拦截系统[动态规划]
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1257 最 ...
- Mybatis入门——基础方式的增删该查、mapper动态代理方式的CRUD、类型转换器
一.基础方式的增删该查: 1.mybatis约定:输入参数parameterType和输出参数resulrType在形式上只能有一个. 2.如果输入/输出参数:是简单类型(8个基本类型加String) ...
- Codeforces Round #523 (Div. 2) Cdp
题:https://codeforces.com/contest/1061/problem/C 题意:给你一个序列,我们求他们子序列的个数,这个子序列有个限制就是每一个子序列上的值都必须是能整除他的下 ...
- RDD(五)——action
reduce(func) 通过func函数聚集RDD中的所有元素并得到最终的结果,先聚合分区内数据,再聚合分区间数据.Func函数决定了聚合的方式. def main(args: Array[Stri ...