如果我们的项目使用的是springmvc,在web.xml中会有一段这的配置。
<servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:ApplicationContext-mvc.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>
其中的DispatcherServlet会拦截一切(<url-pattern>/</url-pattern>)请求,当然也包含静态请求(html,js,css,img等),注意jsp文件不是静态资源。其本质还是一个servlet。我们知道DispatcherServlet拦截完请求以后会交给对应的controllers的requestmapping来处理。那么如果是静态资源该如何处理呢?
举个例子:假设我再webapp根目录下新建了一个index.html文件,而我在某个controllers类下也有一个逻辑名称为index.html的方法。如下所示。
@RequestMapping("index.html") public ModelAndView index() { ModelAndView mv = new ModelAndView("back/main/Login"); return mv; }
运行项目,在浏览器地址栏输入localhost:8080/warrior/index.html。则会去执行public ModelAndView index()的代码。
假如我把这个方法注释掉呢?继续运行localhost:8080/warrior/index.html。则会报404错误。
这是因为spring mvc还是把这个请求地址当成一个逻辑视图地址,而去controllers类中寻找关联这个地址的方法,但是找不到,所以报404了。
我们怎样能让spring mvc识别静态文件以规避这个错误呢?有两种方法。
1.使用<mvc:default-servlet-handler/>
在mvc的配置文件中,加入以下两句代码。
<mvc:annotation-driven/>
<!-- 静态资源访问方式一,推荐使用 -->
<mvc:default-servlet-handler/>
在web.xml中的DispatcherServlet配置前面加上如下代码:
<!-- 对静态资源的配置 --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> <url-pattern>*.css</url-pattern> <url-pattern>*.ico</url-pattern> <url-pattern>/img/*</url-pattern> <url-pattern>/static/*</url-pattern> <url-pattern>/fonts/*</url-pattern> <url-pattern>/font/*</url-pattern> </servlet-mapping>
这样配置了以后,会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。
需要注意的是,这两句必须一同出现,如果没有<mvc:annotation-driven/>这句,会访问不到controllers中的方法。
2.使用 mvc:resources来区分静态资源
为了将静态资源与动态资源进行区分,spring mvc使用<mvc:resources mapping="/**" location="/,/admin/" />这样的配置来标明静态资源所在的路径。
以上述那条语句为例:当我们访问localhost:8080/warrior/index.html的时候,spring mvc先去寻找逻辑名为“index.html”的action,找不到的话,再去location为/,也就是根目录下的index.html,如果还是找不到的话,再去寻找admin/目录下的index.html。而不会报错。
我的理解是,mvc:resources为静态资源定义了一个逻辑名称,或者说映射(mapping),当我们需要访问静态资源的时候,就无需再使用物理地址了,直接使用映射地址就好了。
使用mvc:resources的好处除了创建一个别名以外,是不用再创建一个servlet,不像方法一,而且他可以随意指定静态资源的位置,甚至可以放在web-inf下面。另外,还可以对静态资源做一些配置,好充分利用缓存。
看几个mvc:resources的例子:
<mvc:resources mapping="/**" location="/,/admin/" /><!-- 当访问warrior/demo/index.html时候,先到根目录下去寻找demo/index.html,再到admin目录下去寻找demo/index.html --> <mvc:resources mapping="/admin/**" location="/,/admin/" /><!-- 当访问warrior/static/index.html时候,先到根目录下寻找index.html,再到static下寻找index.html -->
PS:当上述两种配置同时出现在spring mvc的配置文件中,顺序是,先去controllers中寻找,找不到再使用<mvc:default-servlet-handler/>去寻找静态资源,找不到就会报404,不会再使用mvc:resources去寻找了。