JavaWeb学习总结(十三)--数据库连接池

一、数据库连接池的概念#

     用池来管理 Connection,这可以重复使用 Connection。有了池,所以我们就不用自己来创建 Connection,而是通过池来获取 Connection 对象。当使用完 Connection 后,调用 Connection 的 close() 方法也不会真的关闭 Connection,而是把 Connection“归还”给池。池就可以再利用这个 Connection 对象了。

 

 

JDBC数据库连接池接口(DataSource#

 

  Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

 

开源数据库连接池#

  现在很多 WEB 服务器 (Weblogic, WebSphere, Tomcat) 都提供了 DataSoruce 的实现,即连接池的实现。通常我们把 DataSource 的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。
  也有一些开源组织提供了数据源的独立实现:

  • DBCP 数据库连接池
  • C3P0 数据库连接池

  在使用了数据库连接池之后,在项目的实际开发中就不需要编写连接数据库的代码了,直接从数据源获得数据库的连接。

 

JDBC数据库连接池接口(DataSource

  Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

 

 

二、DBCP#

 

   DBCP 是Apache 提供的一款开源免费的数据库连接池!Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。Hibernate3.0 之后不再对DBCP 提供支持!因为Hibernate 声明DBCP 有致命的缺欠!

需要应用程序应在系统中增加如下两个 jar 文件:

  • Commons-dbcp.jar:连接池的实现
  • Commons-pool.jar:连接池实现的依赖库

实现 DBCP#

 1. 加入 jar 包#

2. 编写dbcpconfig.properties#

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testdb
username=root
password=123456

#<!-- 初始化连接 -->
initialSize
=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle
=20

#<!-- 最小空闲连接 -->
minIdle
=5

#<!-- 超时等待时间以毫秒为单位 6000 毫秒 /1000 等于 60 秒 -->
maxWait
=60000

#JDBC 驱动建立连接时附带的连接属性属性的格式必须为这样:[ 属性名 =property;]
#注意:
"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties
=useUnicode=true;characterEncoding=UTF8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit
=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly
=false

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation
=REPEATABLE_READ

 如下图所示:

3、在获取数据库连接的工具类 (如 jdbcUtils) 的静态代码块中创建池#

 

package cn.zy.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

/*

  • 数据库连接工具类 DBCP
    /
    public class JdbcUtils_DBCP {
    /

    • 在 java 中,编写数据库连接池需实现 java.sql.DataSource 接口,每一种数据库连接池都是 DataSource 接口的实现
    • DBCP 连接池就是 javax.sql.DataSource 接口的一个具体实现
      */
      private static DataSource ds =null;
      //在静态代码块中创建数据库连接池
      static {
      try {
      //加载配置文件
      InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
      Properties prop
      = new Properties();
      prop.load(in);
      //创建数据源
      ds = BasicDataSourceFactory.createDataSource(prop);
      }
      catch (Exception e) {
      throw new ExceptionInInitializerError(e);
      }
      }

    /*

    • 从数据源中获取数据库连接
      */
      public static Connection getConnection() throws SQLException{
      return ds.getConnection();
      }

    /* * 释放资源 */ public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{rs.close(); }catch (Exception e){e.printStackTrace(); } if(st!=null){ try {st.close(); } catch (Exception e) {e.printStackTrace(); } if(conn!=null){ try {conn.close(); } catch (SQLException e) {e.printStackTrace(); } } } } }

}

测试连接

package cn.zy.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

import cn.zy.utils.JdbcUtils_DBCP;

