연결 탱크 로 Servlet 데이터베이스 접근 효율 향상

이 글 은 다음 과 같다.
http://www.javanb.com/jsp/1/17150.html
자바 서 블 릿 은 CGI 스 크 립 트 대신 서버 쪽 데이터 처리 기술 을 선 호 합 니 다.Servlet 이 CGI 를 뛰 어 넘 는 장점 중 하 나 는 여러 요청 이 공용 자원 을 공유 할 수 있 을 뿐만 아니 라 서로 다른 사용자 요청 사이 에 지속 적 인 데 이 터 를 유지 할 수 있다 는 것 이다.본 고 는 이 특색 을 충분히 발휘 하 는 실 용적 인 기술, 즉 데이터베이스 연결 탱크 를 소개 한다.
1. 연결 탱크 의 의미 실현
동적 웹 사이트 에 서 는 데이터베이스 에 저 장 된 정보 로 웹 페이지 를 만 들 고 모든 페이지 가 데이터 베 이 스 를 방문 하도록 요청 합 니 다.데이터 베 이 스 를 연결 하려 면 일정한 통신 과 메모리 자원 을 써 야 할 뿐만 아니 라 사용자 검증, 안전 문맥 설정 등 임 무 를 완성 해 야 하기 때문에 가장 시간 이 걸 리 는 작업 이 된다.
물론 실제 연결 시간 비용 은 천변만화 하지만 1 ~ 2 초 지연 은 흔 치 않다.데이터 베 이 스 를 기반 으로 한 웹 애플 리 케 이 션 이 초기 연결 을 한 번 만 만 만 들 면 서로 다른 페이지 가 같은 연결 을 공유 할 수 있 도록 요청 하면 현저 한 성능 개선 을 얻 을 수 있 습 니 다.Servlet 은 자바 클래스 입 니 다.Servlet 엔진 (웹 서비스 소프트웨어 의 일부분 일 수도 있 고 독립 된 추가 모듈 일 수도 있 습 니 다) 시스템 이 시작 되 거나 Servlet 이 처음 요청 되 었 을 때 이 종 류 를 자바 가상 머 신 에 불 러 오고 인 스 턴 스 를 만 듭 니 다.서로 다른 사용자 가 같은 Servlet 인 스 턴 스 의 여러 독립 스 레 드 로 처리 할 것 을 요청 합 니 다.서로 다른 요청 사이 에 지속 적 으로 유효한 데 이 터 를 요구 하 는 데 이 터 는 Servlet 의 실례 변수 로 저장 할 수도 있 고 독립 된 보조 대상 에 저장 할 수도 있다.
JDBC 로 데이터 베 이 스 를 방문 하려 면 먼저 데이터베이스 와 의 연결 을 만 들 고 연결 대상 (Connection) 을 얻어 연결 대상 이 SQL 문 구 를 실행 하 는 방법 을 제공 해 야 한다.
본 고 에서 소개 하 는 데이터베이스 연결 풀 은 관리 클래스 DBConnectionManager 를 포함 하여 여러 개의 연결 풀 대상 (DBConnectionPool 클래스) 과 의 인 터 페 이 스 를 제공 합 니 다. 각 연결 풀 대상 은 JDBC 연결 대상 을 관리 하고 모든 연결 대상 은 임의의 수량의 Servlet 에 의 해 공유 할 수 있 습 니 다.
클래스 DBConnectionPool 은 다음 과 같은 기능 을 제공 합 니 다.
1) 연결 풀 에서 연결 을 가 져 오 거나 만 들 수 있 습 니 다.
2) 연결 을 연결 풀 에 되 돌려 준다.
3) 시스템 이 닫 혔 을 때 모든 자원 을 방출 하고 모든 연결 을 닫 습 니 다.
또한 DBConnectionPool 류 는 잘못된 연결 을 처리 할 수 있 습 니 다 (원래 사용 가능 한 연결 로 등록 되 어 있 었 으 나 시간 초과, 통신 문제 등 어떤 이유 로 사용 할 수 없 었 기 때 문 입 니 다). 또한 연결 풀 의 연결 총수 가 특정한 예 정 된 값 을 초과 하지 않도록 제한 할 수 있 습 니 다.
관리 클래스 DBConnectionManager 는 여러 개의 연결 풀 대상 을 관리 하 는 데 사용 되 며 다음 과 같은 기능 을 제공 합 니 다.
1) JDBC 드라이버 를 불 러 오고 등록 합 니 다.
2) 속성 파일 에 정 의 된 속성 에 따라 연결 풀 대상 을 만 듭 니 다.
3) 연결 탱크 이름과 실례 사이 의 매 핑 을 실현 한다.
4) 클 라 이언 트 프로그램 이 연결 풀 에 대한 인용 을 추적 하여 마지막 클 라 이언 트 프로그램 이 끝 날 때 모든 연결 풀 을 안전하게 닫 도록 합 니 다.
본 논문 의 나머지 부분 은 이 두 가지 유형 을 상세 하 게 설명 하고 마지막 으로 Servlet 이 연결 풀 을 사용 하 는 일반적인 과정 을 보 여 줄 것 이다.
구체 적 실현
DBConnectionManager. java 프로그램 목록 은 다음 과 같 습 니 다.

