Spring Boot 中的自定义异常

Posted

技术标签:

【中文标题】Spring Boot 中的自定义异常【英文标题】:Custom Exception in Sprin Boot 【发布时间】:2019-12-12 09:54:06 【问题描述】:

我在 SPRING BOOT 中编写了以下自定义错误处理程序

@RestControllerAdvice 
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler 

    @ExceptionHandler
   // @ResponseBody
    public ResponseEntity<CustomErrorResponse> customHandleNotFound(Exception ex, WebRequest request) 

        CustomErrorResponse errors = new CustomErrorResponse();
        errors.setTimestamp(LocalDateTime.now());
        errors.setError(ex.getMessage());
        errors.setStatus(HttpStatus.CONFLICT.value());
        errors.setErrorMsg(errors.getErrorMsg());

        return  ResponseEntity.ok(errors);

    

下面是我的代码控制器方法

@RestController
@RequestMapping(value="/api")
public class AppController 




   @Autowired
    private UserRepository userRepository;



      @RequestMapping(value="/home/id1" ,method=RequestMethod.PUT)
     @ResponseBody
      public String home(@PathVariable("id1") Long idValue,    @RequestBody @Valid Student s)
    

         System.out.println( " idValue is  "  + idValue);

        System.out.println( " Student -->" + s.getName()  + " -- "  + s.getId());


      return    "job done";

    



      @RequestMapping("/foos")
    //  @ResponseBody
      public String getFoos(@RequestParam(value="t1",required=true)  String id)  

          int i =1/0;

          System.out.println(" id is " + i++);
            return "ID: " + id + "  status: Success";
      

异常处理程序对于方法 getFoos() 工作正常 当它遇到 1/0 时,我在 POSTMAN 中得到了预期的输出


    "timestamp": "2019-08-04 11:24:22",
    "status": 409,
    "error": "/ by zero",
    "errorMsg": "ERROR-msg"

但是在我的 home() 方法中,我故意将 Student 对象设为无效,并且在 POSTMAN 中没有收到错误消息,而只是在 Eclipse 控制台中。 为什么?

我收到此消息。那么当 Student 对象无效时,我该如何启动 CustomGlobalExceptionHandler

2019-08-04 23:25:57.551 警告 9652 --- [nio-8080-exec-6] .m.m.a.ExceptionHandlerExceptionResolver :已解决 [org.springframework.http.converter.HttpMessageNotReadableException: 缺少所需的请求正文:public java.lang.String com.example.hibernatemapping.controller.AppController.home(java.lang.Long,com.example.hibernatemapping.domain.Student)]

【问题讨论】:

添加@ExceptionHandler(HttpMessageNotReadableException.class, Exception.class) 添加后我的服务器现在甚至都没有启动 为 [class org.springframework.http.converter.HttpMessageNotReadableException] 映射的模糊 @ExceptionHandler 方法:public org.springframework.http.ResponseEntity com.example.hibernatemapping.exception.CustomGlobalExceptionHandler.customHandleNotFound(java. lang.Exception,org.springframework.web.context.request.WebRequest), public final org.springframework.http.ResponseEntity org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception, org.springframework.web.context.request.WebRequest) 好的,所以只是@ExceptionHandler(Exception.class) 它不适用于 home() 方法 【参考方案1】:

嗯,有很多话要说。

首先,异常处理程序将异常类作为参数,它允许您在控制器方法中抛出的异常类之后返回其他错误。

您编写的那个捕获所有异常并返回相同的错误模型,这不是一个正确的想法。正确的做法是编写一个扩展 Exception 的抽象类 AbstractMyAppException,然后为您遇到的每个错误情况实现一个扩展它的新类。

然后,添加两个@ExceptionHandler

AbstractMyAppException 类上的一个绑定,它返回您的应用生成的所有错误 Exception 类上的一个绑定返回所有其他不应发生的错误。

对于您的情况,您似乎正在使用 Spring Validation(您正在使用 @Valid 注释)。所以请确保您已关注this tutorial。

然后,您的问题是关于捕获验证错误以在学生无效时显示自定义消息。然后检查this thread。

【讨论】:

它没有回答我的问题。这个答案让我很困惑 那么对不起,你的问题不是很清楚……你能具体说明你想知道什么吗? 我希望 home() 返回错误与 ` "timestamp": "2019-08-04 11:24:22", "status": 409, "error ": "/ by zero", "errorMsg": "ERROR-msg" ` 这是我的 CustomErrorResponse 类字段【参考方案2】:

我通过在我的 ControllerAdvice 中添加以下内容来解决它我只需更改代码以将错误映射到我的自定义 Pojo 类 CustomErrorResponse

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers,
                                                                  HttpStatus status, WebRequest request) 

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", new Date());
        body.put("status", status.value());

        //Get all errors
        List<String> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(x -> x.getDefaultMessage())
                .collect(Collectors.toList());

        body.put("errors", errors);

         System.out.println( " erro here ");
        return new ResponseEntity<>(body, headers, status);



【讨论】:

以上是关于Spring Boot 中的自定义异常的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC(或 Spring Boot)。针对安全相关异常(例如 401 Unauthorized 或 403 Forbidden)的自定义 JSON 响应)

抛出异常时,Spring Boot 不显示自定义错误

Spring Boot 异常自定义处理 - 意外的 HTTP 状态

缺少资源 bean:Spring Boot webflux 自定义全局异常处理程序

如何处理 grails spring-security-rest 插件中的自定义身份验证异常?

未抛出 spring webflux 的自定义异常