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

📄 406.html

📁 关于jsp的一些好文章 主要介绍一些关于JSP的应用技巧方面的东西
💻 HTML
📖 第 1 页 / 共 2 页
字号:

<STYLE type=text/css>
<!--
body,td { font-size:9pt;}
hr { color: #000000; height: 1px}
-->
</STYLE>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>精选文章 >> Servlet >> 用连接池提高Servlet访问数据库的效率</title>
</head>
<body >

<p><IMG SRC="../image/jsp001_middle_logo.gif" WIDTH="180" HEIGHT="60" BORDER=0 ALT=""></p>

<table width=100% bgcolor="#cccccc" align=center cellpadding="2" cellspacing="0" border=1 bordercolorlight="#000000" bordercolordark="#FFFFFF">
<tr bgcolor="#EFF8FF"><td>
<a href=http://www.jsp001.com/list_thread.php?int_attribute=2>精选文章</a>
>> <a href=http://www.jsp001.com/list_thread.php?forumid=9&int_attribute=2>Servlet</a>
>> 用连接池提高Servlet访问数据库的效率 [<a href=http://www.jsp001.com/forum/showthread.php?goto=newpost&threadid=406>查看别人的评论</a>]<br>

<hr><p>由 macro 发布于: 2001-02-13 16:29</p><p><img src="images/icons/icon6.gif" alt="Cool" border=0> </p><p><br>作者:好兵<br><br>Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本。Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据。本文介绍一种充分发挥该特色的实用技术,即数据库连接池。<br><br><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("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");<br>102 }<br>103 catch (SQLException e) {<br>104 log(e, "无法撤销下列JDBC驱动程序的注册: " + 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(".url")) {<br>119 String poolName = name.substring(0, name.lastIndexOf("."));<br>120 String url = props.getProperty(poolName + ".url");<br>121 if (url == null) {<br>122 log("没有为连接池" + poolName + "指定URL");<br>123 continue;<br>124 }<br>125 String user = props.getProperty(poolName + ".user");<br>126 String password = props.getProperty(poolName + ".password");<br>127 String maxconn = props.getProperty(poolName + ".maxconn", "0");<br>128 int max;<br>129 try {<br>130 max = Integer.valueOf(maxconn).intValue();<br>131 }<br>132 catch (NumberFormatException e) {<br>133 log("错误的最大连接数限制: " + maxconn + " .连接池: " + 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("成功创建连接池" + 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("/db.properties");<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("不能读取属性文件. " +<br>155 "请确保db.properties在CLASSPATH指定的路径中");<br>156 return;<br>157 }<br>158 String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log");<br>159 try {<br>160 log = new PrintWriter(new FileWriter(logFile, true), true);<br>161 }<br>162 catch (IOException e) {<br>163 System.err.println("无法打开日志文件: " + logFile);<br>164 log = new PrintWriter(System.err);<br>165 }<br>166 loadDrivers(dbProps);<br>167 createPools(dbProps);<br>168 }<br>169<br>170 /**<br>171 * 装载和注册所有JDBC驱动程序<br>172 *<br>173 * @param props 属性<br>174 */<br>175 private void loadDrivers(Properties props) {<br>176 String driverClasses = props.getProperty("drivers");<br>177 StringTokenizer st = new StringTokenizer(driverClasses);<br>178 while (st.hasMoreElements()) {<br>179 String driverClassName = st.nextToken().trim();<br>180 try {<br>181 Driver driver = (Driver)<br>182 Class.forName(driverClassName).newInstance();<br>183 DriverManager.registerDriver(driver);<br>184 drivers.addElement(driver);<br>185 log("成功注册JDBC驱动程序" + driverClassName);<br>186 }<br>187 catch (Exception e) {<br>188 log("无法注册JDBC驱动程序: " +<br>189 driverClassName + ", 错误: " + e);<br>190 }<br>191 }<br>192 }<br>193<br>194 /**<br>195 * 将文本信息写入日志文件<br>196 */<br>197 private void log(String msg) {<br>198 log.println(new Date() + ": " + msg);<br>199 }<br>200<br>201 /**<br>202 * 将文本信息与异常写入日志文件<br>203 */<br>204 private void log(Throwable e, String msg) {<br>205 log.println(new Date() + ": " + msg);<br>206 e.printStackTrace(log);<br>207 }<br>208<br>209 /**<br>210 * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最<br>211 * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.<br>212 */<br>213 class DBConnectionPool {<br>214 private int checkedOut;<br>215 private Vector freeConnections = new Vector();<br>216 private int maxConn;<br>217 private String name;<br>218 private String password;<br>

⌨️ 快捷键说明

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