001 import java.io.*;
002 import java.sql.*;
003 import java.util.*;
004 import java.util.Date;
005
006 /**
007 *    DBConnectionManager                     
008 *     .        getInstance()           .
009 */
010 public class DBConnectionManager {
011 static private DBConnectionManager instance; //     
012 static private int clients;
013
014 private Vector drivers = new Vector();
015 private PrintWriter log;
016 private Hashtable pools = new Hashtable();
017
018 /**
019 *       .           ,     
020 *
021 * @return DBConnectionManager     
022 */
023 static synchronized public DBConnectionManager getInstance() {
024 if (instance == null) {
025 instance = new DBConnectionManager();
026 }
027 clients++;
028 return instance;
029 }
030
031 /**
032 *                    
033 */
034 private DBConnectionManager() {
035 init();
036 }
037
038 /**
039 *                  
040 *
041 * @param name               
042 * @param con     
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 *        (   )  .        ,             
053 *   ,         
054 *
055 * @param name               
056 * @return Connection      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 *         .       ,               ,
068 *          .  ,                 .
069 *
070 * @param name      
071 * @param time          
072 * @return Connection      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 *       ,         
084 */
085 public synchronized void release() {
086 //               
087 if (--clients != 0) {
088 return;
089 }
090
091 Enumeration allPools = pools.elements();
092 while (allPools.hasMoreElements()) {
093 DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
094 pool.release();
095 }
096 Enumeration allDrivers = drivers.elements();
097 while (allDrivers.hasMoreElements()) {
098 Driver driver = (Driver) allDrivers.nextElement();
099 try {
100 DriverManager.deregisterDriver(driver);
101 log("  JDBC     " + driver.getClass().getName()+"   ");
102 }
103 catch (SQLException e) {
104 log(e, "      JDBC       : " + driver.getClass().getName());
105 }
106 }
107 }
108
109 /**
110 *              .
111 *
112 * @param props      
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("      " + poolName + "  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("          : " + maxconn + " .   : " + poolName);
134 max = 0;
135 }
136 DBConnectionPool pool =
137 new DBConnectionPool(poolName, url, user, password, max);
138 pools.put(poolName, pool);
139 log("       " + poolName);
140 }
141 }
142 }
143
144 /**
145 *          
146 */
147 private void init() {
148 InputStream is = getClass().getResourceAsStream("/db.properties");
149 Properties dbProps = new Properties();
150 try {
151 dbProps.load(is);
152 }
153 catch (Exception e) {
154 System.err.println("        . " +
155 "   db.properties 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("        : " + logFile);
164 log = new PrintWriter(System.err);
165 }
166 loadDrivers(dbProps);
167 createPools(dbProps);
168 }
169
170 /**
171 *        JDBC    
172 *
173 * @param props   
174 */
175 private void loadDrivers(Properties props) {
176 String driverClasses = props.getProperty("drivers");
177 StringTokenizer st = new StringTokenizer(driverClasses);
178 while (st.hasMoreElements()) {
179 String driverClassName = st.nextToken().trim();
180 try {
181 Driver driver = (Driver)
182 Class.forName(driverClassName).newInstance();
183 DriverManager.registerDriver(driver);
184 drivers.addElement(driver);
185 log("    JDBC    " + driverClassName);
186 }
187 catch (Exception e) {
188 log("    JDBC    : " +
189 driverClassName + ",   : " + e);
190 }
191 }
192 }
193
194 /**
195 *            
196 */
197 private void log(String msg) {
198 log.println(new Date() + ": " + msg);
199 }
200
201 /**
202 *               
203 */
204 private void log(Throwable e, String msg) {
205 log.println(new Date() + ": " + msg);
206 e.printStackTrace(log);
207 }
208
209 /**
210 *             .            ,      
211 *       .            ,           .
212 */
213 class DBConnectionPool {
214 private int checkedOut;
215 private Vector freeConnections = new Vector();
216 private int maxConn;
217 private String name;
218 private String password;
219 private String URL;
220 private String user;
221
222 /**
223 *        
224 *
225 * @param name      
226 * @param URL     JDBC URL
227 * @param user      ,  null
228 * @param password   ,  null
229 * @param maxConn               
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 *               
242 *
243 * @param con          
244 */
245 public synchronized void freeConnection(Connection con) {
246 //             
247 freeConnections.addElement(con);
248 checkedOut--;
249 notifyAll();
250 }
251
252 /**
253 *             .                    
254 *    ,      .               ,       ,
255 *                  .
256 */
257 public synchronized Connection getConnection() {
258 Connection con = null;
259 if (freeConnections.size() > 0) {
260 //             
261 con = (Connection) freeConnections.firstElement();
262 freeConnections.removeElementAt(0);
263 try {
264 if (con.isClosed()) {
265 log("    " + name+"        ");
266 //       ,          
267 con = getConnection();
268 }
269 }
270 catch (SQLException e) {
271 log("    " + name+"        ");
272 //       ,          
273 con = getConnection();
274 }
275 }
276 else if (maxConn == 0 || checkedOut < maxConn) {
277 con = newConnection();
278 }
279 if (con != null) {
280 checkedOut++;
281 }
282 return con;
283 }
284
285 /**
286 *           .                 
287 *      getConnection()  .
288 *
289 * @param timeout            
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 (InterruptedException e) {}
299 if ((new Date().getTime() - startTime) >= timeout) {
300 // wait()        
301 return null;
302 }
303 }
304 return con;
305 }
306
307 /**
308 *       
309 */
310 public synchronized void release() {
311 Enumeration allConnections = freeConnections.elements();
312 while (allConnections.hasMoreElements()) {
313 Connection con = (Connection) allConnections.nextElement();
314 try {
315 con.close();
316 log("     " + name+"      ");
317 }
318 catch (SQLException e) {
319 log(e, "       " + name+"    ");
320 }
321 }
322 freeConnections.removeAllElements();
323 }
324
325 /**
326 *       
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("   " + name+"        ");
338 }
339 catch (SQLException e) {
340 log(e, "      URL   : " + URL);
341 return null;
342 }
343 return con;
344 }
345 }
346 } 

좋은 웹페이지 즐겨찾기