2. 리스너 ServletContextListener 만들기
웹 애플리케이션의 시작과 종료 이벤트를 처리할 리스너는 ServletContextListener 인터페이스를 구현해야 한다. 다음 그림은 이번 실습에서 만들 리스너의 계층도이다(그림 1).
▶ contextInitialized() 메서드는 웹 애플리케이션이 시작될 때 호출된다. 공용 객체를 준비해야 한다면, 이 메서드에 작성하면 된다.
▶ contextDestroyed() 메서드는 웹 애플리케이션이 종료되기 전에 호출된다. 자원 해제를 해야 한다면, 이 메서드에 작성하면 된다.
클래스의 이름을 ContextLoaderListener로 정한 이유는, 나중에 스프링 프레임워크를 배울 때 좀 더 이해하기 쉽게 만들기 위함이다. 스프링 프레임워크에서도 같은 역할의 같은 이름을 가진 클래스가 존재한다.
web05 프로젝트에 spms.listeners 패키지를 만든다. 이후 이 패키지에 ContextLoaderListener 클래스를 생성한다(그림 2).
package spms.listeners;
import java.sql.Connection;
import java.sql.DriverManager;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
//import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebListener;
import spms.dao.MemberDao;
//리스너의 배치 : @WebListener 어노테이션 사용
@WebListener
public class ContextLoaderListener implements ServletContextListener {
Connection conn; //인스턴스 변수
@Override
public void contextInitialized(ServletContextEvent event) {
try {
//DB 커넥션 객체 준비
ServletContext sc = event.getServletContext();
Class.forName(sc.getInitParameter("driver"));
conn = DriverManager.getConnection(
sc.getInitParameter("url"),
sc.getInitParameter("username"),
sc.getInitParameter("password"));
//MemberDao 객체 준비하여 ServletContext에 보관
MemberDao memberDao = new MemberDao();
memberDao.setConnection(conn);
sc.setAttribute("memberDao", memberDao);
} catch(Throwable e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {
try {
conn.close(); //데이터베이스와 연결 끊기
} catch (Exception e) {}
}
}
- ServletContextListener 인터페이스의 구현
웹 애플리케이션의 시작과 종료 사건을 처리하려면, 리스너 클래스는 반드시 ServletContextListener 규칙에 따라 작성해야 한다. ContextLoaderListener 클래스는 이 인터페이스를 구현하고 있다.
public class ContextLoaderListener implements ServletContextListener {
...
}
- contextInitialized() 메서드
contextInitialized() 메서드를 보면, AppInitServlet 클래스에 있던 DB 커넥션 객체를 준비하는 코드를 가져왔다.
//DB 커넥션 객체 준비
ServletContext sc = event.getServletContext();
Class.forName(sc.getInitParameter("driver"));
conn = DriverManager.getConnection(
sc.getInitParameter("url"),
sc.getInitParameter("username"),
sc.getInitParameter("password"));
이 리스너의 핵심은 웹 애플리케이션이 시작될 때 MemberDao 클래스 객체를 준비하여 ServletContext에 보관하는 것이다.
//MemberDao 객체 준비하여 ServletContext에 보관
MemberDao memberDao = new MemberDao();
memberDao.setConnection(conn);
sc.setAttribute("memberDao", memberDao);
- contextDestroyed() 메서드
DB 커넥션 객체의 참조 변수 'conn'은 리스너의 인스턴스 변수이다. 인스턴스 변수로 만든 이유는 contextDestroyed() 메서드에서 변수 'conn'을 사용하기 때문이다. 즉 웹 애플리케이션이 종료되기 전에 데이터베이스와의 연결을 끊어야 하기 때문이다.
Connection conn; //인스턴스 변수
...
@Override
public void contextDestroyed(ServletContextEvent event) {
try {
conn.close(); //데이터베이스와 연결 끊기
} catch (Exception e) {}
}
- ContextLoaderListener 클래스의 배치
리스너의 배치는 두 가지 방법이 있다. 첫 번째는 앞의 예제 코드처럼 어노테이션을 사용하는 방법이다. 클래스 선언 위에 @WebListener라고 어노테이션을 붙이면 된다.
//리스너의 배치 : @WebListener 어노테이션 사용
@WebListener
public class ContextLoaderListener implements ServletContextListener {
...
}
두 번째는 DD 파일(web.xml)에 XML 태그를 선언하는 것이다.
<!-- 리스너 선언 -->
<listener>
<listener-class>spms.listeners.ContextLoaderListener</listener-class>
</listener>
앞의 태그를 web.xml 파일의 <web-app> 태그 안에 작성하면 된다. Servlet 2.4 버전 까지는 <listener> 태그를 작성할 때 순서를 지켜야 하는데, <filter-mapping> 태그 다음에, <servlet> 태그 이전에 와야 한다. Servlet 2.5 버전 부터는 순서에 상관없다.
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
67. DB 커넥션풀 (1) (0) | 2022.07.12 |
---|---|
66. ServletContextListener와 객체 공유 (3) (0) | 2022.07.11 |
64. ServletContextListener와 객체 공유 (1) (0) | 2022.07.09 |
63. DAO 만들기 (2) (1) | 2022.07.07 |
62. DAO 만들기 (1) (0) | 2022.07.06 |
댓글