1. 是什么
JNDI是 Java 命名與目錄接口(Java Naming and Directory Interface),在J2EE規范中是重要的規范之一。JNDI 在 J2EE 中的角色就是“交換機” —— J2EE 組件在運行時間接地查找其他組件、資源或服務的通用機制。在多數情況下,提供 JNDI 供應者的容器可以充當有限的數據存儲,這樣管理員就可以設置應用程序的執行屬性,並讓其他應用程序引用這些屬性(Java 管理擴展(Java Management Extensions,JMX)也可以用作這個目的)。JNDI 在 J2EE 應用程序中的主要角色就是提供間接層,這樣組件就可以發現所需要的資源,而不用了解這些間接性。
2. 為何用
程序員可以不用關心“具體的數據庫后台是什么?JDBC驅動程序是什么?訪問數據庫的用戶名和口令是什么?”等等這些問題,而是把這些問題交給J2EE容器來配置和管理,程序員只需要對這些配置和管理進行引用即可。
3. 怎么用
3.1 整體思路
- 在在J2EE容器如Tomcat中配置一個數據源,給這個數據源設置一個名稱;
- 在項目程序中,通過數據源名稱引用這個數據源從而訪問后台數據庫
3.2 示例
下面在Tomcat6.0+spring+springMVC+mybatis項目中演示用法。
Tomcat
- 方法一:非全局的Resource,只更改context.xml
在context.xml的根節點Context里加入Resource配置
<Resource name="jdbc/mmcDB" //指定的jndi名稱,會用於spring數據源bean的配置和ResourceLink的配置
auth="Container"//認證方式,一般默認這個
type="javax.sql.DataSource" //數據源床型,使用標准的javax.sql.DataSource
driverClassName="com.mysql.jdbc.Driver" //JDBC驅動器
url="jdbc:mysql://localhost:3306/test" //數據庫URL地址
username="test" //數據庫用戶名
password="test" //數據庫密碼
maxIdle="40" //最大的空閑連接數
maxWait="4000" //當池的數據庫連接已經被占用的時候,最大等待時間
maxActive="250" //連接池當中最大的數據庫連接
removeAbandoned="true"
removeAbandonedTimeout="180"
logAbandoned="true" //被丟棄的數據庫連接是否做記錄,以便跟蹤
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" />
-
factory:該Resource 配置使用的是哪個數據源配置類,這里使用的是tomcat自帶的標准數據源Resource配置類,這個類也可以自己寫,實現javax.naming.spi.ObjectFactory 接口即可。
如果使用其他的數據池,如阿里巴巴的druid,要滿足兩個條件:
- 其實現了javax.naming.spi.ObjectFactory,druid的com.alibaba.druid.pool.DruidDataSourceFactory就實現了
- 需把jar及其依賴的jar包 ,都放在tomcat的lib下,光放在工程的WEB-INF/lib下是不夠的。阿里巴巴的druid依賴log4j,所以后者的jar也要復制進去
-
driverClassName的其他寫法:
oracle:oracle.jdbc.driver.OracleDriver
db2:com.ibm.db2.jcc.DB2Driver
SQLServer:com.microsoft.sqlserver.jdbc.SQLServerDriver
-
url的其他寫法示例:
oracle:jdbc:oracle:thin:@192.168.1.249:1521:XE
db2:jdbc:db2://18.1.99.7:55555/esdb:currentSchema=EMPSAL
-
這種配法可寫多個resource給不同的項目使用
-
方法二:全局的 Resource,更改server.xml和context.xml
- server.xml:在server.xml的GlobalNamingResources節點里加入Resource,再在Context節點里加入ResourceLink的配置。全局的resource只是為了重用,方便所有該tomcat下的web工程的數據源管理,但如果你的tomcat不會同時加載多個web工程,也就是說一個tomcat只加載一個web工程時,是沒有必要配置全局的resource的。
把上面的context.xml的Resource標簽加內容直接拷貝到server.xml的GlobalNamingResources標簽里就行了
-
接下來有四種方式引用這個全局的Resource
方法2沒弄出來,方法1,3,4是可以的,事實上3和4是同一種方法,只要在建項目時在項目的webapps/mmc/META-INF/下寫好context.xml,這兩個方法所要求的context.xml都會在啟動tomcat后自動生成(tomcat7.0沒有自動生成,不過這樣寫過后相當於用來方法4,一樣可以成功啟動)
- 直接在conf/context.xml里引用
<ResourceLink global="jdbc/mmcDB" name="jdbc/mmcDB" type="javax.sql.DataSource"/>
- 這個方法我用tomcat6.0和7.0都失敗了,報找不到mmcDB,暫時用不到就不深究了,列出了給大家參考吧 ......conf/server.xml里繼續配置,該方法可以指定把哪些source綁定到哪個web工程下。
<!-- 在host標簽內新增,第一行為加載的工程配置,第二行是該工程需要的ResourceLink配置 --> <context docBase="mmc" path="" reloadable="false"> <ResourceLink global="jdbc/mmcDB" name="jdbc/mmcDB" type="javax.sql.DataSource"/> </context>
- 安裝目錄下的conf/Catalina/localhost/下建立一個xml文件,文件名是<yourAppName>.xml。比如工程名為mmc,則該xml名為mmc.xml。
<?xml version="1.0" encoding="UTF-8"?> <Context> <ResourceLink global="jdbc/mmcDB" name="jdbc/mmcDB" type="javax.sql.DataSource"/> </context>
- tomcat安裝目錄下的\webapps\test\META-INF\context.xml的Context節點中增加:
<ResourceLink global="jdbc/mmcDB" name="jdbc/mmcDB" type="javax.sql.DataSource"/>
Spring
- 方法一:
<bean id="testDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/mmcDB</value>
</property>
</bean>
或者:
<bean id="testDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/mmcDB</value>
</property>
<property name="resourceRef">
<value>true</value>
</property>
</bean>
- 方式二:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/mmcDB" />
3.3 細節解釋
-
Tomcat中在server.xml下配置你必需重啟服務器才能生效,而context.xml配置保存后tomcat會自動加載無需重啟
-
JNDI地址寫法:AB兩種地址的用法可點擊參考資料的第一條鏈接查看
在描述JNDI,例如獲得數據源時,JNDI地址 有兩種寫法,例如同是 jdbc/testDS 數據源:
A: java:comp/env/jdbc/testDS
B: jdbc/testDS
這兩種寫法,配置的方式也不盡相同,用A就行了別糾結,網上查了一堆資料都說的亂七八糟。
java:comp/env 是環境命名上下文(environment naming context(ENC)),是在EJB規范1.1以后引入的,引入這個是為了解決原來JNDI查找所引起的沖突問題,也是為了提高EJB或者J2EE應用的移植性。
在J2EE中的引用常用的有:
JDBC 數據源引用在java:comp/env/jdbc 子上下文中聲明
JMS 連接工廠在java:comp/env/jms 子上下文中聲明
JavaMail 連接工廠在java:comp/env/mail 子上下文中聲明
URL 連接工廠在 java:comp/env/url子上下文中聲明