在guice中使用jndi以及jdbc pool

实现JndiProvider

class JndiProvider<T> implements Provider<T> {

    @Inject
    Context context;
    final Class<T> type;
    final String name;

    public JndiProvider(Class<T> type, String name) {
        this.type = type;
        this.name = name;
    }

    public T get() {
        try {
            return type.cast(context.lookup(name));
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
    }
}

这个Provider的构造函数传入两个参数:

  1. type 要查找的对象的类型,比如javax.sql.DataSource.class
  2. name 是指resource name。在web.xml中配置的那个。

绑定DataSource的实现

在ServletModule或者其它某个Module的配置中写

bind(javax.naming.Context.class).to(javax.naming.InitialContext.class);
bind(javax.sql.DataSource.class).toProvider(
new JndiProvider<javax.sql.DataSource>(javax.sql.DataSource.class, "java:/comp/env/jdbc/mydb"));

那么当你想用javax.sql.DataSource类型的对象时,它就会绑定到JNDI中名为"java:/comp/env/jdbc/mydb"的实例。
但是这么做有个问题,InitialContext不是thread safe的(所以不能做成Singleton),但是构造一个InitialContext对象的代价又很高。所以我暂未找到很好的办法解决这个问题。

使用DataSource

class AccessTokenRepository {
        @Inject
        private javax.sql.DataSource ds;
        public void delete(Long id) {
          try(java.sql.Connection conn=ds.getConnection()){
           //...
        }
};

配置container

下面以tomcat为例,叙述如何配置container

主要有两处配置:

  1. context (位于context.xml或者server.xml中)
  2. web.xml

在WAR中的根目录下放一个名为META-INF的文件夹,里面放一个名为context.xml的配置文件,内容为:

<?xml version='1.0' encoding='utf-8'?>

<Context><Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource" username="xxxxxx" password="xxxxx" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/dbname?useUnicode=true&amp;characterEncoding=UTF-8" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" />
</Context>

其中几个重要的选项:

  • driverClassName: jdbc driver name。一般为com.mysql.jdbc.Driver
  • url: jdbc url
  • username: 连接数据库所需的用户名
  • password: 连接数据库所需的密码

然后在web.xml中引用它。在web.xml中的根节点的里面中加入:

<resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/mydb</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

其中这里的res-ref-name必须与context.xml中Resource节点的name属性一致。

实际上我在这么配置的时候遇到一点点小困难。我在eclipse中调试的时候,eclipse似乎不理会项目中的context.xml。于是我找到eclipse的启动目录,在它的conf目录(C:\Users\cm\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\conf)下找到server.xml,然后修改这里面的Context节点。

此博客中的热门博文

在windows下使用llvm+clang

少写代码,多读别人写的代码

tensorflow distributed runtime初窥