'Java'에 해당되는 글 1건
- 2009.06.15 [Java] Connetion Pool
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;
}
}