headfisrt servlet&jsp chapter 13
TRANSCRIPT
필터와 래퍼 Servlet&JSP 13장
구현은 다 했는데…
• 자꾸만 요구사항이 변한다.
• 이번에는 모든 사용자에 대해서 정보를 추적하라고…
• 어떻게?
구현 변화
• 많고 많은 서블릿 정보를 다 수정할 수 있겠지
• 너무 귀찮다.
• 어떻게 하지?
필터
• 자바 컴포넌트
• 서블릿으로 요청이 넘어가기 전에 요청을 가로채거나
• 서블릿에서 뷰로 응답이 넘어가기 전에 응답을 가로채거나
설정
• 모듈식으로 DD에 설정한다. <filter> <filter-name>BeerReq</filter-name> <filter-class>com.example.web.BeerReqFilter</filter-class> <init-param> <param-name>LogFileName</param-name> <param-value>UserLog.txt</param-value> </init-param></filter> 얘는 없어도 됨
URL과 필터 매핑
<filter-mapping> <filter-name>BeerReq</filter-name> <url-pattern>*.do</url-pattern></filter-mapping>
얘가 앞에 filter-name 하고 같아야 함
서블릿 이름과 필터 매핑
! <filter-mapping> <filter-name>BeerReq</filter-name> <servlet-name>AdviceServlet</servlet-name> </filter-mapping>
얘가 앞에 filter-name 하고 같아야 함
요청 디스패쳐로는?
!<filter-mapping> <filter-name>BeerReq</filter-name> <url-pattern>*.do</url-pattern> <dispatcher>REQUEST</dispatcher><— REQ —> <dispatcher>INCLUDE</dispatcher><— INC —> <dispatcher>FORWARD</dispatcher><— FOR —></filter-mapping>
Filter 실행 순서
• URL -> servlet-name 순으로
• 디테일 한 것부터 매칭됨
필터를 만들자package com.example.web;!import java.io.IOException;!import javax.servlet.*;import javax.servlet.http.HttpServletRequest;!public class BearRequestFilter implements Filter{ private FilterConfig fc; public void init(FilterConfig config) throws ServletException { this.fc = config; } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { HttpServletRequest httpReq = (HttpServletRequest) req; String name = httpReq.getRemoteUser(); if(name != null) { fc.getServletContext().log("User " + name + "is updating"); } chain.doFilter(req, resp); } public void destroy() { }}
응답 필터
• 이전 것이 요청 필터임
• 필터는 Request를 가로챌 수도 있지만 Response를 가로챌 수도 있음
• doFilter 메소드 이후에 response를 가로채는 로직을 사용할 수 있음
Is it OK?
• 출력은 필터를 기다려주지 않고 떠나가버림림
• 그러므로 doFilter 이후에 Response를 낚아채는 코드를 작성해도 이미 출력해버림
• 그럼 어떻게?
Servlet Wrapper• HttpsServletResponse를 직접 구현하는건 무리
• Wrapper 클래스를 구현함
• Wrapper 클래스는 원래 response객체를 wrapping해서, 들어오는 요청을 이 객체로 위임함
• ServletRequestWrapper/HttpServletRequestWrapper/ServletResponseWrapper/HttpServletResponseWrapper
Wrapper
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { HttpServletRequest httpReq = (HttpServletRequest) req; String name = httpReq.getRemoteUser(); if(name != null) { fc.getServletContext().log("User " + name + "is updating"); } CompressionResponseWrapper wrappedResp = new CompressionResponseWrapper(response); chain.doFilter(req, wrappedResps);}
Compression…
public class CompressionResponseWrapper extends HttpServletResponseWrapper{ @Override public ServletOutputStream getOutputStream() throws IOException { return super.getOutputStream(); }}!이 클래스 내에서 재정의 할 함수들을 재정의하면 됨