1. 程式人生 > >史上最全最詳細JNDI數據源配置說明

史上最全最詳細JNDI數據源配置說明

獲取 eba top memory -h lse b2c gin stand

史上最全最詳細JNDI數據源配置說明
轉載 : https://blog.csdn.net/zhanglf02/article/details/76726702
2017年08月05日 17:12:08 閱讀數:4466

環境: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"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

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> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

替換為jndi數據源:

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



配置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>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

對應位置如下圖:
第一種方式-在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"  
/>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

第二步:同樣在本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>  
  • 1
  • 2
  • 3

我把整個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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145

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的確是便於移植的。

參考博文:



1. JNDI學習總結(一)——JNDI數據源的配置
2. 理解JNDI中 java:comp/env/jdbc/datasource 與 jdbc/datasource 的不同之處。
3. 在Tomcat配置JNDI數據源的三種方式

史上最全最詳細JNDI數據源配置說明