【问题标题】:throw custom exception with Spring Data Rest使用 Spring Data Rest 引发自定义异常
【发布时间】:2021-07-09 10:11:18
【问题描述】:

我正在使用 Spring Boot 和 Spring Data Rest 开发一个后端。我需要抛出一个自定义异常,而不是具有不同结构的 Spring Data Rest 异常。

这是我编写的代码,但它不会抛出我的异常,而是一个通用的 RuntimeException

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.rest.webmvc.RepositoryRestController;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.Locale;

@ControllerAdvice(annotations = RepositoryRestController.class)
public class RestRepositoryExceptionHandler {

    @ExceptionHandler({DataIntegrityViolationException.class})
    public RuntimeException handle(Exception e, Locale locale) {
        throw new RuntimeException("REST_REPOSITORY_EXCEPTION", e);
//        throw new RuntimeException("DATA_ALREADY_EXISTS");
    }

}

这是一个存储库

import it.edistribuzione.smartgrid.model.User;
import lombok.NonNull;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

import java.util.Optional;

@RepositoryRestResource(path = "users")
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);

    Boolean existsByUsername(String username);

    boolean existsById(@NonNull Long id);
}

【问题讨论】:

    标签: java spring spring-boot spring-data-jpa


    【解决方案1】:

    通常,您的异常处理程序是您作为开发人员编写的最后一层异常处理程序。您通常不会重新抛出异常,因为它会被交给托管您的应用程序的服务器的默认异常处理机制。

    您通常会返回包含您希望用户看到的错误的响应。

    几乎所有我知道为 500 错误的服务器都会在异常处理机制中匹配抛出 RunntimeException。因此用户会看到一个 500 错误,这似乎是您的后端失败并且出现了问题。

    如果您可以预测会出现什么问题,那么不要让用户看到 500 错误代码,而是告诉他什么是错误的。在这种情况下,当您收到DataIntegrityViolationException 时,这意味着用户提供的输入以某种方式是错误的。所以不可能是后端失败(500错误),而是用户做了一个错误的请求(400错误)。

    当客户端可以使后端失败,并从默认处理机制中检索堆栈跟踪并了解有关如何构建数据库的信息时,这也可能是一个安全问题。

    这是您可以在应用程序中使用的自定义异常

    public class ApplicationException extends RuntimeException  {
    
        private CustomError customError;
    
        public ApplicationException(CustomError customError){
            super();
            this.customError = customError;
        }
    }
    

    这是一个错误模型类

    @Getter
    @Setter
    @NoArgsConstructor
    public class CustomError {
    
        private int code;
        private String message;
        private String cause;
    
        public CustomError(int code, String message, String cause) {
            this.code = code;
            this.message = message;
            this.cause = cause;
        }
     }
    

    这就是您的错误处理方法可用于返回用户理解的响应的方式。

    @ControllerAdvice
    public class RestRepositoryExceptionHandler {
        
        @ExceptionHandler(ApplicationException.class)
        public ResponseEntity handleApplicationException(ApplicationException e) {
            return ResponseEntity.status(e.getCustomError().getCode()).body(e.getCustomError());
        }
    
    
       @ExceptionHandler({DataIntegrityViolationException.class})
        public ResponseEntity handle(Exception e, Locale locale) {
            return ResponseEntity.status(400).body(new CustomError(400, e.getMessage(), "this is the cause that the user will see"));
      }
    }
    

    以下行可以在您的应用程序中的任何地方重用,例如(Controllers、Services、Daos...)

    throw new ApplicationException( new CustomError(400, "This is the error message that the user will see", "this is the cause that the user will see"));
    

    你当然可以修改错误码而不是只抛出400,也可以在抛出ApplicationException之前修改CustomError中的errorMessage和errorCause

    【讨论】:

      猜你喜欢
      • 2017-11-28
      • 2018-03-17
      • 2015-09-26
      • 2016-06-04
      • 2016-10-31
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      相关资源
      最近更新 更多