서블릿에 대한 사전 처리 작업 + 사후 처리 작업
브라우저가 서버에게 HTTP 요청
서블릿 컨테이너에게 요청된 정보를 필터가 가로채고 사전처리
필터가 서블릿 컨테이너를 호출
서블릿 컨테이너가 실행
필터가 사후처리
브라우저에게 HTTP 응답
web.xml
읽어들이면?TimeCheckFilter
바로 생성web.xml
파일에 자동 등록 <filter>
<display-name>timeCheck</display-name>
<filter-name>timeCheck</filter-name>
<filter-class>com.ssamz.web.common.TimeCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>timeCheck</filter-name>
<url-pattern>/getBoardList.do</url-pattern>
</filter-mapping>
public class TimeCheckFilter extends HttpFilter implements Filter {
public TimeCheckFilter() {
System.out.println("===> TimeCheckFilter 생성");
}
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("===> init() 호출");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("===> doFilter() 호출");
chain.doFilter(request, response);
}
public void destroy() {
System.out.println("===> destroy() 호출");
}
}
실행 결과
톰캣 구동하자마자 TimeCheckFilter
생성
필터 생성 직후 init()
호출
브라우저에서 url로 입력 시 , doFilter()
호출
삭제되고 리로딩 되는 순간 destory()
호출
login.do
요청시에만 필터 실행되도록 설정 <filter-mapping>
<filter-name>timeCheck</filter-name>
<url-pattern>/login.do</url-pattern>
</filter-mapping>
public class TimeCheckFilter extends HttpFilter implements Filter {
public TimeCheckFilter() {
System.out.println("===> TimeCheckFilter 생성");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("---[ 사전 처리 ]---");
chain.doFilter(request, response);
System.out.println("---[ 사후 처리 ]---");
}
}
브라우저가 서버에게 요청
필터 즉, doFilter()
가 호출
여기서 사전처리
chain.doFilter()
에서 서블릿 호출
해당 코드 주석 처리하면? 서블릿 실행 안됨
서블릿 실행
실행 후 사후 처리
브라우저에게 응답 전송
public class TimeCheckFilter extends HttpFilter implements Filter {
public TimeCheckFilter() {
System.out.println("===> TimeCheckFilter 생성");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// System.currentTimeMillis()가 호출될 때의 시간 정보를 return
long beforeTime = System.currentTimeMillis();
chain.doFilter(request, response); // Servlet 호출
// System.currentTimeMillis()가 호출한 후의 시간 정보를 return
long afterTime = System.currentTimeMillis();
System.out.println("서블릿 실행에 소요된 시간 : " + (afterTime - beforeTime) + "(ms)초");
}
}
👉 이때 여러 서블릿이 있다면? 속도가 느린 서블릿을 찾아서 속도를 빠르게 해줄 수 있음
*.do
모든 서블릿 동작하게 <filter-mapping>
<filter-name>timeCheck</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
@
어노테이션 사용@WebFilter(urlPatterns = "*.do")
public class TimeCheckFilter extends HttpFilter implements Filter {
public TimeCheckFilter() {
System.out.println("===> TimeCheckFilter 생성");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
long beforeTime = System.currentTimeMillis(); // System.currentTimeMillis()가 호출될 때의 시간 정보를 return
chain.doFilter(request, response); // Servlet 호출
long afterTime = System.currentTimeMillis(); // System.currentTimeMillis()가 호출한 후의 시간 정보를 return
System.out.println("서블릿 실행에 소요된 시간 : " + (afterTime - beforeTime) + "(ms)초");
}
}
public class CharacterEncodingFilter extends HttpFilter implements Filter {
private String encoding;
public CharacterEncodingFilter() {
System.out.println("===> CharacterEncodingFilter() 생성");
}
public void init(FilterConfig fConfig) throws ServletException {
encoding = fConfig.getInitParameter("encoding");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 모든 서블릿 인코딩 처리
request.setCharacterEncoding(encoding);
chain.doFilter(request, response);
}
}
👉 인코딩 설정 한번에! 아주 간편
@
어노테이션 사용 <display-name>BoardWeb</display-name>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
@WebFilter(urlPatterns = "*.do", initParams = @WebInitParam(name = "encoding", value = "UTF-8"))
public class CharacterEncodingFilter extends HttpFilter implements Filter {
private String encoding;
public CharacterEncodingFilter() {
System.out.println("===> CharacterEncodingFilter() 생성");
}
public void init(FilterConfig fConfig) throws ServletException {
encoding = fConfig.getInitParameter("encoding");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 모든 서블릿 인코딩 처리
request.setCharacterEncoding(encoding);
chain.doFilter(request, response);
}
}
doFilter()
매개변수🧐Q. doFilter
메서드가 매개변수로 받는 것은 HttpServletRequest/Response
가 아니다. 그 이유는?
ServletRequest/Response
에서 받아 편하게 사용하기 위해Q. 만약, HttpServletRequest
를 사용한다면?
HttpServletRequest
가 묵시적 타입 변환된 것을 다시 원래 타입으로 되돌리기 @WebFilter(urlPatterns = "*.do")
public class TimeCheckFilter extends HttpFilter implements Filter {
public TimeCheckFilter() {
System.out.println("===> TimeCheckFilter 생성");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request; // 명시적 타입 변환
String uri = req.getRequestURI(); // URI 정보 추출 가능
long beforeTime = System.currentTimeMillis(); // System.currentTimeMillis()가 호출될 때의 시간 정보를 return
chain.doFilter(request, response); // Servlet 호출
long afterTime = System.currentTimeMillis(); // System.currentTimeMillis()가 호출한 후의 시간 정보를 return
System.out.println(**uri** + " 요청 처리에 소요된 시간 : " + (afterTime - beforeTime) + "(ms)초");
}
}
HTTP 요청
TimeCheckFilter
에서 *.do
의 사전 처리 수행
chain.doFilter()
에서 CharacterEncodingFilter
로 요청 전달
CharacterEncodingFilter
에서 *.do
의 사전 처리 수행
chain.doFilter()
에서 서블릿으로 요청 전달
서블릿 실행
서블릿에서 CharacterEncodingFilter
의 chain.doFilter()
로 응답 전달
CharacterEncodingFilter
에서 *.do
의 사후 처리 수행
사후처리가 끝나면 TimeCheckFilter
의 chain.doFilter()
로 응답 전달
사후처리가 끝나면 브라우저에게 HTTP 응답
*.do
에서 실행 될 때는?TimeCheckFilter
, CharacterEncodingFilter
중 뭐가 먼저 실행되는 지 중요하지 않음사전처리→ 다음 필터의 사전처리→ . .
필터가 더이상 없다면 서블릿 수행
사후 처리→ 다음 필터의 사후처리→ . .
이벤트가 발생하면 실행
Container
의 start
과 stop
<listener>
<listener-class>com.ssamz.web.common.BoardWebContextListener</listener-class>
</listener>
@어노테이션
설정 가능@WebListener
public class BoardWebContextListener implements ServletContextListener {
public BoardWebContextListener() {
System.out.println("===> BoardWebContextListener 생성");
}
public void contextInitialized(ServletContextEvent sce) {
System.out.println("---> ServletContxt 생성");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("---> ServletContxt 삭제");
}
}
ServletContextListener
contextInitialized()
메서드를 호출contextDestroyed()
메서드 호출ServletContext
이벤트와 관련된 메서드contextInitialized()
딱 한번 호출contextDestroyed()
딱 한 번 호출BoardWebContextListener
생성이벤트가 발생될 수 있는 객체는 딱 3가지
ServletContext 객체 > HttpSession 객체 > HttpServletRequest 객체
리스너 | 기능 |
---|---|
ServletContextListener | ServletContext 객체의 생성과 삭제 이벤트 처리 |
HttpSessionListener | HttpSession 객체의 생성과 삭제 이벤트 처리 |
ServletRequestListener | HttpServletRequest 객체의 생성과 삭제 이벤트 처리 |
리스너 | 기능 |
---|---|
ServletContextAttributeListener | ServletContext 객체에 정보 등록/삭제/대체 이벤트 처리 |
HttpSessionAttributeListener | HttpSession 객체에 정보 등록/삭제/대체 이벤트 처리 |
ServletRequestAttributeListener | HttpServletRequest 객체에 정보 등록/삭제/대체 이벤트 처리 |
@WebServlet("/sessionTest.do")
public class LintenerTestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(); // 세션 객체 생성
session.setAttribute("person", "yeppi"); // 세션 객체 정보 추가
session.setAttribute("person", "gurum"); // 세션 객체의 정보 덮어쓰기
response.removeAttribute("person"); // 세션 객체 정보 삭제
}
}
문서 작업으로 따지면 템플릿 같은 기능을 가진 필터를 배우고 나니
웹 유지보수 작업이 한결 편해지는 기술이라고 느꼈다