코딩항해기
[JSP] Servlet - 필터 Filter 본문
[JSP] Servlet - 리스너 Listener
리스너 Listener컨테이너에서 발생하는 이벤트를 모니터링하다가 특정 이벤트가 발생하면 실행되는 특수한 서블릿으로, '이벤트 리스너(Event Listener)'라고도 한다. 웹 애플리케이션 실행에 필요한
minibcake.tistory.com
not POJO인 Servlet에는 리스너와 필터가 있다. 리스너는 지난 게시글에서 정리했고, 이번에는 필터를 정리한다.
먼저 POJO란 오래된 방식의 간단한 자바 오브젝트로 종속되지 않은 순수한 자바 객체를 의미한다.
즉, not POJO란, 무언가에 종속된 자바 객체라는 것을 의미한다.
[JAVA] POJO
POJO (Plain Old Java Object)오래된 방식의 간단한 자바 오브젝트라는 말로서 Java EE 등의 중량 프레임워크들을 사용하게 되면서 해당 프레임워크에 종속된 "무거운" 객체를 만들게 된 것
minibcake.tistory.com
리스너와 필터 차이
리스너 | 모니터링, 감지하는 서블릿 (특정 순간에 한 번 실행) |
필터 | 모든 특정 요청에 대해 항상 수행되는 서블릿 (지정된 행동마다 항상 실행) |
필터 Filter
클라이언트로부터 서버로 요청이 들어가기 전에 서블릿을 거쳐 필터링하는 것을 필터라고 한다.
일반 Servlet은 http에 최적화 되어있어 HttpServletRequest과 HttpServletResponse를 인자로 받는데 반해
필터는 ServletRequest와 ServletResponse를 인자로 받는 차이가 있다.
(HttpServletRequest보다 ServletRequest가 더 상위 클래스이다. 필터는 모든 요청에 사용되기 때문에 인자가 다르다.)
필터는 주로 보안 체크, 인가, 허가, 인증, 인코딩, 디코딩 과정을 진행하기 위해 사용된다.
이러한 기능들을 서블릿이 호출되기 전에 전처리 되게 하고 싶거나 호출되고 난 뒤에 후처리하고 싶을 때 필터로 구현하면 된다.
필터는 시작을 감지하는 메서드, 끝을 감지하는 메서드, 항상 실행되는 메서드 3개의 구조로 이뤄져있는데, 이때 시작과 끝을 감지하는 메서드는 리스너에서 처리하는 것이 더욱 일반적이므로 잘 사용되지 않는다.
필터 구조
//어노테이션을 달면 web.xml에서 중복되는 태그를 삭제해야한다.
@WebFilter("*.do") //.do로 끝나는 요청이 올 때마다 프론트 컨트롤러로 가기 전에 필터를 거침
public class VaildFilter extends HttpFilter implements Filter {
//기본생성자
public VaildFilter() {
super();
// TODO Auto-generated constructor stub
}
//종료 시
public void destroy() {
// TODO Auto-generated method stub
}
//항상 실행
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("필터가 호출됨");
//여러 필터를 거칠 수 있으므로 자동으로 다음 필터를 호출하는 역할을 한다.
//다음 필터가 없으면 원래하던 요청을 마저 수행한다.
chain.doFilter(request, response);
}
//시작 시
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
* 주의 : 어노테이션을 사용하면 web.xml에 자동으로 삽입된 태그를 삭제해야한다. (중복된 기능을 하는 태그만)
web.xml
<filter>
<display-name>VailadFilter</display-name>
<filter-name>VailadFilter</filter-name>
<filter-class>controller.common.VailadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>VailadFilter</filter-name>
<url-pattern>/VailadFilter</url-pattern>
</filter-mapping>
사용 예시
만약 마이페이지를 들어갈 때 권한을 확인하는 로직을 작성하고 싶다면, 프론트 컨트롤러처럼 요청을 추출한 후, 해당 요청에 대한 조건을 걸면된다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("필터가 호출됨");
// 사용자가 무슨 요청을 했는지 추출 및 확인
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
String cp = httpRequest.getContextPath();
String command = uri.substring(cp.length());
System.out.println("filter command : "+command);
//권한 확인 로직
if(command.equals("/mypagePage.do")) {//사용자가 mypagePage.do 요청을 하면
if(httpRequest.getSession().getAttribute("loginInfo") == null) {//로그인 안 했는지 확인
//에러페이지로 보내기 (권한 없는 접근)
System.out.println("로그인 안됨 : RuntimeException");//NPE를 많이 사용한다!
throw new RuntimeException();
}
}
//여러 필터를 거칠 수 있으므로 자동으로 다음 필터를 호출하는 역할을 한다.
//다음 필터가 없으면 원래하던 요청을 마저 수행한다.
chain.doFilter(request, response);
}
이때 권한이 없는 경우 에러 페이지로 보내기 위해 오류를 발생시키는 방법을 사용했는데, 이럴 경우 try catch를 하지 않아도 되는 비체크 예외를 사용해야한다. 비체크 예외로는 NullPointerException(NPE)을 많이 사용한다고 한다.
필터의 라이프 사이클
필터는 서블릿과 비슷한 라이프사이클을 가지며, 생성, 초기화, 필터, 종료의 4단계가 있다.
서블릿 컨테이너는 필터 객체가 초기화 파라미터를 접근하는데 사용하는 환경설정 객체(Filter Config)의 레퍼런스를 제공한다. 서블릿 컨테이너가 필더의 init()메서드를 호출하면 필터 인터체이스는 바로 요청을 처리할 수 있는 상태가 된다.
(로그를 찍어보면 서버가 시작될 때 자동 호출되는 것을 확인할 수 있다.)
필터 기능은 doFilter()메서드를 통해 처리되며 모든 요청에 대한 처리가 끝나면 destory()메서드가 호출되어 비활성화 상태로 변경된다.
필터 체인
필터는 연속적인 작용을 수행하기 때문에 여러 필터를 거칠 수 있다. 이 chain.doFilter()를 기준으로 앞이 전처리, 뒤가 후처리가 된다. 이 전처리 후처리는 보완과정에서 구분해 사용된다고 한다.
필터는 한 번만 수행되는 것이 아니라 요청받을 때 수행되고, chain.doFilter()를 만나 다음 부분으로 넘어간다. 그 다음 모든 부분이 수행되면 다시 필요로 완전한 응답객체와 함께 제어권이 넘어와 후처리 부분을 실행한다.
@WebFilter("*.do") //.do로 끝나는 요청이 올 때마다 프론트 컨트롤러를 가기 전에 필터를 거침
public class VaildFilter extends HttpFilter implements Filter {
//기본생성자
public VaildFilter() {
super();
}
//종료 시
public void destroy() {
System.out.println("로그 : 필터 종료");
}
//항상 실행
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("로그 : 필터 실행 (전)");
//사용자가 무슨 요청을 했는지 추출 및 확인
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
String cp = httpRequest.getContextPath();
String command = uri.substring(cp.length());
System.out.println("filter command : "+command);
//권한 확인 로직
if(command.equals("/mypagePage.do")) {//사용자가 mypagePage.do 요청을 하면
if(httpRequest.getSession().getAttribute("loginInfo") == null) {//로그인 안 했는지 확인
//에러페이지로 보내기 (권한 없는 접근)
System.out.println("로그인 안됨 : RuntimeException");//NPE를 많이 사용한다!
throw new RuntimeException();
}
}
//여러 필터를 거칠 수 있으므로 자동으로 다음 필터를 호출하는 역할을 한다.
//다음 필터가 없으면 원래하던 요청을 마저 수행한다.
chain.doFilter(request, response);
//후처리
System.out.println("로그 : 필터 실행 (후)");
}
//시작 시
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("로그 : 필터 시작");
}
}
'JSP' 카테고리의 다른 글
[JSP] 서버 시작할 때 크롤링한 샘플데이터 추가하기 (2) | 2024.09.12 |
---|---|
[JSP] JDBC - 필터 검색 (Model 파트/HashMap 사용) (0) | 2024.09.08 |
[JSP] alert창 띄우고 페이지 전환하기 (0) | 2024.09.04 |
[JSP] Servlet - 리스너 Listener (0) | 2024.09.02 |
[JSP] DB에 있는 게시글 화면에 보여주기 (2) | 2024.08.31 |