首页 > 代码库 > JNDI学习总结(三)——Tomcat下使用Druid配置JNDI数据源

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.DataSource15   • 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_applications17         </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_DBSOURCES29         </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_demo41         </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: release105     * @Description: 释放资源,106     *     要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象107     * @Anthor:孤傲苍狼108     *109     * @param conn110     * @param st111     * @param rs112     */ 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>
 

  运行结果如下:

  

JNDI学习总结(三)——Tomcat下使用Druid配置JNDI数据源