서블릿 필터
필터흐름
HTTP 요청 → WAS → 필터 → 서블릿 → 컨트롤러
필터 제한
HTTP 요청 → WAS → 필터 → 서블릿 → 컨트롤러 //로그인 사용자
HTTP 요청 → WAS → 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) //비 로그인 사용자
필터에서 적절하지 않은 요청이라고 판단하면 필터에서 끝을 낼 수 있다. 따라서 로그인 여부를 체크하기 좋다.
필터 체인
HTTP 요청 → WAS → 필터1 → 필터2 → 필터3 → 서블릿 → 컨트롤러
필터는 체인으로 구성되며, 중간에 필터를 자유롭게 추가할 수 있다.
필터 인터페이스
public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException
{}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public default void destroy() {}
}
- init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
- doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
- destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.
스프링 인터셉터
스프링 인터셉터 흐름
HTTP 요청 → WAS → 필터 → 서블릿 → 스프링 인터셉터 → 컨트롤러
스프링 인터셉터 제한
HTTP 요청 → WAS → 필터 → 서블릿 → 스프링 인터셉터 → 컨트롤러 //로그인 사용자
HTTP 요청 → WAS → 필터 → 서블릿 → 스프링 인터셉터(적절하지 않은 요청이라 판단, 컨트롤러 호출X) //비 로그인 사용자
인터셉터에서 적절하지 않은 요청이라고 판단하면 인터셉터에서 끝낼 수 있다. 따라서 로그인 여부를 체크하기 좋다.
스프링 인터셉터 체인
HTTP 요청 → WAS → 필터 → 서블릿 → 인터셉터1 → 인터셉터2 → 컨트롤러
스프링 인터셉터는 체인으로 구성되는데, 중간에 인터셉터를 자유롭게 추가할 수 있다. 예를 들어, 로그를 남기는 인터셉터를 먼저 적용하고, 그 다음에 로그인 여부를 체크하는 인터셉터를 만들 수 있다.
스프링 인터셉터 인터페이스
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}
}
- 인터셉터는 컨트롤러 호출 전(preHandle), 호출 후(postHandle), 요청 완료 이후(afterCompletion)과 같이 단계적으로 잘 세분화 되어 있다.
- 인터셉터는 어떤 컨트롤러(handler)가 호출되는지 호출 정보도 받을 수 있다. 또한 어떤 modelAndView가 반환되는지 응답 정보도 받을 수 있다.
정상 흐름
- preHandle: 컨트롤러 호출 전 호출된다.
preHandle의 응답 값이 true이면 다음으로 진행하고, false면 더 진행하지 않는다.
- postHandle: 컨트롤러 호출 후 호출된다.
- afterCompletion: 뷰가 렌더링 된 이후에 호출된다.
예외 발생
- preHandle: 컨트롤러 호출 전에 호출된다.
- postHandle: 컨트롤러에서 예외가 발생하면 postHandle은 호출되지 않는다.
- afterCompletion: afterCompletion은 항상 호출된다. 이 경우 예외를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력할 수 있다.
ArgumentResolver 활용
@GetMapping("/")
public String homeLoginV3ArgumentResolver(@Login Member loginMember, Model model) {
//세션에 회원 데이터가 없으면 home
if (loginMember == null) {
return "home";
}
//세션이 유지되면 로그인으로 이동
model.addAttribute("member", loginMember);
return "loginHome";
}
@Login 애노테이션 생성
package hello.login.web.argumentresolver;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
}
- @Target(ElementType.PARAMETER): 파라미터에만 사용
- @Retention(RetentionPolicy.RUNTIME): 리플렉션 등을 활용할 수 있도록 런타임까지 애노테이션 정보가 남아있음
- @Login을 사용해 좀 더 쉽게 로그인 정보를 조회할 수 있다.
'Spring Study > MVC 패턴' 카테고리의 다른 글
[MVC 패턴] API 예외 처리 (2) | 2023.09.04 |
---|---|
[MVC 패턴] 예외 처리와 오류 페이지 (0) | 2023.09.01 |
[MVC 패턴] 로그인 처리1 - 쿠키, 세션 (0) | 2023.08.29 |
[MVC 패턴] 검증2 - Bean Validation (0) | 2023.08.24 |
[MVC 패턴] 검증1 - Validation (0) | 2023.08.24 |
댓글