1. 程式人生 > >史上最全最詳細JNDI資料來源配置說明

史上最全最詳細JNDI資料來源配置說明

環境:tomcat6.0+Maven

要使用資料來源就要知道資料來源的由來:在java開發使用jdbc都要經歷這四步

①載入資料庫驅動程式:(Class.forName(“資料庫驅動類”);) ②連線資料庫(Connection con = DriverManager.getConnection();) ③操作資料庫(PreparedStatement stat = con.prepareStatement(sql); stat.executeQuery();) ④關閉資料庫,釋放連線(con.close();) 其中就第三步我們是個性化的,1,2,4步都是重複性的。就需要一個解決辦法來減去重複性的勞動–>用一個連線池來管理資料庫連結。當需要使用時就去這個池子裡取,當不用了在放回池子,就不用耗費大量資源去建立和關閉連線了。這個池子就是資料來源。 在Tomcat 4.1.27之後,在伺服器上就直接增加了資料來源的配置選項,直接在伺服器上配置好資料來源連線池即可。在J2EE伺服器上儲存著一個數據庫的多個連線。每一個連線通過DataSource可以找到。DataSource被繫結在了JNDI樹上(為每一個DataSource提供一個名字)客戶端通過名稱找到在JNDI樹上繫結的DataSource,再由DataSource找到一個連線。如下圖所示:這裡寫圖片描述

1.常見的幾種資料庫的資料來源配置和屬性解釋

<!--
  |- name:表示以後要查詢的名稱。通過此名稱可以找到DataSource,此名稱任意更換,但是程式中最終要查詢的就是此名稱,
           為了不與其他的名稱混淆,所以使用jdbc/oracle,現在配置的是一個jdbc的關於oracle的命名服務。
  |- auth:由容器進行授權及管理,指的使用者名稱和密碼是否可以在容器上生效
  |- type:此名稱所代表的型別,現在為javax.sql.DataSource
  |- maxActive:表示一個數據庫在此伺服器上所能開啟的最大連線數
  |- maxIdle:表示一個數據庫在此伺服器上維持的最小連線數
  |- maxWait:最大等待時間。10000毫秒
  |- username:資料庫連線的使用者名稱
  |- password:資料庫連線的密碼
  |- driverClassName:資料庫連線的驅動程式
  |- url:資料庫連線的地址
-->
<!--oracle資料庫的jndi資料來源,這裡的lead為service名。-->
<Resource 
        name="jdbc/oracle"
        auth="Container" 
        type="javax.sql.DataSource"
        maxActive="100" 
        maxIdle="30" 
        maxWait="10000"
        username="lead_oams" 
        password="p"
        driverClassName="oracle.jdbc.driver.OracleDriver"
        url="jdbc:oracle:thin:@192.168.1.229:1521:lead"/>

<!--配置MySQL資料庫的JNDI資料來源-->
<Resource 
        name="jdbc/mysql"
        auth="Container" 
        type="javax.sql.DataSource"
        maxActive="100" 
        maxIdle="30" 
        maxWait="10000"
        username="root" 
        password="root"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://192.168.1.144:3306/leadtest?useUnicode=true&amp;characterEncoding=utf-8"/>

<!--配置SQLServer資料庫的JNDI資料來源-->
<Resource 
        name="jdbc/sqlserver"
        auth="Container" 
        type="javax.sql.DataSource"
        maxActive="100" 
        maxIdle="30" 
        maxWait="10000"
        username="sa" 
        password="passw0rd"       driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"       url="jdbc:sqlserver://192.168.1.51:1433;DatabaseName=demo"/>
<!--配置DB2資料庫的JNDI資料來源-->
<Resource 
        name="jdbc/DB2"
        auth="Container" 
        type="javax.sql.DataSource"
        maxActive="100" 
        maxIdle="30" 
        maxWait="10000"
        username="root" 
        password="root"
        driverClassName="com.ibm.db2.jcc.DB2Driver"
        url="jdbc:db2://10.137.23.130:50000/ntsq"/>

2.如何配置,在哪配置?

2.1在eclips開發工具這個前置服務Server下對應Tomcat的配置檔案中配置。這種方式對在eclips裡面Run As Server方式啟動專案時使用

這裡寫圖片描述

2.2 在tomcat目錄conf/下對應檔案修改。這種配置是用於部署到tomcat/webapps目錄下的工程起作用

這裡寫圖片描述

2.3 如何配置?操作步驟。

不管上面的那種方式修改。修改的檔案一樣,配置的內容也是一樣的。首先都是要在applicationContext.xml中引入jndi資料來源。為比較,我這裡把常用的一般資料來源也拿過來一起比較:

<!--普通的資料來源-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
        destroy-method="close">  
        <property name="driverClassName" value="${driver}" />  
        <property name="url" value="${url}" />  
        <property name="username" value="${username}" />  
        <property name="password" value="${password}" />  
        <!-- 初始化連線大小 -->  
        <property name="initialSize" value="${initialSize}"></property>  
        <!-- 連線池最大數量 -->  
        <property name="maxActive" value="${maxActive}"></property>  
        <!-- 連線池最大空閒 -->  
        <property name="maxIdle" value="${maxIdle}"></property>  
        <!-- 連線池最小空閒 -->  
        <property name="minIdle" value="${minIdle}"></property>  
        <!-- 獲取連線最大等待時間 -->  
        <property name="maxWait" value="${maxWait}"></property>  
    </bean> 

替換為jndi資料來源:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/dbpoolmysql"><!--注意:這裡的value值就是在server.xml或者context.xml中配置的name值一樣。-->

