技术分享 JAVA WEB 查看内容

web.xml中servlet匹配优先级探析

老高 | 发布于 2022-03-15 16:24| 浏览()| 评论() | 收藏() | 点赞() | 打印

一. web.xml中配置url-pattern的规则

分为四类

1)精确匹配:

匹配确定uri
/index
/index/xyzabc

2)前缀匹配

/*
/main/*

3)后缀匹配

*.do
*.action

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匹配

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


发表评论(对文章涉及的知识点还有疑问,可以在这里留言,老高看到后会及时回复的。)

表情