du.study기록공간

[Spring MVC] Exeption 처리방법 - AbstractHandlerExceptionResolver 본문

스프링

[Spring MVC] Exeption 처리방법 - AbstractHandlerExceptionResolver

du.study 2019. 11. 17. 22:29
728x90

각각의 컨트롤러에서 Exeption 개별적으로 처리한다는 건 중복되는 코드도 많아질뿐더러 관리하기가 상당히 까다로운것 같아 Exception을 처리하는 방법에 대해 고민 및 조사를 했었습니다. 그래서 이번에는 Exeption에 대해서 공통으로 처리하는 방법 두가지에 대해서 기록하려 합니다.

 

1. AbstractHandlerExceptionResolver 를 사용하는방법

2. @ControllerAdvice, @ExceptionHandler를 이용하는 방법

 

먼저 AbstractHandlerExceptionResolver 를 이용하는 방법에 대해서 기록하겠습니다.

 

우선 AbstractHandlerExceptionResolver를 extends받는 클래스를 생성 후, 이 클레스를 implements WebMvcConfigurer 를 선언해준 곳에서 ExceptionResolvers 에 등록해주면 됩니다. 그럼 관련 코드들을 작성해보면,

 

먼저 설정부분에서 ExceptionResolver를 생성합니다.

@Configuration
@ComponentScan(basePackages = {"du"})
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        resolvers.add(new ExceptionResolver());
    }
}

 

그 다음, 테스트할 컨트롤러,에러를 만들어서 에러를 던지도록 합니다. 

@Controller
@RequestMapping("/error")
public class ExceptionTestController {

    @GetMapping("/common-error")
    @ResponseBody
    public String commonErrorTest(){
        throw new CommonException();
    }

    @GetMapping("/invalid-error")
    @ResponseBody
    public String InvalidErrorTest(){
        throw new InvalidParameterException();
    }

}

public class CommonException extends RuntimeException {

    protected ErrorCodable errorType;
    protected String causeMsg;

    public CommonException() {
        this.errorType = ErrorType.UNKNOWN_ERROR;
    }

    public CommonException(ErrorCodable errorType) {
        this.errorType = errorType;
    }

    public CommonException(ErrorCodable errorType, String causeMsg) {
        this.errorType = errorType;
        this.causeMsg = causeMsg;
    }
    ......
}


public enum ErrorType implements ErrorCodable{
    SUCCESS(0, "SUCCESS", 500),
    INVALID_VALUE(1000, "INVALID_VALUE",403),
    UNKNOWN_ERROR(9999,"UNKNOWN_ERROR",500)
    ;
    ...
}

마지막으로 CommonException, InvalidParameterException 는 Test를 위하여 만들었으며,CommonException는 RuntimeException를 상속받고 있고, InvalidParameterException는 CommonException를 받게끔 작성하였습니다.

 

마지막으로  ExceptionResolver 구현부분을 완성해줍니다.

public class ExceptionResolver extends AbstractHandlerExceptionResolver {
    private static final Gson gson = new GsonBuilder().create();

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        try {
            if (ex instanceof CommonException) {
                ex = (CommonException)ex;
                setResponse(response,(CommonException)ex);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ModelAndView();
    }

    private void setResponse( HttpServletResponse response,CommonException err) throws IOException {
        response.setStatus(err.getErrorType().getStatus());
        response.setHeader("Content-Type","application/json; charset=utf-8");
        PrintWriter writer = null;
        writer = response.getWriter();
        writer.write(gson.toJson(createErrorBody(err)));
        writer.flush();
        writer.close();
    }



    public static class ErrorBody{
        private Integer code;
        private String msg;
        private String cause;

        public ErrorBody(Integer code, String msg, String cause) {
            this.code = code;
            this.msg = msg;
            this.cause = cause;
        }
    }

    public static ErrorBody createErrorBody(CommonException err){
        return new ErrorBody(err.getErrorType().getErrorCode(),err.getErrorType().getErrorMsg(),err.getCauseMsg());
    }

}

 

reponse에 응답값을 gson을 통하여 responseBody에 써주면, 다음과 같은 에러를 받아볼 수 있습니다.

INVALID_VALUE(1000, "INVALID_VALUE",403) 에러를 통해 403으로 받은 결과

 

UNKNOWN_ERROR(9999,"UNKNOWN_ERROR",500)의 결과를 통해 500으로 받은 결과

다음과 같은방법으로 프론트와 약속된? 커스텀 에러코드라던지 HttpStatus 값, 메시지등을 수정하여 error 메시지를 동일하게 내려줄 수 있습니다.

 

다음 글에서@ControllerAdvice, @ExceptionHandler 를 사용한 에러처리법을 기록할 예정이며, 지금 예제로 만든 코드가 뭔가.. 깔끔하지가 않습니다. 운영이슈에 치여서 개발을 메인으로 진행하질 못하니 너무 무뎌진 느낌.. 드내용은 조금씩 수정될 예정입니다.

 

728x90
Comments