web.xml中servlet匹配优先级探析
一. web.xml中配置url-pattern的规则
借鉴
https://www.cnblogs.com/zeling/p/8494844.html
分为四类
1)精确匹配: 匹配确定uri
/index
或
/index/xyzabc
2)前缀匹配:
/*
或
/main/*
3)后缀匹配
*.do
4) / 匹配
/
以上四种匹配的顺序是
精确匹配>前缀匹配>后缀匹配> /匹配
***注意以下三种前两个合法,第三个不合法***
/*.do
/main/*
/main/*.do
二. 理解tomcat中自带的全局的web.xml和单个应用中web.xml配置的servlet
以下是tomcat中的主要配置,省去了不关注的参数
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <!-- The mapping for the default servlet --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- The mappings for the JSP servlet --> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>
tomcat中的web.xml, 在每一个webapp中启动的应用都会继承它, 可以在应用自定义的web.xml中选择性覆盖tomcat中配置的,
两个默认servlet,
jspServlet匹配所有*.jsp, 处理jsp相关, 一般不覆盖,
defaultServlet 匹配/, 由优先级可知, *.jsp匹配不到的由/匹配, 且/匹配属于最后的匹配, 前面所有的匹配都没能匹配到则由/匹配, 可以处理静态资源, defaultServlet的作用类似于 else,
三. 针对以上做几组测试验证url匹配
建立index.jsp和index.html,

以及indexservlet
public class IndexServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get"); doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("UTF-8"); resp.setContentType("application/json;charset=UTF8"); PrintWriter writer = resp.getWriter(); writer.write("welcome"); } }
1)web.xml中不配置任何信息
访问结果:
index.html: 可访问
index.jsp:可访问
理解,
默认情况下, index.jsp被默认jsp servlet处理匹配了
index.html, 被default servlet的"/"匹配了, 可以处理静态资源请求,
2)web.xml中如下配置---index servlet 匹配/
<servlet> <servlet-name>index</servlet-name> <servlet-class>com.bily.springmvc.base.servlet.IndexServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>index</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
访问结果:
index.html: 无法访问原本资源, 而指向了index servlet实现,
index.jsp:可访问
分析
index.jsp还是被jsp servlet匹配了
由于web.xml中覆盖了default servlet匹配的/路径, 所以 没有被jsp匹配的资源找到/匹配, 即index servlet, 此时的indexServlet匹配 / ,相当于else,
3)indexServet匹配 /*
<servlet> <servlet-name>index</servlet-name> <servlet-class>com.bily.springmvc.base.servlet.IndexServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>index</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
测试结果
index.html: 指向了index servlet
index.jsp:指向了index servlet
分析
/*匹配属于前缀匹配,优先于jsp servlet的后缀匹配,
所以index.jsp匹配到了index servlet
所以index.html同上, 无法被最后的默认的 defaultServlet匹配,
4)index servlet 匹配 /index
<servlet> <servlet-name>index</servlet-name> <servlet-class>com.bily.springmvc.base.servlet.IndexServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>index</servlet-name> <url-pattern>/index</url-pattern> </servlet-mapping>
测试结果
index.html , index.jsp, /index 都可以正常且正确匹配
分析
此时三个servelt注册
index 匹配 /index
jsp 匹配*.jsp
default 匹配 /
且indexServlet优先级最高,不影响后续匹配
总结,
1) 注意tomcat汇总的web.xml和应用中的web.xml中的匹配之间相互覆盖
2) 注意url匹配中的优先级问题,
3)以上测试,其实回答了为什么 springmvc的dispatcherServlet需要匹配/, 不能匹配/*, 且匹配/ 后静态资源还要重新配置,
原因是, 请求基本分文
jsp请求,静态资源请求,servlet/controller请求, 结合优先级,
a) 如果dispatcherServlet匹配 /*, 属于前缀匹配, 则所有的后缀匹配*.jsp 无法被正确访问, 会被dispatcherServlet处理,
b)早期的dispatcherServlet匹配 *.do形式, 是为了匹配controller, 保留jsp匹配和/的静态资源匹配, 且还不支持静态资源处理, 后来springmvc加强后, 提供了两个配置后, dispatcherServlet也可以处理静态资源了,
故dispatcherServlet直接匹配/即可, 如果是controller请求,正常处理, 静态资源请求, 开启以上两个配置后可以实现等同于tomcat的静态资源处理,
<mvc:default-servlet-handler/> <mvc:annotation-driven></mvc:annotation-driven>
参考博客(有基于dispatcherServlet映射原理级介绍)
https://www.cnblogs.com/AshOfTime/p/10655014.html
浙公网安备 33010602011771号