스프링 부트에서의 예외처리

이경영·2022년 10월 19일
0

스프링부트2

목록 보기
16/19
post-custom-banner

스프링 부트의 예외처리 방식

  • 스프링 부트의 예외처리 방식은 크게 2개가 존재

  • @ControllerAdvice를 통한 모든 Controller에서 발생할 수 있는 예외처리

  • @ExceptionHandler를 통한 특정 COntroller의 예외처리

@ControllerAdvice로 모든 컨트롤러에서 발생할 예외를 정의하고
@ExceptionHandler를 통해 발생하는 예외마다 처리할 메소드를 정의

예외 클래스


AroundHubException으로 새로운 Exception을 만들 수 있다

모든 예외 클래스는 Throwable클래스를 상속받고 있음
Exception은 수많은 자식 클래스가 있고
RuntimeException은 UncheckedExcpetion이며, 그 외 Exception은 Checked Exception으로 볼 수 있음


처리여부가 가장 큰 차이!

예외처리 (Exception)

- @ControllerAdvice, @RestControllerAdvice

@ControllerAdvice는 Spring에서 제공하는 어노테이션
@Controller나 @RestController에서 발생하는 예외를 한 곳에서 관리하고 처리할 수 있게 하는 어노테이션
설정을 통해 범위 지정이 가능하며, Default값으로 모든 Controller에 대해 예외처리를 관리함

  • @RestControllerAdvice(basePackages="arounghub.thinkground.studio")와 같이 패키지 범위를 설정할 수 있음
    예외 발생 시 json의 형태로 결과를 반환하기 위해서 @RestControllerAdvice
    를 사용하면 됨.

- @ExceptionHandler

예외처리 상황이 발생하면 해당 Handler로 처리하겠다고 명시하는 어노테이션
어노테이션 뒤에 괄호를 붙여 어떤 ExceptionVlass를 처리할지 설정할 수 있음

  • @ExceptionHandler(00Exception.calss)
    Exception.class는 최상위 클래스로 하위 세부 예외 처리 클래스로 설정한 핸들러가 존재하면, 그 핸들러가 우선처리하게 되며, 처리되지 못하는 예외처리에 대해 ExcpetionClass에서 핸들링함.
    @ControllerAdvice로 설정된 클래스 내에서 메소드로 정의할 수 있지만, 각 Controller 안에 설정도 가능
    전역설정(@ControllerAdvice)보다 지역설정(Controller)으로 정의한 Handler가 우선순위를 가짐


: NullPOintException은 자식클래스니까 우선순위를 갖는다.


실습

HelloController.java 내부 클래스로 Exception

    //예외처리 예시
    @PostMapping("/exception")
    public void exceptionTest() throws Exception{
        throw new Exception();
    }

    @ExceptionHandler(value=Exception.class)
    public ResponseEntity<Map<String, String>> ExceptionHandler(Exception e){
        HttpHeaders responseHeaders=new HttpHeaders();
        HttpStatus httpStatus=HttpStatus.BAD_REQUEST;

        LOGGER.info(e.getLocalizedMessage());
        LOGGER.info("Controller 내 Exception 호출");

        Map<String,String> map=new HashMap<>();
        map.put("error type", httpStatus.getReasonPhrase());
        map.put("code", "400");
        map.put("message", "에러 발생");

        return new ResponseEntity<>(map, responseHeaders, httpStatus);
    }

따로 AroundHubExceptionHandler.java에 Exception 설정

package com.example.testproject.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HelloController {
    //
    private final Logger LOGGER= LoggerFactory.getLogger(HelloController.class);

    @RequestMapping("/hello")
    public String hello(){
        return "Hello World";
    }

    @PostMapping("log-test")
    public void logTest(){
        LOGGER.trace("trace log");
        LOGGER.debug("debug log");
        LOGGER.info("info log");
        LOGGER.warn("warn log");
        LOGGER.error("error log");
    }

    //예외처리 예시
    @PostMapping("/exception")
    public void exceptionTest() throws Exception{
        throw new Exception();
    }

    @ExceptionHandler(value=Exception.class)
    public ResponseEntity<Map<String, String>> ExceptionHandler(Exception e){
        HttpHeaders responseHeaders=new HttpHeaders();
        HttpStatus httpStatus=HttpStatus.BAD_REQUEST;

        LOGGER.info(e.getLocalizedMessage());
        LOGGER.info("Controller 내 Exception 호출");

        Map<String,String> map=new HashMap<>();
        map.put("error type", httpStatus.getReasonPhrase());
        map.put("code", "400");
        map.put("message", "에러 발생");

        return new ResponseEntity<>(map, responseHeaders, httpStatus);
    }
}
  • HelloController 스웨거 실행
    json형태의 responsebody를 받고 HelloController null 찍힘.
    HelloController.java vs @RestControllerAdvice 어노테이션 설정한ConAroundHubExcpetionHandler.java 둘중 HelloController가 우선함을 알 수 있음.

  • HelloController의 @ExceptionHandler 주석 처리하고 진행하면?
    -> @RestControllerAdvice 어노테이션 설정한ConAroundHubExcpetionHandler.java 를 타서 예외를 설정한다.

예외처리 2가지

  1. 예외가 발생해서 처리할 수 있는 경우
    try-catch : 대체 데이터로 처리 가능
    @RestControllerAdvice(통합적으로 관리 가능한 @Exception 처리) : 에러메세지를 어떻게 통합적으로 관리를 할것인가? 처리하지 않고 오류발생했다고 클라이언트쪽에 되받아치는 방식 사용가능 / 각각의 상황에 따라 디테일하게 처리 해주면 통합처리 필요없을수도 있음.
  2. 처리할 수 없는 경우
    자바에서 제공해주는 Exception으로 처리가능한 부분 처리해주고, 미세포인트 잡아서 처리가능한 부분은 => 커스텀으로 관리해줄수 있음.
profile
꾸준히
post-custom-banner

0개의 댓글