Spring flash属性在反向代理后面不起作用

时间:2013-10-14 19:13:38

标签: spring tomcat spring-mvc redirect proxy

我在尝试使RedirectAttributes的flashAttributes工作时遇到问题。 我在Tomcat 7.0上设置了一个使用Spring MVC构建的网站,并使用Apache mod_proxy和ajp设置了一个反向代理。

我面临的问题也在this question中描述,但是那里提供的答案根本不适用于我的情况(我使用的是Tomcat的单个实例)。

这是我用于测试目的的控制器片段:

@RequestMapping(value = "/land", method = RequestMethod.GET)
    public String land(RedirectAttributes redirectAttrs, Model model) {
    return "redirect_landing";
}

@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect(RedirectAttributes redirectAttrs, HttpSession session) {

    // add a session message
    session.setAttribute("sessionMessage", "a session message");

    // add a flash message
    redirectAttrs.addFlashAttribute("flashMessage", "a flash message");

    // define the base url
    String baseUrl = "http://localhost:8080/MyApp/";
    // String baseUrl = "http://dev.myapp.lan/";

    return "redirect:" + baseUrl + "land";
}

模板就像这样简单:

Flash message: ${flashMessage}
Session message: ${sessionMessage}

相同的代码会给出不同的结果,具体取决于我是直接在Tomcat上访问网站还是通过apache反向代理访问网站:

Tomcat的回复:
Flash消息:flash消息
会话消息:会话消息

在apache mod_proxy后面
Flash消息:
会话消息:会话消息

为什么通过代理访问网站时没有flash消息?

我查看了RedirectAttributesModelMap.javaModelMap.java的代码,但是没有足够的信息(显然逻辑是在其他地方实现的)。

注意:我总是可以回到会话属性来实现我的目标,但是这个问题对于那些在反向代理后面使用Tomcat的人来说感觉很有趣


代理配置(摘要):

<VirtualHost *:80>
    ServerName dev.myapp.lan    

    ProxyPass / ajp://localhost:8009/MyApp/

    ProxyPassReverseCookiePath /MyApp /
    ProxyPassReverseCookieDomain localhost MyApp

    ErrorLog /var/log/apache2/phonebook-error.log
    LogLevel warn

    CustomLog /var/log/apache2/phonebook-access.log combined
</VirtualHost> 

TIA。

2 个答案:

答案 0 :(得分:2)

更改反向代理中的上下文路径通常是解决问题的方法。假设这是问题,你有两个选择。

  1. 将您的应用程序部署为Tomcat上的ROOT应用程序,方法是将MyApp.war重命名为ROOT.war(如果是目录,则将MyApp目录重命名为ROOT)。

  2. 启动一个合适的工具来查看HTTP标头和内容(Wireshark,FireBug,ieHttpHeaders等 - 选择适合您和您的环境的工具)并查找路径需要的所有位置改变了,但没有改变。使用mod_headers和mod_substitute(或等效项)在反向代理中进行必要的更改。

  3. 就个人而言,我总是选择1,因为它更简单,更快捷,更容易且更不容易出错。当他们坚持要求他们必须在反向代理中更改上下文路径时,我花了好几天帮助客户调试问题。

    为什么会这样?

    当反向代理中的上下文路径发生变化时,有许多地方可能需要更改该路径:

    1. 从用户代理
    2. 收到的请求网址
    3. 后端服务器返回的重定向位置
    4. 网页链接的网址
    5. 应用程序(或应用程序正在使用的库)设置的自定义HTTP响应标头
    6. Cookie路径
    7. ProxyPass处理1

      ProxyPassReverse处理位置,内容位置和URI标头(2)

      ProxyPassReverseCookiePath处理5

      mod_proxy不处理案例4或案例5,因为这很难做到。您最终必须根据具体情况编写一些非常仔细的正则表达式,以获得所需的结果。

      我怀疑flashAttributes正在使用包含路径的自定义HTTP标头,这就是它们不起作用的原因。会话将起作用,因为它通常由会话cookie管理,并且您已配置ProxyPassReverseCookiePath。

答案 1 :(得分:0)

我知道这个问题很老了。

但是有一种方法可以通过代理和Spring Flash属性来解决这种情况。

我为FlashMapManager创建了一个自定义实现,覆盖了isFlashMapForRequest方法。

<bean id="flashMapManager" class="my.package.CustomSessionFlashMapManager" >
    </bean>

并声明一个bean:

function cds() {
        cd $1; ls -lart

        current_dir=$PWD
        venv_dir="$current_dir/venv"
        if [ -d $venv_dir ];
        then
                venv_activate="$venv_dir/bin/activate"
                echo "Directory has corresponding virtual environment.."
                echo "Sourcing $venv_activate.."
                source $venv_activate
        else
                deactivate
        fi
}

不幸的是,Spring使用请求路径来存储和检索Flash属性。因此,重定向时的/ someUrl在代理后变为/ myApp / someURL。