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

参考:https://www.cnblogs.com/xdp-gacl/p/4040019.html

 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文件中加入如下配置信息

<Context>
    <!-- 使用阿里巴巴的DruidDataSource配置针对Oracle数据库的JNDI数据源 -->
    <Resource 
        name="jdbc/OracleDataSource"
        factory="com.alibaba.druid.pool.DruidDataSourceFactory"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@192.168.1.229:1521:lead"
        username="lead_oams"
        password="p"
        maxActive="50"
        maxWait="10000"
        removeabandoned="true"
        removeabandonedtimeout="60"
        logabandoned="false"
        filters="stat"/>
        
    <!-- 使用阿里巴巴的DruidDataSource配置针对MySQL数据库的JNDI数据源 -->
     <Resource 
        name="jdbc/MysqlDataSource"
        factory="com.alibaba.druid.pool.DruidDataSourceFactory"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://192.168.1.233:3306/lead_oams?useUnicode=true&amp;characterEncoding=utf-8"
        username="lead_system"
        password="password"
        maxActive="50"
        maxWait="10000"
        removeabandoned="true"
        removeabandonedtimeout="60"
        logabandoned="false"
        filters="stat"/>
        
    <!--使用阿里巴巴的DruidDataSource配置针对SQLServer数据库的JNDI数据源-->
    <Resource 
        name="jdbc/SqlServerDataSource"
        auth="Container"
        factory="com.alibaba.druid.pool.DruidDataSourceFactory" 
        type="javax.sql.DataSource"
        driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver"
        url="jdbc:sqlserver://192.168.1.61:1433;DatabaseName=gaclTest"
        username="sa" 
        password="p@ssw0rd"
        maxActive="50"
        maxWait="10000"
        removeabandoned="true"
        removeabandonedtimeout="60"
        logabandoned="false"
        filters="stat"/>
</Context>

   配置项中指定了各个参数后,在连接池内部是这么使用这些参数的。数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。同时连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后任然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),不过这样会影响性能。

2.3、在web.xml引用JDNI数据源

  在web.xml文件中加入如下的配置引用JNDI数据源

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 
      JNDI配置的资源引用:
  • res-ref-name:表示引用资源的名称
  • res-type:此资源对应的类型为javax.sql.DataSource
  • res-auth:容器授权管理
   -->
   <!--Oracle数据库JNDI数据源引用 -->
  <resource-ref>
      <description>Oracle DB Connection</description>
      <res-ref-name>jdbc/OracleDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
 </resource-ref>
  
  <!--MySQL数据库JNDI数据 -->
  <resource-ref>
      <description>MySQL DB Connection</description>
      <res-ref-name>jdbc/MysqlDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
  
   <!--SQLServer数据库JNDI数据源引用 -->
  <resource-ref>
      <description>SQLServer DB Connection</description>
      <res-ref-name>jdbc/SqlServerDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</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测试页面如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%--引入JSTL标签库 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>DRUID配置JNDI数据源连接测试</title>
  </head>
  
  <body>
    <h3>针对MySQL数据库JNDI数据源测试</h3>
        <%--使用sql:query标签发送SQL语句去数据库查询数据,查询的结果集保存到rs变量当中,dataSource属性指明使用的数据源--%>
        <sql:query var="rs" dataSource="jdbc/MysqlDataSource">
            <%--MySQL JNDI数据源测试 SQL--%>
             select * from lead_oams_applications
        </sql:query>
        <%--使用c:forEach标签遍历查询结果集rs中的每一行--%>
        <c:forEach var="row" items="${rs.rows}">
            <%--${row.字段名}获取字段的值--%>
            ${row.resourceid}---${row.app_name}<br/>
        </c:forEach>
        <hr/>
        <h3>针对Oracle数据库JNDI数据源测试</h3>
          <%--使用sql:query标签发送SQL语句去数据库查询数据,查询的结果集保存到rs变量当中,dataSource属性指明使用的数据源--%>
        <sql:query var="rs" dataSource="jdbc/OracleDataSource">
            <%--Oracle JNDI数据源测试 SQL--%>
            SELECT * FROM LEAD_OAMS_DBSOURCES
        </sql:query>
        <%--使用c:forEach标签遍历查询结果集rs中的每一行--%>
        <c:forEach var="row" items="${rs.rows}">
            <%--${row.字段名}获取字段的值--%>
            ${row.RESOURCEID}---${row.DBSOURCE_NAME}---${row.DBSOURCE_TYPE}<br/>
        </c:forEach>
        <hr/>
        <h3>SQLServer JNDI数据源测试</h3>
        <%--使用sql:query标签发送SQL语句去数据库查询数据,查询的结果集保存到rs变量当中,dataSource属性指明使用的数据源--%>
        <sql:query var="rs" dataSource="jdbc/SqlServerDataSource">
            <%--SQLServer JNDI数据源测试 SQL--%>
            select * from t_demo
        </sql:query>
        <%--使用c:forEach标签遍历查询结果集rs中的每一行--%>
        <c:forEach var="row" items="${rs.rows}">
            <%--${row.字段名}获取字段的值--%>
            ${row.id}---${row.name}<br/>
        </c:forEach>
  </body>
