'Java'에 해당되는 글 1건

  1. 2009.06.15 [Java] Connetion Pool
2009. 6. 15. 09:51


Made in 홍승수

=============================== ConnPool.java ==================================

package common.util;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.Vector;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Calendar;

public class ConnPool {
 private Vector connections = new Vector(10); // 커넥션을 벡터에 10개까지 커넥션풀만들수있게 선언한다. 이하 "커넥션풀"이라고하겠음.

    private static ConnPool connPool = new ConnPool();
    private static String m_strMySQL_Driver = null;
    private static String m_strMySQL_Url = null;
    private static String m_strMySQL_User = null;
    private static String m_strMySQL_Pwd = null;
    private static int m_intMySQL_Maxconn = 10; // 연결된 커넥션 갯수 지정
 private boolean _traceOn = false; // 요새는 log4j를 사용해서 로그를 찍는데요.. 변수가 true 아면 로그를 찍을수 있게되어있네요..
 private boolean initialized = false; //

 private static ConnPool instance = null;

 static{
  try{
    loadInfoXml();
        }catch(Exception e){
         System.out.println("기본 설정 XML 파일을 읽어 올 수 없습니다.");
         e.printStackTrace();
        }
 }

 public ConnPool() {
  System.out.println(m_strMySQL_Url);
 }

 /** Use this method to set the maximum number of open connections beforeunused connections are closed.*/

 /**
 * java 디자인패턴중 singleton 패턴으로 항상 이 클래스의 인스턴스를 하나만 유지한다
 */
 public static ConnPool getInstance() {
  if (instance == null) { // ConnPool 의 인스턴스가 없으면
   synchronized (ConnPool.class) { // 동기화 유지해서 동시간대에 다른 유저가 들어와서 인스턴스를 생성하는 것을 막기
    if (instance == null) { // ConnPool 의 인스턴스가 없으면 (한번 더 체큭하는 이유는 동시간대에 다른 유저가 들어왔을 경우가 있으므로
     instance = new ConnPool(); // 인스턴스 생성
    }
   }
  }
  return instance;
 }

 /**
 * 커넥션풀 카운트를 세팅한다.
 * @param count
 */
 public void setOpenConnectionCount(int count) {
  m_intMySQL_Maxconn = count;
 }

 /**
 * 로그 사용 여부를 세팅한다.
 * @param enable
 */
 public void setEnableTrace(boolean enable) {
  _traceOn = enable;
 }

 /** Returns a Vector of java.sql.Connection objects */
 public Vector getConnectionList() {
  return connections;
 }

 /** Opens specified "count" of connections and adds them to the existing pool */
 /**
 * 커넥션을 count 만클 생성한후 커넥션사용관리 클래스(ConnectionObject)에 각각 담는다.
 * 사용여부는 false 이다
 * 이 메서드는 최초 커넥션 기동시 정책에 따라 사용될수도 있고 아닐수도 있다
 */

 public synchronized void setInitOpenConnections(int count) throws SQLException {
  Connection c = null;
  ConnectionObject co = null;
  for (int i = 0; i < count; i++) {
   c = createConnection();
   co = new ConnectionObject(c, false);
   connections.addElement(co);
   trace("ConnectionPoolManager: Adding new DB connection to pool (" + connections.size() + ")");
  }
 }

 /** Returns a count of open connections // 커넥션풀에 있는 커넥션수 */
 public int getConnectionCount() {
  return connections.size();
 }

