1. 程式人生 > >JNDI在Spring和tomcat下的使用

JNDI在Spring和tomcat下的使用

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 整體思路

  1. 在在J2EE容器如Tomcat中配置一個數據源,給這個資料來源設定一個名稱;
  2. 在專案程式中,通過資料來源名稱引用這個資料來源從而訪問後臺資料庫

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,要滿足兩個條件:

    1. 其實現了javax.naming.spi.ObjectFactory,druid的com.alibaba.druid.pool.DruidDataSourceFactory就實現了
    2. 需把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.xmlResource標籤加內容直接拷貝到server.xmlGlobalNamingResources標籤裡就行了
    • 接下來有四種方式引用這個全域性的Resource

      方法2沒弄出來,方法1,3,4是可以的,事實上3和4是同一種方法,只要在建專案時在專案的webapps/mmc/META-INF/下寫好context.xml,這兩個方法所要求的context.xml都會在啟動tomcat後自動生成(tomcat7.0沒有自動生成,不過這樣寫過後相當於用來方法4,一樣可以成功啟動)

      1. 直接在conf/context.xml裡引用
      <ResourceLink global="jdbc/mmcDB" name="jdbc/mmcDB" type="javax.sql.DataSource"/>      
      1. 這個方法我用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>
      1. 安裝目錄下的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>
      1. 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子上下文中宣告

4. 參考資料

  1. http://stackoverflow.com/questions/4099095/what-does-javacomp-env-do
  2. http://blog.csdn.net/cyong888/article/details/7361466