학습목표
Filter를 이용해 요청 및 응답 데이터를 핸들링 할 수 있다.
Listener를 이용해 다양한 순간의 이벤트를 처리할 수 있다.
Filter
- 클라이언트의 Request가 Servlet에 도달하기 전에 요청 데이터를 원하는 형태로 조작하는 사전처리(Pre Process)
- Servlet에서 나온 응답 데이터를 조작하여 사후처리(Post Process)
- Servlet JSP 이외에 Filter를 만들어 작업을 해놓으면 편한 경우가 있음
Filter의 활용
데이터가 암호화돼있는 경우, 암호 복호화와 같은 작업은 Servlet의 메인 작업이 아니기 때문에 Filter에서 복호화하여 전송
Filter에 구현하여 공통코드가 실행되게 할 수 있음(Servlet에 일일이 쓰는것보다 낫다.)
- Request data의 de-encryping, response data의 encrypting
- Request data의 uncompressing, response data의 compressing
- User 인증 (로그인이 됐냐, 안됐냐 - Session 기술 이용해서 판단) :
- Image 변환
- 각종 정보의 logging
- XML/JSON transformation
Filter API
javax.servlet.Filter : 필터클래스를 구현하기 위해서는 Filter 인터페이스를 implements 해야 함
- void init(FilterConfig filterConfig)
- Servlet Container에 의해 한 번만 호출되며 초기화 기능을 담당
- void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- 실질적인 Filter의 기능이 구현되는 메서드
- void destroy()
- 서비스에서 삭제될 때 마지막으로 호출된다.
- Filter가 서비스에서 삭제되기 전에 Servlet Container에 의해 호출됨
FilterConfig : Filter를 초기화할 때 필터에 정보를 전달하기 위해서 Servlet Container에 의해 사용됨
- String getFilterName() : 필터의 이름을 리턴함
- String getinitParameter(String name) : 초기화 파라미터의 값을 리턴, 파라미터가 없는 경우 null 리턴
- Enumeration getInitParameterNames() : 초기화 파라미터 이름들을 리턴, 파라미터가 없는 경우 null 리턴
- 여러건이 있을 경우 이름을 전체로 받아서 핸들링하기 위함
javax.servlet.FilterChain : 여러 기능의 Filter를 같이 실행하기 위한 클래스
- void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) : 체인에 있는 다음 필터를 호출함
public class OneFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain
chain) throws IOExcption, ServletExcpeion {
// 그 다음 실행시킬 코드가 실행된다. (다른 필터 혹은 다른 서블릿 ... )
// 클라이언트 요청 정보로 사전 필터링
chain.doFilter(request, response);
}
// 응답되기 전의 사후 필터링
public void init(FilterConfig fConfig) throws ServletExcpetion {
}
}
Filter 등록 방법 (1)
web.xml 파일에 Filter 등록
Container에게 우리 Filter를 알려줘야 Filter를 실행시키기 때문에 web.xml 파일에 등록한다.
web.xml 파일에 <filter> 태그로 Filter를 등록하고 <filter-mapping> 태그로 Filter가 실행될 URL 조건 명시
// <filter> 태그로 내가 만든 class를 EduFilter 이름으로 등록해놓고
<filter>
<filter-name>EduFilter</filter-name>
<filter-class>edu.servlet.filter.Edufilter</filter-class>
</filter>
// <filter-mapping>으로 실행되는 URL조건을 명시
<filter-mapping>
<filter-name>EduFilter</filter-name>
<url-pattern>/myweb/*</url-pattern>
</filter-mapping>
Filter 등록 방법 (2)
@WebFilter로 Filter 등록
- Filter 클래스에 @WebFilter 어노테이션을 이용해 Filter 등록
- 어노테이션 정보로 Filter가 실행될 URL 조건 명시
@WebFilter("/*")
public class OneFilter implements Filter {
}
지금처럼 URL 조건이 " /* " 인 경우 모든 클라이언트 요청 시 실행됨
Listener
= Event (특정상황에서 지정된 코드가 발생하는 것) 개념
- Servlet과 관련된 event를 발생하고 발생된 event를 처리할 수 있도록 고안된 기술
- 웹 어플리케이션과 Session이 시작되거나 종료되는 순간의 이벤트 등을 제공함
- 예) 클라이언트 요청이 들어오는 순간 따로 처리할 일이 있다면 Event를 판단하여 특정 무엇인가 실행될 수 있게 만드는 것
Listener 개념
- 이벤트 : 특정 상황이 발생하는 상황
- 이벤트 핸들러 : 이벤트 발생 시 실행되어야 하는 내용을 가지는 객체
- 이벤트 소스 : 이벤트가 발생한 객체
- 이벤트 리스너 : 이벤트 소스와 이벤트 핸들러를 연결하는 역할
ServletContext 관련 이벤트
ServletContext : 웹 애플리케이션을 구동시켜주는 컨테이너
Event Source | Listener | Event |
ServletContext | ServletContextListener | ServletContextEvent |
ServletContextAttributeListener | ServletContextAttributeEvent |
ServletContextEvent
- 웹 애플리케이션의 시작, 종료 시점의 이벤트
- 해당 객체가 최초로 생성되거나 소멸된 객체를 지칭하기 위한 이벤트
ServletContextAttributeEvent
- 해당 객체에 특정 데이터가 담기는 이벤트
- ServletContext에 attribute가 추가되거나 제거되는 순간의 이벤트
HttpSession 관련 이벤트
Event Source | Listener | Event |
HttpSession | HttpSesionListener | HttpSessionEvent |
HttpSesionAttributeListener | HttpSessionBindingEvent | |
HttpSesionBindingListener | HttpSessionBindingEvent | |
HttpSesionActivationListener | HttpSessionEvent |
HttpSessionListender
- HttpSession의 시작, 종료 시점의 이벤트
HttpSessionAttributeListender
- HttpSession에 attribute가 추가 또는 제거되는 순간의 이벤트
HttpSessionBindingListener
BindingListener : Session에 등록되는 데이터
- HttpSession에 add 되는 객체에 등록하는 이벤트
- 객체가 HttpSession에 추가 또는 제거되는 순간의 이벤트
HttpSessionActivationListener
- HttpSession이 활성화 되거나 비활성화 되는 순간의 이벤트
ServletRequest 관련 이벤트
Event Source | Listener | Event |
ServletRequest | ServletRequestListener | ServletRequestEvent |
ServletRequestAttributeListener | ServletRequestAttributeEvent |
ServletRequestEvent
- 클라이언트 요청에 의해 ServletRequest 생성 및 제거되는 순간의 이벤트
ServletRequestAttributeEvent
- ServletRequest에 attribute가 추가되거나 제거되는 순간의 이벤트
Listener 작성
필요한 Listener를 구현한 클래스를 만듦
클래스에 @WebListener 어노테이션을 추가헤서 등록함
@WebListener
public class AppServletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
}
public void contextInitialized(ServletContextEvent arg0) {
}
실습
FilterListenerServlet.java
// 유저에게 입력을 받는 역할
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("euc-kr");
response.setContentType("text/html;charset=EUC-KR");
// 유저 화면 구성을 위해 PrintWriter 객체 준비
PrintWriter out = response.getWriter();
// 화면 구성 -> form Tag 구성
// doGet 화면에서 form Tag의 submit이 클릭되면, post 방식으로 자기 자신을 실행시킴
out.println("<form method='post' action='FilterListenerServlet'>");
out.println("name : <input type='text' name='id'/>");
out.println("<input type='submit'>/");
out.println("</form>");
}
// 유저의 입력을 확인하는 역할
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ID 값 입력 후 submit 눌렀을 대 doPost 실행
request.setCharacterEncoding("euc-kr");
response.setCharacterEncoding("text/html;charset=EUC-KR");
// 유저가 전달한 데이터 획득
String id = request.getParameter("id");
// ID 값을 이후 테스트를 위해 Session에 저장
HttpSession session = request.getSession();
session.setAttribute("id", new String(id));
PrintWriter out = response.getWriter();
out.println(id+" 로 로그인 되었습니다.");
}
OneFilter.java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 클라이언트 요청 시 Servlet 실행 및 해당 Filter의 실행 순서 확인하기 위해 로그 출력
System.out.println("OneFilter before...");
// 클라이언트가 ID 값을 전달 시 Filter에서 ID 값 추출 가능
String id = request.getParameter("id");
// ID 값이 전달되지 않은 상황에서도 실행이 될 수 있기 때문에 null 체크
if(id != null) {
System.out.println(id+" 로 로그인 시도 되었습니다.");
}
// ID 값이 정상이면 로그 출력
// chain.doFilter는 Filter 동작 후 다음 순서가 실행되고 끝나면 되돌아옴
chain.doFilter(request, response);
System.out.println("OneFilter end....");
}
TwoFilter.java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 로그 확인
System.out.println("TwoFilter before ...");
chain.doFilter(request, response);
System.out.println("TwoFilter end ...");
}
화면 확인을 위해 Refresh
정상 작동 시 Servlet 실행 및 작성했던 Filter도 실행됨
요청 시 OneFilter의 앞 부분 실행 -> TwoFilter의 앞 부분 실행 -> Servlet 실행
그 이후 TwoFilter end, OneFilter end 실행
Servlet과 Filter에서 클라이언트 요청 데이터 이용이 가능하다.
AppServletContextListener.java
// 애플리케이션이 컨테이너 종료 시에도 실행되는지 확인
public void contextDestroyed(ServletContextEvent sce) {
//로그로 확인
System.out.println("application 이 종료 되었습니다........");
}
// 컨테이너가 초기화 후 애플리케이션을 처음 실행될 때, contextInitialized
public void contextInitialized(ServletContextEvent sce) {
//로그로 확인
System.out.println("application 이 실행 되었습니다........");
}
CountSessionListener.java
클라이언트가 로그인할 때 Session이 데이터를 담는데, Session이 몇 개가 유지되는지를 가지고 몇 명의 접속자가 있는지를 확인하는 목적의 Listerner 생성
@WebListener
public class CountSessionListener implements HttpSessionAttributeListener {
// Session에 담겨 있는 카운트 수, 지금 로그인한 접속자 수, 유지하기 위한 상수변수 선언
int sessionCount;
public CountSessionListener() {
// TODO Auto-generated constructor stub
}
// Session Arrtibute 값에 add 될 때 호출되는 함수
public void attributeAdded(HttpSessionBindingEvent se) {
sessionCount++;
System.out.println("현재 접속자는 "+sessionCount+" 입니다.");
}
// 제거될 수도 있으므로 Removed 작성
public void attributeRemoved(HttpSessionBindingEvent se) {
sessionCount--;
System.out.println("현재 접속자는 "+sessionCount+" 입니다.");
}
Listener의 컨테이너가 구동되면서 애플리케이션이 초기화 됐을 때, 혹은 종료를 확인하기 위한 목적으로 Tomcat 서버가 Start 상황이었다고 하면 테스트를 원활하게 하기 위해서 Stop 해놓고 테스트 진행
정상 작동 시 서버가 실행되면서 cosole창에 'application이 실행되었습니다.' 라는 로그가 출력됨
= 우리가 만든 Listener가 정상적으로 실행되었다.
'현재 접속자는 1명입니다.' 라고 뜬다면 또다른 Listener가 실행된 것
테스트 진행을 위해 다른 브라우저 실행
다른 브라우저를 통해서 로그인을 시도하면 '로그인이 시도 되었습니다.' 와 '현재 접속자는 2명 입니다.' 문구 등장
--
쿠키랑 세션까진 내가 저만큼 작성은 못해도 재밌네 수준이었는데 필터랑 리스너는 재미없다 ㅎ....
'온라인 강좌 > JSP & Servlet 활용' 카테고리의 다른 글
10차시 JSP 내장 객체 (0) | 2023.06.30 |
---|---|
9차시 JSP 프로그래밍 (0) | 2023.06.30 |
7차시 상태 정보 활용 (0) | 2023.06.30 |
6차시 Servlet 설정 (0) | 2023.06.29 |
5차시 웹 Query 문자열 (0) | 2023.06.29 |