使用JNDI在Tomcat中共享servlet会话对象和数据

在过去的几周里,我一直在寻找在两个上下文/战争文件之间共享对象的解决方案。 有很多种方法可以做,其中一种是JNDI。

我对Tomcat中使用的JNDI不太熟悉,所以想澄清一些问题:

基本上我有一个对象的实例,它将为多个上下文/应用程序提供以下服务

  • 检查用户是否已登录
  • 检查用户的会话是否有效
  • 登录用户 – 包括记录登录详细信息
  • 注销用户 – 删除会话

每个应用程序将在处理任何请求之前调用此对象以validation用户。 我不明白的是如果对象存储在JNDI上,该对象将如何工作。 我已经看到了一些如何在Tomcat中使用JNDI的示例,但99%的示例显示了如何配置JDBC数据源。

  • 对象在JNDI中的确切初始化程度。 例如,Tomcat文档中的以下配置显示了JDBC的配置
 

在我的情况下,我将如何做类似的事情,最重要的是,如何在将对象放入JNDI树之前初始化该对象。 一旦它在JNDI树上,它是如何更新的?

我想我想要的是在Tomcat中使用JNDI的简单示例,但不是数据库连接,而是服务提供者类型对象。

我一直在阅读本教程http://docs.oracle.com/javase/tutorial/jndi/ops/bind.html,但它更侧重于LDAP命名目录,这并没有真正帮助。

编辑

好的,我确实在上面列出的教程中找到了一个示例,它显示了如何将对象“绑定”到JNDI树中。

 class SerObj { public static void main(String[] args) { // Set up environment for creating initial context Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial"); try { // Create the initial context Context ctx = new InitialContext(env); // Create object to be bound Button b = new Button("Push me"); // Perform bind ctx.bind("cn=Button", b); // Check that it is bound Button b2 = (Button)ctx.lookup("cn=Button"); System.out.println(b2); // Close the context when we're done ctx.close(); } catch (NamingException e) { System.out.println("Operation failed: " + e); } } } 
  • 我如何修改它以使用Tomcat环境而不是如上所示的LDAP环境?
  • 绑定是存储对象的副本还是对象的引用? 我不确定的是,例如,如果3个webapps访问该对象,它们是否都将访问该对象的同一个实例或不同的实例? 我希望只有一个我放在JNDI树中的对象实例。

编辑

我必须遗漏一些非常简单的事情。 这是我发现的另一个例子,它展示了如何在Tomcat中配置JNDI对象 – http://flylib.com/books/en/4.255.1.275/1/

  • 如何初始化com.jspservletcookbook.StockPriceBean
  • 如果一个webapp使用com.jspservletcookbook.StockPriceBean对象并更改其状态,那么此更改是否会反映在访问此对象的所有其他Web应用程序中?
  • 最重要的是,将创建多少个com.jspservletcookbook.StockPriceBean实例 – 我需要将它作为访问该对象的所有com.jspservletcookbook.StockPriceBean的相同实例。

编辑

@Ben Brunk – 目前会话数据存储在由其中一个应用程序(上下文)管理的Map中。 我需要的是其他应用程序调用此应用程序来检查会话是否有效。 我的问题是,对于这些应用程序来获取管理会话数据的应用程序的服务,我需要使用JNDI来获取对相关对象的引用。

数据不会存储在JNDI中。 我只想使用JNDI作为应用程序查找和使用Session Manager对象的手段。 但问题是我读到的关于JNDI的所有内容都让我相信每次在目录中搜索或“查找”对象时它都会用于创建新对象。

这是图表,我认为显示我想要实现的目标:

获得参考

编辑

@EJP – 只是为了澄清,我上面列出的函数只是共享对象可能做的例子。 这些仅作为示例提供。 它将执行的所有function都与用户和登录的会话相关。 例如账户信息(用户名,上次登录等),密码信息(有效期等),用户权限(即允许用户访问的应用程序的哪些区域)。

鉴于这个问题确实与通过JNDI(或任何其他方式)的多上下文通信有关,而不是关于对象的要求,列出对象应该做的所有事情并没有真正意义,所以我刚刚列出了示例它能做什么。

如果我把这个问题的方式弄糊涂了,那就道歉了。

如果您不关心使用LDAP,只需通过在其中创建表来管理会话信息来使用数据库本身。 您应该能够找到大量有关如何执行此操作的示例,因为它是企业应用程序中的常见需求。 事实上,我之前没有看过使用LDAP目录进行此操作的示例。 看起来LDAP不适合跨域管理会话,因为它实际上并不是为了更新而设计的。

需要明确的是:JNDI不是一种存储机制。 它是一种在企业环境中命名资源,然后让容器管理与这些资源的连接的机制。 您需要将会话数据存储在数据库中,或者您可以使用文件系统或NoSQL地图类型解决方案。

还有其他几种方法可以实现这一目标。

  1. 使用与JAAS关联的Tomcat容器管理身份validation。 然后您的模块成为JAAS LoginModule。

  2. 将Tomcat容器管理身份validation与Tomcat Single Sign-on模块一起使用。