配置jndi資料來源有三種範圍。以在eclips中配置為例,和在tomcat中是一樣的。實際這兩種最後都是對tomcat本身的配置檔案進行操作。a. 單個應用獨享資料來源

在eclips的Server對應tomcat或者本地對應tomcat/conf目錄下的server.xml找到工程的Context節點,新增一個私有資料來源(注意,這裡如果配置到context.xml檔案的<Context>節點下,則變成全域性的jndi資料來源,即第三種範圍配置。)
<Context docBase="WebApp" path="/WebApp" reloadable="true" source="org.eclipse.jst.jee.server:WebApp">  
<Resource  
    name="jdbc/dbpoolmysql"   
    scope="Shareable"   
    type="javax.sql.DataSource"  
    factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"  
    url="jdbc:mysql://localhost:3306/test"  
    driverClassName ="com.mysql.jdbc.Driver"  
    username="root"  
    password="root"  
/>  
</Context>  

對應位置如下圖: 第一種方式-在context.xml <context>節點中配置。(糾正一下~這個不是單個數據源配置,而是全域性資料來源的配置方式。是第三中jndi全域性配置的一種)這裡寫圖片描述 第二種方式-在server.xml 的<context>節點中配置這裡寫圖片描述 優點:重用性,可控性 缺點:配置相對第三種方法要繁瑣一點,每個工程都得配

b.配置全域性JNDI資料來源,應用到單個應用. 這種就是<Resource.../> 這樣的jndi不用配置了,哪個專案需要引入,只要在自己的專案中引入就可以了,即用第二種情況的第二步即可 第二種分為兩步配置:

第一步, 找到Tomcat的server.xml中GlobalNamingResources節點,在節點下加一個全域性資料來源。這個就是做一次,其他專案在引入就只要第二步就行了。這裡我說的是一開始還沒有配置的時候最全的配置步驟。

<Resource  
    name="jdbc/mysql"   
    scope="Shareable"   
    type="javax.sql.DataSource"  
    factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"  
    url="jdbc:mysql://localhost:3306/test"  
    driverClassName ="com.mysql.jdbc.Driver"  
    username="root"  
    password="root"  
/>  

第二步:同樣在本server.xml中找到要應用此JNDI資料來源的工程Context節點(在文字最下面幾行裡找到),增加對全域性資料來源的引用ResourceLink。這裡注意一個對映關係要知道—applicationContext.xml中的name要和server.xml中引入的ResourceLink中的name一樣。然後ResourceLink中的global要和GlobalNamingResources引入的全域性jnid的name一樣。這樣應用就會由applicationContext.xml中的資料來源找到本專案引入的name,得到對應的global的名字,進而找到了全域性jndi。

<Context docBase="WebApp" path="/WebApp" reloadable="true">  
    <ResourceLink global="jdbc/mysql" name="jdbc/dbpoolmysql" type="javax.sql.DataSource" />  
</Context>  

我把整個server.xml貼出來更直觀來看:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
--><!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 --><Server port="8006" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener"/>
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
    <Resource 
      name="jdbc/mysql"
      auth="Container" 
      type="javax.sql.DataSource"
      maxActive="100" 
      maxIdle="30" 
      maxWait="10000"
      username="root" 
      password="root"
      driverClassName="com.mysql.jdbc.Driver"/>
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->


    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector connectionTimeout="20000" port="8081" protocol="HTTP/1.1" redirectPort="8443"/>
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Define a SSL HTTP/1.1 Connector on port 8443
         This connector uses the BIO implementation that requires the JSSE
         style configuration. When using the APR/native implementation, the
         OpenSSL style configuration is required as described in the APR/native
         documentation -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8010" protocol="AJP/1.3" redirectPort="8443"/>


    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine defaultHost="localhost" name="Catalina">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>

      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log." suffix=".txt"/>

      <Context docBase="springQuartzReadFile" path="/springQuarztDemo" reloadable="true" source="org.eclipse.jst.jee.server:springQuartzReadFile">
            <ResourceLink global="jdbc/mysql" name="jdbc/dbpoolmysql" type="javax.sql.DataSource"/>
      </Context>
      </Host>
    </Engine>
  </Service>
</Server>

c.配置全域性JNDI資料來源,應用到所有Tomcat下部署的應用。

這裡的全域性的效果是隻要你的專案啟動用的是這個tomcat,只要在applicationContext.xml中對應jndi名字對應上就可以直接啟動成功。資料來源就連線上了。不需要對tomcat做任何操作。

上面第一第二種配置都是基於之前沒有配置過的情況下,且不共存,你只能選擇三種中的一種。 第三種也是分為兩步。第一步和第二種的第一步一樣。在server.xml中的GlobalNamingResources標籤中引入全域性jndi資料來源,不用多說了。 第二步是把第二種的引入到server.xml的對應應用上的<ResourceLink.../> 換到Context.xml的<context>標籤下即可,如下圖:

這裡寫圖片描述

以上就是資料來源的全部配置。這裡還有一個點就是:java:comp/env字首在資料來源前面的作用? 在描述JNDI,例如獲得資料來源時,JNDI地址有兩種寫法,例如同是 jdbc/testDS 資料來源: A: Java:comp/env/jdbc/testDS B: jdbc/testDS

這兩種寫法,配置的方式也不盡相同,第一種方法應該算是一種利於程式移植或遷移的方法,它的實現與“對映”的概念相同,而B方法,則是一個硬引用。 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子上下文中宣告

可以通過下面的結構示意來發現這兩種描述的不同之處: A: java:comp/env/jdbc/testDS(虛地址) ——> 對映描述符 ——> jdbc/testDS (實際的地址) B: jdbc/testDS (實際的地址) 從這種結構上來看,A的確是便於移植的。

參考博文: