728x90

1. ServletContextListener

Servlet/JSP가 들어있는 Web application의 LifeCycle의 event를 관리할 수 있다 ! 

웹 컨테이너 웹 어플리케이션( ServletContext )이 시작·종료되는 시점에 

특정 클래스의 메서드를 실행할 수 있는 기능을 제공

   - 이 기능을 통해 웹 어플리케이션 실행시 필요한 초기화 작업 또는 종료된 후 사용된 자원을 반환하는 작업 등을 수행 

public void contextInitialized(ServletContext sce) //웹 어플리케이션을 초기화할 때 호출
public void contextDestroyed(ServletContext sce) // 웹 어플리케이션을 종료할 때 호출

 

웹 어플리케이션이 시작·종료될 때 ServletContextListener 인터페이스를 구현한 클래스를 실행하려면,  web.xml 파일에 <listener> 태그 <listener-class> 태그를 사용해서 완전한 클래스 이름을 명시하고  <listener> 태그는 반드시 한 개의 <listener-class> 태그를 자식으로 가져야함<listener-class> 태그는 웹 어플리케이션의 시작/종료 이벤트를 처리할 리스너 클래스의 완전한 이름을 값으로 갖음

	<listener>
		<listener-class>com.bbb.framework.listener.DBCPInitListener</listener-class>
	        <!-- src / main / java 기준 -->
	</listener>

 

 

getServletContext() 메서드가 리턴하는 ServletContext 객체는 JSP의 application 기본 객체와 동일한 객체입니다.

   - 이것을 이용하면 web.xml 파일에 설정된 컨텍스트 초기화 파라미터를 구할 수 있음

   - 컨텍스트 초기화 파라미터는 <context-param> 태그를 사용하여 web.xml 파일에 설정

 

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:/spring/context-*.xml</param-value>
    </context-param>
    
     <!-- 
     	예시 2
     -->
    <listener>
        <listener-class>com.bbb.framework.listener.DBCPInitListener</listener-class>
    </listener>
    
    <context-param>
        <param-name>bbbConfig</param-name>
        <param-value>
        jdbcdriver=com.mysql.jdbc.Driver
        jdbcUrl=jdbc:mysql://localhost:3306/bbbDb?characterEncoding=utf-8
        dbUser=bbUser
        dbPass=bbPw
        poolName=bbb
        </param-value>
    </context-param>
    
</web-app>

 

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.dbcp2.*;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import java.io.IOException;
import java.io.StringReader;
import java.sql.DriverManager;
import java.util.Properties;

public class DBCPInitListener implements ServletContextListener {
    
    //웹 어플리케이션을 초기화할 때 호출
    @Override
    public void contextInitialized(ServletContextEvent sce){
        String poolConfig = sce.getServletContext().getInitParameter("bbbConfig");
        Properties prop = new Properties();
        try{
            prop.load(new StringReader(poolConfig));
        }catch (IOException e){
            throw new RuntimeException(e);
        }
        loadJDBCDriver(prop);
        initConnectionPool(prop);
    }
    
    private void loadJDBCDriver(Properties prop){
        String driverClass = prop.getProperty("jdbcdriver");
        try{
            Class.forName(driverClass);
        }catch (ClassNotFoundException ex){
            throw new RuntimeException("fail to load JDBC Driver", ex);
        }
    }
    
    private void initConnectionPool(Properties prop){
        try{
            String jdbcUrl = prop.getProperty("jdbcUrl");
            String username = prop.getProperty("dbUser");
            String pw = prop.getProperty("dbPass");
            
            ConnectionFactory connFactory = new DriverManagerConnectionFactory(jdbcUrl, username, pw);
            
            PoolableConnectionFactory poolableConnFactory = new PoolableConnectionFactory(connFactory, null);
            
            poolableConnFactory.setValidationQuery("select 1");
            
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 5L);
            poolConfig.setTestWhileIdle(true);
            poolConfig.setMinIdle(4);
            poolConfig.setMaxTotal(50);
            
            GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnFactory, poolConfig);
            poolableConnFactory.setPool(connectionPool);
            
            Class.forName("org.apache.commons.dbcp2.PoolingDriver");
            PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
            String poolName = prop.getProperty("poolName");
            driver.registerPool(poolName, connectionPool);
            }catch (Exception e){
                throw new RuntimeException(e);
            }
    }
             
    // 웹 어플리케이션을 종료할 때 호출         
    @Override
    public void contextDestroyed(ServletContextEvent sce){
    
    }
}

 

 

리스너 Exception 처리

