Spring MVC - 예외처리

공부한것 다 기록해·2023년 8월 9일
0

스프링 MVC - 예외처리

상당히 중요한 파트이다!

예외란

프로그램이 예상치 못한 상황을 만났을 때 오류를 발생시키는 것(throw new Exception())

일반적인 자바 프로그램이 예외를 처리하는 방법

try {
	doSomething();
} catch(Exception e){
	handleException(e);
    // throw e;
}

스프링 MVC에서 예외처리를 활용하는 방법(REST API용)

@ExceptionHandler

컨트롤러 기반 예외 처리
HTTP Status code를 변경하는 방법

HTTP Status code를 변경하는 방법

@ResponseStatus
ResponseEntity활용

예외처리 우선순위

  1. 해당 Exception이 정확히 지정된 Handler
  2. 해당 Exception의 부모 예외 Handler
  3. 이도 저도 아니면 그냥 Exception(모든 예외의 부모)
@ResponseStatus(HttpStatus.FORBIDDEN)
@ExceptionHandler(IllegalAccessException.class)
public ErrorResponse handleIllegalAccessException(IllegalAccessException e){
        log.error("IllegalAccessException is occurred.", e);

        // error를 json 형태로 날려준다.
        return new ErrorResponse("INVALID_ACCESS","IllegalAccessException is occured.");
    }

ErrorResponse Dto

@AllArgsConstructor // 자동 생성자
@Data // getter, setter
public class ErrorResponse {
    private String errorCode;
    private String message;
}

ResponseEntity를 활용한 응답

@ResponseStatus(HttpStatus.FORBIDDEN)
@ExceptionHandler(IllegalAccessException.class)
public ResponseEntity<ErrorResponse> handleIllegalAccessException(IllegalAccessException e){
        log.error("IllegalAccessException is occurred.", e);
        return ResponseEntity
                .status(HttpStatus.FORBIDDEN)
                .header("newHeader", "Some value")
                .body(new ErrorResponse("INVALID_ACCESS","IllegalAccessException is occured."));
    }

상태코드, 헤더 등등 세부적으로 조절이 가능하다.

@RestControllerAdvice

어플리케이션의 전역적 예외 처리
@ControllerAdvice랑 차이는?

  • Controller vs RestController 차이와 동일
  • ControllerAdvice : 기본적으로 view를 응답하는 방식
  • RestControllerAdivce : REST API 용으로 객체를 응답하는 방식(주로 JSON)

스프링 백엔드 개발에서 현재 가장 많이 활용되는 기술(일관적인 예외 및 응답처리)

Controller를 새로 추가하더라도 추가적으로 예외를 처리해줄 필요가 없다. 전역적으로 예외처리가 되므로 모든 Controller에 적용이 된다.

package com.example.demo.exception;

import com.example.demo.dto.ErrorResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    // 예외처리
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(IllegalAccessException.class)
    public ResponseEntity<ErrorResponse> handleIllegalAccessException(IllegalAccessException e){
        log.error("IllegalAccessException is occurred.", e);
        return ResponseEntity
                .status(HttpStatus.FORBIDDEN)
                .header("newHeader", "Some value")
                .body(new ErrorResponse(ErrorCode.TOO_BIG_ID_ERROR,"IllegalAccessException is occurred."));
    }

    @ExceptionHandler(WebSampleException.class)
    public ResponseEntity<ErrorResponse> handleWebSampleException(WebSampleException e){
        log.error("IllegalAccessException is occurred.", e);
        return ResponseEntity
                .status(HttpStatus.INSUFFICIENT_STORAGE)
                .body(new ErrorResponse(e.getErrorCode(),"WebSampleException is occurred."));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e){
        log.error("IllegalAccessException is occurred.", e);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERROR,"WebSampleException is occurred."));
    }
}

0개의 댓글