如何使用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映射规则是按顺序使用的。 第一场成功的比赛是没有进一步的匹配尝试使用

  1. 容器将尝试find请求path与servletpath的完全匹配。 成功的匹配selectservlet。
  2. 容器将recursion地尝试匹配最长的path前缀。 这是通过一次一个地删除path树目录来完成的,使用'/'字符作为path分隔符。 最长的匹配决定了所select的servlet。
  3. 如果URLpath中的最后一个段包含扩展名(例如.jsp),则servlet容器将尝试匹配处理扩展请求的servlet。 扩展名被定义为最后一个段之后的最后一个段的一部分。 字符。
  4. 如果前三条规则都不导致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