解决tomcat关于配置servlet的url-pattern的问题

服务器

这篇文章主要讲解了解决tomcat关于配置servlet的url-pattern的问题,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。

盂县网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、自适应网站建设等网站项目制作,到程序开发,运营维护。创新互联自2013年起到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联

tomcat在配置web.xml的时候,servlet是一个比较重要的问题,在这里讨论一下servlet中的几个痛点

servlet url-pattern的匹配问题url-pattern中 //*的区别url-pattern的优先级问题根路径 /的匹配问题

1 servlet url-pattern的匹配问题

url-pattern有三种匹配模式,分别是路径匹配、精确匹配、后缀匹配

1.1 精确匹配

中配置的项必须与url完全精确匹配。

代码举例:point_down:


 MyServlet
 /kata/detail.html
 /demo.html
 /table

当在浏览器中输入如下几种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 路径匹配

以“/”字符开头,并以“/*”结尾的字符串用于路径匹配

代码举例:point_down:


 MyServlet
 *.jsp
 *.action

路径以/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 后缀匹配

以“*.”开头的字符串被用于后缀匹配

代码举例:point_down:


 MyServlet
 *.jsp
 *.action

则任何扩展名为jsp或action的url请求都会匹配,比如下面的url都会被匹配

http://localhost:8080/appDemo/user/users.jsp

http://localhost:8080/appDemo/toHome.action

注意:路径和后缀匹配无法同时设置

注意:路径和扩展名匹配无法同时设置,比如下面的三个都是非法的,如果设置,启动tomcat服务器会报错。

/kata/*.jsp

/*.jsp

he*.jsp

几个实例:point_down:,不明白请看本文第三章

2 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里面会有如下配置


 default
 /




 jsp
 *.jsp
 *.jspx

:point_up_2:可以清楚地看到 *.jsp作为名为jsp的servlet的后缀匹配,/*是路径匹配,其优先级高于后缀匹配,所以能匹配到后缀为jsp的文件。而 /是级别低的匹配,其级别低于后缀匹配,所以jsp文件不会被 url-pattern为/的匹配到。

4 根路径 /的匹配问题

大家应该会注意到一个问题,就是当url-pattern为/*的时候访问http://localhost:8080/会404,但是访问http://localhost:8080/index.html却没有问题(当然前提是在spring容器里面配置了 )。当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源代码中找到如下片段可以佐证我的看法:point_down: