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

时间:2012-02-12 18:30:35

标签: java tomcat servlets ant build

我有一个基于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文件进行部署。 (即forum.war,articles.war和guestbook.war)。新war文件的内容仅包含与模块相关的文件。例如,forum.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文件中都是通用的。如果我有不同的war文件,我将在每个war文件中有一份css文件的副本。有没有什么办法可以用一种通用方法传递资源文件(css,js,静态文件),以便共享它们。我想也许我应该包含一个名为common.war的新war文件并包含共享的静态数据。 (我认为其他war文件可以使用URL访问这些文件,因为它们是静态资源。对吗?)

共享课程

有一些全球共享的课程。例如,有一个名为UserSession的类。当用户登录到应用程序时,将创建UserSession对象并将其存储在Hashtable中,并将用户的会话ID作为Hashtable的键。只要用户尝试访问应用程序的任何部分,就会根据Hashtable中的sesion 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的另一个List对象吗?

我也看到了使用JNDI进行对象共享的引用。我对JNDI不太熟悉。我已经将JNDI用于DataSources,但就目前而言。它究竟会如何运作?如果有人能给我一个示例,展示如何使用JNDI来共享数据,我将不胜感激。 JNDI是更好的方法,为什么会这样?

最后,UserSession.class文件驻留在哪里?我知道我可以把它放在$TOMCAT_HOME/lib的jar文件中,但通常不建议这样做。但问题是,如果它位于其中一个war文件的WEB-INF/lib文件夹中,则任何其他war文件都无法访问它。

会欣赏一些意见/建议。我很想知道您使用什么策略来部署由多个war文件组成的应用程序。

谢谢

修改

好的,我忘了提到为什么我要拆分war文件。基本上,我们有几个开发团队。我们遇到过一个团队正在处理应用程序的特定区域而另一个团队正在另一个区域工作的情况。

例如,假设以下情形 -

Team1正在研究将于下个月发布的论坛模块。 Team2已被要求对文章进行更改,并应在下周发布。

如果Team1检查了他们的代码并且正在执行需要一周以上的系统/集成测试,Team2就会被填满,因为他们必须等待。

这些问题通常使用分支来解决,但我们倾向于避免分支,因为它引入了很多并发症,我们决定避免分支。

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

此外,很多人对如果进行简单更改(例如,将新样式表定义添加到单个css文件)这一事实持怀疑态度,则必须重新构建并重新部署整个应用程序。

其他原因包括

  • 可以简化可扩展性/负载平衡 - (可能?)不确定这个。我在考虑将每个war文件部署到不同的服务器/集群。
  • 降低PERMGEN内存要求
  • 等...

2 个答案:

答案 0 :(得分:2)

我不确定您是否理解正确,但HttpSession对于每个用户(浏览器会话)以及每个应用程序AFAIK都不同,因此您无法使用它来共享数据。

基本上,您需要在Web应用程序之间进行通信。 您可以让一场战争充当您的UserSession的数据管理器,以及与此通信的所有其他战争。数据管理器应用程序需要公开服务,例如可以通过其他应用程序访问的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");

希望这有帮助, 吉尔特。

答案 1 :(得分:1)

  

如果Team1检查了他们的代码并且正在执行需要一周以上的系统/集成测试,那么Team2就会被填满,因为他们必须等待。

     

这些问题通常使用分支来解决,但我们倾向于避免分支,因为它引入了很多并发症,我们决定避免分支。

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

  

此外,很多人对如果进行简单更改(例如,将新样式表定义添加到单个css文件)这一事实持怀疑态度,则必须重新构建并重新部署整个应用程序。

这就是Java Web应用程序的本质。如果您将CSS文件放入单独的战争中,那么您仍然需要重建并重新部署该战争。通过多次战争,这个过程将变得更加复杂,而不是更少。

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

  

可以简化可扩展性/负载平衡 - (可能吗?)

可能。但是你知道他们对过早优化的看法。