今天同事说我们的后台要支持weblogic的jndi数据源,之前不支持,只要修改下部分代码,之前的代码是这样的.使用的dbcp连接池

    dataSource = (BasicDataSource) BasicDataSourceFactory

                    .createDataSource(SystemContext.getSysProperties());

要支持jndi,首先jndi的配置参数需要3个,分别为jndiName,jndiServer和jndiDriver当然实际配置参数不是这个名字,是INITIAL_CONTEXT_FACTORY和PROVIDER_URL,一般如果应用是发布在服务器下的,不需要这两个参数,只要提供jndi数据源的名称就可以了.连接数据源的代码如下

private static DataSource lookupSource(String jndi, String driver,

        String server) {

    logger.debug("通过 JNDI 获得数据源:server=" + server + ", jndi=" + jndi);

    Context ctx = null;

    try {

        // 如果没有在配置文件中指定 jndi 配置

        if (StringUtils.isNullOrEmpty(driver)

                || StringUtils.isNullOrEmpty(server)) {

            ctx = new InitialContext();

        } else {

            Properties p = new Properties();

            if (!StringUtils.isNullOrEmpty(driver)) {

                p.put(Context.INITIAL_CONTEXT_FACTORY, driver);

            }

            if (!StringUtils.isNullOrEmpty(server)) {

                p.put(Context.PROVIDER_URL, server);

            }

            ctx = new InitialContext(p);

        }

        return (DataSource) (ctx.lookup(jndi));

    } catch (NamingException e) {

            throw new DBException(e);

        }

    }

在tomcat的context.xml中配置下数据源

<Resource name="jndi/test"

      type="javax.sql.DataSource"

      driverClassName="com.mysql.jdbc.Driver"

      url="jdbc:mysql://localhost:3306/task"

      username="root" password="xxx" maxActive="200" maxIdle="10"

      maxWait="-1"

/>

数据源的名字为jndi/test,在java中获取的为这个即可

启动tomcat,执行测试,出现如下异常。

javax.naming.NameNotFoundException: Name jndi is not bound in this Context

没有找到这个数据源,名字也不太对啊。。我们的是jndi/test。通过google,查看tomcat的官方文档。

http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html,发现官方的示例代码如下

InitialContext cxt = new InitialContext();

if ( cxt == null ) {

throw new Exception("Uh oh -- no context!");

}

DataSource ds = (DataSource) cxt.lookup( "java:/comp/env/jdbc/postgres" );

if ( ds == null ) {

throw new Exception("Data source not found!");

}

原来如此。需要在jndi/test前面加上java:/comp/env/ 。好吧。。加上了。再次运行。果然没有问题了。那么这个java:/comp/env是什么呢。。看起来好像一个环境变量似的。实际他是用来定义资源的,个人理解就好像是命名空间,更多详细的解释稍后再说

修改之后打包发布了。不一会儿同事电话来了,报错。。查看错误日志,发现 依然是绑定的问题,异常提示找不到数据源java,不应该啊。数据源名称和java没有一分钱关系,难道是java:/comp/env/的问题?google下,查看了weblogic的文档,果然如此,去掉tomcat需要的,果然没问题了。

关于这个前缀的详细解释,见http://f543711700.iteye.com/blog/1173618

其实说得简单点:context.lookup("java:comp/env/XXX")只能用在J2EE环境,即是如果你自己写一个main函数,想通过context.lookup("java:comp/env/XXX")这样的方式来访问JNDI服务,这是不可能的

因为:java:comp/env/是一个J2EE环境的定义,说白了就是代表当前J2EE应用的环境,比如你自己项目的Web环境或者是EJB环境,那是不是只要是个Web项目,就能用context.lookup("java:comp/env/XXX")这种方式访问JNDI服务了呢?也不是!!

使用这样的方式必须做一次 当前应用环境 到 资源名 的映射

在web.xml文件中有这样的标签

</resource-env-ref&gt

</resource-ref&gt

</ejb-local-ref&gt

</ejb-ref&gt

这些标签就是用来建立当前应用环境到服务器资源的映射的

有了这样的映射之后,就能采用context.lookup("java:comp/env/XXX")的方式来访问JNDI资源了。

注意:context.lookup("XXX")在任何时候都是有效的,只要XXX确实是一个存在的JNDI名。

最后为了两种不同实现的服务器,我们的代码变成了这样.

private static DataSource lookupSource(String jndi, String driver,

        String server) {

    logger.debug("通过 JNDI 获得数据源:server=" + server + ", jndi=" + jndi);

    Context ctx = null;

    try {

        // 如果没有在配置文件中指定 jndi 配置

        if (StringUtils.isNullOrEmpty(driver)

                || StringUtils.isNullOrEmpty(server)) {

            ctx = new InitialContext();

        } else {

            Properties p = new Properties();

            if (!StringUtils.isNullOrEmpty(driver)) {

                p.put(Context.INITIAL_CONTEXT_FACTORY, driver);

            }

            if (!StringUtils.isNullOrEmpty(server)) {

                p.put(Context.PROVIDER_URL, server);

            }

            ctx = new InitialContext(p);

        }

        return (DataSource) (ctx.lookup(jndi));

    } catch (NamingException e) {

        // 如果私有的jndi资源访问不到,切换到全局的重试一次

        try {

            if (StringUtils.isNotNullOrEmpty(jndi)

                    && !jndi.startsWith("java:comp/env/")) {

                jndi = "java:comp/env/" + jndi;

            }

            return (DataSource) (ctx.lookup(jndi));

        } catch (NamingException e1) {

            throw new DBException(e);

        }

    }

}
Comments
Write a Comment