 /** Returns an unused existing or new connection. */
 /**
 * 존재하는 커넥션중 사용하지 않은 커넥션 또는 새로운 커넥션을 리턴한다.
 */
 public synchronized Connection getConnection() throws Exception {
  if (!initialized) { // initialized == false 이면 최초에 오라클 커넥션을 연결하면
   System.out.println(m_strMySQL_Driver);
   Class c = Class.forName( m_strMySQL_Driver ); // 어떤 드라이버로 커넥션을 연결한다는 정보가 필요합니다. DB2 ,ms sql , my sql
   DriverManager.registerDriver((Driver) c.newInstance()); // Driver의 새로운 인스턴스를 생성하고 DriverManager에 정보를 등록한다.
   initialized = true; // 한번만 등록하게 initialized 를 true 로 변경
  }
  Connection c = null;
  ConnectionObject co = null; // ConnectionObject
  boolean badConnection = false; // 커넥션풀에는 있는 사용하지 않는 커넥션중 올바르게 종료되지 않는 커넥션 여부
  // 커넥션을 얻기 위해 커넥션풀을 검사하기위한 반복문
  for (int i = 0; i < connections.size(); i++) {
   co = (ConnectionObject) connections.elementAt(i); // 커넥션을 얻는다.
   // If connection is not in use, test to ensure it's still valid!
   if (!co.inUse) { // 커넥션을 사용여부를 체크한다.
    try {
     badConnection = co.connection.isClosed(); // 사용하지않는 커넥션인 경우 다시한번 커넥션이 종료되어있는지 체크한다.
     if (!badConnection){ // 커넥션이 종료되지 않았으면
      badConnection = (co.connection.getWarnings() != null); // getWarnings 이 커넥션 객체의 호출에 의한 경고가 있는지 체크 있으면 SQLWaring 없으면 null 반환
     }
    } catch (Exception e) {
     badConnection = true;
     e.printStackTrace();
    }
    // Connection is bad, remove from pool
    if (badConnection) { // 올바르게 종료되지 않은 커넥션이 있으면
     connections.removeElementAt(i); // 커넥션풀에서 제거
     trace("ConnectionPoolManager: Remove disconnected DB connection #" + i);
     continue;
    }

    c = co.connection; // 존재하지만 사용하지 않는 커넥션이 있는경우 커넥션을 얻고
    co.inUse = true; // 커넥션 사용관리 클래스(ConnectionObject)에 이 커넥션을 사용이라고 변경한다.
    trace("ConnectionPoolManager: Using existing DB connection #" + (i + 1));
    break;
   }
  }
  if (c == null) { // 위에서 존재하지만 사용하지 않는 커넥션이 없으면
   c = createConnection(); // 새로운 커넥션을 생성한다.
   co = new ConnectionObject(c, true); // 커넥션사용관리클래스(ConnectionObject)를 생성
   connections.addElement(co); // 커넥션풀에 등록한다.
   trace("ConnectionPoolManager: Creating new DB connection #" + connections.size());
  }
  return c;
 }

 /** Marks a flag in the ConnectionObject to indicate this connection is no longer in use */
 /**
 * 커넥션을 종료시키거나 사용해지를 한다.
 */
 public synchronized void freeConnection(Connection c) {
  if (c == null){ // 커넥션이 없으면 리턴
   return;
  }
  ConnectionObject co = null;
  // 커넥션풀에서 해당 커넥션이 있는지 찾는다.
  for (int i = 0; i < connections.size(); i++) {
   co = (ConnectionObject) connections.elementAt(i);
   if (c == co.connection) {
    co.inUse = false; // 해당커넥션이 있으면 사용해지 한다.
    break;
   }
  }
  // 커넥션풀에 있는 커넥션중에 연결된 커넥션이 보다 큰지 체크해서 크면 커넥션을 종료한다.
  for (int i = 0; i < connections.size(); i++) {
   co = (ConnectionObject) connections.elementAt(i);
   if ((i + 1) > m_intMySQL_Maxconn && !co.inUse){ // 커넥션풀의 크기가 연결된 커넥션의 갯수보다 크고 사용해지인 커넥션 여부체크
    removeConnection(co.connection); // 커넥션을 종료하고 커넥션사용관리클래스(ConnectionObject)에서 제거한다.
   }
  }
 }

