如何在Google App Engine Java应用程序上的模块之间共享会话? [英] How to share sessions between modules on a Google App Engine Java application?

查看:300
本文介绍了如何在Google App Engine Java应用程序上的模块之间共享会话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我通过模块A中的 HttpSession 在会话中存储某些内容时:

  HttpSession session = req.getSession(true); 
session.setAttribute(username,Eng.Fouad);

然后我尝试从模块B中检索此信息(在同一浏览器会话期间) p>

  HttpSession session = req.getSession(true); 
String username = session.getAttribute(username); // 空值!

我得到了 null 作为值,指的是不同的会话。



如何在GAE中的多个模块之间共享会话?




我认为它效果不好:





我一直在努力解决这个问题数周。事实证明,这些模块不会共享会话,因为cookie在不同的子域(module1.apphost.com cookies!= module2.apphost.com cookies)中是不同的。要解决这个问题,只需在每个模块的 web.xml 中设置cookie域:

 <?xml version =1.0encoding =UTF-8?> 
< web-app xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns =http://java.sun.com/xml/ns / javaee
xsi:schemaLocation =http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5 .xsd
id =WebApp_IDversion =2.5>

< context-param>
< param-name> org.mortbay.jetty.servlet.SessionDomain< / param-name>
< param-value> .apphost.com< / param-value>
< / context-param>
< context-param>
< param-name> org.mortbay.jetty.servlet.SessionPath< / param-name>
< param-value> /< / param-value>
< / context-param>
< context-param>
< param-name> org.mortbay.jetty.servlet.SessionURL< / param-name>
< param-value> none< / param-value>
< / context-param>

...

< / web-app>






em>



以下是可用于Jetty cookie的所有初始参数的列表:








编辑:适用于开发环境的解决方法:
$ b 修复每个模块的端口(使用JVM参数 -Dcom.google.appengine.devappserver_module。{module_name} .port = 8081 )。例如,module1始终托管在localhost:8888,而module2始终托管在localhost:8889。 查看此答案

  • 将本地主机与每个模块的端口绑定到一个使用Fiddler的自定义域。例如,moule1.gaelocal.com指向localhost:8888,moule2.gaelocal.com指向localhost:8889。 查看此答案

  • 更新 web.xml ,并用 .gaelocal.com 替换 .apphost.com .apphost.com )。

  • 解决方案

    您可以实现HttpServletFilter和HttpSessionListener的组合,以同时处理两个webapps。当请求修改会话状态时,将其保存到持久性存储(db)中,并且对于每个请求,检查会话对象是否与db保持最新。



    注意这需要两个Web应用程序在相同的域下(例如:mydomain.com/webapp1和mydomain.com/webapp2)提供服务。否则,JSESSIONID cookie将不会被浏览器交付。



    现在有一种现成的解决方案,例如 Hazelcast 。它是专为负载平衡/故障转移而设计的,但您可能可以将其用于预期目的。



    另外考虑使用HttpSession的可能性是错误的架构设计。也许你应该用数据库/ API进行交易?


    When I store something in the session via HttpSession in module A:

    HttpSession session = req.getSession(true);
    session.setAttribute("username", "Eng.Fouad");
    

    then I try to retrieve this information from within module B (during the same browser session):

    HttpSession session = req.getSession(true);
    String username = session.getAttribute("username"); // null!
    

    I got null as a value, which means different session.

    How to share session across multiple modules in GAE?


    Old Answer which I think it doesn't work well:

    I've been trying to solving this issue for weeks. It turns out that the modules don't share sessions because the cookies are different across different sub-domains (module1.apphost.com cookies != module2.apphost.com cookies). To solve it, simply set cookies domain in web.xml of each module:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             id="WebApp_ID" version="2.5">
    
      <context-param>
        <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
        <param-value>.apphost.com</param-value>
      </context-param>
      <context-param>
        <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
        <param-value>/</param-value>
      </context-param>
      <context-param>
        <param-name>org.mortbay.jetty.servlet.SessionURL</param-name>
        <param-value>none</param-value>
      </context-param>
    
      ...
    
    </web-app>
    


    EXTRA:

    Here is a list of all init parameters you can use with Jetty cookies:


    EDIT: Workaround for development environment:

    1. Make the port of each module fixed (using JVM arg -Dcom.google.appengine.devappserver_module.{module_name}.port=8081). For example, module1 is always hosted at localhost:8888, and module2 is always hosted at localhost:8889. See this answer.
    2. Bind the localhost with the port of each module to a custom domain using Fiddler. For example, moule1.gaelocal.com points to localhost:8888 and moule2.gaelocal.com points to localhost:8889. See this answer.
    3. Update web.xml of each module and replace .apphost.com with .gaelocal.com (or just use .apphost.com for both environment).

    解决方案

    You can implement a combination of HttpServletFilter and HttpSessionListener that synchronizes accross both webapps. When a request modifies session state, save it to a persistent store (db), and for each requests, checks if the session objects are up to date with db.

    Note that this require both web app to be served under the same domain (eg: mydomain.com/webapp1 and mydomain.com/webapp2). Otherwise the JSESSIONID cookie wouldn't be delivered by the browser.

    There's an off the shelf solution that does this such as Hazelcast. It's designed for load balancing / failover but you might be able to use it for the intended purpose.

    Also consider the possibility using HttpSession is a wrong architectural design. Maybe you should be transacting with a database / API instead?

    这篇关于如何在Google App Engine Java应用程序上的模块之间共享会话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