⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 0049.htm

📁 JspServlet教程专栏 对javaservlet讲述的非常详细
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<html>

<head>
<title>新时代软件教程:操作系统 主页制作 服务器 设计软件 网络技术 编程语言 文字编辑</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style>
<!--
body, table {font-size: 9pt; font-family: 宋体}
a {text-decoration:none}
a:hover {color: red;text-decoration:underline}
.1  {background-color: rgb(245,245,245)}
-->
</style>
</head>
<p align="center"><script src="../../1.js"></script></a>
    <p align="center"><big><strong>用连接池提高Servlet访问数据库的效率(上)</strong></big></p>

<div align="right">(文/好兵)</div>

<br>
一、实现连接池的意义
<br>
<br>
动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问。连接数据库不仅要开销一定的通讯和内存资源,还必须完成用户验证、安全上下文配置这类任务,因而往往成为最为耗时的操作。当然,实际的连接时间开销千变万化,但1到2秒延迟并非不常见。如果某个基于数据库的Web应用只需建立一次初始连接,不同页面请求能够共享同一连接,就能获得显著的性能改善。
<br>
Servlet是一个Java类。Servlet引擎(它可能是Web服务软件的一部分,也可能是一个独立的附加模块)在系统启动或Servlet第一次被请求时将该类装入Java虚拟机并创建它的一个实例。不同用户请求由同一Servlet实例的多个独立线程处理。那些要求在不同请求之间持续有效的数据既可以用Servlet的实例变量来保存,也可以保存在独立的辅助对象中。
<br>
用JDBC访问数据库首先要创建与数据库之间的连接,获得一个连接对象(Connection),由连接对象提供执行SQL语句的方法。本文介绍的数据库连接池包括一个管理类DBConnectionManager,负责提供与多个连接池对象(DBConnectionPool类)之间的接口。每一个连接池对象管理一组JDBC连接对象,每一个连接对象可以被任意数量的Servlet共享。
<br>
类DBConnectionPool提供以下功能:
<br>
<br>
1) 从连接池获取(或创建)可用连接。
<br>
2) 把连接返回给连接池。
<br>
3) 在系统关闭时释放所有资源,关闭所有连接。
<br>
<br>
此外, DBConnectionPool类还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不超过某个预定值。
<br>
管理类DBConnectionManager用于管理多个连接池对象,它提供以下功能:
<br>
<br>
1) 装载和注册JDBC驱动程序。
<br>
2) 根据在属性文件中定义的属性创建连接池对象。
<br>
3) 实现连接池名字与其实例之间的映射。
<br>
4) 跟踪客户程序对连接池的引用,保证在最后一个客户程序结束时安全地关闭所有连接池。
<br>
<br>
本文余下部分将详细说明这两个类,最后给出一个示例演示Servlet使用连接池的一般过程。
<br>
<br>
<br>
二、具体实现
<br>
<br>
DBConnectionManager.java程序清单如下:
<br>
<br>
001 import java.io.*;
<br>
002 import java.sql.*;
<br>
003 import java.util.*;
<br>
004 import java.util.Date;
<br>
005
<br>
006 /**
<br>
007 * 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接
<br>
008 * 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.
<br>
009 */
<br>
010 public class DBConnectionManager {
<br>
011 static private DBConnectionManager instance; // 唯一实例
<br>
012 static private int clients;
<br>
013
<br>
014 private Vector drivers = new Vector();
<br>
015 private PrintWriter log;
<br>
016 private Hashtable pools = new Hashtable();
<br>
017
<br>
018 /**
<br>
019 * 返回唯一实例.如果是第一次调用此方法,则创建实例
<br>
020 *
<br>
021 * @return DBConnectionManager 唯一实例
<br>
022 */
<br>
023 static synchronized public DBConnectionManager getInstance() {
<br>
024 if (instance == null) {
<br>
025 instance = new DBConnectionManager();
<br>
026 }
<br>
027 clients++;
<br>
028 return instance;
<br>
029 }
<br>
030
<br>
031 /**
<br>
032 * 建构函数私有以防止其它对象创建本类实例
<br>
033 */
<br>
034 private DBConnectionManager() {
<br>
035 init();
<br>
036 }
<br>
037
<br>
038 /**
<br>
039 * 将连接对象返回给由名字指定的连接池
<br>
040 *
<br>
041 * @param name 在属性文件中定义的连接池名字
<br>
042 * @param con 连接对象
<br>
043 */
<br>
044 public void freeConnection(String name, Connection con) {
<br>
045 DBConnectionPool pool = (DBConnectionPool) pools.get(name);
<br>
046 if (pool != null) {
<br>
047 pool.freeConnection(con);
<br>
048 }
<br>
049 }
<br>
050
<br>
051 /**
<br>
052 * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数
<br>
053 * 限制,则创建并返回新连接
<br>
054 *
<br>
055 * @param name 在属性文件中定义的连接池名字
<br>
056 * @return Connection 可用连接或null
<br>
057 */
<br>
058 public Connection getConnection(String name) {
<br>
059 DBConnectionPool pool = (DBConnectionPool) pools.get(name);
<br>
060 if (pool != null) {
<br>
061 return pool.getConnection();
<br>
062 }
<br>
063 return null;
<br>
064 }
<br>
065
<br>
066 /**
<br>
067 * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,
<br>
068 * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
<br>
069 *
<br>
070 * @param name 连接池名字
<br>
071 * @param time 以毫秒计的等待时间
<br>
072 * @return Connection 可用连接或null
<br>
073 */
<br>
074 public Connection getConnection(String name, long time) {
<br>
075 DBConnectionPool pool = (DBConnectionPool) pools.get(name);
<br>
076 if (pool != null) {
<br>
077 return pool.getConnection(time);
<br>
078 }
<br>
079 return null;
<br>
080 }
<br>
081
<br>
082 /**
<br>
083 * 关闭所有连接,撤销驱动程序的注册
<br>
084 */
<br>
085 public synchronized void release() {
<br>
086 // 等待直到最后一个客户程序调用
<br>
087 if (--clients != 0) {
<br>
088 return;
<br>
089 }
<br>
090
<br>
091 Enumeration allPools = pools.elements();
<br>
092 while (allPools.hasMoreElements()) {
<br>
093 DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
<br>
094 pool.release();
<br>
095 }
<br>
096 Enumeration allDrivers = drivers.elements();
<br>
097 while (allDrivers.hasMoreElements()) {
<br>
098 Driver driver = (Driver) allDrivers.nextElement();
<br>
099 try {
<br>
100 DriverManager.deregisterDriver(driver);
<br>
101 log(&quot;撤销JDBC驱动程序 &quot; + driver.getClass().getName()+&quot;的注册&quot;);
<br>
102 }
<br>
103 catch (SQLException e) {
<br>
104 log(e, &quot;无法撤销下列JDBC驱动程序的注册: &quot; + driver.getClass().getName());
<br>
105 }
<br>
106 }
<br>
107 }
<br>
108
<br>
109 /**
<br>
110 * 根据指定属性创建连接池实例.
<br>
111 *
<br>
112 * @param props 连接池属性
<br>
113 */
<br>
114 private void createPools(Properties props) {
<br>
115 Enumeration propNames = props.propertyNames();
<br>
116 while (propNames.hasMoreElements()) {
<br>
117 String name = (String) propNames.nextElement();
<br>
118 if (name.endsWith(&quot;.url&quot;)) {
<br>
119 String poolName = name.substring(0, name.lastIndexOf(&quot;.&quot;));
<br>
120 String url = props.getProperty(poolName + &quot;.url&quot;);
<br>
121 if (url == null) {
<br>
122 log(&quot;没有为连接池&quot; + poolName + &quot;指定URL&quot;);
<br>
123 continue;
<br>
124 }
<br>
125 String user = props.getProperty(poolName + &quot;.user&quot;);
<br>
126 String password = props.getProperty(poolName + &quot;.password&quot;);
<br>
127 String maxconn = props.getProperty(poolName + &quot;.maxconn&quot;, &quot;0&quot;);
<br>
128 int max;
<br>
129 try {
<br>
130 max = Integer.valueOf(maxconn).intValue();
<br>
131 }
<br>
132 catch (NumberFormatException e) {
<br>
133 log(&quot;错误的最大连接数限制: &quot; + maxconn + &quot; .连接池: &quot; + poolName);
<br>
134 max = 0;
<br>
135 }
<br>
136 DBConnectionPool pool =
<br>
137 new DBConnectionPool(poolName, url, user, password, max);
<br>
138 pools.put(poolName, pool);
<br>
139 log(&quot;成功创建连接池&quot; + poolName);
<br>
140 }
<br>
141 }
<br>
142 }
<br>
143
<br>
144 /**
<br>
145 * 读取属性完成初始化
<br>
146 */
<br>
147 private void init() {
<br>
148 InputStream is = getClass().getResourceAsStream(&quot;/db.properties&quot;);
<br>
149 Properties dbProps = new Properties();
<br>
150 try {
<br>
151 dbProps.load(is);
<br>
152 }
<br>
153 catch (Exception e) {
<br>
154 System.err.println(&quot;不能读取属性文件. &quot; +
<br>
155 &quot;请确保db.properties在CLASSPATH指定的路径中&quot;);
<br>
156 return;
<br>
157 }
<br>
158 String logFile = dbProps.getProperty(&quot;logfile&quot;, &quot;DBConnectionManager.log&quot;);
<br>
159 try {
<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -