如何使用web.xml中的Servlet URL映射?
我有一个web.xml文件的内容:
<servlet> <servlet-name>servlet1</servlet-name> <servlet-class>org.mycompany.test1</servlet-class> </servlet> <servlet> <servlet-name>servlet2</servlet-name> <servlet-class>org.mycompany.test2</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet1</servlet-name> <url-pattern>/path/test</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>servlet2</servlet-name> <url-pattern>/path/test/*</url-pattern> </servlet-mapping>
我试过请求
.../path/test/abc .../path/test
这两个请求都由Servlet2处理。 为什么?
UPDATE
谢谢你们的帮助。 我意识到,行为取决于servlet映射声明的顺序。 我试过这个web.xml
<servlet> <servlet-name>servlet1</servlet-name> <servlet-class>org.mycompany.test1</servlet-class> </servlet> <servlet> <servlet-name>servlet2</servlet-name> <servlet-class>org.mycompany.test2</servlet-class> </servlet> <servlet> <servlet-name>servlet3</servlet-name> <servlet-class>org.mycompany.test3</servlet-class> </servlet> <servlet> <servlet-name>servlet4</servlet-name> <servlet-class>org.mycompany.test4</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet1</servlet-name> <url-pattern>/path/test</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>servlet2</servlet-name> <url-pattern>/path/test/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>servlet3</servlet-name> <url-pattern>/path/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>servlet4</servlet-name> <url-pattern>/path</url-pattern> </servlet-mapping>
结果:
.../path/test/abc - servlet2 .../path/test/ - servlet2 .../path/test - servlet2 .../path/abc - servlet3 .../path/ - servlet4 .../path - servlet4
从Servlet 3.0 规范 ,这是Web容器如何在接收到请求后重定位servlet(重点是我的):
用于映射到servlet的path是请求对象的请求URL减去上下文path和path参数。 下面的URLpath映射规则是按顺序使用的。 第一场成功的比赛是没有进一步的匹配尝试使用 :
- 容器将尝试find请求path与servletpath的完全匹配。 成功的匹配selectservlet。
- 容器将recursion地尝试匹配最长的path前缀。 这是通过一次一个地删除path树目录来完成的,使用'/'字符作为path分隔符。 最长的匹配决定了所select的servlet。
- 如果URLpath中的最后一个段包含扩展名(例如.jsp),则servlet容器将尝试匹配处理扩展请求的servlet。 扩展名被定义为最后一个段之后的最后一个段的一部分。 字符。
- 如果前三条规则都不导致servlet匹配,则容器将尝试提供适合于所请求的资源的内容。 如果为应用程序定义了一个“默认”servlet,它将被使用。 许多容器提供了一个隐含的默认servlet来提供内容。
容器必须使用区分大小写的string比较进行匹配。
你也应该看看映射的规范(下面给出):
在Web应用程序部署描述符中,使用以下语法来定义映射:
以
'/'
字符开头并以'/*'
后缀结尾的string用于path映射。以
'*.'
开头的string 前缀被用作扩展映射。空string
("")
是一个特殊的URL模式,它准确地映射到应用程序的上下文根,即格式为http://host:port/<contextroot>/
。 在这种情况下,path信息是'/'
,servletpath和上下文path是空string(““)
。只包含
'/'
字符的string表示应用程序的“默认”servlet。 在这种情况下,servletpath是请求URI减去上下文path,path信息为空。所有其他string仅用于精确匹配
现在让我们看看例子。 考虑以下一组映射:
path模式Servlet / foo / bar / * servlet1 / baz / * servlet2 /目录servlet3 * .bop servlet4
以下行为将导致:
传入pathServlet处理请求 /foo/bar/index.html servlet1 /foo/bar/index.bop servlet1 / baz servlet2 /baz/index.html servlet2 /目录servlet3 /catalog/index.html“默认”的servlet /catalog/racecar.bop servlet4 /index.bop servlet4
请注意,对于/catalog/index.html
和/catalog/racecar.bop
,映射到“/catalog”
的servlet未使用,因为匹配不正确。
现在到你的问题:)
/path/test
属于映射规范的第5个点。 这意味着只有以/path/test
结尾的/path/test
才能servlet1
。
但是/path/test/*
符合相同规范的第一个要点。 这意味着:
.../path/test
将由servlet1
和
.../path/test/abc
将由servlet2
处理
这是我在testing应用程序validation。
你的path冲突。
两条路都是一样的,'/ *'没有任何区别。 显然,当你尝试你的path,最后一个匹配(servlet2)被执行。
您通常使用Servlet名称inputpath,例如:
/path/test/servlet1 /path/test/servlet2