/*

  • 测试 DBCP 数据源
    */
    public class DbcpTest {
    @Test
    public void dbcpDataSourceTest(){
    Connection conn
    = null;
    PreparedStatement st
    = null;
    ResultSet rs
    = null;
    try {
    //获取数据库连接
    conn = JdbcUtils_DBCP.getConnection();
    String sql
    = "insert into account(name,money) values(?,?)";
    st
    = conn.prepareStatement(sql);
    st.setString(
    1, "D");
    st.setFloat(
    2, 2000);
    st.executeUpdate();
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    finally{
    //释放资源
    JdbcUtils_DBCP.release(conn, st, rs);
    }
    }

}

 

三、C3P0 数据源#

C3P0 是一个开源的 JDBC 连接池,它实现了数据源和 JNDI 绑定,支持 JDBC3 规范和 JDBC2 的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0 数据源在项目开发中使用得比较多。

  c3p0 与 dbcp 区别
  1. dbcp 没有自动回收空闲连接的功能
  2. c3p0 有自动回收空闲连接功能

在应用程序中加入 C3P0 连接池#

1.导入相关 jar 包#

c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar,如果操作的是 Oracle 数据库,那么还需要导入 c3p0-oracle-thin-extras-0.9.2-pre1.jar

2、在 src 下加入 C3P0 的配置文件:c3p0-config.xml,注意:

配置文件要求:

l  文件名称:必须叫 c3p0-config.xml

l  文件位置:必须在 src 下

   c3p0-config.xml的配置信息如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--
c3p0-config.xml 必须位于类路径下面
private static ComboPooledDataSource ds;
static{
    try {ds = new ComboPooledDataSource("MySQL");
    } catch (Exception e) {throw new ExceptionInInitializerError(e);
    }
}
-->

<c3p0-config>
<!--
C3P0 的缺省 (默认) 配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是 C3P0 的缺省 (默认) 配置信息来创建数据源
-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/testdb</property>
<property name="user">root</property>
<property name="password">123456</property>

    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireIncrement"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="initialPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>10<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="minPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="maxPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>20<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">default-config</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">
C3P0的命名配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
</span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">named-config </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="MySQL"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="driverClass"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>com.mysql.jdbc.Driver<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="jdbcUrl"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>jdbc:mysql://localhost:3306/testdb<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="user"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>root<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="password"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>123456<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireIncrement"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="initialPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>10<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="minPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="maxPoolSize"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>20<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">named-config</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</c3p0-config>

如图:

3、在获取数据库连接的工具类 (如 jdbcUtils) 的静态代码块中创建池

 1 package cn.zy.utils;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7
 8 import javax.sql.DataSource;
 9 
10 
11 import com.mchange.v2.c3p0.ComboPooledDataSource;
12 
13 /*
14  * 数据库连接工具类
15  */
16 public class JdbcUtils_C3P0 {
17     private static ComboPooledDataSource dataSource = null;
18     //在静态块中创建数据库连接池
19     static{
20         try {
21             //通过代码创建数据库连接池
22             /*ds = new ComboPooledDataSource();
23             ds.setDriverClass("com.mysql.jdbc.Driver");
24             ds.setJdbcUrl("jdbc:mysql://localhost:3306/testdb");
25             ds.setUser("root");
26             ds.setPassword("123456");
27             ds.setInitialPoolSize(10);
28             ds.setMinPoolSize(5);
29             ds.setMinPoolSize(20);*/
30             
31             //通过读取 xml 来获取数据源
32             //ds = new ComboPooledDataSource();//使用 C3P0 的默认配置来创建数据源
33             dataSource = new ComboPooledDataSource("MySQL");//使用 C3P0 的命名配置来创建数据源    
34         } catch (Exception e) {
35             throw new ExceptionInInitializerError(e);
36         }
37     }
38     
39     /*
40      * 从数据源中获取数据库连接
41      */
42     public static Connection getConnection() throws SQLException {
43         return dataSource.getConnection();
44     }
45     
46     /*
47      * 返回连接池
48      */
49     public static DataSource getDataSource() {
50         return dataSource;
51     }
52     /*
53      * 释放资源
54      */
55     public static void release(Connection conn,Statement st,ResultSet rs){
56         if(rs!=null){
57             try{
58                 //关闭存储查询结果的 ResultSet 对象
59                 rs.close();
60             }catch (Exception e) {
61                 e.printStackTrace();
62             }
63             rs = null;
64         }
65         if(st!=null){
66             try{
67                 //关闭负责执行 SQL 命令的 Statement 对象
68                 st.close();
69             }catch (Exception e) {
70                 e.printStackTrace();
71             }
72         }
73         
74         if(conn!=null){
75             try{
76                 //将 Connection 连接对象还给数据库连接池
77                 conn.close();
78             }catch (Exception e) {
79                 e.printStackTrace();
80             }
81         }
82     }
83 }
84         

 

编写测试类:

package cn.zy.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

import cn.zy.utils.JdbcUtils_C3P0;

public class C3p0Test {
@Test
public void fun(){
Connection conn
= null;
PreparedStatement st
= null;
ResultSet rs
= null;
try {
conn
= JdbcUtils_C3P0.getConnection();
String sql
= "insert into account(name,money) values(?,?)";
st
= conn.prepareStatement(sql);
st.setString(
1, "F");
st.setFloat(
2,3000);
st.executeUpdate();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

 

四、配置 Tomcat 数据源#

     在实际开发中,我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望 Tomcat 服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用 Tomcat 服务器创建好的数据库连接池即可。要想让 Tomcat 服务器在启动的时候帮我们创建一个数据库连接池,那么需要简单配置一下 Tomcat 服务器。

4.1 Tomcat 配置 JNDI 资源#

JNDI(Java Naming and Directory Interface),Java 命名和目录接口,它对应于 J2SE 中的 javax.naming 包,
  这 套 API 的主要作用在于:它可以把 Java 对象放在一个容器中(JNDI 容器),并为容器中的 java 对象取一个名称,以后程序想获得 Java 对象,只需 通过名称检索即可。其核心 API 为 Context,它代表 JNDI 容器,其 lookup 方法为检索容器中对应名称的对象。

Tomcat 服务器创建的数据源是以 JNDI 资源的形式发布的,所以说在 Tomat 服务器中配置一个数据源实际上就是在配置一个 JNDI 资源,通过查看 Tomcat 文档,我们知道使用如下的方式配置 tomcat 服务器的数据源:

<Context>
  <Resource name="jdbc/datasource" auth="Container"
            type="javax.sql.DataSource" username="root" password="123456"
            driverClassName="com.mysql.jdbc.Driver" 
            url="jdbc:mysql://localhost:3306/testdb"
            maxActive="8" maxIdle="4"/>
</Context>

服务器创建好数据源之后,我们的应用程序又该怎么样得到这个数据源呢,Tomcat 服务器创建好数据源之后是以 JNDI 的形式绑定到一个 JNDI 容器中的,我们可以把 JNDI 想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI 容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从 JNDI 容器中获取资源时,只需要告诉 JNDI 容器要获取的资源的名称,JNDI 根据名称去找到对应的资源后返回给应用程序。我们平时做 javaEE 开发时,服务器会为我们的应用程序创建很多资源,比如 request 对象,response 对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:第一种是通过方法参数的形式传递进来,比如我们在 Servlet 中写的 doPost 和 doGet 方法中使用到的 request 对象和 response 对象就是服务器以参数的形式传递给我们的。第二种就是 JNDI 的方式,服务器把创建好的资源绑定到 JNDI 容器中去,应用程序想要使用资源时,就直接从 JNDI 容器中获取相应的资源即可。

  对于上面的 name="jdbc/datasource" 数据源资源,在应用程序中可以用如下的代码去获取

1 Context initCtx = new InitialContext();
2 Context envCtx = (Context) initCtx.lookup("java:comp/env");
3 dataSource = (DataSource)envCtx.lookup("jdbc/datasource");

此种配置下,数据库的驱动 jar 文件需放置在 tomcat 的 lib 下

4.2、配置 Tomcat 数据源#

1、在 Web 项目的 WebRoot 目录下的 META-INF 目录创建一个 context.xml 文件

 

2、在 Web 项目的 WebRoot 目录下的 META-INF 目录创建一个 context.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<Context>
   <Resource 
       name="jdbc/datasource" 
       auth="Container"
       type="javax.sql.DataSource" 
       username="root" 
       password="123456"
       driverClassName="com.mysql.jdbc.Driver" 
       url="jdbc:mysql://localhost:3306/testdb"
       maxActive="8" 
       maxIdle="4"/>
</Context>

 

3、将数据库的驱动 jar 文件需放置在 tomcat 的 lib 下

 

4、在获取数据库连接的工具类 (如 jdbcUtils) 的静态代码块中获取 JNDI 容器中的数据源

 

 

package cn.zy.utils;

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.sql.DataSource;

public class JdbcUtils_JNDI {
private static DataSource ds = null;
//在静态代码块中创建数据库连接池
static{
try {
//初始化 JNDI
Context initCtx = new InitialContext();
//得到 JNDI 容器
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//从 JNDI 容器中检索 name 为 jdbc/datasource 的数据源
ds = (DataSource)envCtx.lookup("jdbc/datasource");
}
catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
 * 从数据源中获取连接
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ds.getConnection();
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
 * 释放资源
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> release(Connection conn,Statement st,ResultSet rs){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(rs!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">{
            rs.close();
        }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e){
            e.printStackTrace();
        }
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(st!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                st.close();
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
                e.printStackTrace();
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(conn!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
                </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                    conn.close();
                } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

}

写一个 Servlet 进行测试:

package cn.zy.test;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.zy.utils.JdbcUtils_JNDI;

public class JNDITest extends HttpServlet {

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> doGet(HttpServletRequest request, HttpServletResponse response)
        </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException {
    response.setContentType(</span>"text/html;charset=utf-8"<span style="color: rgba(0, 0, 0, 1)">);
    Connection conn </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    PreparedStatement st </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    ResultSet rs </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取连接</span>
        conn =<span style="color: rgba(0, 0, 0, 1)"> JdbcUtils_JNDI.getConnection();
        String sql </span>= "insert into account(name,money) values(?,?)"<span style="color: rgba(0, 0, 0, 1)">;
        st </span>=<span style="color: rgba(0, 0, 0, 1)"> conn.prepareStatement(sql);
        st.setString(</span>1, "F"<span style="color: rgba(0, 0, 0, 1)">);
        st.setFloat(</span>2, 2000<span style="color: rgba(0, 0, 0, 1)">);
        st.executeUpdate();
        response.getWriter().print(</span>"插入成功"<span style="color: rgba(0, 0, 0, 1)">);
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
        e.printStackTrace();
    }</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">{
        JdbcUtils_JNDI.release(conn, st, rs);
    }

}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> doPost(HttpServletRequest request, HttpServletResponse response)
        </span><span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException {
    doGet(request, response);
}

}