【问题标题】:Forwarding requests between contexts in Tomcat在 Tomcat 中的上下文之间转发请求
【发布时间】:2012-06-12 17:21:17
【问题描述】:

我希望能够使用 Tuckey URLRewrite 过滤器在 Tomcat 中进行跨上下文请求转发。例如,我希望能够将传入的请求与 SEO-/用户友好的 URL(如 http://example.com/group-elements/300245/some-descriptive-text,其中“group-elements”不是已部署应用程序的名称)路由到映射到的 URL应用程序 'foo' 的 Java Spring 控制器方法,例如 http://example.com/foo/app/group/300245/elements。我正在使用 Tomcat 7.0.27 和 URLRewrite 3.2.0;我正在使用 Java Spring 3.1 Web 应用程序。

URLRewrite 3.20 documentation 为“to”过滤器参数元素添加了一个可选的“context”属性:

If your application server is configured to allow "cross context" communication then this attribute can be used to forward (and only forward, not redirect or other "to" types) requests to a named servlet context.

On Tomcat, for instance, the application contexts in the server configuration (server.xml or context.xml) need the option crossContext="true". For instance, the two applications mentioned before ("app" and "forum") have to be defined as:

<Context docBase="app" path="/app" reloadable="true" crossContext="true"/>
<Context docBase="forum" path="/forum" reloadable="true" crossContext="true"/>

鉴于此和original discussion about the feature,'context' 属性似乎是我正在寻找的。但是,我无法正确启用跨上下文请求转发。

这是我在 conf/server.xml 中的“上下文”条目应用程序“foo”:

<Context docBase="foo" path="/foo" reloadable="true" crossContext="true"/>

我在 webapps/ROOT/WEB-INF/ 中有我的 urlrewrite.xml 文件和 web.xml 文件。它们的外观如下:

urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" 
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">

<urlrewrite>    
    <rule>
        <from>baz</from>
        <!-- Note: this 'to' element's value has an error.  See the edit at bottom of this post for corrected version. -->
        <to context="foo">/foo/app/group/300245/elements</to> 
    </rule> 
</urlrewrite>

web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" version="2.5">

    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
        <init-param>
            <param-name>logLevel</param-name>
            <param-value>WARN</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

上面在 urlrewrite.xml 中定义的规则故意是基本的和硬编码的。在这种情况下,我只是想在开发“to”和“from”中的正则表达式之前让规则的跨上下文方面起作用。

当我使用该规则请求 http://example.com/baz 时,Tomcat 返回 404 错误,提示“请求的资源 (/baz) 不可用。”我在“to”过滤器参数中尝试了一些变体,但还没有任何效果。而且我还没有找到任何应​​该如何使用“上下文”的例子。

关于如何使这种跨上下文请求过滤起作用的任何想法?甚至可能吗?我想我可以通过将 foo.war 重命名为 ROOT.war 或更改 here 中提到的根应用程序来实现我想要做的事情,但我想通过 URLRewrite 尝试这样做,除非这样做是表面上看是不可行的或坏主意。

如果显示更多我的配置会有所帮助,请告诉我。提前感谢您的任何意见。

编辑

感谢 Christopher Schultz 提供的有用答案。就我而言,问题是由两件事引起的:1)在 webapps/ROOT/META-INF 中没有 context.xml 文件,以及 2)在 webapps/ 中的 URL 重写规则中的“to”元素中有错误根/WEB-INF/urlrewrite.xml。

修复涉及在 webapps/ROOT/META-INF 中放置一个正确的 context.xml 文件。供遇到此问题的其他人参考,该文件最终看起来像这样:

webapps/ROOT/META-INF/context.xml

<?xml version='1.0' encoding='utf-8'?>

<Context docBase="ROOT" path="/" reloadable="true" crossContext="true" />

正如 Schultz 所提到的,只需要为给定 URL 重写规则(此处为 ROOT)中的 'from' 元素中隐含的上下文定义一个带有 crossContext="true" 的上下文。不必在“to”URL 重写规则中为应用程序显式定义上下文。换句话说,您不需要为该应用程序手动创建 context.xml 文件——因此继续上面的示例,您不需要手动定义 context.xml 文件并将其放入 webapps/foo/META-INF /.

