在 Tomcat 中调用 JNDI 数据源的正确方法

Posted

技术标签:

【中文标题】在 Tomcat 中调用 JNDI 数据源的正确方法【英文标题】:Proper way to call JNDI datasource within Tomcat 【发布时间】:2011-06-16 05:02:08 【问题描述】:

我在 Tomcat 服务器上使用 Java Web 应用程序,想知道从 Tomcat 的 JNDI 中访问数据库连接的“最佳实践”是什么?

目前这基本上是我每次需要访问数据库时都在做的事情:

Context envContext = null;
DataSource dataSource = null;
try 
    envContext  = (Context)ctx.lookup("java:/comp/env");
    dataSource = (DataSource)envContext.lookup("jdbc/datasource");
    return dataSource.getConnection();
 catch (Exception e)
    e.printStackTrace();
    return null;
finally 
    if(envContext != null)
        try
           envContext.close();
         catch (NamingException e)
            e.printStackTrace();
        
    

但是,这是每次我想访问数据库时从 JNDI 查找连接的正确方法吗?我应该保留对上下文或数据源的引用吗?

【问题讨论】:

【参考方案1】:

您的查找代码看起来没问题 在您的问题上下文中,只要您不缓存实际的连接对象,缓存数据源似乎没问题。

不过,我已经有一段时间没有使用这种方法了。这些天,我至少使用spring来注入数据源/初始化JdbcTemplate

【讨论】:

是的,通常我只会使用一些第三方实用程序,比如hibernate,但是为此,我不允许使用除直接java之外的任何东西。【参考方案2】:

你也可以这样做:-

...

Context initContext = new InitialContext();
DataSource dataSource = (DataSource) initContext.lookup("java:comp/env/jdbc/datasource");

...

【讨论】:

【参考方案3】:

jndi 查找本质上是 Map 查找,因此它们的开销很小。但最好是获取一次数据源并“缓存”它。因此,如果有的话 - 编写一个返回 DataSource 的方法是理想的,以免将太多代码绑定到 J2EE 内部并使代码更易于测试。

【讨论】:

正是我正在寻找的那种答案,谢谢。另一个问题,每次我进行数据访问时创建一个新的上下文是否有很多开销? 相对而言——我不这么认为。但是,如果您对它进行基准测试并每次都创建一个上下文而不是仅缓存数据源-我怀疑您会看到不同之处。但实际上,与处理请求的其他活动相比,您获得数据源(或上下文)的次数是最少的。 JNDI 查找并不昂贵,InitialContext 查找在每个应用程序容器中都非常昂贵,并且只应在应用程序启动时进行一次。大多数人不知道其中的区别。【参考方案4】:

new InitialContext() 在每个应用程序容器中都很昂贵,它应该是 static final 并在 static 块中创建,有效地使其成为 Singleton。您应该只需要创建一次此引用,然后在需要它的任何地方重复使用它。

DataSource 也应该是 static。您应该有一个public static Connection getConnection(); 方法来检索Connection 对象,代码永远不必直接处理DataSource。这对PooledDataSource 实现特别有效。

【讨论】:

为什么这么贵?它不需要做很多事情,特别是它不需要做任何网络 I/O?我怀疑这是都市神话。 @EJP 不是一个城市神话,我有一个合同,其中一个“主要”开发人员(一个 VB 人员)正在编写 Servlet,他在每个请求上创建 new InitialContext()。每个请求都花费了将近一分钟。他抱怨Java有多慢,等等,等等,等等。我查看了他的代码并将那一行移到private static final 和繁荣。请求在 hundreds of millisecond 范围内。这是 WebLogic 的一个非常早期的版本,因此由于摩尔定律,它现在可能还没有那么糟糕。但是当我在 2011 年 3 月写这个答案时,这是一个可重现的问题。 你还没有回答我的问题。 为什么很贵?并且,从另一个地方引用你的话,YEINU: Your experience is not universal。您是否实际测试过“每个应用程序容器”?没有这个,你的回答是没有根据的。 'new InitialContext() 很贵' 与您上面的评论“InitialContext 查找 非常昂贵”有何一致?下定决心。

以上是关于在 Tomcat 中调用 JNDI 数据源的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

如何为 tomcat 6 及其部署的 webapps 正确配置 JNDI?

在tomcat中绑定JNDI数据源?

Tomcat8.0配置JNDI多数据源

Tomcat 7.0 for Hibernate 中的数据源 JNDI 配置

在tomcat下context.xml中配置各种数据库连接池(JNDI)

JNDI Tomcat