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
public class T07_ServletFilter implements Filter {
@Override
public void destory() {
System.out.println("T07_ServletFilter의 destroy() 호출됨...");
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc)
throws IOException, ServletException {
System.out.println("T07_ServletFilter doFilter()시작.");
String ipAddress = req.getRemoteAddr();
System.out.println("IP주소 : " + ipAddress
+ "\n포트번호 : " + req.getRemotePort()
+ "\n현재시간 : " + new Date().toString());
fc.doFilter(req, resp);
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
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()메서드 시작");
long startTime = System.nanoTime();
fc.doFilter(req, resp);
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()메서드 호출");
}
}
필터등록 - 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 - 인코딩 필터★
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이 적용되었을 때