目录
1 servlet url-pattern 的匹配问题
1.1 精确匹配
1.2 路径匹配
1.3 后缀匹配
注意: 路径和后缀匹配无法同时设置
2 url-pattern 中 / 和 /* 的区别
3 url-pattern 的优先级问题
4 根路径 / 的匹配问题
tomcat 在配置 web.xml 的时候, servlet 是一个比较重要的问题, 在这里讨论一下 servlet 中的几个痛点
servlet url-pattern 的匹配问题
url-pattern 中 / 和 /* 的区别
url-pattern 的优先级问题
根路径 / 的匹配问题
1 servlet url-pattern 的匹配问题
url-pattern 有三种匹配模式, 分别是路径匹配, 精确匹配, 后缀匹配
1.1 精确匹配
<url-pattern > 中配置的项必须与 url 完全精确匹配.
代码举例
- <servlet-mapping>
- <servlet-name>MyServlet</servlet-name>
- <url-pattern>/kata/detail.html</url-pattern>
- <url-pattern>/demo.HTML</url-pattern>
- <url-pattern>/table</url-pattern>
- </servlet-mapping>
当在浏览器中输入如下几种 url 时, 都会被匹配到该 servlet
- http://10.43.11.143/myapp/kata/detail.html
- http://10.43.11.143/myapp/demo.html
- http://10.43.11.143/myapp/table
注意:
http://10.43.11.143/myapp/table/ 是非法的 url, 不会被当作 http://10.43.11.143/myapp/table 识别
另外上述 url 后面可以跟任意的查询条件, 都会被匹配, 如
http://10.43.11.143/myapp/table?hello 这个请求就会被匹配到 MyServlet.
1.2 路径匹配
以 "/" 字符开头, 并以 "/*" 结尾的字符串用于路径匹配
代码举例
- <servlet-mapping>
- <servlet-name>MyServlet</servlet-name>
- <url-pattern>/user/*</url-pattern>
- </servlet-mapping>
路径以 / user / 开始, 后面的路径可以任意. 比如下面的 url 都会被匹配.
- http://localhost:8080/appDemo/user/users.HTML
- http://localhost:8080/appDemo/user/addUser.action
- http://localhost:8080/appDemo/user/updateUser.actionl
1.3 后缀匹配
以 "*." 开头的字符串被用于后缀匹配
代码举例
- <servlet-mapping>
- <servlet-name>MyServlet</servlet-name>
- <url-pattern>*.jsp</url-pattern>
- <url-pattern>*.action</url-pattern>
- </servlet-mapping>
则任何扩展名为 jsp 或 action 的 url 请求都会匹配, 比如下面的 url 都会被匹配
- http://localhost:8080/appDemo/user/users.jsp
- http://localhost:8080/appDemo/toHome.action
注意: 路径和后缀匹配无法同时设置
注意: 路径和扩展名匹配无法同时设置, 比如下面的三个都是非法的, 如果设置, 启动 tomcat 服务器会报错.
- <url-pattern>
- /kata/*.jsp
- </url-pattern>
- <url-pattern>
- /*.jsp
- </url-pattern>
- <url-pattern>
- he*.jsp
- </url-pattern>
几个实例, 不明白请看本文第三章
2 url-pattern 中 / 和 /* 的区别
- <url-pattern>
- /
- </url-pattern>
- <url-pattern>
- /*
- </url-pattern>
先说 /*,/* 相对来讲比较好理解, 它是路径匹配的一种, 从范围上来讲, 它是范围最广的路径匹配, 所有的请求都符合它的要求, 从精度上来讲, 它是精度最低的路径匹配(注意! 我说的是路径匹配), 路径匹配的优先级是从长到短的(具体请看本文第三章), 所以说它是精度最低的路径匹配. 很多博客中说它的特点是匹配 *.jsp, 这不是废话吗? /* 本身就是路径匹配, 它当然可以匹配 *.jsp.
再说 /,/ 是匹配优先级最低的匹配, 当一个 url 和所有的 url-pattern 匹配都不合适的时候, 这个 url 就会走 / 匹配, 根本就没有什么 *.jsp 的限制, 大家之所以产生了(客观上也确实是这样)/ 不会匹配 *.jsp 但是 /* 会匹配 *.jsp 的原因是在 tomcat/conf/Web.xml 里面单独配置了 *.jsp 的配置, 具体请看本文第三章
3 url-pattern 的优先级问题
当一个 url 与多个 servlet 的匹配规则可以匹配时, 则按照 "精确路径> 最长路径>后缀匹配" 这样的优先级匹配到对应的 servlet.
例 1: 比如 servletA 的 url-pattern 为 /test,servletB 的 url-pattern 为 /* , 这个时候, 如果我访问的 url 为 http://localhost/test , 这个时候容器就会先进行精确路径匹配, 发现 / test 正好被 servletA 精确匹配, 那么就去调用 servletA, 不会去管 servletB.
例 2: 比如 servletA 的 url-pattern 为 / test/, 而 servletB 的 url-pattern 为 / test/a/, 此时访问 http://localhost/test/a 时, 容器会选择路径最长的 servlet 来匹配, 也就是这里的 servletB.
例 3: 比如 servletA 的 url-pattern:*.action ,servletB 的 url-pattern 为 /*, 这个时候, 如果我访问的 url 为 http://localhost/test.action, 这个时候容器就会优先进行路径匹配, 而不是去匹配扩展名, 这样就去调用 servletB.
那么就产生了一个疑问. 为什么 /* 会匹配到 *.jsp, 但是 / 匹配不到 *.jsp 呢
原因很简单, 在 tomcat/conf/Web.xml 里面会有如下配置
- <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>
可以清楚地看到 *.jsp 作为名为 jsp 的 servlet 的后缀匹配,/* 是路径匹配, 其优先级高于后缀匹配, 所以能匹配到后缀为 jsp 的文件. 而 / 是级别最低的匹配, 其级别低于后缀匹配, 所以 jsp 文件不会被 url-pattern 为 / 的匹配到.
4 根路径 / 的匹配问题
大家应该会注意到一个问题, 就是当 url-pattern 为 /* 的时候访问 http://localhost:8080 / 会 404, 但是访问 http://localhost:8080/index.HTML 却没有问题(当然前提是在 spring 容器里面配置了 < mvc:default-servlet-handler/>). 当 url-pattern 为 / 时, http://localhost:8080/ 会自动转发到 http://localhost:8080/index.HTML 而不会 404. 原因是什么呢?
首先, 我们必须要明确, 一个网址的根目录即 /(比如 http://localhost:8080/)到底意味着什么? 经过实验发现 / 是很特殊的, 它会被 url-pattern 为 /* 的匹配, 但他不会被 url-pattern 为 / 匹配.
在 tomcat 中,/ 默认是属于会被 defaultservlet 匹配, 但是其优先级低于路径匹配, 所以当某一个 servlet 的 url-pattern 为 /* 时,/ 就会被这个 servlet 匹配, 从而不被 defaultservlet 匹配.
在 tomcat 源代码中找到如下片段可以佐证我的看法
- <!--====================D efault Welcome File List=====================-
- ->
- <!-- When a request URI refers to a directory, the default servlet looks -->
- <!-- for a "welcome file" within that directory and, if present, to the
- -->
- <!-- corresponding resource URI for display. -->
- <!-- If no welcome files are present, the default servlet either serves
- a -->
- <!-- directory listing (see default servlet configuration on how to -->
- <!-- customize) or returns a 404 status, depending on the value of the
- -->
- <!-- listings setting. -->
- <!-- -->
- <!-- If you define welcome files in your own application's web.xml -->
- <!-- deployment descriptor, that list *replaces* the list configured -->
- <!-- here, so be sure to include any of the default values that you wish
- -->
- <!-- to use within your application. -->
上面是讲 Welcome File List 的, 即 / 路径会被默认转发到 Welcome File List 中规定的网页, 即初始页. 我翻译一下上面的一部分, 具体的可以谷歌翻译, 翻译
翻译
当请求 URI 指向目录时, 默认 servlet 在该目录中查找 "欢迎文件", 如果存在, 则在相应的资源 URI 中查找以进行显示. 如果不存在欢迎文件, 则默认 servlet 会提供目录列表 (请参阅默认 servlet 配置中的有关如何自定义的内容) 或返回 404 状态, 具体取决于列表设置的值
/ 会重定向到欢迎页面的原因是 Welcome File List 的存在, Welcome File List 发挥效果的前提是 / 必须被 defaultservlet 匹配. 当某一个 servlet 的 url-pattern 为 /* 时,/ 就会被这个 servlet 匹配, 从而不被 defaultservlet 匹配. 所以只有在自己定义的 servlet 的 url-pattern 为 / 时, http://localhost:8080/ 会自动转发到 http://localhost:8080/index.HTML 而不会 404
来源: https://www.cnblogs.com/sogeisetsu/p/12950699.html