任何人都可以解释servlet映射吗?

2022-08-31 20:38:32

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

将我的上下文路径下的所有内容映射到前端控制器(让我们称之为“应用程序”)意味着我也应该处理静态文件,这是我宁愿不做的事情(为什么要重新发明另一个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>

任何人都可以透露一些光明吗?


答案 1

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

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

在“失败 1”中,/* 映射似乎是有效的路径映射。使用 Web 中的 /* 映射.xml它可以应答除其他路径映射之外的所有请求。根据规范,扩展映射是被显式映射覆盖的隐式映射。这就是扩展映射失败的原因。所有内容都显式映射到应用程序。

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

尝试访问测试.png我尝试了:

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

并且找不到该文件。但是尝试

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

它出现了。因此,Tomcat 默认 servlet(至少 6.0.16)似乎删除了 servlet 映射,并将尝试使用剩余的路径查找该文件。根据这篇文章,Servlet提供静态内容,Jetty给出了你和我期望的行为。

有没有某种原因,你不能做一些事情,比如映射你的休息调用的根目录。类似于映射到 /rest_root/* 的应用程序,而不是您对 rest_root 文件夹中发生的任何事情负责,但其他任何地方都应该由 Tomcat 处理,除非您进行另一个显式映射。我建议将 rest servlet 设置为路径映射,因为它更好地声明了意图。使用 / 或 /* 似乎不合适,因为您必须绘制出异常。以 SO 为例,我的 rest 映射将类似于

/users/* for the user servlet

/posts/* for the posts servlet

映射顺序

  1. 显式(路径映射)
  2. 隐式(扩展映射)
  3. 默认值 (/)

请纠正我做错的任何事情。


答案 2

作为参考,“失败的尝试#2”在Tomcat >=到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>

推荐