Java - 18. 서블릿 컨텍스트, 필터

갓김치·2020년 10월 23일
0

고급자바

목록 보기
44/47

Servlet Context

  • 어플리케이션 전체가 같이 쓰는 전역변수와 같은 것
    • doFilter(ServletRequest, ServletResponse, chain)
    • init()
    • destory()
  • 예시
    • 서블릿이 동작할때마다 사용자 로그를 db에 저장하라고 설정해둠
    • 그러면 우리는 각각 서블릿안에 dao를 호출해서 db에 인서트하도록 할 것임
    • 근데 만약 이런 서블릿이 100개라면?? 1억개라면..? 끔찍
    • 그래서 우리는 filter를 이용해야합니다~~

필터

  • 사용자 요청을 가로채서 중간에 작업할거하고 그다음에 서블릿한테 전달하는 역할
  • 필터가 여러개? --> 요청받아서 1번필터하고 2번한테넘기고 2번필터실행하고 3번한테넘길라하는데 필터없네 그럼 이제 진짜 일해야할 서블릿한테 resp, req전달 -> 서블렛 메서드끝나면 -> 다시 마지막 필터일하고 역순으로 1번필터까지 마무리하면 이제 response
  • 필터 순서: web.xml에 기술된 순서

사용 목적

  • 클라이언트의 요청을 수행하기 전에 가로채 필요한 작업을 수행할 수 있다
  • 클라이언트에 응답정보를 제공하기 전에 응답 정보에 필요한 작업을 수행

사용 예

  • 인증 필터
    • 로그인하고 나중에 url에 직접 /main.do 같은 거 치고 들어왔을 때, 이사람이 로그인했는지 안했는지 세션뒤져서 검사
    • 로그인 안했으면 리다이렉트로 로그인하라고 빠꾸먹임
  • 데이터 압축 필터
    • 네트워크 대역폭을 효율적으로 쓰기 위해 response를 압축해서 전송할 수 있게해줌
  • 인코딩 필터
    • 반복되는 인코딩 작업을 필터에서 간편하게
  • 로깅 및 감사처리 필터
    • 권한 관련
  • 이미지 변환 필터 등..

예제1

  • T07_ServletFilter
public class T07_ServletFilter implements Filter {
  @Override
  public void destory() {
  // 필터객체가 웹컨테이너(=톰캣, 서블릿 컨테이너, WAS)에 의해 서비스로부터 제거되기전에 호출됨.
  System.out.println("T07_ServletFilter의 destroy() 호출됨...");
  }

  @Override
  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc)
      throws IOException, ServletException {

    // ServletRequest는 우리가 알고있는 HttpServletRequest의 상위
    // 이 필터는 HttpServletRequest만을 위한 필터가 아니기때문에 매개변수가 Servlet~ 인것 (타입만 상위타입)
    System.out.println("T07_ServletFilter doFilter()시작.");

    // 클라이언트의 IP 주소 가져오기
    String ipAddress = req.getRemoteAddr();
    System.out.println("IP주소 : " + ipAddress 
                  + "\n포트번호 : " + req.getRemotePort()
                  + "\n현재시간 : " + new Date().toString());

    // 필터체인을 실행한다. (req 및 resp 객체 전달)
    fc.doFilter(req, resp); // 두번째 필터로 go go

    System.out.println("T07_ServletFilter doFilter()완료.");
  }

  @Override
  public void init(FilterConfig fc) throws ServletException {
  System.out.println("T07_ServletFilter의 init() 호출됨...");

  // 초기화 파라미터 정보 가져오기
  String initParam = fc.getInitParameter("init-param"); // 우리가 지을 이름
  System.out.println("init-param : " + initParam);

  }
}

필터등록 - web.xml

<filter>
  <filter-name>ServletFilter</filter-name>
  <filter-class>kr.or.ddit.basic.T07_ServletFilter</filter-class>
  <init-param>
    <param-name>init-param</param-name>
    <param-value>로그필터정상작동</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>ServletFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

결과

예제2

  • T07_ServletFilter2.java
public class T07_ServletFilter2 implements Filter{
  @Override
  public void destroy() {
  }

  @Override
  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) 
      throws IOException, ServletException {
    // 서블릿의 수행시간을 알아보는 필터
    System.out.println("T07_ServletFilter2 : doFilter()메서드 시작");

    // 1. 서블릿 시작시간 마크
    long startTime = System.nanoTime();

    // 2. 필터체인을 실행 (req, resp객체 전달)
    fc.doFilter(req, resp); // 세번째 필터로 gogo, 없으면 서블릿 실행

    // 3. endTime - startTime
    System.out.println("수행 시간(ns) : " + (System.nanoTime() - startTime));

    System.out.println("T07_ServletFilter2 : dofilter()메서드 완료");
  }

  @Override
  public void init(FilterConfig config) throws ServletException {
    System.out.println("T07_ServletFilter2 : init()메서드 호출");
  }
} // class

필터등록 - web.xml

<filter>
  <filter-name>ServletFilter2</filter-name>
  <filter-class>kr.or.ddit.basic.T07_ServletFilter2</filter-class>
</filter>
<filter-mapping>
  <filter-name>ServletFilter2</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

결과

    • 첫번째 필터(로그) 수행 후 두번째 필터(수행시간 계산) 작동

예제3 - 인코딩 필터★

  • CustomEncoding.java
public class CustomEncoding implements Filter{
  private String encoding; // 인코딩 정보

  @Override
  public void init(FilterConfig config) throws ServletException {
    encoding = config.getInitParameter("encoding") == null ? "utf-8" : config.getInitParameter("encoding");
  }

  @Override
  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) 
      throws IOException, ServletException{
    System.out.println("request 인코딩 설정 : " + encoding);
    req.setCharacterEncoding(encoding);

    System.out.println("response 인코딩 설정 : " + encoding);
    resp.setCharacterEncoding(encoding);

    fc.doFilter(req, resp); // 다음 필터나 실행되어야 할 서블릿으로 넘김
  }

  @Override
  public void destory() {}
}

필터등록 - web.xml

<filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>kr.or.ddit.basic.CustomEncoding</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>ISO-8859-1</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

결과

    • init-param이 ISO-8859-1로 설정되어있을 때
    • init-param이 null이어서 필터에 설정한 utf-8이 적용되었을 때
profile
갈 길이 멀다

0개의 댓글