谁能解释servlet映射?

时间:2008-10-24 16:16:54

标签: java java-ee servlets spring-mvc web.xml

我正在尝试使用SpringMVC编写Web应用程序。通常我只是将一些伪造的文件扩展名映射到Spring的前端控制器并幸福地生活,但这次我要使用类似REST的URL,没有文件扩展名。

将我的上下文路径下的所有内容映射到前端控制器(让我们称之为“ app ”)意味着我也应该处理静态文件,这是我不想做的事情(为什么重新发明另一个weel?),所以与tomcat的默认servlet的一些组合(让我们称之为“ tomcat ”)似乎是要走的路。

我做了像

这样的工作
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tomcat</servlet-name>
  <url-pattern>*.ext</url-pattern>
</servlet-mapping>

并为我的静态内容的每个文件扩展名重复后者。我只是想知道为什么以下设置对我来说与上面的设置相同,不起作用。

<!-- failed attempt #1 -->
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tomcat</servlet-name>
  <url-pattern>*.ext</url-pattern>
</servlet-mapping>

<!-- failed attempt #2 -->
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tomcat</servlet-name>
  <url-pattern>/some-static-content-folder/*</url-pattern>
</servlet-mapping>

任何人都能解释一下吗?

3 个答案:

答案 0 :(得分:43)

我想我可能知道发生了什么。

在你工作的web.xml中,你已经将servlet设置为默认的servlet(如果没有其他匹配,它本身就是默认的servlet),它将回答任何与另一个映射不匹配的请求。 / p>

在失败1中,您的/ *映射似乎确实是有效的路径映射。使用web.xml中的/ *映射,它可以响应除其他路径映射之外的所有请求。根据规范,扩展映射是由显式映射覆盖的隐式映射。这就是扩展映射失败的原因。一切都明确映射到app。

在失败2中,除了与静态内容映射匹配的内容外,App负责所有内容。为了显示我设置的快速测试中发生了什么。这是一个例子。 /some-static-content-folder/包含test.png

尝试访问test.png我试过:

/some-static-content-folder/test.png

,找不到该文件。无论如何尝试

/some-static-content-folder/some-static-content-folder/test.png
它出现了。因此,似乎Tomcat默认servlet(至少6.0.16)删除了servlet映射,并将尝试使用剩余路径查找该文件。根据这篇文章Servlet for serving static content Jetty给出了你和我期待的行为。

是否有某些原因使您无法执行某些操作,例如为您的其余调用映射根目录。像app映射到/ rest_root / *之类的东西比你负责rest_root文件夹中发生的任何事情,但是其他地方应该由Tomcat处理,除非你做了另一个显式映射。我建议将其余的servlet设置为路径映射,因为它更好地声明了intent。使用/或/ *似乎不合适,因为您必须映射异常。以SO为例,我的其余映射类似于

  用户servlet的

/ users / *

     帖子servlet的

/ posts / *

映射顺序

  1. 明确(路径映射)
  2. 隐式(扩展映射)
  3. 默认(/)
  4. 请纠正我出错的任何事情。

答案 1 :(得分:3)

作为参考,“失败的尝试#2”在Tomcat的版本中完全正确&gt; =到6.0.29。

这是在版本6.0.29中修复的Tomcat错误的结果:

https://issues.apache.org/bugzilla/show_bug.cgi?id=50026

<!-- Correct for Tomcat >= 6.0.29 or other Servlet containers -->
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>/some-static-content-folder/*</url-pattern>
</servlet-mapping>

答案 2 :(得分:2)

我从未试图像这样映射一个servlet,但我认为/ *在技术上确实都以/开头,并以/ *结尾,即使两者都使用相同的字符匹配。