 /**
 * ResultSet PreparedStatement 를 닫는다(종료).
 * Connection 은 사용해지( 커넥션사용관리클래스(ConnectionObject)의 inUse) 또는 커넥션을 종료한다.
 * @param c
 * @param p
 * @param r
 */
 public void freeConnection(Connection c, PreparedStatement p, ResultSet r) {
  try {
   if (r != null) r.close();
   if (p != null) p.close();
   freeConnection(c);
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

 /**
 * ResultSet Statement 를 닫는다(종료).
 * Connection 은 사용해지( 커넥션사용관리클래스(ConnectionObject)의 inUse) 또는 커넥션을 종료한다.
 * @param c
 * @param s
 * @param r
 */
 public void freeConnection(Connection c, Statement s, ResultSet r) {
  try {
   if (r != null) r.close();
   if (s != null) s.close();
   freeConnection(c);
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

 /**
 * PreparedStatement 를 닫는다(종료).
 * Connection 은 사용해지( 커넥션사용관리클래스(ConnectionObject)의 inUse) 또는 커넥션을 종료한다.
 * @param c
 * @param p
 */
 public void freeConnection(Connection c, PreparedStatement p) {
  try {
   if (p != null) p.close();
   freeConnection(c);
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

 /**
 * Statement 를 닫는다(종료).
 * Connection 은 사용해지( 커넥션사용관리클래스(ConnectionObject)의 inUse) 또는 커넥션을 종료한다.
 * @param c
 * @param s
 */
 public void freeConnection(Connection c, Statement s) {
  try {
   if (s != null) s.close();
   freeConnection(c);
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

 /** Marks a flag in the ConnectionObject to indicate this connection is no longer in use */
 /**
 * 커넥션을 연결종료하고 커넥션풀에서 제거한다.
 */
 public synchronized void removeConnection(Connection c) {
  if (c == null){ // 커넥션이 널이면 리턴한다.
   return;
  }
  ConnectionObject co = null;
  // 커넥션풀에서 해당 커넥션이 있는지 체크한다.
  for (int i = 0; i < connections.size(); i++) {
   co = (ConnectionObject) connections.elementAt(i);
   if (c == co.connection) { // 해당 커넥션이 있으면
    try {
     c.close(); // 커넥션을 닫는다.(종료)
     connections.removeElementAt(i); // 커넥션풀에서 해당커넥션을 제거한다.
     trace("Removed " + c.toString());
    } catch (Exception e) {
     e.printStackTrace();
    }
    break;
   }
  }
 }

 /**
 * 커넥션을 생성한다.
 * @return
 * @throws SQLException
 */
 private Connection createConnection() throws SQLException {
  Connection con = null;
  try {
   if ( m_strMySQL_User == null){
    m_strMySQL_User = "";
   }
   if (m_strMySQL_Pwd == null){
    m_strMySQL_Pwd = "";
   }
   Properties props = new Properties(); // 프로퍼티를 생성한다.
   props.put("user", m_strMySQL_User); // 유저을 프로퍼티에 put 한다.
   props.put("password", m_strMySQL_Pwd); // 패스워드를 프로퍼티에 put 한다.
   con = DriverManager.getConnection( m_strMySQL_Url, props); // 커넥션을 생성한다.
  } catch (Throwable t) {
   //throw new SQLException(t.getMessage());
   this.fileWrite( "c:/", t.getMessage() );
   this.releaseFreeConnections();

  }
  return con;
 }

 /** Closes all connections and clears out the connection pool */
 /**
 * 사용중이 아닌 모든 커넥션을 종료하고 커넥션풀에서 제거한다.
 */
 public void releaseFreeConnections() {
  trace("ConnectionPoolManager.releaseFreeConnections()");
  Connection c = null;
  ConnectionObject co = null;
  for (int i = 0; i < connections.size(); i++) {
   co = (ConnectionObject) connections.elementAt(i);
   if (!co.inUse){ // 커넥션 사용여부를 체크한다.
    removeConnection(co.connection); // 커넥션을 종료하고 커넥션풀에서 제거한다.
   }
  }
 }

 /** Closes all connections and clears out the connection pool */
 /**
 * 모든 커넥션을 강제종료하고 커넥션풀을 초기화한다.
 */

 public void finalize() {
  trace("ConnectionPoolManager.finalize()");
  Connection c = null;
  ConnectionObject co = null;
  for (int i = 0; i < connections.size(); i++) {
   co = (ConnectionObject) connections.elementAt(i);
   try {
    co.connection.close(); // 커넥션 강제종료
   } catch (Exception e) {
    e.printStackTrace();
   }
   co = null;
  }
  connections.removeAllElements(); // 커넥션풀을 모두 제거한다.
 }

 /**
 * ConnPool 클래스 안에서만 로그를 찍는다.
 * _traceOn 이 true 인 경우만
 * @param s
 */
 private void trace(String s) {
  if (_traceOn){
   System.err.println(s);
  }
 }

 public static String getData1(Element element, String tagName){
  NodeList list = element.getElementsByTagName(tagName);
  if( list != null ){
   Element cElement = (Element)list.item(0);
   if(cElement.getFirstChild()!=null){
    return cElement.getFirstChild().getNodeValue();
   } else{
    return "-";
   }
  }
  return "";
    }

 public static void loadInfoXml() throws Exception{
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
     DocumentBuilder builder = factory.newDocumentBuilder();

     Document xmlDoc = builder.parse("./Info.xml");
     Element root = xmlDoc.getDocumentElement();
     NodeList list = root.getElementsByTagName("sysInfo");
     for(int i=0; i<list.getLength();i++)
     {
             Element element = (Element)list.item(i);

             m_strMySQL_Driver = getData1(element, "MYSQL_DRIVER");
             m_strMySQL_Url = getData1(element, "MYSQL_DB");
             m_strMySQL_User = getData1(element, "MYSQL_USER");
             m_strMySQL_Pwd = getData1(element, "MYSQL_PWD");
             m_intMySQL_Maxconn = Integer.parseInt( getData1(element, "MYSQL_MAXCONN") );

             System.out.println( m_strMySQL_Driver );
             System.out.println( m_strMySQL_Url );
             System.out.println( m_strMySQL_User );
             System.out.println( m_strMySQL_Pwd );
             System.out.println( m_intMySQL_Maxconn );
     }
 }
 //----------------------------------------- log 파일 쓰기 -------------------------------------
 /**
  *
  * @param str
  * @return
  */
  public String fileNameCheck( String str ) {

    String temp = "";
    int i = str.length();
    temp = str.substring( i-4, i );
    return temp;
 }

  /*****************************************************************/

  /********logFile파일 만들기******************************************/
  public void fileWrite( String directory, String str ){

   File file = new File( directory + fileName() );

   java.io.FileOutputStream writer;
   java.io.RandomAccessFile raf = null;

   try{

    String strLine = "";

    raf = new java.io.RandomAccessFile(file, "rw");
    raf.seek(raf.length());

    writer = new java.io.FileOutputStream(raf.getFD());

    strLine = new String( str +"\r\n" );
    writer.write(strLine.getBytes());
    raf.close();

   }catch( Exception e ){
    e.printStackTrace();
   }

  }
  /*****************************************************************/

  /*******logFile불러오기*********************************************/
  public String loadFile( String directory, String filename) {

   //Vector vec = new Vector();

   StringBuffer buffer = new StringBuffer();
   BufferedReader in = null;

   //LogfileData logFileData = new LogfileData();

   try {
    in = new BufferedReader(new FileReader( directory + filename),1024);
    String str=null;

    while ((str=in.readLine()) != null){

     buffer.append( str +"\r\n" );
    // LogFile file = logFileData.logFile( str );

    // vec.add( file );

    }

    in.close();

   }catch (IOException ie){
    System.err.println("File Read Error : "+ie.getMessage());
   }

   return buffer.toString();
  }
  /*****************************************************************/

  /*******현재 시간 나타내기******************************************/
  public String nowTime(){

   String temp = "";

   Calendar calender;

   String year, month, date, hour, minute, sec;

   calender = Calendar.getInstance();

   calender.get(Calendar.AM_PM);

   year = String.valueOf( calender.get(Calendar.YEAR) );
   month = String.valueOf( calender.get(Calendar.MONTH) + 1 );
   date = String.valueOf( calender.get(Calendar.DATE) );
   hour = String.valueOf( calender.get(Calendar.HOUR_OF_DAY) );
   minute = String.valueOf( calender.get(Calendar.MINUTE) );
   sec = String.valueOf( calender.get(Calendar.SECOND) );


   temp =  year + "년" + month + "월" + date + "일" + hour + "시" + minute + "분" + sec +"초";

   return temp;

  }
  /*****************************************************************/

  public String fileName(){

   String temp = "";

   Calendar calender;

   String year, month, date;

   calender = Calendar.getInstance();
   year = String.valueOf( calender.get(Calendar.YEAR) );
   month = String.valueOf( calender.get(Calendar.MONTH) + 1 );
   date = String.valueOf( calender.get(Calendar.DATE) );

   temp = year + "년" + month + "월" + date + "일.txt";

   return temp;
  }

 public static void main( String[] args ){
  ConnPool aaa = new ConnPool();
  try {
   for( int i = 0; i < 200; i++ ){
    Connection con = aaa.getConnection();
    System.out.println( i + " ======================> " + con );
   }
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

/**
* 커넥션풀 사용여부 관리 클래스
* @author ZZ08257
*
*/
class ConnectionObject {
 public java.sql.Connection connection = null;
 public boolean inUse = false;

 public ConnectionObject(Connection c, boolean useFlag){
  connection = c;
  inUse = useFlag;
 }
}

Posted by Kimos