在 Tomcat 中的上下文之间共享会话数据
Posted
技术标签:
【中文标题】在 Tomcat 中的上下文之间共享会话数据【英文标题】:Sharing session data between contexts in Tomcat 【发布时间】:2012-03-15 06:09:21 【问题描述】:我一直在寻找在多个战争文件之间共享会话数据的解决方案。我遇到了以下解决方案http://www.fwd.at/tomcat/sharing-session-data-howto.html
它的基本思想是,如果你有多个war文件,你可以使用第一个上下文的sessionid设置一个cookie。
可以使用适用于所有上下文/应用程序的路径设置 cookie。
例如,如果我有 3 个应用程序的以下配置
/myapp/app1
/myapp/app2
/myapp/app3
我可以如下设置一个cookie
/myapp 会话标识。
然后,sessionid cookie 将被发送到地址中包含 /myapp 的任何请求。这允许会话 ID 被任何上下文使用。
这种方法的唯一问题是它是在 2003 年编写并在 Tomcat 4 上测试的。
您对这种方法有何看法?有没有更好的方法?
谢谢
【问题讨论】:
【参考方案1】:据我所知,没有直接的方法可以做到这一点,但是如果这些上下文共享同一个域,您可以使用域级别的 cookie。
您可以将数据放入 cookie 中(我不建议这样做)。
或者放置一个安全的会话 ID,您可以使用它来访问某种形式的存储(数据库或分布式缓存等)以检索您需要的数据。
【讨论】:
我忘了说,上下文都在同一个 Tomcat 实例中运行。 我不认为这有什么区别,但我很可能是错的。 我猜的另一个选项是将cookie路径设置为“/” 这就是我将其设置为域的意思。我认为这是这里唯一的选择。【参考方案2】:如果数据量不是天文数字并且数据本身变化不是太快,您可能需要考虑使用 JNDI。此解决方案专为您的需求而设计。
您可以查看official documentation 或this post to tomcat-user mailing list 以获取参考和示例。
【讨论】:
你能给我举个例子来说明如何实现这一点。谢谢【参考方案3】:那篇文章确实过时了。
在 Tomcat 5.5 和 6.0 上,您只需在 /conf/server.xml
的 <Connector>
元素中将 emptySessionPath
属性设置为 true
。
<Connector ... emptySessionPath="true">
在 Tomcat 7.0 上,这已经改变,因为现在可以从 Servlet 3.0 API 配置。然后在 Tomcat 一侧,可通过在任何负责的 context.xml
文件中的 <Context>
元素中将 sessionCookiePath
设置为 /
进行配置。
<Context ... sessionCookiePath="/">
如前所述,有一个新的 Servlet 3.0 API 允许您通过标准 API 配置会话 cookie。您可以通过将以下内容添加到web.xml
以声明方式执行此操作:
<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>
或通过SessionCookieConfig
以编程方式通过ServletContext#getSessionCookieConfig()
提供。
getServletContext().getSessionCookieConfig().setPath("/");
您可以在ServletContextListener#contextInitialized()
或HttpServlet#init()
中执行此操作。
另见:
Tomcat 5.5 HTTP connector documentation Tomcat 6.0 HTTP connector documentation - 提到潜在的安全漏洞 Tomcat 7.0 context documentation【讨论】:
这是非常有用的信息。我不太明白其中大部分是如何工作的,但至少它给了我一个指向进一步调查的地点和内容的指针。是否有任何使用这些方法的示例?我正在使用 Tomcat 6.0/conf/server.xml
在 Tomcat 的安装文件夹中。只需在 text/xml 编辑器中打开 XML 文件,找到用于为您的 web 应用程序提供服务的 <Connector>
元素,并将 emptySessionPath="true"
属性添加到该元素。
如果我将 emptySessionPath 设置为 true,是否所有应用程序都获得相同的 jsessionid 还是仍然获得不同的 jsessionid?谢谢
在 web.xml
上设置 cookie 路径也适用于 Glassfish,确实
在 Tomcat 9 (***.com/q/40753753/274677) 中,web.xml
中的 sessionCookiePath
在tomcat 范围内的context.xml
(在/conf
中)或特定于WAR 的context.xml
在META-INF
中的值。您能否澄清您的答案是否需要同时设置 context.xml
和 web.xml
或者是否需要设置,优先级是什么?根据我的经验,只使用了context.xml
。这里也没有提到web.xml
:tomcat.apache.org/tomcat-7.0-doc/config/context.html对于 Tomcat 8,我使用以下配置在 2 个 web 应用程序之间共享会话:
conf/context.xml
<Context sessionCookiePath="/">
<Valve className="org.apache.catalina.valves.PersistentValve"/>
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore" directory="$catalina.base/temp/sessions"/>
</Manager>
...
</Context>
我两次部署相同的简单 webapp log.war 和 log2.war:
/log
/log2
我现在可以登录/log
并在/log2
中显示用户,这不适用于tomcat 默认配置。
设置并读取会话值:
HttpSession session=request.getSession();
session.setAttribute("name",name);
HttpSession session=request.getSession(false);
String name=(String)session.getAttribute("name");
我以这个项目为例:https://www.javatpoint.com/servlet-http-session-login-and-logout-example
大多数示例/解决方案使用需要更多设置工作的内存数据库:
redis hazelcast【讨论】:
以上是关于在 Tomcat 中的上下文之间共享会话数据的主要内容,如果未能解决你的问题,请参考以下文章
有啥方法可以在tomcat中的不同应用程序之间共享会话状态?
当每个线程可以处理与其他线程中的数据无关的数据时,是不是可以在线程之间重用一个共享托管对象上下文?