</html>

  运行结果如下:

  

三、在Java代码中获取JNDI中的数据源

3.1、获取JNDI中的数据源

  编写一个JdbcUtil工具类,JdbcUtil工具类负责从JNDI容器中获取DataSource,再通过DataSource获取数据库连接。

代码如下:

package me.gacl.util;

/**
 * <p>ClassName: JdbcUtil<p>
 * <p>Description: 从JNDI容器中获取DataSource,再通过DataSource获取数据库连接<p>
 */
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.alibaba.druid.pool.DruidDataSource;

public class JdbcUtil {
    
/*
 web.xml文件中的JNDI数据源引用配置
 
  <!--Oracle数据库JNDI数据源引用 -->
  <resource-ref>
      <description>Oracle DB Connection</description>
      <res-ref-name>jdbc/OracleDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
 </resource-ref>
  
  <!--MySQL数据库JNDI数据 -->
  <resource-ref>
      <description>MySQL DB Connection</description>
      <res-ref-name>jdbc/MysqlDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
  
   <!--SQLServer数据库JNDI数据源引用 -->
  <resource-ref>
      <description>SQLServer DB Connection</description>
      <res-ref-name>jdbc/SqlServerDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
*/
    
    //Oracle数据库配置的JNDI数据源连接名,后面跟的是DataSource名,DataSource名在web.xml文件中的<res-ref-name></res-ref-name>进行了配置
    private static final String ORACLE_DB_JNDINAME = "java:comp/env/jdbc/OracleDataSource";
    //MySQL数据库配置的JNDI数据源连接名,java:comp/env是必须加的,后面跟的是DataSource名
    private static final String MYSQL_DB_JNDINAME = "java:comp/env/jdbc/MysqlDataSource";
    //SQLServer数据库配置的JNDI数据源连接名,java:comp/env是必须加的,后面跟的是DataSource名
    private static final String SQLSERVER_DB_JNDINAME = "java:comp/env/jdbc/SqlServerDataSource";
    
    private static DruidDataSource dsOracle = null;
    private static DruidDataSource dsMySql = null;
    private static DruidDataSource dsSqlServer = null;
    
