15

我正在尝试实现一个获取原始请求的 servlet,并决定要么处理它们,要么将它们转发到另一个后端服务器。它类似于负载均衡器,其中接收到的请求被转发到(在我的情况下为 2)目的地之一。其中一个目的地是远程的(在另一台主机上)。此外,请求可能会到达根目录 ( http://mycompany.com/ )。

因为我想获得原始请求,所以我实现了自己的 servlet(子类化HttpServlet),效果很好。我的 servlet 看起来像:

public class MyProxyServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        processOrForward(req, resp);
    }
    // also doGet(), doHead(), ...
}

由于我要处理的服务可能会向根发送请求,因此我想将我的 servlet 映射为默认 servlet,从而接收任何没有显式 servlet 映射的请求。假设我的 servlet 的名称是“myservlet”,并且与另一个 servlet“foo”一起运行,我希望所有以http://mycompany.com/foo/ ... 形式的请求都被传递给 foo,并且一切其他(例如,/、/bar/...、/myservlet/...)到“myservlet”。查看之前的帖子(例如,此处此处的根映射,或此处的 url 重写),我以为我想通了,但它不起作用。

这是我的web.xml

<web-app>
  <servlet>
    <servlet-name>ProxyServlet</servlet-name>
    <servlet-class>com.mycompany.MyProxyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>ProxyServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

在上面的web.xml中,对于 url-pattern 我试过

"/" and "/*" and empty (i.e., <url-pattern></url-pattern>), all behave the same -->
    Requests to root (/)goes to tomcat's default servlet
    Requests to /myservlet/... are handled by "myservlet"
    Requests to /fubar/... are always 404

有没有办法将我的 servlet 设置为默认值。即,任何不专门映射到 servlet 的请求都会出现在我的面前(接收所有请求甚至是可以接受的,因为我可以将这个 servlet 部署在它自己的容器中)。万一这很重要,我在 Ubuntu 12.10 上使用 Tomcat 7.0.30。

4

2 回答 2

35

这应该对你有用。

来自Java™ Servlet 规范版本 3.1 (JSR 340)

第 12 章 将请求映射到 Servlet

12.2 映射规范

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

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

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

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

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

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


另外,请阅读Head First Servlets & JSP: Passing the Sun Certified Web Component Developer Exam (2nd edition) (quote) 一书中的简短示例的精彩解释:

三种<url-pattern>元素

1) 完全匹配

例子:
<url-pattern>/Beer/SelectBeer.do</url-pattern>

  • 必须以斜杠 ( ) 开头/
  • 可以有扩展名(如 .do),但这不是必需的。

2) 目录匹配

例子:
<url-pattern>/Beer/*</url-pattern>

  • 必须以斜杠 ( ) 开头/
  • 始终以斜杠/星号 ( /*) 结尾。

3) 扩展匹配

例子:
<url-pattern>*.do</url-pattern>

  • 必须以星号 ( ) 开头*(切勿使用斜杠)。
  • 在星号之后,它必须有一个点扩展名(.do、.jsp 等)。


重要提示:
URL 模式代表逻辑/虚拟结构,即指定的模式(路径)不需要物理存在


更新

如果你愿意,正如你在评论中所说,

我希望 host:port 访问我的 servlet,而不是默认的 tomcat servlet

然后在此处查看解决方案:
如何使我的 Web 应用程序成为 Tomcat 默认应用程序

也就是说,你想要的是一个没有应用上下文的路径,它暗示了Tomcat默认应用的应用上下文。

从上面的链接引用:

在标准的 Tomcat 安装中,您会注意到在同一目录 (CATALINA_BASE)/webapps/ 下,有一个名为ROOT的目录 (大写字母很重要,即使在 Windows 下也是如此)。这是当前 Tomcat 默认应用程序的驻留地,当用户调用 http://myhost.company.com[:port]. 诀窍是把你的应用程序放在它的位置。

于 2013-01-08T22:59:59.390 回答
1

我不确定我是否理解你想要的,但可能拦截 404 是你想要做的,然后重定向到你想要的地方。

我来到这里是因为我对 tomcat 7 有奇怪的问题,我正在做你想要的;)

这只是我获得root权限的一种方式,EMPTY

<servlet-mapping>
    <servlet-name>Default</servlet-name>
    <url-pattern></url-pattern>
</servlet-mapping>

这样:任何东西都被重定向到这个 servlet,包括图像等,例如,我打开另一个页面,这显示了这个,root,然后我可以在日志中看到 4 个对同一页面的更多请求,3 个用于 css,一个用于图像.

<servlet-mapping>
    <servlet-name>Default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
于 2013-07-10T08:03:47.077 回答