Schultz 的回答反映了官方 Tomcat 文档中定义上下文的建议:http://tomcat.apache.org/tomcat-7.0-doc/config/context.html#Defining_a_context

这个问题也是因为我最初的帖子中的 URL 重写规则有错误。正确的版本应该是:

urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" 
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">

<urlrewrite>    
    <rule>
        <from>baz</from>
        <!-- Note: the use of '/app' instead of '/foo/app/' below -->
        <to context="foo">/app/group/300245/elements</to> 
    </rule> 
</urlrewrite>

【问题讨论】:

  • 也许是个愚蠢的问题,但是你的 url 在你的应用程序中没有任何关于跨上下文的工作吗?
  • 如果我正确理解您的问题,不。 SEO-/用户友好的 URL 当前不映射到任何内容并产生 404。
  • 如果你已经有了一个没有跨上下文的 404,为什么你还期待一个没有跨上下文的 404 呢?
  • 因为我试图将指向根上下文(未部署任何内容)的用户友好 URL 映射到已部署应用程序的上下文 - 最好使用 URLRewrite。
  • 您的 Web 应用程序实际上位于磁盘的哪个位置?根据你的&lt;Context&gt;,应用在$CATALINA_BASE/foo

标签: spring tomcat servlets url-rewriting tuckey-urlrewrite-filter


【解决方案1】:

如果您的(真实)Web 应用程序部署到 /foo,并且您想即时重写 /group-elements/baz 之类的 URL 以转发(重定向)到/foo/app/group/300245/elements,那么您将不得不将重写过滤器部署到以下两个位置之一:/group-elements/

上述配置似乎部署到 ROOT( /),但随后将 URL /baz 映射到 /foo/app/group/300245/elements。相反,您可能想要这样:

<rule>
    <from>/group-elements/baz</from>
    <to context="foo">/foo/app/group/300245/elements</to>
</rule>

看起来你试图点击http://example.com/baz,我本来希望它会起作用。最后一点魔法是让ROOT 上下文跨上下文(注意你的webapp 不需要是跨上下文的:只有urlrewrite 可以)。您可以通过将crossContext="true" 添加到webapps/ROOT/META-INF/context.xmlROOT webapp 更改为跨上下文。

最后,您真的应该停止将&lt;Context&gt; 元素放在 server.xml 中:将它们留在其中基本上意味着您需要重新启动 Tomcat 才能更改您的 webapp 部署。

【讨论】:

  • 谢谢,上面答案中的方法效果很好。就我而言,这里的关键部分是在 webapps/ROOT/META-INF/context.xml 中定义 元素。
  • 哦,对上面代码示例中的“规则”语法进行更正:“to”元素值中的“/foo/app”段不正确;它应该只是“/app”,即/app/group/300245/elements
【解决方案2】:

在cmets之后我来做这个可能的结论:

我认为您将反向代理的概念与跨上下文混为一谈。跨上下文是在同一应用程序服务器内的两个 Web 应用程序之间共享数据的方法。像 'Apache http' 这样的反向代理可以重写一个 url 以将其传递给它后面的某个服务器,从而有效地隐藏任何不需要的部分或执行其他操作,如负载平衡。

基础设施是:客户端 --> 反向代理 --> 应用服务器

【讨论】:

  • “ROOT”不是 Tomcat 中的上下文吗,即使它没有部署常规应用程序?我描述的用例与功能的初始补丁here 中描述的用例有何不同?我在阅读它时可能遗漏了一些东西,但补丁的初始使用似乎没有从一个已部署的 Web 应用程序转发到另一个已部署的 Web 应用程序——或者是这样吗?
  • 我认为,如果您想使用该过滤器,您需要在根目录中部署一个带有该过滤器的应用程序。如果您不这样做,将没有人在该 url 上监听,所以除了 404 之外什么都不会发生。Tomcat 并不神奇。它只做你告诉它做的事情。
  • 我认为值得在这里跟进提到“客户端 --> 反向代理 --> 应用程序”基础设施似乎是启用我正在尝试做的事情的一个可能选项,但不是必需的.使用舒尔茨的回答中提到的方法,只能在 Tomcat 中进行跨上下文转发。可能的术语混淆(至少在我这边)可能会导致这里的一些混乱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 2012-03-15
相关资源
最近更新 更多