JNDI數據源(在Tomcat下配置JNDI多數據源實例)

一,添加數據庫驅動包加入classpath。

這裏我用到了oracle和mysql。
因此由兩個jar包:ojdbc14.jar和mysql-connector-java-5.1.13-bin.jar。


(有的也說須要添加commons-dbcp-1.4.jar,commons-pool-1.5.4.jar和commons-collections.jar,
我作了測試,不用的。
網上查了下,DBCP使用Jakarta-Commons Database Connection Pool,它依賴如下三個包:
Jakarta-Commons DBCP,Jakarta-Commons Collections,Jakarta-Commons Pool。
在Tomcat的安裝目錄提供了一個集成的jar包 $CATALINA_HOME/lib/tomcat-dbcp.jar。
因此有這個tomcat-dbcp.jar就能夠了。
html

 

 

二,修改Tomcat_Home/conf/server.xml,在GlobalNamingResources中加入:

 

<Resource name="jdbc/cdbank" auth="Container" 
     type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"  
     url="jdbc:oracle:thin:@10.55.15.66:1521:cdbank"  
     username="ccdb" password="ccdb" maxActive="10" maxIdle="5"  
     maxWait="-1"/>

<Resource name="jdbc/mydb" auth="Container" 
     type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"  
     url="jdbc:mysql://127.0.0.1:3306/mydb"  
     username="root" password="root" maxActive="10" maxIdle="5"  
     maxWait="-1"/>


屬性說明:
name:數據源的名稱。


auth:指定管理Resource的Manager,由兩個可選值:Container和Application。
Container表示由容器來建立和管理Resource。
Application表示由WEB應用來建立和管理Resource。
若是在web application deployment descriptor中使用<resource-ref>,這個屬性是必需的。
若是使用<resource-env-ref>,這個屬性是可選的。


type:指定Resource所屬的java類名:javax.sql.DataSource。

maxActive: 指定數據庫鏈接池中處於活動狀態的數據庫鏈接最大數目,0表示不受限制 

maxIdle: 指定數據庫鏈接池中處於空閒狀態的數據庫鏈接的最大數目,0表示不受限制 

maxWait: 指定數據庫鏈接池中的數據庫鏈接處於空閒狀態的最長時間(單位爲毫秒),超過這一事件,
將會拋出異常。-1表示能夠無限期等待。 

username: 鏈接數據庫的用戶名 

password: 鏈接數據庫的密碼 

driverClassName: 指定鏈接數據庫的JDBC驅動程序。
(oracle驅動:oracle.jdbc.OracleDriver
 mysql驅動: com.mysql.jdbc.Driver)

url:鏈接數據庫的URL


完整server.xml以下:java

 

<?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">

  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--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" />
  <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

  <!-- 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 name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />

	<Resource name="jdbc/cdbank" auth="Container" 
     type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"  
     url="jdbc:oracle:thin:@10.55.15.66:1521:cdbank"  
     username="ccdb" password="ccdb" maxActive="10" maxIdle="5"  
     maxWait="-1"/>

	 <Resource name="jdbc/mydb" auth="Container" 
     type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"  
     url="jdbc:mysql://127.0.0.1:3306/mydb"  
     username="root" password="root" maxActive="10" maxIdle="5"  
     maxWait="-1"/>

  </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 port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8453" />
    <!-- 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 JSSE configuration, when using APR, the 
         connector should be using the OpenSSL style configuration
         described in the APR documentation -->
    <!--
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

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


    <!-- 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 name="Catalina" defaultHost="localhost">

      <!--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"/>
      -->        

      <!-- The request dumper valve dumps useful debugging information about
           the request and response data received and sent by Tomcat.
           Documentation at: /docs/config/valve.html -->
      <!--
      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
      -->

      <!-- 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"/>

      <!-- Define the default virtual host
           Note: XML Schema validation will not work with Xerces 2.2.
       -->
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">

        <!-- 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 -->
        <!--
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"  
               prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
        -->

      </Host>
    </Engine>
  </Service>
</Server>

 

三,再在context.xml中加入引用:

 

 

<ResourceLink name="jdbc/cdbank" global="jdbc/cdbank"  
      type="javax.sql.DataSource"/> 

<ResourceLink name="jdbc/mydb" global="jdbc/mydb"  
      type="javax.sql.DataSource"/> 


在這裏要說明一下,我用的項目發佈方式是一個xml文件發佈一個工程。
因此我把ResourceLink寫在context.xml中。
其實還能夠配置到項目xml文件的context標籤裏。
若是你用的是server.xml方式發佈的話,還能夠在server.xml裏面的host下的context標籤裏
配置。例如:
<Host appBase="webapps" name="localhost">
   <Context  docBase="D:\ChinaDevelopmentBankJBPM\workSpace\dataSourceApp\WebContent" 
   path="/dataSourceApp" reloadable="true" debug="0" crossContext="true">
      <Resource  name="jdbc/mysql"  type="javax.sql.DataSource" password="123456" maxIdle="2" 
         maxWait="5000" username="root" maxActive="4" />
   </Context>
</Host>
總之都是要配置到context標籤裏,而且能被Tomcat讀取到就能夠。至於那種方式更方便
那就要根據本身的選擇了,實質其實都同樣,即context.xml文件對應<Context>標籤裏的內容。
只要裏面能被Tomcat讀取到就能夠。




完整context.xml以下:mysql

 

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

<!-- The contents of this file will be loaded for each web application -->
<Context>

    <ResourceLink name="jdbc/cdbank" global="jdbc/cdbank"  
      type="javax.sql.DataSource"/> 
	<ResourceLink name="jdbc/mydb" global="jdbc/mydb"  
      type="javax.sql.DataSource"/> 


    <!-- Default set of monitored resources -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
	
	
</Context>

 

四,在web.xml中加入<resource-ref>。

<resource-ref>  
        <description>tomcat datasource test,one oracle datasource</description>  
        <res-ref-name>jdbc/cdbank</res-ref-name>  
        <res-type>javax.sql.DataSource</res-type>  
        <res-auth>Container</res-auth>  
    </resource-ref>
    
    <resource-ref>  
        <description>tomcat datasource test,one mysql datasource</description>  
        <res-ref-name>jdbc/mydb</res-ref-name>  
        <res-type>javax.sql.DataSource</res-type>  
        <res-auth>Container</res-auth>  
    </resource-ref>

關於這一步,我作過測試,實際上是不用的!
寫上也不會報錯。爲何會有這一步,大概是網上都是這麼說的吧。
或者還有更深的意義。反正我這裏作的實際測試結果就是不必。
寫上也不會起什麼做用,也不報錯。


個人完整web.xml以下;
 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  
   <!-- tomcat數據源start -->
   <!--
   <resource-ref>  
        <description>tomcat datasource test,one oracle datasource</description>  
        <res-ref-name>jdbc/cdbank</res-ref-name>  
        <res-type>javax.sql.DataSource</res-type>  
        <res-auth>Container</res-auth>  
    </resource-ref>
    
    <resource-ref>  
        <description>tomcat datasource test,one mysql datasource</description>  
        <res-ref-name>jdbc/mydb</res-ref-name>  
        <res-type>javax.sql.DataSource</res-type>  
        <res-auth>Container</res-auth>  
    </resource-ref>
    -->
  
    <servlet>
		<servlet-name>TestServlet</servlet-name>
		<servlet-class>
			 org.test.TestServlet
		</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>TestServlet</servlet-name>
		<url-pattern>/TestServlet</url-pattern>
	</servlet-mapping>
    <!-- tomcat數據源 end -->
    
</web-app>

#############################################################


寫一個servlet來作測試TestServlet:
 
package org.test;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.test.util.DataSourceUtil;

public class TestServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	
	
	public void init() throws ServletException {
		System.out.println(TestServlet.class.getName() + " is inited");
	}

	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("doGet");
		doPost(req, resp);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("doPost");

		// 編碼設置
		resp.setContentType("text/html");
		resp.setHeader("Cache-Control", "no-cache");
		resp.setCharacterEncoding("UTF-8");
		
		oneEditCase(req,resp);//業務開始
		resp.getWriter().println("success!");
	}

	public void oneEditCase(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("oneEditCase start");
		
		//oracle數據庫對象
        Connection conn=null;
        PreparedStatement pstmt=null;
        ResultSet rs =null;
        
        //mysql數據庫對象
        Connection conn_mysql=null;
        PreparedStatement pstmt_mysql=null;
        ResultSet rs_mysql =null;
        
		try {
//			conn = DataSourceUtil.getJNDIOracleDataSourceConnection();
			conn = DataSourceUtil.getDataSourceOracleCdbankConnection();
			conn_mysql=DataSourceUtil.getDataSourceMysqlMydbConnection();
			
			conn.setAutoCommit(false);// 更改事務的提交方式
			conn_mysql.setAutoCommit(false);
			
			String sql_select2 = " select t.dep_name,t.company  from LSY_DEPARTMENT  t where t.dep_id='11' ";
			pstmt = conn.prepareStatement(sql_select2);//查詢
			rs = pstmt.executeQuery();
			
			while(rs.next()){
				System.out.println("查到數據。。。");
				String dep_name=rs.getString("dep_name");
				String company=rs.getString("company");
				System.out.println(dep_name+"--"+company);
				
				company+="haha";
				String sql_update2 = " update LSY_DEPARTMENT a set a.company='"+company+"'  where a.dep_id='11' ";
				
				pstmt = conn.prepareStatement(sql_update2);//更新oracle數據庫字段
				pstmt.execute();
				
				//一下開始對另外的mysql數據庫進行同步更新
				String sql_mysql_select="select DEP_ID	from  lsy_department where dep_id='11' ";
				pstmt_mysql = conn_mysql.prepareStatement(sql_mysql_select);//查詢是否存在該數據
				rs_mysql = pstmt_mysql.executeQuery();
				
				if(rs_mysql.next()){
					System.out.println("存在相同的數據,就更新相關字段");
					String sql_mysql_update="update mydb.lsy_department set " +
							"  DEP_NAME = '"+dep_name+"' , " +
							" COMPANY = '"+company+"' " +
							" where DEP_ID = '11' ";
					pstmt_mysql = conn_mysql.prepareStatement(sql_mysql_update);
					pstmt_mysql.execute();
				}else{
					System.out.println("不存在相同的數據,就做爲新數據插入");
					String sql_mysql_insert="insert into lsy_department (DEP_ID, DEP_NAME, COMPANY) values('11', '"+dep_name+"', '"+company+"') ";
					pstmt_mysql = conn_mysql.prepareStatement(sql_mysql_insert);
					pstmt_mysql.execute();
				}
				conn_mysql.commit();
				conn_mysql.setAutoCommit(true);
			}
			conn.commit();//提交事務
			conn.setAutoCommit(true);// 恢復事務的默認提交方式
			
		}catch (SQLException e) {
			try {
				System.out.println("提交發生錯誤,開始回滾事務...");
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally{
			try {
				if(rs != null){
					rs.close();
				}
				if(pstmt != null){
					pstmt.close();
				}
				if(conn != null){
					conn.close();
				}
				if(rs_mysql != null){
					rs_mysql.close();
				}
				if(pstmt_mysql != null){
					pstmt_mysql.close();
				}
				if(conn_mysql != null){
					conn_mysql.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}
		
	}

}


裏面須要一個工具類來管理鏈接DataSourceUtil:
 
package org.test.util;

import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DataSourceUtil {
	
	private static DataSource dataSource_oracle_cdbank=null;//一個oracle數據源
	private static DataSource dataSource_mysql_mydb=null;//一個mysql數據源
	
	//若果只須要從一個數據源獲取連接就能夠向下面這樣寫。不然,把DataSource單獨提出。
//	public static Connection getJNDIOracleDataSourceConnection(){
//		Connection conn=null;
//		InitialContext ctx=null;
//		try {
//			ctx = new InitialContext();
//			if(dataSource_oracle_cdbank == null){
//				System.out.println("dataSource_oracle_cdbank start connnectiong...");
//				
//				//獲取數據源,其中java:comp/env是Tomcat規定的,Tomcat提供的JNDI綁定都必須加該前綴。後面就是Resource的name屬性
//				dataSource_oracle_cdbank = (DataSource)ctx.lookup("java:comp/env/jdbc/cdbank");//context.xml 文件裏 Resource 項下 name 的值 "jdbc/qwe"
//				
//				if(dataSource_oracle_cdbank != null){
//					//獲取連接(根據須要能夠獲取多個)
//					conn= dataSource_oracle_cdbank.getConnection();
//				}else{
//					System.out.println("鏈接發生異常...");
//				}
//			}
//		}catch(NamingException e) {
//			e.printStackTrace();
//		}catch (SQLException e) {
//			e.printStackTrace();
//		}
//		
//		return conn;
//	}
	
	//獲取oracle的DataSource
	public static DataSource getDataSourceOracleCdbank(){
		InitialContext ctx=null;
		try {
			ctx = new InitialContext();
			if(dataSource_oracle_cdbank == null){
				System.out.println("dataSource_oracle_cdbank start connnectiong...");
				//獲取數據源,其中java:comp/env是Tomcat規定的,Tomcat提供的JNDI綁定都必須加該前綴。後面就是Resource的name屬性
				dataSource_oracle_cdbank = (DataSource)ctx.lookup("java:comp/env/jdbc/cdbank");//context.xml 文件裏 Resource 項下 name 的值 "jdbc/qwe"
				
			}
		}catch(NamingException e) {
			e.printStackTrace();
		}
		
		return dataSource_oracle_cdbank;
	
	}
	//獲取DataSource對象
	public static DataSource getDataSourceOracleCdbankInstance(){
		if(dataSource_oracle_cdbank==null){
			dataSource_oracle_cdbank=getDataSourceOracleCdbank();
		}
		return dataSource_oracle_cdbank;
	}
	//獲取Connection
	public static Connection getDataSourceOracleCdbankConnection(){
		Connection conn=null;
		try {
			if(getDataSourceOracleCdbankInstance() != null){
				//獲取連接(根據須要能夠獲取多個)
				conn= getDataSourceOracleCdbankInstance().getConnection();
			}else{
				System.out.println("鏈接發生異常...");
			}
		}catch (SQLException e) {
			e.printStackTrace();
		}
		
		return conn;
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	//獲取mysql的DataSource
	public static DataSource getDataSourceMysqlMydb(){
		InitialContext ctx=null;
		try {
			ctx = new InitialContext();
			if(dataSource_mysql_mydb == null){
				System.out.println("dataSource_mysql_mydb start connnectiong...");
				//獲取數據源,其中java:comp/env是Tomcat規定的,Tomcat提供的JNDI綁定都必須加該前綴。後面就是Resource的name屬性
				dataSource_mysql_mydb = (DataSource)ctx.lookup("java:comp/env/jdbc/mydb");
				
			}
		}catch(NamingException e) {
			e.printStackTrace();
		}
		
		return dataSource_mysql_mydb;
	
	}
	//獲取DataSource對象
	public static DataSource getDataSourceMysqlMydbInstance(){
		if(dataSource_mysql_mydb==null){
			dataSource_mysql_mydb=getDataSourceMysqlMydb();
		}
		return dataSource_mysql_mydb;
	}
	//獲取Connection
	public static Connection getDataSourceMysqlMydbConnection(){
		Connection conn=null;
		try {
			if(getDataSourceMysqlMydbInstance() != null){
				//獲取連接(根據須要能夠獲取多個)
				conn= getDataSourceMysqlMydbInstance().getConnection();
			}else{
				System.out.println("鏈接發生異常...");
			}
		}catch (SQLException e) {
			e.printStackTrace();
		}
		
		return conn;
	}
	
}


第一次訪問http://localhost:8080/dataSourceApp/TestServlet


打印:
org.test.TestServlet is inited
doGet
doPost
oneEditCase start
dataSource_oracle_cdbank start connnectiong...
dataSource_mysql_mydb start connnectiong...
查到數據。。。
研發部--百度
不存在相同的數據,就做爲新數據插入



第二次訪問http://localhost:8080/dataSourceApp/TestServlet


打印:
doGet
doPost
oneEditCase start
查到數據。。。
研發部--百度haha
存在相同的數據,就更新相關字段


同時兩個數據庫的值都已經正確修改。
 
再說些廢話,jndi的數據源對象也能夠在spring註冊。 大多數狀況,應該不會用到。 爲何呢?若是你用到了spring,你徹底能夠把新的數據源配置到spring裏, 固然不會是使用jndi了,徹底可使用c3p0,dbcp,或者jdbc。 同時遷移服務器的時候也好遷移。 若是已經使用了spring,再去配置JNDI數據源,感受像殺雞用牛刀。 JNDI的方式,我以爲大多數狀況使用小型的應用,或者作數據處理,好比兩個數據庫 之間的數據傳遞(不是簡簡單單的倒庫)。個人例子就是這種狀況。 小型的應用,功能不多,這樣配置數據源仍是很方便的(jdbc也不錯)
相關文章
相關標籤/搜索