1、web项目中web.xml的配置
在一个使用springmvc的web项目中,必然在web.xml中要配置前端控制器 DispatcherServlet
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 服务器启动的时候,让DispatcherServlet对象创建 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern> <!--注意这里-->
</servlet-mapping>
这里的 url-pattern
有两种配置方式:
- 扩展名,比如.do,古老的方式,不会导致静态资源文件被拦截的问题,但 是不支持RESTful编码风格。
- /,支持RESTful风格,但是会导致静态资源文件被拦截。
还有一种错误的配置方式:
- /*,错误的方式,可以请求到Controller方法,但是跳转到JSP时会被拦截,JSP不能正常显示 XX。
一般来说,企业中更多的是采用第二种配置方式,但这导致了静态资源被拦截。
2、静态资源为什么会被拦截
我们知道,我们的web项目最终要部署到服务器上,以我们熟悉的Tomcat服务器为例进行说明。
当我们将web应用部署到tomcat服务器上,服务器是先加载全局的 web.xml
,即tomcat自带的web.xml文件,然后才会加载我们自己web项目中的 web.xml
,当我们把 url-pattern
配置成 <url-pattern>/</url-pattern>
会覆盖掉全局web.xml中对于静态资源的处理,具体可以参考全局web.xml中:
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- The mapping for the default servlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
这就是默认的servlet,发现与我们配置的url-pattern一样了,导致静态资源也被我们自定义的dispatcherServlet所拦截,那这个类就会去找controller里面的映射了,比如我们访问http://localhost:8080/springmvc/img.png
,显然是Controller里面是没有这个映射路径的。
3、如何过滤静态资源
首先要明白过滤的必要性:
一般来说,HTTP 请求都会被映射到 DispatcherServlet,进而由具体的类来承接处理,但对于类似 js 或者 css 这样的静态资源则没必要这样,因为对资源的获取只需返回资源本身即可,无需做其他处理,那么这时就需要对一系列的资源文件做过滤处理。
有三种方式:
- 方式一:手动排除法
在我们的 web.xml
添加如下配置:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
其他地方保持不变,这个粒度显然是比 <url-pattern>/</url-pattern>
更小的,它会将*.jpg文件交给 servlet-name
为default的servlet去处理该请求,默认的servlet为什么就没有拦截了呢?因为它是直接访问。
当然不好的地方是,如果你需要拦截 *.html
又得配一个,所以比较麻烦。一般不采用。
- 方式二:在springmvc的配置文件中加入
<mvc:default-servlet-handler/>
<mvc:default-servlet-handler/>
在springMVC-servlet.xml中配置<mvc:default-servlet-handler />后,会在Spring MVC上下文中定义一个 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler
,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。
一般Web应用服务器默认的Servlet名称是"default",因此DefaultServletHttpRequestHandler可以找到它。如果你所有的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定:
<mvc:default-servlet-handler default-servlet-name="所使用的Web服务器默认使用的Servlet名称" />
- 方式三:在springmvc配置文件中手动指定静态资源路径
<!-- 设置静态资源不过滤 -->
<mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/img/" mapping="/img/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/plugins/" mapping="/plugins/**" />
mapping属性为映射路径,location属性为本地静态资源路径。这种方式更灵活,功能更丰富,也是可以的。
还有静态资源放在WEB-INF目录下虽然在IDEA中运行没有问题,都可以进行访问,但是打包成war包放入tomcat中部署时会导致无法访问,所以我一般将静态资源放在和WEB-INF平级的目录下。
《参考文章》
Spring MVC 过滤静态资源访问 ——溪边静禅
<mvc:default-servlet-handler/>的作用 ——多弗朗明哥
SpringMVC中静态资源的处理 ——HeliusKing