First, realize the meaning of connecting pool
Dynamic Web site often generates a web page with information stored in the database, each page request, resulting in a database access. The connection database not only has to overhead a certain communication and memory resources, but also the user verification, security context is configured to configure such tasks, and it is often the most time consuming operation. Of course, the actual connection time is overhead, but the 1 to 2 seconds delay is not very common. If a database-based web app requires only an initial connection, the different page requests can share the same connection, and a significant performance improvement can be obtained.
Servlet is a Java class. The servlet engine (it may be part of the web service software, or a separate additional module) puts the class into a Java virtual machine when the system start or servlet is requested for the first time, and one instance of the Java virtual machine and creates it. Different users are processed by multiple independent threads of the same servlet instance. Those data that requires continuous effectiveness between different requests can be saved with instance variables of the servlet, or in a separate auxiliary object.
Accessing the database with a JDBC first creates a connection between the database to obtain a connection object (Connection), providing a method of executing a SQL statement by the connection object. The database connection pool described herein includes a management class DBConnectionManager, which is responsible for providing an interface between multiple connection pool objects (DBConnectionPool classes). Each connection pool object manages a set of JDBC connection objects, each connection object can be shared by any number of servlet.
Class DBConnectionPool provides the following features:
1) Get (or create) available connections from the connection pool.
2) Return the connection to the connection pool.
3) Release all resources when the system is turned off, close all connections.
In addition, the DBConnectionPool class can also handle invalid connections (originally registered as available connections, for some reason no longer available, such as timeout, communication issues), and can limit the total number of connections in the connection pool does not exceed a certain predetermined value.
Administration DBConnectionManager is used to manage multiple connection pool objects, which provide the following features:
1) Load and register the JDBC driver.
2) Creating a connection pool object based on the attribute defined in the properties file.
3) Implement the mapping between the connection pool name and its instance.
4) Track the client's reference to the connection pool to ensure that all connected pools are securely turned off at the end of the last client.
The rest of this article will detail the two classes in detail, and finally give an example demonstrate the general process of servlet uses the connection pool.
Second, the specific implementation
The list of DBConnectionManager.java proceedings is as follows:
001 import java.io. *;
002 Import java.sql. *;
003 Import java.util. *;
004 Import Java.util.date;
005
006 / **
007 * Management class DBConnectionManager supports a database connection to one or more demonstrated by the property file
008 * Access to the pool. The client can call the GetInstance () method to access the unique instances of this class.
009 * /
010 Public Class DbconnectionManager {
011 Static Private DBConnectionManager Instance; // Unique Example
012 static private int clients;
013
014 privator drivers = new vector ();
015 prinTwriter log;
016 private hashtable pools = new hashtable ();
017
018 / **
019 * Returns the only instance. If this method is called for the first time, an instance 020 *
021 * @Return DBConnectionManager Unique instance
022 * /
023 static synchronized public dbconnectionManager getinstance () {
024 if (instance == null) {
025 Instance = New dbconnectionManager ();
026}
027 Clients ;
028 returnit;
029}
030
031 / **
032 * Structure function private to prevent other objects from creating this type of instance
033 * /
034 private dbconnectionmanager () {
035 init ();
036}
037
038 / **
039 * Return the connection object to the connection pool specified by the name
040 *
041 * @Param Name The connection pool name defined in the properties file
042 * @Param CON connection object
043 * /
044 Public Void FreeConnection (String Name, Connection Con) {
045 dbconnectionPool pool = (dbconnectionpool) pools.get (name);
046 IF (pool! = Null) {
047 pool.freeConnection (con);
048}
049}
050
051 / **
052 * Get a available (idle) connection. If there is no connection available, and the number of connections is less than the maximum connection
053 * Restriction, create and return new connection
054 *
055 * @Param Name The connection pool name defined in the properties file
056 * @Return Connection Available Connections or Null
057 * /
058 public connection getConnection (String name) {
059 DBConnectionPool Pool = (dbconnectionpool) pools.get (name);
060 IF (pool! = Null) {
061 Return pool.getConnection ();
062}
063 RETURN NULL;
064}
065
066 / **
067 * Get a available connection. If there is no connection available, and the existing connection is less than the maximum number of connections,
068 * is created and returned to a new connection. Otherwise, wait for other thread release connections within the specified time.
069 *
070 * @Param Name connection pool name
071 * @Param Time Waiting time in millisecond
072 * @Return Connection Available Connection or Null
073 * /
074 Public Connection getConnection (String Name, long time) {
075 dbconnectionPool pool = (dbconnectionpool) pools.get (name);
076 IF (pool! = Null) {
077 Return pool.getConnection (Time);
078}
079 RETURN NULL;
080}
081
082 / **
083 * Close all connections, revoke the registration of the driver
084 * /
085 public synchronized void release () {
086 // Wait until the last customer program is called
087 IF (--Clients! = 0) {
088 return;
089}
090
091 Enumeration AllPools = pools.ersion (); 092 While (allPools.hasMoreElements ()) {
093 dbconnectionPool pool = (dbconnectionpool) AllPools.nexTelement ();
094 pool.release ();
095}
096 enumeration alldrivers = drivers.efficient ();
097 While (alldrivers.hasmorelements ()) {
098 Driver Driver = (driver) alldrivers.nextelement ();
099 try {
100 DriverManager.deregisterDriver (driver);
101 log ("Revocation JDBC Driver" Driver.getClass (). GetName () "Registration");
102}
103 catch (sqlexception e) {
104 log (e, "Unable to revoke the following JDBC driver registration:" Driver.getClass (). GetName ());
105}
106}
107}
108
109 / **
110 * Create a connection pool instance based on the specified property.
111 *
112 * @Param PROPS connection pool properties
113 * /
114 Private Void CreatePools (Properties PROPS) {
115 enumeration propnames = props.propertynames ();
116 While (PropNames.hasMoreElements ()) {
117 string name = (string) propNames.nexTelement ();
118 IF (name.endswith (". URL")) {
119 string poolname = name.substring (0, name.lastIndexof ("."));
120 string url = props.getproperty (poolname ".url");
121 IF (URL == NULL) {
122 log ("No Pool" poolname "Specify URL");
123 Continue;
124}
125 string user = props.getProperty (poolname ".user");
126 string password = props.getproperty (poolname ".password");
127 string maxconn = props.getProperty (poolname ".maxconn", "0");
128 int MAX;
129 try {
130 MAX = Integer.Valueof (MaxConn) .intValue ();
131}
132 catch (NumberFormatexception E) {
133 log ("Error's maximum connection limit:" maxconn ". Connection pool:" poolname);
134 MAX = 0;
135}
136 dbconnectionpool pool =
137 New DbConnectionPool (PoolName, URL, User, Password, Max); 138 pools.put (poolname, pool);
139 log ("successfully created the connection pool" poolname);
140}
141}
142}
143
144 / **
145 * Read attribute to complete the initialization
146 * /
147 private vidinit () {
148 InputStream IS = getClass (). GetResourceAsStream ("/ db.properties");
149 Properties dbprops = new profment ();
150 try {
151 dbprops.load (IS);
152}
153 Catch (Exception E) {
154 System.err.Println ("You cannot read the property file."
155 "Please make sure DB.Properties in the path specified by classpath");
156 Return;
157}
158 string logfile = dbprops.getProperty ("logfile", "dbconnectionmanager.log");
159 try {
160 log = new printwriter (new filewriter (logfile, true), true
161}
162 Catch (IOException E) {
163 System.err.Println ("Unable to open the log file:" logfile);
164 log = new printwriter (system.err);
165}
166 loadingDrivers (dbprops);
167 CreatePools (dbprops);
168}
169
170 / **
171 * Loading and register all JDBC drivers
172 *
173 * @Param PROPS attribute
174 * /
175 Private Void LoadDrivers (Properties PROPS) {
176 String DriverClasses = Props.GetProperty ("drivers");
177 StringTokenizer ST = New StringTokenizer (DriverClasses);
178 While (st.hasmorelements ()) {
179 string driverclassname = st.nextToken (). TRIM ();
180 try {
181 Driver Driver = (Driver)
182 Class.Forname (driverclassname) .newinstance ();
183 DriverManager.RegisterDriver (driver);
184 Drivers.AddeElement (driver);
185 log ("successfully registered JDBC driver" driverclassname);
186}
187 catch (Exception E) {
188 log ("Unable to register the JDBC driver:"
189 DriverClassName ", error:" e);
190}
191}
192}
193
194 / **
195 * written text information to log files
196 * /
197 private void log (string msg) {
198 log.println (New Date () ":" msg); 199}
200
201 / **
202 * Writing text information with exceptions to log files
203 * /
204 Private Void log (throwable E, STRING MSG) {
205 log.println (New Date () ":" MSG);
206 E.PrintStackTrace (LOG);
207}
208
209 / **
210 * This internal class defines a connection pool. It can create new connections as required until the predetermined most
211 * Dalian Digital. Before returning to the client, it can verify the validity of the connection.
212 * /
213 Class DbconnectionPool {
214 Private Int Checkedout;
215 private vector freeconnections = new vector ();
216 private int mapconn;
217 private string name;
218 private string password;
219 private string URL;
220 private string user;
221
222 / **
223 * Create a new connection pool
224 *
225 * @Param Name connection pool name
226 * @Param URL Database JDBC URL
227 * @Param User database account, or null
228 * @Param Password password, or null
229 * @Param MaxConn This connection pool allows the maximum number of connections to be established
230 * /
231 Public DBConnectionPool (String Name, String Url, String User, String Password,
232 int maxconn) {
233 this.name = name;
234 this.url = URL;
235 this.user = user;
236 this.password = password;
237 this.maxconn = maxconn;
238}
239
240 / **
241 * Back to the connection to the connection pool
242 *
243 * @Param CON Client Release Connection
244 * /
245 Public Synchronized Void FreeConnection (Connection Con) {
246 // Add the specified connection to the end of the vector
247 FreeConnections.addelement (con);
248 checkedout -;
249 NotifyAll ();
250}
251
252 / **
253 * A available connection from the connection pool. If there is no idle connection, the current connection is less than the maximum connection
254 * Significance, create a new connection. If the connection to the available connection is no longer valid, it is deleted from the vector.
255 * Then recursively call yourself to try new available connections.
256 * /
257 public synchronized connection getConnection () {
258 connection con = NULL;
259 IF (freeConnections.size ()> 0) {
260 // Get the first available connection in the vector
261 con = (connection) freeConnections.FirstElec ();
262 FreeConnections.removeElementat (0);
263 try {
264 if (con?isclosed ()) {
265 log ("From the connection pool" Name "to delete an invalid connection");
266 // Removable calls yourself, try again to get available connections
267 con = GetConnection ();
268}
269}
270 catch (sqlexception e) {
271 log ("From the connection pool" Name "to delete an invalid connection");
272 // Recursive calls yourself, try again to get available connections
273 con = GetConnection ();
274}
275}
276 else if (MaxConn == 0 || Checkedout 277 con = NewConnection (); 278} 279 if (con! = NULL) { 280 checkedout ; 281} 282 return con; 283} 284 285 / ** 286 * Get available connections from the connection pool. You can specify the longest time for the client to wait. 287 * See the previous getConnection () method. 288 * 289 * @Param Timeout in millisecing waiting time limit 290 * / 291 Public Synchronized Connection getConnection (long timeout) { 292 long starttime = new date (). Gettime (); 293 Connection CON; 294 While ((con = getConnection ()) == null) { 295 try { 296 WAIT (TIMEOUT); 297} 298 catch (InterruptedExcection E) {} 299 IF (NEW DATE (). Gettime () - starttime)> = timeout) { 300 // Wait () returned reason is timeout 301 Return NULL; 302} 303} 304 return con; 305} 306 307 / ** 308 * Close all connections 309 * / 310 Public Synchronized Void Release () { 311 enumeration allConnections = freeConnections.efficient (); 312 While (allConnections.haASMoreElements ()) { 313 Connection Con = (Connection) AllConnections.nexTelement (); 314 try { 315 con. close (); 316 LOG ("Close a connection in the connection pool" Name "); 317} 318 catch (SQLEXCEPTION E) { 319 log (e, "Unable to close the connection in the connection pool" Name "); 320} 321} 322 FreeConnections.removeAllelements (); 323} 324 325 / ** 326 * Create a new connection 327 * / 328 private connection newconnection () { 329 Connection Con = NULL; 330 try { 331 IF (user == null) { 332 Con = DriverManager.getConnection (URL); 333} 334 else { 335 con = DriverManager.getConnection (URL, User, Password); 336} 337 log ("Connection Pool" Name "creates a new connection"); 338} 339 catch (SQLEXCEPTION E) { 340 log (e, "Unable to create the connection:" URL); 341 RETURN NULL; 342} 343 return con; 344} 345} 346}