分为四类
匹配确定uri /index /index/xyzabc
/* /main/*
*.do *.action
/
以上四种匹配的顺序是 精确匹配 > 前缀匹配 > 后缀匹配 > /匹配
***注意以下三种前两个合法,第三个不合法*** /*.do /main/* /main/*.do
以下是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
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"); } }
访问结果
index.html: 可访问 index.jsp:可访问
理解
默认情况下, index.jsp被默认jsp servlet处理匹配了 index.html, 被default 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
<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匹配,
<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
发表评论(对文章涉及的知识点还有疑问,可以在这里留言,老高看到后会及时回复的。)