com.alibaba.druid.pool.DruidDataSourceFactory實現了javax.naming.spi.ObjectFactory,可以作為JNDI數據源來配置。
一、下載Druid的jar包
下載地址:http://mvnrepository.com/artifact/com.alibaba/druid/1.0.9,如下圖所示:
druid.jar依賴log4j的jar包,所以還需要下載log4j的jar包。
log4j的下載地址如下:http://mvnrepository.com/artifact/log4j/log4j/1.2.17,如下圖所示:
二、使用Druid配置JNDI數據源
2.1、前期准備工作
創建一個Web測試項目Druid_JNDI_Config,將下載下來druid-1.0.9.jar和log4j-1.2.17.jar添加到項目中,在項目的META-INF目錄下創建一個context.xml文件
目錄結構如下圖所示:
在tomcat服務器的lib目錄下添加Oracle、MySQL、SQLServer三種數據庫的驅動jar包,如下圖所示:
2.2、在context.xml文件中加入JNDI的配置信息
在context.xml文件中加入如下配置信息
1 <Context> 2 <!-- 使用阿里巴巴的DruidDataSource配置針對Oracle數據庫的JNDI數據源 --> 3 <Resource 4 name="jdbc/OracleDataSource" 5 factory="com.alibaba.druid.pool.DruidDataSourceFactory" 6 auth="Container" 7 type="javax.sql.DataSource" 8 driverClassName="oracle.jdbc.OracleDriver" 9 url="jdbc:oracle:thin:@192.168.1.229:1521:lead" 10 username="lead_oams" 11 password="p" 12 maxActive="50" 13 maxWait="10000" 14 removeabandoned="true" 15 removeabandonedtimeout="60" 16 logabandoned="false" 17 filters="stat"/> 18 19 <!-- 使用阿里巴巴的DruidDataSource配置針對MySQL數據庫的JNDI數據源 --> 20 <Resource 21 name="jdbc/MysqlDataSource" 22 factory="com.alibaba.druid.pool.DruidDataSourceFactory" 23 auth="Container" 24 type="javax.sql.DataSource" 25 driverClassName="com.mysql.jdbc.Driver" 26 url="jdbc:mysql://192.168.1.233:3306/lead_oams?useUnicode=true&characterEncoding=utf-8" 27 username="lead_system" 28 password="password" 29 maxActive="50" 30 maxWait="10000" 31 removeabandoned="true" 32 removeabandonedtimeout="60" 33 logabandoned="false" 34 filters="stat"/> 35 36 <!--使用阿里巴巴的DruidDataSource配置針對SQLServer數據庫的JNDI數據源--> 37 <Resource 38 name="jdbc/SqlServerDataSource" 39 auth="Container" 40 factory="com.alibaba.druid.pool.DruidDataSourceFactory" 41 type="javax.sql.DataSource" 42 driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" 43 url="jdbc:sqlserver://192.168.1.61:1433;DatabaseName=gaclTest" 44 username="sa" 45 password="p@ssw0rd" 46 maxActive="50" 47 maxWait="10000" 48 removeabandoned="true" 49 removeabandonedtimeout="60" 50 logabandoned="false" 51 filters="stat"/> 52 </Context>
配置項中指定了各個參數后,在連接池內部是這么使用這些參數的。數據庫連接池在初始化的時候會創建initialSize個連接,當有數據庫操作時,會從池中取出一個連接。如果當前池中正在使用的連接數等於maxActive,則會等待一段時間,等待其他操作釋放掉某一個連接,如果這個等待時間超過了maxWait,則會報錯;如果當前正在使用的連接數沒有達到maxActive,則判斷當前是否空閑連接,如果有則直接使用空閑連接,如果沒有則新建立一個連接。在連接使用完畢后,不是將其物理連接關閉,而是將其放入池中等待其他操作復用。同時連接池內部有機制判斷,如果當前的總的連接數少於miniIdle,則會建立新的空閑連接,以保證連接數得到miniIdle。如果當前連接池中某個連接在空閑了timeBetweenEvictionRunsMillis時間后任然沒有使用,則被物理性的關閉掉。有些數據庫連接的時候有超時限制(mysql連接在8小時后斷開),或者由於網絡中斷等原因,連接池的連接會出現失效的情況,這時候設置一個testWhileIdle參數為true,可以保證連接池內部定時檢測連接的可用性,不可用的連接會被拋棄或者重建,最大情況的保證從連接池中得到的Connection對象是可用的。當然,為了保證絕對的可用性,你也可以使用testOnBorrow為true(即在獲取Connection對象時檢測其可用性),
不過這樣會影響性能。
2.3、在web.xml引用JDNI數據源
在web.xml文件中加入如下的配置引用JNDI數據源
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <welcome-file-list> 8 <welcome-file>index.jsp</welcome-file> 9 </welcome-file-list> 10 11 <!-- 12 JNDI配置的資源引用: 13 • res-ref-name:表示引用資源的名稱 14 • res-type:此資源對應的類型為javax.sql.DataSource 15 • res-auth:容器授權管理 16 --> 17 <!--Oracle數據庫JNDI數據源引用 --> 18 <resource-ref> 19 <description>Oracle DB Connection</description> 20 <res-ref-name>jdbc/OracleDataSource</res-ref-name> 21 <res-type>javax.sql.DataSource</res-type> 22 <res-auth>Container</res-auth> 23 </resource-ref> 24 25 <!--MySQL數據庫JNDI數據 --> 26 <resource-ref> 27 <description>MySQL DB Connection</description> 28 <res-ref-name>jdbc/MysqlDataSource</res-ref-name> 29 <res-type>javax.sql.DataSource</res-type> 30 <res-auth>Container</res-auth> 31 </resource-ref> 32 33 <!--SQLServer數據庫JNDI數據源引用 --> 34 <resource-ref> 35 <description>SQLServer DB Connection</description> 36 <res-ref-name>jdbc/SqlServerDataSource</res-ref-name> 37 <res-type>javax.sql.DataSource</res-type> 38 <res-auth>Container</res-auth> 39 </resource-ref> 40 </web-app>
2.4、測試JNDI數據源
部署Druid_JNDI_Config Web應用到Tomcat服務器測試JNDI數據源,如下圖所示:
部署到tomcat服務器的webapps目錄之后,tomcat服務器就會自動在\conf\Catalina\localhost目錄下生成一個Druid_JNDI_Config.xml文件,如下圖所示:
Druid_JNDI_Config.xml文件中的內容就是我們在META-INF目錄的context.xml文件中配置的那些內容。
jsp測試頁面如下:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%--引入JSTL標簽庫 --%> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 4 <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> 5 <!DOCTYPE HTML> 6 <html> 7 <head> 8 <title>DRUID配置JNDI數據源連接測試</title> 9 </head> 10 11 <body> 12 <h3>針對MySQL數據庫JNDI數據源測試</h3> 13 <%--使用sql:query標簽發送SQL語句去數據庫查詢數據,查詢的結果集保存到rs變量當中,dataSource屬性指明使用的數據源--%> 14 <sql:query var="rs" dataSource="jdbc/MysqlDataSource"> 15 <%--MySQL JNDI數據源測試 SQL--%> 16 select * from lead_oams_applications 17 </sql:query> 18 <%--使用c:forEach標簽遍歷查詢結果集rs中的每一行--%> 19 <c:forEach var="row" items="${rs.rows}"> 20 <%--${row.字段名}獲取字段的值--%> 21 ${row.resourceid}---${row.app_name}<br/> 22 </c:forEach> 23 <hr/> 24 <h3>針對Oracle數據庫JNDI數據源測試</h3> 25 <%--使用sql:query標簽發送SQL語句去數據庫查詢數據,查詢的結果集保存到rs變量當中,dataSource屬性指明使用的數據源--%> 26 <sql:query var="rs" dataSource="jdbc/OracleDataSource"> 27 <%--Oracle JNDI數據源測試 SQL--%> 28 SELECT * FROM LEAD_OAMS_DBSOURCES 29 </sql:query> 30 <%--使用c:forEach標簽遍歷查詢結果集rs中的每一行--%> 31 <c:forEach var="row" items="${rs.rows}"> 32 <%--${row.字段名}獲取字段的值--%> 33 ${row.RESOURCEID}---${row.DBSOURCE_NAME}---${row.DBSOURCE_TYPE}<br/> 34 </c:forEach> 35 <hr/> 36 <h3>SQLServer JNDI數據源測試</h3> 37 <%--使用sql:query標簽發送SQL語句去數據庫查詢數據,查詢的結果集保存到rs變量當中,dataSource屬性指明使用的數據源--%> 38 <sql:query var="rs" dataSource="jdbc/SqlServerDataSource"> 39 <%--SQLServer JNDI數據源測試 SQL--%> 40 select * from t_demo 41 </sql:query> 42 <%--使用c:forEach標簽遍歷查詢結果集rs中的每一行--%> 43 <c:forEach var="row" items="${rs.rows}"> 44 <%--${row.字段名}獲取字段的值--%> 45 ${row.id}---${row.name}<br/> 46 </c:forEach> 47 </body> 48 </html>
運行結果如下:
三、在Java代碼中獲取JNDI中的數據源
3.1、獲取JNDI中的數據源
編寫一個JdbcUtil工具類,JdbcUtil工具類負責從JNDI容器中獲取DataSource,再通過DataSource獲取數據庫連接。
代碼如下:
1 package me.gacl.util; 2 3 /** 4 * <p>ClassName: JdbcUtil<p> 5 * <p>Description: 從JNDI容器中獲取DataSource,再通過DataSource獲取數據庫連接<p> 6 */ 7 import java.sql.Connection; 8 import java.sql.ResultSet; 9 import java.sql.SQLException; 10 import java.sql.Statement; 11 import javax.naming.Context; 12 import javax.naming.InitialContext; 13 import javax.naming.NamingException; 14 import com.alibaba.druid.pool.DruidDataSource; 15 16 public class JdbcUtil { 17 18 /* 19 web.xml文件中的JNDI數據源引用配置 20 21 <!--Oracle數據庫JNDI數據源引用 --> 22 <resource-ref> 23 <description>Oracle DB Connection</description> 24 <res-ref-name>jdbc/OracleDataSource</res-ref-name> 25 <res-type>javax.sql.DataSource</res-type> 26 <res-auth>Container</res-auth> 27 </resource-ref> 28 29 <!--MySQL數據庫JNDI數據 --> 30 <resource-ref> 31 <description>MySQL DB Connection</description> 32 <res-ref-name>jdbc/MysqlDataSource</res-ref-name> 33 <res-type>javax.sql.DataSource</res-type> 34 <res-auth>Container</res-auth> 35 </resource-ref> 36 37 <!--SQLServer數據庫JNDI數據源引用 --> 38 <resource-ref> 39 <description>SQLServer DB Connection</description> 40 <res-ref-name>jdbc/SqlServerDataSource</res-ref-name> 41 <res-type>javax.sql.DataSource</res-type> 42 <res-auth>Container</res-auth> 43 </resource-ref> 44 */ 45 46 //Oracle數據庫配置的JNDI數據源連接名,后面跟的是DataSource名,DataSource名在web.xml文件中的<res-ref-name></res-ref-name>進行了配置 47 private static final String ORACLE_DB_JNDINAME = "java:comp/env/jdbc/OracleDataSource"; 48 //MySQL數據庫配置的JNDI數據源連接名,java:comp/env是必須加的,后面跟的是DataSource名 49 private static final String MYSQL_DB_JNDINAME = "java:comp/env/jdbc/MysqlDataSource"; 50 //SQLServer數據庫配置的JNDI數據源連接名,java:comp/env是必須加的,后面跟的是DataSource名 51 private static final String SQLSERVER_DB_JNDINAME = "java:comp/env/jdbc/SqlServerDataSource"; 52 53 private static DruidDataSource dsOracle = null; 54 private static DruidDataSource dsMySql = null; 55 private static DruidDataSource dsSqlServer = null; 56 57 static{ 58 try { 59 //1、初始化名稱查找上下文 60 Context ctx = new InitialContext(); 61 //2、通過JNDI名稱找到DataSource 62 dsOracle = (DruidDataSource) ctx.lookup(ORACLE_DB_JNDINAME); 63 dsMySql = (DruidDataSource) ctx.lookup(MYSQL_DB_JNDINAME); 64 dsSqlServer = (DruidDataSource) ctx.lookup(SQLSERVER_DB_JNDINAME); 65 } catch (NamingException e) { 66 e.printStackTrace(); 67 } 68 } 69 70 /** 71 * MethodName: getOracleConnection 72 * Description: 獲取Oracle數據庫連接 73 * @author xudp 74 * @return 75 * @throws SQLException 76 */ 77 public static Connection getOracleConnection() throws SQLException { 78 return dsOracle.getConnection(); 79 } 80 81 /** 82 * MethodName: getMySqlConnection 83 * Description: 獲取MySQL數據庫連接 84 * @author xudp 85 * @return 86 * @throws SQLException 87 */ 88 public static Connection getMySqlConnection() throws SQLException { 89 return dsMySql.getConnection(); 90 } 91 92 /** 93 * MethodName: getSqlServerConnection 94 * Description: 獲取SQLServer數據庫連接 95 * @author xudp 96 * @return 97 * @throws SQLException 98 */ 99 public static Connection getSqlServerConnection() throws SQLException { 100 return dsSqlServer.getConnection(); 101 } 102 103 /** 104 * @Method: release 105 * @Description: 釋放資源, 106 * 要釋放的資源包括Connection數據庫連接對象,負責執行SQL命令的Statement對象,存儲查詢結果的ResultSet對象 107 * @Anthor:孤傲蒼狼 108 * 109 * @param conn 110 * @param st 111 * @param rs 112 */ 113 public static void release(Connection conn,Statement st,ResultSet rs){ 114 if(rs!=null){ 115 try{ 116 //關閉存儲查詢結果的ResultSet對象 117 rs.close(); 118 }catch (Exception e) { 119 e.printStackTrace(); 120 } 121 rs = null; 122 } 123 if(st!=null){ 124 try{ 125 //關閉負責執行SQL命令的Statement對象 126 st.close(); 127 }catch (Exception e) { 128 e.printStackTrace(); 129 } 130 } 131 132 if(conn!=null){ 133 try{ 134 //關閉Connection數據庫連接對象 135 conn.close(); 136 }catch (Exception e) { 137 e.printStackTrace(); 138 } 139 } 140 } 141 }
3.2、測試JNDI數據源
編寫一個測試的Servlet,測試代碼如下:
1 package me.gacl.test; 2 3 import java.io.IOException; 4 import java.sql.Connection; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.util.ArrayList; 9 import java.util.LinkedHashMap; 10 import java.util.List; 11 import java.util.Map; 12 import javax.servlet.ServletException; 13 import javax.servlet.http.HttpServlet; 14 import javax.servlet.http.HttpServletRequest; 15 import javax.servlet.http.HttpServletResponse; 16 import me.gacl.util.JdbcUtil; 17 18 /** 19 * <p>ClassName: JNDITestServlet<p> 20 * <p>Description: <p> 21 * <p>Company:廣州利迪網絡科技有限公司 <p> 22 * @author xudp 23 * @version 1.0 V 24 * @createTime 2014-10-23 上午09:32:52 25 */ 26 public class JNDITestServlet extends HttpServlet { 27 28 public void doGet(HttpServletRequest request, HttpServletResponse response) 29 throws ServletException, IOException { 30 31 //Oracle數據庫連接 32 Connection oracleConnection = null; 33 //MySql數據庫連接 34 Connection mySqlConnection = null; 35 //SQLServer數據庫連接 36 Connection sqlServerConnection = null; 37 38 //負責執行SQL的PreparedStatement對象 39 PreparedStatement pstmtOracle = null; 40 PreparedStatement pstmtMySQL = null; 41 PreparedStatement pstmtSqlServer = null; 42 43 //查詢出來的結果集 44 ResultSet rsOracle = null; 45 ResultSet rsMySQL = null; 46 ResultSet rsSqlServer = null; 47 48 //存儲查詢出來的數據,每一行數據映射成一個Map,字段名作為key,字段的值作為value 49 List<Map<String, String>> oracleDataList = new ArrayList<Map<String, String>>(); 50 List<Map<String, String>> mySqlDataList = new ArrayList<Map<String, String>>(); 51 List<Map<String, String>> sqlServerDataList = new ArrayList<Map<String, String>>(); 52 53 try { 54 55 //獲取Oracle數據庫連接 56 oracleConnection = JdbcUtil.getOracleConnection(); 57 //獲取MySql數據庫連接 58 mySqlConnection = JdbcUtil.getMySqlConnection(); 59 //獲取SQLServer數據庫連接 60 sqlServerConnection =JdbcUtil.getSqlServerConnection(); 61 62 String oracleDb_Sql = "SELECT * FROM LEAD_OAMS_DBSOURCES"; 63 String mySqlDb_Sql = "SELECT * FROM LEAD_OAMS_APPLICATIONS"; 64 String sqlServerDb_Sql = "SELECT * FROM T_DEMO"; 65 66 pstmtOracle = oracleConnection.prepareStatement(oracleDb_Sql); 67 pstmtMySQL = mySqlConnection.prepareStatement(mySqlDb_Sql); 68 pstmtSqlServer = sqlServerConnection.prepareStatement(sqlServerDb_Sql); 69 70 //執行查詢,查詢結果存儲到ResultSet結果集中 71 rsOracle = pstmtOracle.executeQuery(); 72 rsMySQL = pstmtMySQL.executeQuery(); 73 rsSqlServer = pstmtSqlServer.executeQuery(); 74 75 //循環結果集中的數據 76 while(rsOracle.next()){ 77 Map<String, String> oracleDataMap = new LinkedHashMap<String, String>(); 78 //取出結果集中的數據,每一行數據映射成一個map集合 79 oracleDataMap.put("resourceid", rsOracle.getString("RESOURCEID")); 80 oracleDataMap.put("dbsource_name", rsOracle.getString("DBSOURCE_NAME")); 81 oracleDataMap.put("dbsource_type", rsOracle.getString("DBSOURCE_TYPE")); 82 //將代表每一行數據的Map集合添加到List集合中 83 oracleDataList.add(oracleDataMap); 84 } 85 86 while(rsMySQL.next()){ 87 Map<String, String> mySqlDataMap = new LinkedHashMap<String, String>(); 88 mySqlDataMap.put("resourceid", rsMySQL.getString("resourceid")); 89 mySqlDataMap.put("app_name", rsMySQL.getString("app_name")); 90 mySqlDataList.add(mySqlDataMap); 91 } 92 93 while(rsSqlServer.next()){ 94 Map<String, String> sqlServerDataMap = new LinkedHashMap<String, String>(); 95 sqlServerDataMap.put("id", rsSqlServer.getString("id")); 96 sqlServerDataMap.put("name", rsSqlServer.getString("name")); 97 sqlServerDataList.add(sqlServerDataMap); 98 } 99 100 //將數據集合存儲到request對象發送到頁面進行顯示 101 request.setAttribute("oracleDataList", oracleDataList); 102 request.setAttribute("mySqlDataList", mySqlDataList); 103 request.setAttribute("sqlServerDataList", sqlServerDataList); 104 //跳轉到JNDITest.jsp頁面顯示數據 105 request.getRequestDispatcher("/JNDITest.jsp").forward(request, response); 106 107 } catch (SQLException e) { 108 e.printStackTrace(); 109 }finally{ 110 //釋放資源 111 JdbcUtil.release(oracleConnection, pstmtOracle, rsOracle); 112 JdbcUtil.release(mySqlConnection, pstmtMySQL, rsMySQL); 113 JdbcUtil.release(sqlServerConnection, pstmtSqlServer, rsSqlServer); 114 } 115 } 116 117 public void doPost(HttpServletRequest request, HttpServletResponse response) 118 throws ServletException, IOException { 119 doGet(request,response); 120 } 121 }
JNDITest.jsp頁面代碼如下:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%--引入JSTL標簽庫 --%> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>JNDI測試</title> 8 </head> 9 10 <body> 11 <h3>從Oracle數據庫中取出來的數據</h3> 12 <%--使用c:forEach標簽遍歷List集合--%> 13 <c:forEach var="oracleDataMap" items="${oracleDataList}"> 14 ${oracleDataMap.resourceid}---${oracleDataMap.dbsource_name}---${oracleDataMap.dbsource_type}<br/> 15 </c:forEach> 16 <hr/> 17 <h3>從mySql數據庫中取出來的數據</h3> 18 <%--使用c:forEach標簽遍歷List集合--%> 19 <c:forEach var="mySqlDataMap" items="${mySqlDataList}"> 20 ${mySqlDataMap.resourceid}---${mySqlDataMap.app_name}<br/> 21 </c:forEach> 22 <hr/> 23 <h3>從sqlServer數據庫中取出來的數據</h3> 24 <%--使用c:forEach標簽遍歷List集合--%> 25 <c:forEach var="sqlServerDataMap" items="${sqlServerDataList}"> 26 ${sqlServerDataMap.id}---${sqlServerDataMap.name}<br/> 27 </c:forEach> 28 </body> 29 </html>
運行結果如下: