在Tomcat中的上下文之间转发请求

时间:2012-06-12 17:21:17

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

我希望能够使用Tuckey URLRewrite过滤器在Tomcat中进行跨上下文请求转发。例如,我希望能够将传入的请求与一个SEO- /用户友好的URL(如http://example.com/group-elements/300245/some-descriptive-text)路由到URL,其中“group-elements”不是已部署应用程序的名称映射到应用程序'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中的'Context'条目应用程序'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'元素有错误ROOT / 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>

2 个答案:

答案 0 :(得分:3)

如果您的(真实)网络应用已部署到/foo,并且您希望即时重写网址,例如/group-elements/baz转发( 重定向到/foo/app/group/300245/elements,然后您必须将重写过滤器部署到以下两个位置之一:/group-elements/

上述配置似乎正在部署到ROOT( /),但随后将网址/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才能实现)。您可以将ROOT webapp更改为addint crossContext="true"webapps/ROOT/META-INF/context.xml的跨上下文。

最后,您应该停止在server.xml中放置<Context>元素:将它们留在那里基本上意味着您需要重新启动Tomcat才能更改您的Web应用程序部署。

答案 1 :(得分:1)

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

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

基础设施将是:客户端 - &gt;反向代理 - &gt;应用服务器