1. DispatcherServlet拦截路径导致静态资源无法访问的问题
首先谈一下Tomcat几个内置的用于处理请求资源的Servlet。
- DefaultServlet:拦截所有的静态资源请求,返回给客户端
- JspServlet:拦截所有的jsp请求,渲染jsp页面返回给客户端
1 | <!-- |
1 | <servlet> |
DispatcherServlet常用URL映射拦截规则如下:
/*:拦截所有请求,优先级高于DefaultServlet和JspServlet的url-pattern,所以静态资源和jsp都无法获取/:覆盖DefaultServlet的url-pattern,所以静态资源无法获取,jsp页面正常显示.action或.do:只拦截指定后缀的请求。静态资源和jsp都正常获取
DispatcherServlet的常用URL映射拦截规则如下,/*的拦截范围比/更大,还会拦截到*.jsp请求,这样jsp页面就无法显示了
2. 问题解决
你可能会想,那直接把DispatcherServlet的url-pattern设置为.do之类的后缀,不能自然而然解决了吗。
但是实际上不建议处理带后缀的请求,因为优秀的REST风格的URL不希望带有任何后缀。
一般我们会把DispatcherServlet的url-pattern设置为/,但是会导致静态资源无法获取。解决方法如下:
2.1. 方式一:激活Tomcat的defaultServlet来处理静态文件
给DefaultServlet添加多个url-pattern,能够处理各种静态文件
1 | <servlet-mapping> |
2.2. 方式二:使用<mvc:resources/>
<mvc:resources/>最灵活,可以拦截各种形式的请求。location可以是webapp的路径,也可以是classpath路径
1 | <!-- resources mapping --> |
2.3. 方式三:使用<mvc:default-servlet-handler/>
<mvc:default-servlet-handler/>的作用是,对进入DispatcherServlet的请求进行筛选
- 将无法处理的请求(没有经过映射的请求)转发给DefaultServlet去处理
- 如果是经过映射的请求,则交给DispatcherServlet继续进行处理
在springmvc.xml中配置如下:
1 | <mvc:default-servlet-handler/> |
配置<mvc:default-servlet-handler/>之后,你会发现所有的静态资源都可以访问了,但是访问@Controller中的url映射,都是返回404。这是因为default-servlet-handler只认识通过BeanNameUrlHandlerMapping方式配置的处理器,但是不认识@RequestMapping注解方式配置的处理器。所以default-servlet-handler误以为该请求没有对应的处理器,所以直接将给DispatcherServlet去处理,因为没有对应的资源,所以返回404
解决方法是加上<mvc:annotation-driven/>,这样就有HandlerMapping和HandlerAdapter支持注解方式的配置
1 | <mvc:annotation-driven/> |