JNDI學習總結(三)——Tomcat下使用Druid配置JNDI數據源


  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&amp;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>

  運行結果如下:

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM