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

Spring 在Tomcat中在上下文之间转发请求,spring,tomcat,servlets,url-rewriting,tuckey-urlrewrite-filter,Spring,Tomcat,Servlets,Url Rewriting,Tuckey Urlrewrite Filter,我希望能够使用Tuckey URLRewrite过滤器在Tomcat中进行跨上下文请求转发。例如,我希望能够使用SEO-/用户友好的URL(其中“组元素”不是已部署应用程序的名称)将传入请求路由到映射到应用程序“foo”的Java Spring控制器方法的URL,如。我正在使用Tomcat 7.0.27和URLRewite 3.2.0;我正在使用JavaSpring3.1Web应用程序 注释“to”过滤器参数元素的可选“context”属性: If your application server

我希望能够使用Tuckey URLRewrite过滤器在Tomcat中进行跨上下文请求转发。例如,我希望能够使用SEO-/用户友好的URL(其中“组元素”不是已部署应用程序的名称)将传入请求路由到映射到应用程序“foo”的Java Spring控制器方法的URL,如。我正在使用Tomcat 7.0.27和URLRewite 3.2.0;我正在使用JavaSpring3.1Web应用程序

注释“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"/>
如果您的应用程序服务器配置为允许“跨上下文”通信,则此属性可用于将请求转发(且仅转发、不重定向或其他“到”类型)到命名的servlet上下文。
例如,在Tomcat上,服务器配置中的应用程序上下文(server.xml或context.xml)需要crossContext=“true”选项。例如,前面提到的两个应用程序(“应用程序”和“论坛”)必须定义为:
考虑到这一点和其他因素,“上下文”属性似乎就是我要寻找的。但是,我无法正确启用跨上下文请求转发

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

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

我的urlrewrite.xml文件和web.xml文件位于webapps/ROOT/web-INF/中。下面是它们的样子:

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>
<?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>

巴兹
/foo/app/group/300245/elements
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>

URL重写过滤器
org.tuckey.web.filters.urlrewrite.UrlRewriteFilter
对数电平
警告
URL重写过滤器
/*
上面在urlrewrite.xml中定义的规则是故意使用的基本规则和硬编码规则。在本例中,我只是想在开发“to”和“from”中的正则表达式之前,让规则的跨上下文方面发挥作用

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

关于如何让这种跨上下文请求过滤工作,有什么想法吗?有可能吗?我想我可以通过将foo.war重命名为ROOT.war或更改前面提到的根应用程序来实现我的目标,但我希望通过URLEWRITE来实现这一点,除非这样做不可行或表面上是个坏主意

如果显示更多我的配置将有所帮助,请让我知道。提前感谢您的任何意见

编辑

感谢克里斯托弗·舒尔茨的帮助回答。在我的例子中,问题是由两件事引起的:1)webapps/ROOT/META-INF中没有context.xml文件,2)webapps/ROOT/WEB-INF/urlrewrite.xml中URL重写规则中的“to”元素出错

修复方法包括在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重写规则中“from”元素中隐含的上下文定义crossContext=“true”的上下文(这里是根)。无需在“to”URL重写规则中为应用程序显式定义上下文。换句话说,您不需要为该应用程序手动创建context.xml文件——因此继续上面的示例,您不需要手动定义context.xml文件并将其放入webapps/foo/META-INF/中

Schultz的回答反映了在官方Tomcat文档中定义上下文的建议:

问题的另一个原因是,我的第一篇文章中的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: 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>
<?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>

巴兹
/app/组/300245/元素

在我发表评论之后,请得出以下可能的结论:

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

如果您的(真实的)webapp部署到
/foo
,并且您希望动态地重写URL,如
/group elements/baz
,以转发(而非重定向)到
/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>

/组元素/baz
/foo/app/group/300245/elements
看起来您试图点击
http://example.com/baz
这是我本该工作的。最后一点神奇之处是让
上下文跨上下文(请注意,您的webapp不需要跨上下文:只有urlrewrite一个需要跨上下文)。通过将
crossContext=“true”
添加到
webapps/ROOT/META-INF/context.xml,可以将
ROOT
webapp更改为跨上下文

最后,您应该真正停止将
元素放在server.xml中:将它们留在那里基本上意味着您需要重新启动Tomcat以更改您的webapp部署