    static{
        try {
            //1、初始化名称查找上下文
            Context ctx = new InitialContext();
            //2、通过JNDI名称找到DataSource
            dsOracle = (DruidDataSource) ctx.lookup(ORACLE_DB_JNDINAME);
            dsMySql = (DruidDataSource) ctx.lookup(MYSQL_DB_JNDINAME);
            dsSqlServer = (DruidDataSource) ctx.lookup(SQLSERVER_DB_JNDINAME);
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }

    /**
     * MethodName: getOracleConnection
     * Description: 获取Oracle数据库连接
     * @author xudp        
     * @return
     * @throws SQLException
     */
    public static Connection getOracleConnection() throws SQLException {
        return dsOracle.getConnection();
    }
    
    /**
     * MethodName: getMySqlConnection
     * Description: 获取MySQL数据库连接
     * @author xudp        
     * @return
     * @throws SQLException
     */
    public static Connection getMySqlConnection() throws SQLException {
        return dsMySql.getConnection();
    }
    
    /**
     * MethodName: getSqlServerConnection
     * Description: 获取SQLServer数据库连接
     * @author xudp        
     * @return
     * @throws SQLException
     */
    public static Connection getSqlServerConnection() throws SQLException {
        return dsSqlServer.getConnection();
    }

    /**
    * @Method: release
    * @Description: 释放资源,
    *     要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
    * @Anthor:孤傲苍狼
    *
    * @param conn
    * @param st
    * @param rs
    */ 
    public static void release(Connection conn,Statement st,ResultSet rs){
        if(rs!=null){
            try{
                //关闭存储查询结果的ResultSet对象
                rs.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try{
                //关闭负责执行SQL命令的Statement对象
                st.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        if(conn!=null){
            try{
                //关闭Connection数据库连接对象
                conn.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

3.2、测试JNDI数据源

  编写一个测试的Servlet,测试代码如下:

package me.gacl.test;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import me.gacl.util.JdbcUtil;

/**
 * <p>ClassName: JNDITestServlet<p>
 * <p>Description: <p>
 * <p>Company:广州利迪网络科技有限公司 <p>    
 * @author xudp
 * @version 1.0 V
 * @createTime 2014-10-23 上午09:32:52
 */
public class JNDITestServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //Oracle数据库连接
        Connection oracleConnection = null;
        //MySql数据库连接
        Connection mySqlConnection = null;
        //SQLServer数据库连接
        Connection sqlServerConnection = null;
        
        //负责执行SQL的PreparedStatement对象
        PreparedStatement pstmtOracle = null;
        PreparedStatement pstmtMySQL = null;
        PreparedStatement pstmtSqlServer = null;
        
        //查询出来的结果集
        ResultSet rsOracle = null;
        ResultSet rsMySQL = null;
        ResultSet rsSqlServer = null;
        
        //存储查询出来的数据,每一行数据映射成一个Map,字段名作为key,字段的值作为value
        List<Map<String, String>> oracleDataList = new ArrayList<Map<String, String>>();
        List<Map<String, String>> mySqlDataList = new ArrayList<Map<String, String>>();
        List<Map<String, String>> sqlServerDataList = new ArrayList<Map<String, String>>();
        
        try {
            
            //获取Oracle数据库连接
             oracleConnection = JdbcUtil.getOracleConnection();
            //获取MySql数据库连接
             mySqlConnection = JdbcUtil.getMySqlConnection();
            //获取SQLServer数据库连接
             sqlServerConnection =JdbcUtil.getSqlServerConnection();
            
             String oracleDb_Sql = "SELECT * FROM LEAD_OAMS_DBSOURCES";
             String mySqlDb_Sql = "SELECT * FROM LEAD_OAMS_APPLICATIONS";
             String sqlServerDb_Sql = "SELECT * FROM T_DEMO";
                
             pstmtOracle = oracleConnection.prepareStatement(oracleDb_Sql);
             pstmtMySQL = mySqlConnection.prepareStatement(mySqlDb_Sql);
             pstmtSqlServer = sqlServerConnection.prepareStatement(sqlServerDb_Sql);
            
             //执行查询,查询结果存储到ResultSet结果集中
             rsOracle = pstmtOracle.executeQuery();
             rsMySQL = pstmtMySQL.executeQuery();
             rsSqlServer = pstmtSqlServer.executeQuery();
            
            //循环结果集中的数据 
            while(rsOracle.next()){
                Map<String, String> oracleDataMap = new LinkedHashMap<String, String>();
                //取出结果集中的数据,每一行数据映射成一个map集合
                oracleDataMap.put("resourceid", rsOracle.getString("RESOURCEID"));
                oracleDataMap.put("dbsource_name", rsOracle.getString("DBSOURCE_NAME"));
                oracleDataMap.put("dbsource_type", rsOracle.getString("DBSOURCE_TYPE"));
                //将代表每一行数据的Map集合添加到List集合中
                oracleDataList.add(oracleDataMap);
            }
            
            while(rsMySQL.next()){
                Map<String, String> mySqlDataMap = new LinkedHashMap<String, String>();
                mySqlDataMap.put("resourceid", rsMySQL.getString("resourceid"));
                mySqlDataMap.put("app_name", rsMySQL.getString("app_name"));
                mySqlDataList.add(mySqlDataMap);
            }
            
            while(rsSqlServer.next()){
                Map<String, String> sqlServerDataMap = new LinkedHashMap<String, String>();
                sqlServerDataMap.put("id", rsSqlServer.getString("id"));
                sqlServerDataMap.put("name", rsSqlServer.getString("name"));
                sqlServerDataList.add(sqlServerDataMap);
            }
            
            //将数据集合存储到request对象发送到页面进行显示
            request.setAttribute("oracleDataList", oracleDataList);
            request.setAttribute("mySqlDataList", mySqlDataList);
            request.setAttribute("sqlServerDataList", sqlServerDataList);
            //跳转到JNDITest.jsp页面显示数据
            request.getRequestDispatcher("/JNDITest.jsp").forward(request, response);
            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            //释放资源
            JdbcUtil.release(oracleConnection, pstmtOracle, rsOracle);
            JdbcUtil.release(mySqlConnection, pstmtMySQL, rsMySQL);
            JdbcUtil.release(sqlServerConnection, pstmtSqlServer, rsSqlServer);
        }
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }
}

  JNDITest.jsp页面代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%--引入JSTL标签库 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>JNDI测试</title>
  </head>
  
  <body>
        <h3>从Oracle数据库中取出来的数据</h3>
        <%--使用c:forEach标签遍历List集合--%>
        <c:forEach var="oracleDataMap" items="${oracleDataList}">
            ${oracleDataMap.resourceid}---${oracleDataMap.dbsource_name}---${oracleDataMap.dbsource_type}<br/>
        </c:forEach>
        <hr/>
        <h3>从mySql数据库中取出来的数据</h3>
        <%--使用c:forEach标签遍历List集合--%>
        <c:forEach var="mySqlDataMap" items="${mySqlDataList}">
            ${mySqlDataMap.resourceid}---${mySqlDataMap.app_name}<br/>
        </c:forEach>
        <hr/>
        <h3>从sqlServer数据库中取出来的数据</h3>
        <%--使用c:forEach标签遍历List集合--%>
        <c:forEach var="sqlServerDataMap" items="${sqlServerDataList}">
            ${sqlServerDataMap.id}---${sqlServerDataMap.name}<br/>
        </c:forEach>
  </body>
</html>

  运行结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值