改进 Spring Boot REST API 错误处理

栏目: IT技术 · 发布时间: 5年前

内容简介:来自作者投稿 作者:覃佑桦dzone.com/articles/rest-api-error-handling-with-spring-boot

(给 ImportNew 加星标,提高 Java 技能)

来自作者投稿 作者:覃佑桦

dzone.com/articles/rest-api-error-handling-with-spring-boot

引言

Spring Boot提供了优秀的异常处理机制。ErrorController的默认实现能够很好地捕获和处理异常。此外,还可以自己实现@ExceptionHandler捕获和处理特定异常。然而,这里还有可以改进的空间:

·  即使采用了自定义@ExceptionHandler实现某些异常还是会漏网,这时ErrorController会进行处理。@ExceptionHandler与ErrorController的方案可以改进。

·   默认错误有时候看起来比较混乱:   

{
  "timestamp": "2018-09-23T15:05:32.681+0000",
  "status": 400,
  "error": "Bad Request",
  "errors": [
    {
      "codes": [
        "NotBlank.dto.name",
        "NotBlank.name",
        "NotBlank.java.lang.String",
        "NotBlank"
      ],
      "arguments": [
        {
          "codes": [
            "dto.name",
            "name"
          ],
          "arguments": null,
          "defaultMessage": "name",
          "code": "name"
        }
      ],
      "defaultMessage": "{name.not_blank}",
      "objectName": "dto",
      "field": "name",
      "rejectedValue": null,
      "bindingFailure": false,
      "code": "NotBlank"
    }
  ],
  "message": "Validation failed for object='dto'. Error count: 1",
  "path": "/"
}

当然,我们可以注册自定义ErrorAttributes达成这一点,但是如果默认错误实现改进一下岂不更好。

·   对于验证产生的错误,可以把约束条件中的某些参数开放给信息显示。比如可以使用{}占位符把int最小值传给消息显示。但是这种方式并不适用其它异常处理:   

public class UserAlreadyExistsException extends RuntimeException {

    // How can I expose this value to the interpolated message?
    private final String username;

    // constructors and getters and setters
}		

·   如果所有异常都支持应用级的内置错误码当然是极好的。有时候,只有HTTP状态码根本无法定位问题。比如同一个EndPoint发生了不同的错误,报告了同一个状态码该如何分析?

改进方案

errors-spring-boot-starter为各种异常提供了统一处理。errors-spring-boot-starter在Spring Boot异常处理机制基础上提供了:

·   所有异常处理实现一致:不论是验证或绑定错误、domain错误、甚至Spring相关的错误都没有问题。所有异常都交由WebErrorHandler实现处理(不再需要ErrorController与@ExceptionHandler)

·   内建支持应用级错误码。

·   使用MessageSource进行简单的信息插入。

·   支持HTTP错误码自定义显示。

·   允许异常参数暴露给错误消息使用。

默认错误显示

错误的默认格式为JSON,schema定义如下:    

// errors数组为每个错误都定义了code/messsge组合
{
  "errors": [
    {
      "code": "first_error_code",
      "message": "1st error message"
    }
  ]
}

自定义显示只要注册HttpErrorAttributesAdapter实现一个Spring Bean。

统一错误处理

所有异常都交给WebErrorHandler处理。Starter 默认会查询内建WebErrorHandler处理以下异常:

·   所有验证或绑定异常。

·   所有带@ExceptionMapping注解的自定义异常。

·  Spring MVC异常。

·   Spring Security如果在classpath中也会处理。

也可以实现WebErrorHandler注册一个自定义异常处理Spring Bean。

内建错误码支持

尽管RESTful API推荐使用HTTP状态代码,但有时我们需要更多信息定位问题。这时候就需要使用错误码。可以把错误代码看成可读性更好的错误描述机器码。每个异常可以映射至少一个错误码。

exception-to-error-code根据不同的异常类型有所差别:

·   验证产生的错误码从注解中message属性提取,例如@NotBlank(message = "name.required")。

·   @ExceptionMapping注解中的errorCode属性看起来像下面这样:    

@ExceptionMapping(statusCode = BAD_REQUEST, errorCode = "user.already_exists")
public class UserAlreadyExistsException extends RuntimeException {}

·   下面是WebErrorHandler自定义实现:    

public class ExistedUserHandler implements WebErrorHandler {

    @Override
    public boolean canHandle(Throwable exception) {
        return exception instanceof UserAlreadyExistsException;
    }

    @Override
    public HandledException handle(Throwable exception) {
        return new HandledException("user.already_exists", BAD_REQUEST, null);
    }
}

暴露参数

与Spring Boot一样,你也可以通过注解传递验证参数,例如用@Min(value = 18, message = "age.min")把参数内插到显示的消息中:

age.min = The minimum age is {0}!

此外,还可以使用@ExposeAsArg注解自定义异常。例如,如果在下面的消息中报告username已被占用:

user.already_exists=Another user with the '{0}' username already exists

实现代码:    

@ExceptionMapping(statusCode = BAD_REQUEST, errorCode = "user.already_exists")
public class UserAlreadyExistsException extends RuntimeException {
    @ExposeAsArg(0) private final String username;

    // constructor
}

总结

本文介绍了Errors-spring-boot-starter对Spring Boot异常处理的一些改进。了解更多信息请移步GitHub。

看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

改进 Spring Boot REST API 错误处理

好文章,我 在看 :heart:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

High Performance Python

High Performance Python

Micha Gorelick、Ian Ozsvald / O'Reilly Media / 2014-9-10 / USD 39.99

If you're an experienced Python programmer, High Performance Python will guide you through the various routes of code optimization. You'll learn how to use smarter algorithms and leverage peripheral t......一起来看看 《High Performance Python》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器