스프링이 아닌 순수 서블릿 컨테이너는 어떻게 리 

 

서블릿은 다음 2가지 방식 예외처리 

exception 

response.sendError(Http상태 코드, 오류메세지) 

 

 

Exception 

자바 직접 실행 

자바의 메인 메서드를 직접 실행하는 경우 main이라는 이름의 쓰레드가 실행 

실행도중 예외를 잡지 못하고 처음 실행한 main()메서드를 넘어서 예외가 던져지면 예외정보를 남기고 해당 쓰레드는 종료된다. 

 

웹 어플리케이션 

사용자 요청별로 별도의 쓰레드가 할당되고, 서블릿 컨테이너 안에서 실행된다. 

애플리케이션에서 예외가 발생했는데, 어디선가 try ~ catch로 잡아서 예외를 처리하면 아무런 문제가 없다. 

 

was <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생) 

 

결국 톰캣같은 was까지 예외가 전달된다. was는 예외가 올라오면 어떻게 처리? 

 

 

오류 화면 제공 - 친절하게 고객에게 보여줄 수 있다. 

 

 

컬럼 셀렉션 모드 -> alt + shift + insert 

한번에 변수 끝까지 선택 -> ctrl + shift + -> 

 

이렇게 예외처리를 하면 필터가 두번 발생한다. 

로그인 인증 체크 할때 사용했기 대문에 또 사용하게 되면은 비효율 적이다. 

 

서블릿은 이렇ㅁㄴ 문제를 해결하기 위해 dispachertype이라는 추가 정보를 제공한다. 

 

dispatcherType 

필터의 경우는 dispatcherTypes라는 옵션을 제공한다. 

 

출력해보면 dispatchertype=error로 나오는것을 확인할 수 있다. 

 

dispatchertypeRequest 

서블릿 

 

prehandle에서 에러가 터지면 postHandle은 호출이 안된다 하지만 afterCompletion은 항상 호출이 된다. 

 

 

@API 예외처리 

API는 생각할 내용이 더 많은데, 오류 페이지는 단순히 고객에게 오류 화면을 보여주고 끝이지만, API는 각 오류 상황에 맞는 오류 응답 스펙을 정하고, JSON으로 데이터를 내려주어야 한다. 

 

 

- @ExceptionHandler 

API Exception Version2 Codes below 

@ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(IllegalArgumentException.class)
    public ErrorResult illegalExHandler(IllegalArgumentException e) {
        log.error("[exceptionHandler] ex", e);
        return new ErrorResult("BAD", e.getMessage());
    }

 

위에 코드에서 return ErrorResult 에서 호출하고 정상흐름으로 끝이 나버린다. 

 

 

 @ExceptionHandler
    public ResponseEntity<ErrorResult> userHanlder(UserException e) {
        log.error("[exceptionHandler] ex", e);
        ErrorResult errorResult = new ErrorResult("USER_EX", e.getMessage());
        return new ResponseEntity(errorResult, HttpStatus.BAD_REQUEST);
    }

 

위의 코드는 회원 예외를 처리하는 코드이다. 위에서 ResponseEntity란 무엇인가? 생각해보자 

 

ResponseEntity는 HttpEntity를 상속받음으로써 HttpHeader와 Body를 가질 수 있다. 이러한 값들을 통해 좀 더 세밀하고 견고한 API 예외처리를 할 수 있다. 

 

 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler
    public ErrorResult exHandler(Exception e){
        log.error("exceptionHandler] ex", e);
        return new ErrorResult("EX", "내부 오류");
    }

 

 

 

ExceptionHandler의 예외 처리 방법 

@ExceptionHanlder애노테이션을 선언하고, 해당 컨트롤러에서 처리하고 싶은 예외를 지정해주면 된다. 해당 컨트롤러에서 예외가 발생하면 이 메서드가 호출 된다. 지정한 예외 또는 그 예외의 자식 클래스는 모두 잡을 수 있다. 

 

 

@ControllerAdvice 

@ExceptionHanlder를 사용해서 예외를 깔끔하게 처리할 수 있게 되었지만, 정상 코드와 예외 처리 코드가 하나의 컨트롤러에 섞여 있다. @ControllerAdvice또는 @RestControllerAdvice를 사용하면 둘을 분리 할 수 있다. 

 

@ControllerAdvice는 대상을 지정하지 않으면 모든 컨트롤러에 적용된다 (글로벌 적용_ 

@RestControllerAdvice는 @ControllerAdvice와 같고 @ResponseBody가 추가되어 있다. @Controller @RestController의 차이와 같다.    

 

 

+ Recent posts