如何使用 web.xml 中的 Servlet url 映射? [英] How are Servlet url mappings in web.xml used?

查看:29
本文介绍了如何使用 web.xml 中的 Servlet url 映射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含内容的 web.xml 文件:

<servlet-name>servlet1</servlet-name><servlet-class>org.mycompany.test1</servlet-class></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.../路径/测试

两个请求都由 Servlet2 处理.为什么?

更新

谢谢大家的帮助.我意识到行为取决于 servlet 映射声明的顺序.我试过这个 web.xml

<servlet-name>servlet1</servlet-name><servlet-class>org.mycompany.test1</servlet-class></servlet><小服务程序><servlet-name>servlet2</servlet-name><servlet-class>org.mycompany.test2</servlet-class></servlet><小服务程序><servlet-name>servlet3</servlet-name><servlet-class>org.mycompany.test3</servlet-class></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.../路径/测试/- servlet2.../路径/测试 - servlet2.../path/abc - servlet3.../路径/- servlet4.../路径 - servlet4

解决方案

来自 Servlet 3.0 规范,这是 web 容器在收到请求后必须如何定位 servlet(重点是我的):

<块引用>

用于映射到 servlet 的路径是来自请求对象减去上下文路径和路径参数.这以下 URL 路径映射规则按顺序使用.第一次成功使用 match 后不再尝试匹配:

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

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

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

<块引用>

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

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

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

  • 空字符串 ("") 是一种特殊的 URL 模式,它精确地映射到应用程序的上下文根,即表单的请求http://host:port//.在这种情况下,路径信息是 '/' 和servlet 路径和上下文路径为空字符串 (").

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

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

现在让我们看一下示例.考虑以下一组映射:

<前>路径模式 Servlet/foo/bar/* servlet1/baz/* servlet2/目录servlet3*.bop servlet4

将导致以下行为:

<前>传入路径 Servlet 处理请求/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 结尾的路径才会以 servlet1 为目标.

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

.../path/test 将由 servlet1

处理

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

处理

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

I have a web.xml file with content:

<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>

I tried requests

.../path/test/abc 
.../path/test

Both requests are processed by Servlet2. Why?

UPDATE

Thank you guys for your help. I realised that behaviour depends on order of servlet-mapping declaration. I tried this 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>

results:

.../path/test/abc - servlet2
.../path/test/ - servlet2
.../path/test - servlet2

.../path/abc - servlet3
.../path/ - servlet4
.../path - servlet4

解决方案

From Servlet 3.0 specification, this is how the web container must locate the servlet after receiving a request (emphasis mine):

The path used for mapping to a servlet is the request URL from the request object minus the context path and the path parameters. The URL path mapping rules below are used in order. The first successful match is used with no further matches attempted:

  1. The container will try to find an exact match of the path of the request to the path of the servlet. A successful match selects the servlet.
  2. The container will recursively try to match the longest path-prefix. This is done by stepping down the path tree a directory at a time, using the ’/’ character as a path separator. The longest match determines the servlet selected.
  3. If the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that handles requests for the extension. An extension is defined as the part of the last segment after the last ’.’ character.
  4. If neither of the previous three rules result in a servlet match, the container will attempt to serve content appropriate for the resource requested. If a "default" servlet is defined for the application, it will be used. Many containers provide an implicit default servlet for serving content.

The container must use case-sensitive string comparisons for matching.

You should also look the specification of mappings (given below):

In the Web application deployment descriptor, the following syntax is used to define mappings:

  • A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used for path mapping.

  • A string beginning with a ‘*.’ prefix is used as an extension mapping.

  • The empty string ("") is a special URL pattern that exactly maps to the application's context root, i.e., requests of the form http://host:port/<contextroot>/. In this case the path info is ’/’ and the servlet path and context path is empty string ("").

  • A string containing only the ’/’ character indicates the "default" servlet of the application. In this case the servlet path is the request URI minus the context path and the path info is null.

  • All other strings are used for exact matches only

Let us look at examples now. Consider the following set of mappings:

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

The following behavior would result:

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

Note that in the case of /catalog/index.html and /catalog/racecar.bop, the servlet mapped to "/catalog" is not used because the match is not exact.

Now coming to your problem :)

/path/test belongs to the 5th point of specification of mappings. Which means only the paths ending in /path/test will target servlet1.

However /path/test/* qualifies for the first point of the same specification. This means that:

.../path/test will be handled by servlet1 and

.../path/test/abc will be handled by servlet2

Which was verified by me in a test application.

这篇关于如何使用 web.xml 中的 Servlet url 映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