使用 Spring Data Rest 抛出自定义异常 [英] throw custom exception with Spring Data Rest

查看:45
本文介绍了使用 Spring Data Rest 抛出自定义异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm developing a backend with Spring Boot and Spring Data Rest. I need to throw a custom exception instead of the Spring Data Rest exceptions that have a different structure.

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

This is a code that I wrote but it doesn't throw my exception but a generic 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);
}

推荐答案

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

Normally your exception handler is the last layer of exception handling that you write as a developer. You normaly don't re-throw an exception because then it will be handed to default exception handling mechanism of the server that hosts your application.

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

You normally return a response with the error that you want the user to see.

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

Also throwing a RunntimeException will be matched in exception handling mechanism by almost all servers that I know as a 500 error. So the user will see a 500 error which seems like your backend failed and something is messed up.

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

If you can predict what can go wrong then don't let the user see a 500 error code but instead inform him for what is bad. In that case when you have received DataIntegrityViolationException it means that in one way or another the input that the user provided is wrong. So it can not be the backend that failed (500 error) but the user that had done a bad request (400 error).

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

It can also be a safety issue when the client can make the backend fail, and retrieve the stack trace from the default handling mechanism and know information about how the database is built.

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

Here is a custom exception that you can use in your application

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;
    }
 }

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

And this is how your error handling method could be used to return a response that the user understands.

@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"));
  }
}

以下行可以在您的应用程序中的任何地方重复使用,例如(控制器、服务、Daos 等)

The following line could be reused anywhere in your application like (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,也可以修改CustomError中的errorMessageerrorCause,然后再抛出ApplicationException

You can of course modify the error code and not throw only 400, and also modify the errorMessage and errorCause in CustomError before throwing the ApplicationException

这篇关于使用 Spring Data Rest 抛出自定义异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