Tomcat ServletContext vs JNDI用于跨多个war文件共享会话数据



我有一个基于Struts的web应用程序,其结构类似于下面所示的。(不是这只是一个例子)

$TOMCAT_HOME/webapps/myapp
|-css
|-myapp.css
|-js
|-myapp.js
|-forum
|-index.jsp
|-list.jsp
|-users.jsp
|-Articles
|-index.jsp
|-ListArticles.jsp
|-Guestbook
|-viewGuestBook.jsp
|-AddnewEntry.jsp
|-WEB-INF
|-classes
com
|-myapp
|-forum
|-DisplayForum.class
|-ListUsers.class
|-article
|-ArticleList.class
|-AddArticle.class
|-guestbk
|-LoadGuestBook.class
|-ProcessGuestBook.class

目前,该应用程序是使用ANT构建的,并作为单个war文件(名为myapp.war)部署到Tomcat应用服务器上。我想分开的应用程序,使其部署使用多个战争文件的每个模块。(即论坛。战争的文章。War和留言簿(War)。新war文件的内容将只包含与模块相关的文件。例如,论坛。War文件将包含

$TOMCAT_HOME/webapps/forum              
|-forum
|-index.jsp
|-list.jsp
|-users.jsp             
|-WEB-INF
|-classes
com
|-myapp
|-forum
|-DisplayForum.class
|-ListUsers.class

对于这种方法,有几件事我不确定。

共享静态资源

*.css和*.js文件在每个war文件中都是通用的。如果我有不同的战争文件,我将有一个副本的css文件在每个战争文件。是否有任何方式,我可以提供资源文件(css, js,静态文件)在一个共同的方法,使他们共享。我想也许我应该包括一个新的战争文件称为共同。War和包含共享的静态数据。(我认为其他战争文件可以使用URL访问这些文件,因为它们是静态资源。对吧?)

共享类

有些类是全局共享的。举个例子,有一个类叫做UserSession。当用户登录到应用程序时,创建UserSession对象并将其存储在Hashtable中,并将用户的会话id作为Hashtable的键。每当用户尝试访问应用程序的任何部分时,都会根据Hashtable中的会话id检查会话id。

UserSession对象做很多事情——比如

  • 验证用户登录
  • 跟踪用户活动
  • 记录用户登录历史到数据库
  • 等等……

我需要所有的war文件(应用程序/模块)都可以访问UserSession对象,但是每个会话只关联一个。我应该如何构建它,以便用户的会话跨越不同的war文件?

我一直在阅读有关如何共享对象的文章,并提出了两个选项

  • 通过JNDI共享对象
  • 通过Tomcat ServletContext共享对象

据我所知,如果一个对象存储在ServletContext中,它可以被任何应用程序(即war文件)访问。如果我想要每个用户会话的不同实例,这将如何工作。例如

User1登录- UserSession存储在ServletContext中User2登录-我在哪里存储User2的UserSession对象?

目前,我将sessionID存储在HTTPSession中,UserSession对象存储在HashTable中。

HttpSession session = request.getSession(true);
UserSession userSession = getUserSession(session.getId());

User1是否获得相同的sessionId,而不管他/她正在访问的war文件?如果是这样,我可以在ServletContext中存储另一个包含sessionid的列表对象吗?

我还看到了使用JNDI的对象共享的引用。我对JNDI不是很熟悉。我对数据源使用了JNDI,但仅此而已。它究竟是如何运作的?如果有人能给我提供一个示例,说明如何使用JNDI来共享数据,我将不胜感激。JNDI真的是更好的方法吗?为什么?

最后,UserSession.class文件驻留在哪里?我知道我可以把它放在一个jar文件在$TOMCAT_HOME/lib,但这通常不推荐。问题是,如果它在一个战争文件的WEB-INF/lib文件夹中,它不能被任何其他战争文件访问。

希望能得到一些建议。我很想知道您使用什么策略来部署由多个war文件组成的应用程序。

感谢

编辑

好吧,我忘了说为什么我想分割战争文件。基本上,我们有几个开发团队。我们遇到过这样的情况:一个团队在开发应用程序的特定区域,而另一个团队在开发不同的区域。

例如,假设以下场景-

Team1正在开发论坛模块,预计下个月发布。Team2已经被要求交付对文章的修改,应该会在下周发布。

如果Team1已经签入了他们的代码,并且正在执行系统/集成测试,这将花费超过一周的时间,那么Team2就被填满了,因为他们必须等待。

这类问题通常使用分支来解决,但我们倾向于避免分支,因为它引入了许多合并的复杂性,所以我们决定避免分支。

另一个原因是我们有一个旧的应用程序,我正在考虑重用这个应用程序。旧的基于纯HTTPServlet的应用程序。即不基于任何框架(即结构,弹簧等)。如果我想集成它与我现有的应用程序,我将需要使用会话/servletcontext。

而且,很多人都怀疑这样一个事实:如果你做了一个简单的改变(例如,你在一个css文件中添加了一个新的样式表定义),你必须重新构建和重新部署整个应用程序。

其他原因包括

  • 可以简化可伸缩性/负载平衡-(可能?)这个不太确定。我正在考虑将每个战争文件部署到不同的服务器/集群。
  • 降低PERMGEN内存需求
  • 等等…

我不确定你是否正确理解,但是HttpSession对于每个用户(浏览器会话)和每个应用程序都是不同的,AFAIK,所以你不能用它来共享数据。

基本上,你需要在你的web应用程序之间进行通信。您可以使用一个war作为UserSession的数据管理器,而所有其他war都与此进行通信。数据管理器应用程序需要公开一个服务,例如UserSessionManager,它可以通过其他应用程序访问。 JNDI是这方面的传统解决方案。Spring对此提供了一些帮助,但是JNDI API也不是太复杂。在数据管理器之争中,您可以在初始化方法中执行如下操作:
DataManager mgr = new DataManagerImpl(...);
InitialContext ic = new InitialContext();
ic.rebind("java:global/env/datamanager", mgr);

你使用的接口和数据对象需要放在一个jar中,在所有的"客户端"战争中共享,实现只在数据管理器战争中。在客户机大战中,您可以这样做:

InitialContext ic = new InitialContext();
DataManager mgr = (DataManager)ic.lookup("java:global/env/datamanager");

希望这有帮助,基尔特•。

如果Team1已经签入了他们的代码,并且正在执行将花费一周以上的系统/集成测试,那么Team2就被填满了,因为他们必须等待。

这类问题通常可以使用分支来解决,但我们倾向于避免分支,因为它会给合并带来很多复杂性,因此我们决定避免分支。

嗯,这就是你的问题。这就是分支的作用。如果它给你带来了问题,那么答案就是解决这些问题,而不是完全避免分支。这可能就像切换到一个更好的VCS一样简单。(你现在用的是哪一个?)

而且,很多人都怀疑这样一个事实:如果你做了一个简单的改变(例如,你在单个css文件中添加了一个新的样式表定义),你必须重新构建和重新部署整个应用程序。

这就是Java web应用程序的本质。如果将CSS文件放入单独的war中,那么仍然需要重新构建和重新部署该war。而随着多场战争的爆发,这个过程将变得更加复杂,而不是更简单。

无论如何,每个Java IDE都允许您通过单个按键来完成此操作,因此我不认为这有什么大不了的。

可以简化可伸缩性/负载平衡-(可能?)

可能。但你知道他们怎么说过早的优化。

相关内容

  • 没有找到相关文章

最新更新