谁能解释 servlet 映射?

Posted

技术标签:

【中文标题】谁能解释 servlet 映射?【英文标题】:Can anyone explain servlet mapping? 【发布时间】:2010-09-19 01:14:39 【问题描述】:

我正在尝试使用 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>

谁能解释一下?

【问题讨论】:

static.springsource.org/spring-webflow/docs/2.0.x/reference/… 相关: ***.com/a/14225540/814702 【参考方案1】:

作为参考,“失败的尝试 #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>

【讨论】:

【参考方案2】:

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

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

在 Failed 1 中,您的 /* 映射确实是有效的路径映射。使用 web.xml 中的 /* 映射,它会回答除其他路径映射之外的所有请求。根据规范,扩展映射是被显式映射覆盖的隐式映射。这就是扩展映射失败的原因。一切都明确映射到应用程序。

在 Failed 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 contentJetty 给出了你和我所期待的行为。

有什么原因你不能为你的休息调用映射一个根目录。像 app 映射到 /rest_root/* 之类的东西比您负责 rest_root 文件夹中发生的任何事情,但其他任何地方都应由 Tomcat 处理,除非您进行另一个显式映射。我建议将您的 rest servlet 设置为路径映射,因为它可以更好地声明意图。使用 / 或 /* 似乎不合适,因为您必须列出例外情况。以 SO 为例,我的其余映射将类似于

/users/* 用于用户 servlet

/posts/* 用于帖子 servlet

映射顺序

    显式(路径映射) 隐式(扩展映射) 默认 (/)

请纠正我的错误。

【讨论】:

“失败尝试 #1”的解释在目标上已失效。还是想不出另一个。 如果 /* 已经映射到“app” servlet,那么映射“/”还能得到什么? 如果使用 /*,映射出 / 并没有任何好处,因为它永远不会被调用。 /* 的缺点是你需要处理所有事情,使用 / 你仍然可以设置扩展映射。 好的,我试图围绕你对案例 #2 的解释来思考。至于您的问题,不,没有特别的理由不创建 /rest_root/* 映射,只是个人喜好。听起来比使用默认映射和扩展映射更简单 :-) 意识到 Servlet 不支持像 '/myAppModules/*/Services/*' 这样的通配符,有点发疯。我可以想到许多其他可以处理此问题的服务器,但不是 Servlet。有趣的是,业余爱好者级 WAMP 可以做到,但不是“企业级”Servlet。【参考方案3】:

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

【讨论】:

以上是关于谁能解释 servlet 映射?的主要内容,如果未能解决你的问题,请参考以下文章

Java Servlets 线程模型

Servlet 过滤器和 Jersey 过滤器有啥区别?

如何连接 Derby 数据库和 Servlet?

Servlet规范之Requests与Servlets映射

servlet虚拟路径映射

URL 模式 servlet 映射