Spring MVC/03.예외 처리

[spring 예외 처리] 03.프로그래밍을 통한 예외 처리 2

  • -
반응형

이전 포스트에서 @ControllerAdvice를 통한 예외 처리에 대해서 살펴보았다. 이번 포스트에서는 SpringBoot에서 특화된 처리방법을 살펴보자.

 

SpringBoot의 오류 페이지

 

BasicErrorController

SpringBoot에서 /error에 대한 처리를 담당하는 @Controller는 BasicErrorController이다.  이 녀석의 핵심되는 코드만 잠깐 살펴보자.

@Controller
// ${server.error.path} 또는 ${error.path} 또는 /error 요청에 대해 처리
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {

    // 일반 HTTP 요청이 왔을 때의 처리
    @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        Map<String, Object> model = Collections
                .unmodifiableMap(getErrorAttributes(request, 
                getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = resolveErrorView(request, response, status, model);
        return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
    }

    // errorHtml에서 처리하지 않는 즉 ajax 요청에 대해 처리
    @RequestMapping
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity<>(status);
        }
        Map<String, Object> body = getErrorAttributes(request, 
                                   getErrorAttributeOptions(request, MediaType.ALL));
        return new ResponseEntity<>(body, status);
    }
}

주석에 적힌바대로 BasicErrorController는 /error 요청에 대해서 일반 http 요청(errorHtml)과 ajax 요청(error)을 구분해서 처리하고 있다. 여기에 추가로 처리하고 싶은 내용이 있다면 BasicErrorController를 상속 받아서 위 두 개의 메서드를 재정의 해주면 된다.

 

BasicErrorController 확장

이제 BasicErrorController를 확장해서 사용자 정의 ErrorController를 작성해보자.

@Controller
@Slf4j
public class MyErrorController extends BasicErrorController {

    public MyErrorController(ErrorAttributes errorAttributes,
            ServerProperties serverProperties,
            List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, serverProperties.getError(), errorViewResolvers);
    }

    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mnv = super.errorHtml(request, response);
        // 부가적으로 필요한 작업
        log.debug("model: {}", mnv.getModel());
        log.debug("view: {}", mnv.getViewName());

        HttpStatus hs = getStatus(request);
        switch (hs) {
        case UNAUTHORIZED:
            mnv.setViewName("/error/401");
            break;
        case NOT_ACCEPTABLE:
            mnv.setViewName("/error/406");
            break;
            ...
        default:
            mnv.setViewName("/error/500");
            break;
        }
        return mnv;
    }

    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        ResponseEntity<Map<String, Object>> entity = super.error(request);
        // 부가적으로 필요한 작업
        return entity;
    }
}

 

@ControllerAdvice가 사실 예외 처리를 전담하는 녀석도 아니고 일반 요청인지 ajax요청인지 직접 판단해서 처리해야했던 것에 비해 훨씬 깔끔해졌다.

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.