2013년 8월 6일 화요일

[오라클자바닷넷교육강좌, ORACLEJAVA]이벤트 리스너를 이용한 로깅, Event Listener Logging

이벤트 리스너를 이용한 로깅 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)   

웹애플리케이션의 이벤트 리스너는 서블릿의 이벤트 리스너 인터페이스를 구현한 자바 클래스이며 ServletContext, HttpSession 객체에 상태 변화가 생길 때 이를 알려 줍니다. 그래서 이것을 이용하면 현재 사이트에 로그인 한 사용자들의 이름을 Display하는 것들이 가능 한겁니다.

이벤트의 유형에 따라 리스너는 여러 개가 지정 가능 하며 개발자는 원하는 이벤트의 유형에 따라 리스너를 구현하면 됩니다.


[ServletContext 관련]
ServletContextListener : ServletContext가 처음 요청에 대해 서비스 할 때 또는 서블릿 컨테이너에 의해 종료 될 때 실행

ServletContextAttributeListener : ServletContext에 속성이 추가 , 제거되는 경우에 실행


[HttpSession 관련]
HttpSessionListener : HttpSession 객체가 생성/소멸 되는 경우에 실행

HttpSessionAttributeListener : 세션에 속성이 추가, 제거되는 경우에 실행



-------------------------
이벤트 리스너 생성
-------------------------

1.        원하는 이벤트 유형과 이벤트 리스너 인터페이스를 구현한 자바 클래스를 생성 (반드시 인자 없는 생성자를 포함해야 합니다.)
2.        listener 요소를 이용하여 web.xml에 선언
3.        웹 애플리케이션 리소스와 함께 필터 클래스를 패키징



----------------------------------
이벤트 리스너 클래스 만들기
----------------------------------

javax.servlet.ServletContextListener 인터페이스를 구현 한 클래스

[LoggingListener.java]

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class LoggingListener implements ServletContextListener{
private ServletContext context = null;

        /**
        * Called by the container before the first request is
        * processed. This is a good time to initialize
        * the logging service.
        */
        public void contextInitialized( ServletContextEvent event ){
                this.context = event.getServletContext( );
                // Initialize the logging service here
                // Log a message that the listener has started
                log( "LoggingListener initialized" );
        }

        /**
        * Called by the container when the ServletContext is about
        * ready to be removed. This is a good time to clean up
        * any open resources.
        */
        public void contextDestroyed( ServletContextEvent event ){
                // Clean up the logging service here
                // Log a message that the LoggingListener has been stopped
                log( "LoggingListener destroyed" );
        }

        /**
        * Log a message to the servlet context application log or
        * system out if the ServletContext is unavailable.
        */
        protected void log( String message ) {
                if (context != null){
                        context.log("LoggingListener: " + message );
                }else{
                        System.out.println("LoggingListener: " + message);
                }
        }
}



동일한 이벤트에 대해 이벤트 리스너를 구현한 클래스가 여러 개 있을 수 있습니다. 또 다른 ServletContext 이벤트 리스너 클래스를 만들어 보도록 합니다.

아래의 예문을 컴파일 하기 위해서는 클래스 패스네 bitmechanic Connection Pool의 jar 파일을 클래스 패스에 위치시켜야 합니다. “DB를 이용하여 로그인 하기” 강좌를 참고하세요~

=============================================================

[DBConnectionPoolListener.java]

import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContext;

//Connection Pool
import com.bitmechanic.sql.*;

public class DBConnectionPoolListener implements ServletContextListener{

        private ServletContext context = null;

        private ConnectionPoolManager cpm;

        /*
    * poolAias는 커넥션 풀을 별칭(Alias)를 줘서 여러 개의 풀을 이용할 수 있게 해줍니다.
    * 이 값을 잘 기억하였다가 LoginDAO.java에서 실제 커넥션을 수립할때 인자로 줘야 합니다.
    */               
    private String POOL_ALIAS = "wink";
       
    private String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver";  // driver
    private String DB_URL = "jdbc:oracle:thin:@localhost:1521:WINK"; // url
    private String DB_USER = "SCOTT"; // id
    private String DB_PASSWORD = "TIGER"; // pw
   
