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

时间:2012-02-26 12:34:16

标签: java oop tomcat servlets jndi

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

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

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

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

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

  • 如何在JNDI中初始化对象。例如,Tomcat文档中的以下配置显示了JDBC的配置
<Resource name="jdbc/db1"
   auth="Container"
   type="oracle.jdbc.pool.OracleDataSource"
   driverClassName="oracle.jdbc.driver.OracleDriver"
   factory="oracle.jdbc.pool.OracleDataSourceFactory"
   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db1"
   user="scott"
   password="tiger"
   maxActive="20"
   maxIdle="10"
   maxWait="-1">

在我的情况下,我将如何做类似的事情,最重要的是,如何在将对象放到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<String, Object> env = new Hashtable<String, Object>(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的多少个实例 - 我需要将它作为访问该对象的所有webapp的相同实例。

修改

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

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

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

Obtaining a reference

修改

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

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

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

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

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

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

  2. 将Tomcat容器管理身份验证与Tomcat单点登录模块一起使用。