• JNDI学习总结(4)——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服务器就会自动在confCatalinalocalhost目录下生成一个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>
    复制代码

      运行结果如下:

      

  • 相关阅读:
    Visual Studio 2010 Preview (cont.)
    Office VBA 进阶(开篇)
    Two cool debugger tips that I learnt today
    Send GMail
    Google Email Uploader
    看看.NET 4.0 都有些什么?
    XML Serializer in .NET
    Timeloc: 一个Adobe AIR程序
    SDC task library 一个MSBuild Task的有益补充。
    不考虑促销活动的百货业态供应商结算设计
  • 原文地址:https://www.cnblogs.com/zhanghaiyang/p/7213322.html
Copyright © 2020-2023  润新知