管理大型 Spring Boot 应用程序中的错误消息和代码

问题描述 投票:0回答:1

大型应用程序如何使用 Spring Boot 和 Java 系统地为其所有 API 设置错误消息及其对应的代码,尤其是当它们有超过 100 种与 HTTP 状态代码一致的不同错误消息时?

是否有像@ControllerAdvice这样更通用的方法,而不是处理每个API方法中的每个异常?使用 @ControllerAdvice 有哪些缺点,特别是在异常处理程序的顺序方面?

@GetMapping("/user/{id}")
    public ResponseEntity<UserResponse> getUserById(@PathVariable String id) {
        List<UserInfo> userInfoByIdList = null;
        try {
            userInfoByIdList = userService.getUserById(id);
            if (userInfoByIdList.isEmpty()) {
                throw new NoUserFoundException("No user found with ID: " + id);
            }
            if (userInfoByIdList.get(0).isDeleted()) {
                throw new UserDeletedException("User with ID: " + id + " has been deleted");
            }
            if (!userService.isUserEligible(userInfoByIdList.get(0))) {
                throw new UserNotEligibleForAccessingUserException("User with ID: " + id + " is not eligible for access");
            }
        } catch (NoUserFoundException e) {
            log.error("NoUserFoundException while fetching user for ID {}: {}", id, e.getMessage(), e);
            return new ResponseEntity<>(new UserResponse(HttpStatus.NOT_FOUND.value(), e.getMessage()), 
                                        HttpStatus.NOT_FOUND);
        } catch (UserDeletedException e) {
            log.error("UserDeletedException while fetching user for ID {}: {}", id, e.getMessage(), e);
            return new ResponseEntity<>(new UserResponse(HttpStatus.GONE.value(), e.getMessage()), 
                                        HttpStatus.GONE);
        } catch (UserNotEligibleForAccessingUserException e) {
            log.error("UserNotEligibleForAccessingUserException while fetching user for ID {}: {}", id, e.getMessage(), e);
            return new ResponseEntity<>(new UserResponse(HttpStatus.FORBIDDEN.value(), e.getMessage()), 
                                        HttpStatus.FORBIDDEN);
        } catch (ServiceException e) {
            log.error("ServiceException while fetching user for ID {}: {}", id, e.getMessage(), e);
            return new ResponseEntity<>(new UserResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()), 
                                        HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (Exception e) {
            log.error("Error while fetching user for ID {}: {}", id, e.getMessage(), e);
            return new ResponseEntity<>(new UserResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()), 
                                        HttpStatus.INTERNAL_SERVER_ERROR);
        }

        return new ResponseEntity<>(new UserResponse(HttpStatus.OK.value(), userInfoByIdList), HttpStatus.OK);
    }
java spring-boot error-handling controller
1个回答
0
投票

@ControllerAdvice 是大多数时候的选择,因为集中的错误处理和代码的整洁。在你的情况下,它看起来像这样:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NoUserFoundException.class)
    public ResponseEntity<ErrorResponse> handleNoUserFoundException(NoUserFoundException ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(UserDeletedException.class)
    public ResponseEntity<ErrorResponse> handleUserDeletedException(UserDeletedException ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.GONE.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.GONE);
    }

    @ExceptionHandler(UserNotEligibleForAccessingUserException.class)
    public ResponseEntity<ErrorResponse> handleUserNotEligibleForAccessingUserException(UserNotEligibleForAccessingUserException ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.FORBIDDEN.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.FORBIDDEN);
    }

    @ExceptionHandler(ServiceException.class)
    public ResponseEntity<ErrorResponse> handleServiceException(ServiceException ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

但正如上面提到的,这更多的是一个建议问题,而不是一个技术问题。

© www.soinside.com 2019 - 2024. All rights reserved.