Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

[예외] Servlet 예외처리 - 필터, DispatcherType 본문

인프런/[인프런] 스프링 MVC 2

[예외] Servlet 예외처리 - 필터, DispatcherType

Seung__ 2021. 9. 27. 22:47

1. 예외 발생과 오류 페이지 요청 흐름


1. WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
  ↓
2. WAS `/error-page/500` 다시 요청 -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러(/errorpage/ 500) -> View
  • 오류가 발생하면 오츄 페이지 출력을 위해 WAS내부에서 다시 호출이 발생함.
  • 필터, 서블릿, 인터셉터가 다시 호출된다.
  • 로그인 인증같은 경우 컨트롤러까지 들어갔다는 것은 이미 인증을 통과한 것인디...
  • 다시 필터, 인터셉터가 호출되어야 하나?? 비효율적인디..
  • 결국 클라이언트로 부터 발생한 정상 요청인지, 아니면 오류 페이지를 출력하기 위한 내부 요청인지 구분 필요!
  • 서블릿은 이런 문제를 해결하기 위해 DispatcherType 이라는 추가 정보를 제공

 

 

2. Dispatcher Type


  • 필터는 이런 경우를 위해서 dispatcherTypes 라는 옵션을 제공
log.info("dispatcherTYpe={}", request.getDispatcherType());
  • 위와 같이 로그를 남기면, 예외가 터졌을 때 dispatcherTYpe=ERROR 라고 찍힌다.
  • 반면 클라이언트로부터 발생한 요청이면  dispatcherType=REQUEST
  • 즉 Servlet Spec은 실제 고객이 요청한 것인지,
  • 서버가 내부에서 오류 페이지를 요청하는 것인지 DispatcherType 으로 구분
  • DispatcherType
    • REQUEST : 클라이언트의 요청
    • ERROR : 오류발생으로 인한 요청
    • FORWARD : MVC에서 배웠던 서블릿에서 다른 서블릿이나 JSP를 호출할 때
      • RequestDispatcher.forward(request, response);
    • INCLUDE : 서블릿에서 다른 서블릿이나 JSP의 결과를 포함할 때
      • RequestDispatcher.include(request, response);
    • ASYNC : 서블릿 비동기 호출

 

3. 필터와 DispatcherType


  • 모든 요청에 대해 로그를 남기는  filter를 적용해보자.
  • 모든 경로에 대해 dispatcherType이 REQUEST, ERROR인 경우 해당 메서드가 실행된다.
import hello.exception.filter.LogFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public FilterRegistrationBean logFilter(){
        FilterRegistrationBean<Filter> filterRegistrationBean =  new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LogFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
        //request, error인 경우 다 호출
        return filterRegistrationBean;
    }
}

  • filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
  • 이렇게 두 가지를 모두 넣으면 클라이언트 요청은 물론이고, 오류 페이지 요청에서도 필터가 호출된다.
  • 아무것도 넣지 않으면 기본 값이 DispatcherType.REQUEST 이다. 
  • 즉 클라이언트의 요청이 있는 경우에만  필터가 적용된다. 
  • 특별히 오류 페이지 경로도 필터를 적용할 것이 아니면, 기본 값을 그대로 사용하면 된다.
  • 물론 오류 페이지 요청 전용 필터를 적용하고 싶으면 DispatcherType.ERROR 만 지정하면 됨.

 

4. GitHub : 210927 Dispatcher Type


 

bsh6463/Exception

Contribute to bsh6463/Exception development by creating an account on GitHub.

github.com

 

Comments