public void contextInitialized(ServletContextEvent sce){
    String poolConfig = sce.getServletContext().getInitParameter("bbbConfig");
    Properties prop = new Properties();
    try{
        prop.load(new StringReader(poolConfig));
    }catch (IOException e){
        throw new RuntimeException(e);
    }
    loadJDBCDriver(prop);
    initConnectionPool(prop);
}

 

서블릿 3.0 버전부터  @WebListener 애너테이션을 리스터 클래스에 적용하면,

web.xml 파일에 등록하지 않아도 자동으로 리스너로 등록 가능

@WebListener
public class CListener implements ServletContextListener{
    ...
}

 

 

2. HttpSessionListener

동시 접속자수 파악하는방법

 <!-- 세션 이용한 동시 접속자수 체크 -->
<listener>
    <listener-class>com.jiransnc.framework.listener.SessionCountListener</listener-class>
</listener>
package com.bbbbb.framework.listener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// 동영상 스트리밍시에 최대 세션수 확인을 위해 추가함
public class SessionCountListener implements HttpSessionListener {
	private Log logger = LogFactory.getLog (this.getClass ());
	
	private static int numberOfSessions;
  
    public void sessionCreated(HttpSessionEvent se)  {
        ++numberOfSessions;
        logger.debug("** 생성된 SESSIONID : " +  se.getSession().getId());
        logger.debug("활성화된 세션 수 : " + numberOfSessions);
    }
 
 
    public void sessionDestroyed(HttpSessionEvent se)  {
        --numberOfSessions;
        if(numberOfSessions < 0) {
        	numberOfSessions = 0;
        }
        
        logger.debug("** 제거된 SESSIONID : " +  se.getSession().getId());
        logger.debug("활성화된 세션 수 : " + numberOfSessions);
    }
    
    public static int getNumberOfSessions()
    {
      return numberOfSessions;
    }
     
}

 

 

3. QuartzListener

배치 리스너

<!-- ServletContext 구동시 작동할 batch -->
<listener>
    <listener-class>com.jiransnc.framework.listener.QuartzListener</listener-class>
</listener>

 

 public class QuartzListener implements ServletContextListener{

	public static Scheduler sched = null;
	private final Log logger = LogFactory.getLog (this.getClass ());
	public static Map<String,TriggerKey> triggerMap = new HashMap<String,TriggerKey>();

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put("servletContext", sce.getServletContext());
		logger.debug("================= Start Scheduler =================");
		String cronStr = "";
		
		/* 매월 1일 */ 
		try{ 
			WebApplicationContext wContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
			//MailDao mailDao = (MailDao)wContext.getBean("mailDao");
 
			sched = new StdSchedulerFactory().getScheduler();
			sched.start();
			
			cronStr = "0 0 10 1 * ?"; // 초	분	시	일	월	요일	년(생략 가능)
			JobDetail updateTestJob = JobBuilder.newJob(UpdateTestJob.class).withIdentity("updateTestJob", "batch").usingJobData(jobDataMap).build();
			Trigger updateTestTrigger = TriggerBuilder.newTrigger().withIdentity("updateTestTrigger", "batch").withSchedule(CronScheduleBuilder.cronSchedule(cronStr)).build();
			triggerMap.put("updateTestTrigger",updateTestTrigger.getKey());
			sched.scheduleJob(updateTestJob, updateTestTrigger);
			  
		}catch(Exception e){
			logger.error(ExceptionUtils.getFullStackTrace(e));
		}
		logger.debug("===============================================================");
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		try{ 
			logger.debug("================  Quartz Scheduler Shutdown  =================");
			StdSchedulerFactory.getDefaultScheduler();
			Scheduler defaultscheduler = StdSchedulerFactory.getDefaultScheduler();
			defaultscheduler.shutdown(true);
			if( null != sce && null != sce.getServletContext() ){
				Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
				scheduler.shutdown(true);
				Thread.sleep(1000);
			}
			logger.debug("==============================================================="); 
		}catch(Exception e){logger.error(ExceptionUtils.getFullStackTrace(e));}
	} 
}

 

import javax.servlet.ServletContext;
  
public class UpdateTestJob implements Job
{
	private Log logger = LogFactory.getLog (this.getClass ());
	public void execute(JobExecutionContext context)throws JobExecutionException {

		logger.debug("=================== UpdateTestJob ===================");
		 
		ServletContext servletContext = (ServletContext) context.getMergedJobDataMap().get("servletContext");
		WebApplicationContext wContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		BatchService batchService = (BatchService)wContext.getBean("batchServiceImpl"); 
		 
		batchService.insertTestCheckSchedule();
	} 
}

 

728x90

+ Recent posts