SpringBoot(4) Exception 처리

Yeppi's 개발 일기·2022년 7월 4일
0

Spring&SpringBoot

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

1. 예외 처리 방법

웹 애플리케이션

  1. 에러 페이지
  2. 4XX or 5XX 에러
  3. Clinet 가 200외의 처리를 하지 못할 때는
    200을 내려주고 별도의 에러 message 전달

Spring

  1. @ControllerAdvice
    전역(Global) 예외 처리, 특정 패키지, 특정 컨트롤러
  2. @ExceptionHandler
    특정 컨트롤러


2. 실습

📌예외 발생📌

  • APIController.java
  • @RequestParam(required = false)
    • 꼭 필수가 아니여도 됨

    • 주소?name=1234 이런 값이 없어도 일단 실행시키겠다는 뜻

      @RestController
      @RequestMapping("/api")
      public class APIController {
      
          @GetMapping("")
          public User get(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age) {
              User user = new User();
              user.setName(name);
              user.setAge(age);
      
              // 예외 발생
              int a = 10+age;
              return user;
          }
      
          @PostMapping("")
          public User post(@Valid @RequestBody User user) {
              System.out.println(user);
              return user;
          }
      }

  • User.java
  • @NotNull
    • null 이면 안됨
    • 위 컨트롤러에서 값이 없더라도 실행시키도록 설정했기 때문에
      두개의 설정이 충돌나서 nullpointexception 이 발생할 것
      	@NotEmpty
          @Size(min = 1, max = 10)
          private String name;
      
          @Min(1)
          @NotNull
          private Integer age;

  • 브라우저 출력 결과

  • Get 방식으로 http://localhost:9090/api/user?name&age

    • 파라미터 name 과 age 은 값 없는 상태
    • 500 에러와 함께 콘솔창에는 NullPointerException 이 뜸
  • POST 방식으로 http://localhost:9090/api/user

    {
      "name" : "",
      "age" : 0
    }
    • clinet 에러는 400 → 불친절하게 보여줌(에러처리는 바로 밑에 실습에서부터 진행된다)
    • 콘솔창에는 default message [크기가 1에서 10 사이여야 합니다]




오류 처리하기 방법1 📌글로벌(전역)📌

모든 예외 처리

  • 예외 처리 클래스

    @RestControllerAdvice
    public class GlobalControllerAdvice {
    
        // 예외 잡는 메서드
        @ExceptionHandler(value = Exception.class) // 모든 예외
        public ResponseEntity exception(Exception e) {
            System.out.println("!예외 발생!");
            System.out.println(e.getLocalizedMessage()); // 예외 메시지 출력
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("");
        }
    
    }
  • 아까와 동일하게 POST 방식으로 http://localhost:9090/api/user

    {
      "name" : "",
      "age" : 0
    }
    • clinet 에러는 500 → NoContent 로 보여줌
    • 콘솔창에는 내가 원하는 오류 메시지와 같이 예외를 출력



지정한 예외만 처리

  • 예외 처리 클래스
    @RestControllerAdvice
    public class GlobalControllerAdvice {
    
        // 예외 잡는 메서드
        @ExceptionHandler(value = Exception.class) // 모든 예외
        public ResponseEntity exception(Exception e) {
            System.out.println("!특정 예외 발생!");
            System.out.println(e.getClass().getName()); // 예외가 어디서 발생했는 지 찾음
    
            System.out.println("!예외 발생!");
            System.out.println(e.getLocalizedMessage()); // 예외 메시지 출력
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("");
        }
    
        // 특정 예외를 처리하는 메서드
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public ResponseEntity methodArgumentNotValidException(MethodArgumentNotValidException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        }
    
    }
    • 특정 예외가 어디서 발생했는 지 찾고 난 후,
    • methodArgumentNotValidException 메서드로 해당 특정 예외 처리
    • methodArgumentNotValidException 메서드가 실행되면 기존에 특정 예외를 찾았던 ResponseEntity 메서드는 실행되지 않음

  • methodArgumentNotValidException 메서드로 처리하기 전 실행 결과
  • methodArgumentNotValidException 메서드로 처리하고 난 후 실행 결과

    • 아까와 동일하게 POST 방식으로 http://localhost:9090/api/user

      {
        "name" : "",
        "age" : 0
      }
    • clinet 에러는 400 → 발생한 에러 메시지를 보여줌

    깔끔한 에러 메시지 출력은 아래실습에서

👉 글로벌한 예외를 잡았다





오류 처리하기 방법2 📌특정 구역에서만📌

  • 글로벌 클래스
    @RestControllerAdvice
    public class GlobalControllerAdvice {
    
      	    .
    		.
    
        // 특정 예외를 처리하는 메서드
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public ResponseEntity methodArgumentNotValidException(MethodArgumentNotValidException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        }
    
    }
  • 컨트롤러 클래스
    @RestController
    @RequestMapping("/api/user")
    public class APIController {
    
    		.
    		.
    
        // 특정 예외를 처리하는 메서드
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public ResponseEntity methodArgumentNotValidException(MethodArgumentNotValidException e) {
            System.out.println("api controller");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        }
    }
  • 글로벌한 클래스와 컨트롤러로 지정된 클래스에 같은 예외처리 메서드가 존재한다면?
    → 오류발생 시 컨트롤러 클래스의 예외 처리 메서드를 타게됨
  • 위 실습처럼 브라우저에 실행시 콘솔에 api controller 출력


🍑정리🍑

👉 특정한 컨트롤러에 예외 처리 하고 싶다면? @ExceptionHandler

👉 전체 시스템에 적용하고 싶다면? @RestControllerAdvice

profile
imaginative and free developer. 백엔드 / UX / DATA / 기획에 관심있지만 고양이는 없는 예비 개발자👋
post-custom-banner

0개의 댓글