将特定 servlet 映射为 Tomcat 中的默认 servlet

Posted

技术标签:

【中文标题】将特定 servlet 映射为 Tomcat 中的默认 servlet【英文标题】:Mapping a specific servlet to be the default servlet in Tomcat 【发布时间】:2012-12-22 18:54:33 【问题描述】:

我正在尝试实现一个获取原始请求的 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”。查看之前的帖子(例如,根映射here 和here,或url 重写here),我以为我想通了,但它不起作用。

这是我的 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。

【问题讨论】:

我认为我的问题与this 相同(或者这个问题的答案将解决我遇到的问题) 如果我理解正确,那么您说的是如何在 Tomcat 中设置后备 Web 应用程序。如果是这样,那么摆弄 web.xml (另一个 web 应用程序)将无济于事。相反,您应该查看 Tomcat 的文档如何存档,即您必须更改 Tomcat 的配置。 【参考方案1】:

这应该对你有用。

来自Java™ Servlet Specification Version 3.1 (JSR 340)

第 12 章。将请求映射到 Servlet

12.2 映射规范

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

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

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

空字符串("") 是一个特殊的URL 模式,它精确地映射到 应用程序的上下文根,即http://host:port/&lt;contextroot&gt;/ 形式的请求。 在这种情况下,路径信息是 /,servlet 路径和上下文路径是 空字符串("")

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

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

另外,请阅读本书Head First Servlets & JSP: Passing the Sun Certified Web Component Developer Exam (2nd edition) 中的简短示例(引用):

&lt;url-pattern&gt; 元素的三种类型

1) 完全匹配

示例:&lt;url-pattern&gt;/Beer/SelectBeer.do&lt;/url-pattern&gt;

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

2) 目录匹配

示例:&lt;url-pattern&gt;/Beer/*&lt;/url-pattern&gt;

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

3) 扩展匹配

示例:&lt;url-pattern&gt;*.do&lt;/url-pattern&gt;

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

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


更新

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

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

然后在此处查看解决方案:How do I make my web application be the Tomcat default application

换句话说,你想要的是一个没有应用程序上下文的路径,这意味着Tomcat默认应用程序的应用程序上下文。

引用以上链接:

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

【讨论】:

感谢您的宝贵时间。在发布我的请求之前,我确实阅读了此内容。但是,我的问题仍然存在。简单地说,我希望host:port 访问我的 servlet,而不是默认的 tomcat servlet。但在撰写本文时,当我这样做时,它总是返回 webapps/ROOT/index.html,它由 org.apache.catalina.servlets.DefaultServlet 返回,而不是我正在部署的 MyProxyServlet。 @VirtuallyReal 好的,我刚刚通过实现自定义默认 servlet 进行了快速测试。我制作了一个简单的Servlet,它只打印出一条消息“Default Servlet”,将它在web.xml 中映射到/。结果是,每当使用 web.xml 中未配置的路径发送请求时,都会触发我的 default servlet。所以它起作用了。 再次感谢。在我自己的 web.xml 中简单地做 / 是行不通的。但是,将我的 webapp 放到 ROOT 目录中就可以了。【参考方案2】:

我不确定我是否理解你想要的,但可能拦截 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>

【讨论】:

以上是关于将特定 servlet 映射为 Tomcat 中的默认 servlet的主要内容,如果未能解决你的问题,请参考以下文章

servlet(学习基本原理)

关于Tomcat启动Servlet工程与映射的访问JavaWeb

关于 websocket 的说明

Tomcat——Mapper(url到Wrapper的映射)

如何在 Jetty 中的 /* 上映射 servlet 过滤器?

servlet映射路径