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();
}
}