    /* reapConnInterval은 다른 커넥션 풀들과는 틀린 부분이며 중요한
    * 옵션입니다.
    * reapConnInterval은 두가지 경우에 커넥션 풀의 connVector에서 커넥션을 제거하게 됩니다.
    * 1. 풀에서 conn이 나갔는데(checkout) checkoutTimeout 시간안에 돌아오지 않을 경우
    * 2. 풀의 connVector에서 전혀사용되지 않는 상태(idle)로 idleTimeout 시간을 초과할 경우
    * bitmechanic의  커넥션 풀은 최대 Connection 수를 설정해도  30이면 30개 커넥션이 담겨져
    * 있는 것이 아니라 상황에 따라 적절히 조정 하며 전혀 사용이 되지 않으면(Idle)수를 줄입니다.
    * 즉, maxConn이 30이어도 사용특성에 따라 몇 개만이 풀에서 운용될 수도 있다는 이야기 입니다. 
    */
    private int REAP_CONN_INTERVAL = 300; // 여기서부터는 bitmechanic 을 위한 환경 설정 값
   
    /* 커넥션 풀에 담을 수 있는 커넥션의 최대 수 */
    private int MAX_CONNECTION = 20;
   
    /* idleTimeout은  ConnectionPoolManager가 그 간격으로 수행을
    * 하게 되므로 적당한 시간을 설정하면 됩니다.
    * (데이터베이스의 불필요한 Open Session 수를 줄일 수 있슴)
    */
    private int IDLE_TIMEOUT = 60;
   
    /* checkoutTimeout은 너무 짧게 설정해도 안되는게 정상적인 query 수행시간이 길다면
    * 정상적으로 작동하는 query 수행 중에 Connection을 Reaping(제거)해 버리므로
    * 최대의 쿼리 수행 시간보다 크게 설정해야 합니다.
    * 즉 풀에서 나갔다가 돌아오는 시간의 Timeout 설정
    */
    private int CHECKOUT_TIMEOUT = 60;
   
    //Checkout의 최대 수를 지정 합니다         
    private int MAX_CHECKOUT = 15;


        public void contextInitialized( ServletContextEvent event ){
                // Initialize the connection pooling here

                try
                {
                                Class.forName(JDBC_DRIVER);
                               
                                cpm = new ConnectionPoolManager(REAP_CONN_INTERVAL);
                               
                                cpm.addAlias(POOL_ALIAS,JDBC_DRIVER,DB_URL,DB_USER,DB_PASSWORD,MAX_CONNECTION,IDLE_TIMEOUT,CHECKOUT_TIMEOUT, MAX_CHECKOUT);                               

                                log( "Connection Pool initialized" );
                }
                catch ( Exception e1 )
                {
                        log( "Connection Pool initialize fail..." );
                        e1.printStackTrace();
                }
        }
        /**
        * Called by the container when the ServletContext is about
        * ready to be removed. This is a good time to clean up
        * any open resources.
        */
        public void contextDestroyed( ServletContextEvent event ){
                // Shut down the connection pooling and open database connections
        }

        /**
        * Log a message to the servlet context application log or
        * system out if the ServletContext is unavailable.
        */
        protected void log( String message ) {
                if (context != null){
                        context.log("LoggingListener: " + message );
                }else{
                        System.out.println("LoggingListener: " + message);
                }
        }
}

=======================================================

이제 남은 일은 web.xml의 listener 요소에 선언을 하는 일입니다.
Web.xml의 <web-app> 요소 안에 다음을 추가 하세요~

[web.xml]
<listener>
<listener-class>LoggingListener</listener-class>
</listener>

<listener>
<listener-class>DBConnectionPoolListener</listener-class>
</listener>



이제 Tomcat을 재시작 하면 다음과 같은 로그를 콘솔화면에서 볼 수 가 있습니다.

2011. 1. 29 오전 9:58:28 org.apache.catalina.core.ApplicationContext log
정보: LoggingListener: LoggingListener initialized
LoggingListener: Connection Pool initialized

댓글 없음:

댓글 쓰기