본문 바로가기

백엔드

[Spring Boot] RESTAPI - 예외처리

728x90

 

/* 특수 예외처리  (유저 찾기 실패 시)*/

 

@GetMapping("/users/{id}")
public EntityModel<User> retrieveUser(@PathVariable int id) {
    User user = userDaoService.findById(id);
    if (user == null) {
        throw new UserNotFoundException("id:" + id);
    }
    EntityModel<User> entityModel = EntityModel.of(user);
    WebMvcLinkBuilder link = linkTo(methodOn(this.getClass()).retrieveUserList());
    entityModel.add(link.withRel("all-users"));
    return entityModel;
}

 

Controller 클래스 안에 user 가 null 일 경우 예외를 발생시키고 싶다면? 클래스를 만들수 있다.

나는 UserNotFoundException이라는 클래스를 만들겠다.

 

package com.learning.webservices.user;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(code= HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

 

이때의 상태처리는 @ResponseStatus를 이용해 NOT_FOUND 상태를 넣을 수 있고 RuntimeException을 extends했다.

 

/* ExceptionHandler 클래스 안에 재정의*/

 

public class ErrorDetails {

    private LocalDateTime timestamp;
    private String message;
    private String details;

    public ErrorDetails(LocalDateTime timestamp, String message, String details) {
        this.timestamp = timestamp;
        this.message = message;
        this.details = details;
    }

    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    public String getMessage() {
        return message;
    }

    public String getDetails() {
        return details;
    }
}

 

 

@ControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(Exception.class)
    public final ResponseEntity<ErrorDetails> handleAllException(Exception ex, WebRequest request) throws Exception {
        ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(),ex.getMessage(),request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(UserNotFoundException.class)
    public final ResponseEntity<ErrorDetails> handleUserNotFoundException(Exception ex, WebRequest request) throws Exception {
        ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(),ex.getMessage(),request.getDescription(false));
        return new ResponseEntity<ErrorDetails>(errorDetails, HttpStatus.NOT_FOUND);
    }
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
        ErrorDetails errorDetails =
                new ErrorDetails(LocalDateTime.now(),
                        "Total Errors: " + ex.getErrorCount() + " First Error: " + Objects.requireNonNull(ex.getFieldError()).getDefaultMessage(),
                        request.getDescription(false));

        return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
    }
}

 

@ControllerAdvice를 통해 애플리케이션의 모든 Controller에서 발생할 수 있는 예외를 처리할 수 있다. 

@ExceptionHandler 어노테이션을 통해 사용하거나, 세번 째 메서드 처럼 ExceptionHandler 클래스를 상속해 @Override를 통해 사용할 수도 있다.

 

handleAllException - 이 메서드는 모든 종류의 Exception을 처리한다. (Exception.class) 예외가 발생하면 ErrorDetails 객체를 생성하여 SERVER_ERROR 상태코드와 함께 반환

 

handlerUserNotFoundException - 처음에 소개했던 user가 null일때 이 메서드를 실행시킨다. 

 

handleMethodArgumentNotValid - 이 메서드는 MethodArgumentNotValidException 예외를 처리한다. 요청의 메소드 패러미터가 @Valid를 통해 검사했는데 유효하지 않을 때 발생한다.

 

728x90