如何使用web.xml中的Servlet URL映射?

时间:2013-03-13 12:38:20

标签: java java-ee servlets

我有一个包含内容的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处理。为什么呢?

更新

谢谢你们的帮助。 我意识到行为取决于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

2 个答案:

答案 0 :(得分:49)

从Servlet 3.0 specification,这是Web容器在收到请求后必须找到servlet的方式(强调我的):

  

用于映射到servlet的路径是来自的请求URL   请求对象减去上下文路径和路径参数。该   下面的URL路径映射规则按顺序使用。 第一次成功   匹配用于未尝试进一步匹配

     
      
  1. 容器将尝试查找请求路径与servlet路径的完全匹配。成功的比赛选择   的servlet。
  2.   
  3. 容器将递归尝试匹配最长的路径前缀。这是通过逐步降低路径树的目录来完成的   一次,使用'/'字符作为路径分隔符。最长的   match确定所选的servlet。
  4.   
  5. 如果URL路径中的最后一个段包含扩展名(例如.jsp),则servlet容器将尝试匹配处理的servlet   请求延期。扩展名被定义为   最后一个'。'字符后的最后一段。
  6.   
  7. 如果前三个规则都没有导致servlet匹配,则容器将尝试提供适合的内容   资源要求。如果为此定义了“默认”servlet   应用程序,它将被使用。许多容器提供隐含的   用于提供内容的默认servlet。
  8.         

    容器必须使用区分大小写的字符串比较进行匹配。

您还应该查看映射的规范(如下所示):

  

在Web应用程序部署描述符中,使用以下语法   用于定义映射:

     
      
  • ‘/’字符开头并以‘/*’后缀结尾的字符串   用于路径映射。

  •   
  • ‘*.’前缀开头的字符串用作扩展名映射。

  •   
  • 空字符串("")是一个精确映射到的特殊网址格式   应用程序的上下文根,即表单的请求   http://host:port/<contextroot>/。在这种情况下,路径信息为’/’和   servlet路径和上下文路径为空字符串(““)

  •   
  • 仅包含’/’字符的字符串表示“默认”   应用程序的servlet。在这种情况下,servlet路径是   请求URI减去上下文路径,路径信息为空。

  •   
  • 所有其他字符串仅用于完全匹配

  •   

现在让我们看看例子。考虑以下映射集:

Path Pattern            Servlet
/foo/bar/*              servlet1
/baz/*                  servlet2
/catalog                servlet3
*.bop                   servlet4

将导致以下行为:

Incoming Path           Servlet Handling Request
/foo/bar/index.html     servlet1
/foo/bar/index.bop      servlet1
/baz                    servlet2
/baz/index.html         servlet2
/catalog                servlet3
/catalog/index.html     “default” servlet
/catalog/racecar.bop    servlet4
/index.bop              servlet4

请注意,如果是/catalog/index.html/catalog/racecar.bop,则为。{ 未使用映射到“/catalog”的servlet,因为匹配不准确。

现在出现问题:)

/path/test属于映射规范的第5点。这意味着只有以/path/test结尾的路径才会定位servlet1

但是/path/test/*符合相同规范的第一点。这意味着:

.../path/test将由servlet1

处理

.../path/test/abc将由servlet2

处理

我在测试应用程序中验证了这一点。

答案 1 :(得分:1)

你的路径冲突。

你的两条路径都是一样的,'/ *'没有任何区别。 显然,当你尝试路径时,最后一次匹配(servlet2)就会被执行。

您通常会在Servlet名称中添加一个路径,例如:

/path/test/servlet1
/path/test/servlet2