前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring boot的异常处理

Spring boot的异常处理

作者头像
用户7386338
发布2020-05-29 15:33:12
1.1K0
发布2020-05-29 15:33:12
举报
文章被收录于专栏:Java患者Java患者

Spring boot的默认异常处理机制

我们以访问一个不存在的页面的场景为例,结果是返回一个错误页面:

而我们一个前后端分离的架构,我们写的Restful API往往会被多个渠道访问,比如浏览器,app。而我们的spring boo会根据不同的渠道做出不同的响应,是浏览器发的就返回html,不是则是json。若报错回跳转到/error的URL,同一个URL不同的处理方式是由Spring boot提供的BasicErrorController错误控制器实现的。

代码语言:javascript
复制
  // 如果请求头中accept有text/html这个值
  @RequestMapping(produces = "text/html")
  public ModelAndView errorHtml(HttpServletRequest request,
      HttpServletResponse response) {
    HttpStatus status = getStatus(request);
    Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
        request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
    response.setStatus(status.value());
    ModelAndView modelAndView = resolveErrorView(request, response, status, model);
    return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
  }
  // 没有则进到到这个方法里面
  @RequestMapping
  @ResponseBody
  public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
    Map<String, Object> body = getErrorAttributes(request,
        isIncludeStackTrace(request, MediaType.ALL));
    HttpStatus status = getStatus(request);
    return new ResponseEntity<Map<String, Object>>(body, status);
  }

当我们对请求的参数进行校验,当校验不通过时,spring boot会返回一个400状态码,并且并把我们所有的错误信息放进一个error里面来告诉我们客户端哪些字段有问题,问题是什么。

代码语言:javascript
复制
{
    "timestamp": 1584868482621,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
    "errors": [
        {
            "codes": [
                "NotBlank.user.password",
                "NotBlank.password",
                "NotBlank.java.lang.String",
                "NotBlank"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.password",
                        "password"
                    ],
                    "arguments": null,
                    "defaultMessage": "password",
                    "code": "password"
                }
            ],
            "defaultMessage": "密码不能为空",
            "objectName": "user",
            "field": "password",
            "rejectedValue": null,
            "bindingFailure": false,
            "code": "NotBlank"
        }
    ],
    "message": "Validation failed for object='user'. Error count: 1",
    "path": "/user/1"
}

进入到服务里面抛出异常的处理机制

一般如果是在我们的服务里面报的错误,Spring boot默认会响应给浏览器的是一个状态码的500的服务器错误。

我们用postman模拟其他的渠道,返回的是:

代码语言:javascript
复制
{
    "timestamp": 1584869332592,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "java.lang.RuntimeException",
    "message": "user not exist",
    "path": "/user/1"
}

浏览器端自定义错误处理机制

虽然由spring boot提供的默认处理机制可以很好的处理我们的异常。但有时候,我们也要去自定义异常处理来满足我们特定的需求场景。那么该如何自定义异常处理的呢?

下面我们来实现404和500跳转到我们指定的页面,在我们的resources目录下创建我们相应的的html文件。注意文件目录和文件名要固定。

浏览器访问结果是跳转到我们特定的页面,

这种方式是安装spring boot的约束来自定义的,他仅能适用于浏览器的请求,而对app返回的任然是json。

其他的客户端自定义错误处理机制

有些时候,我们的想要的异常返回结果还需要有其他的错误信息。下面我来实现用户不存在的异常。并且返回的异常包含不存在的用户得id。

代码语言:javascript
复制
public class UserNotExistException extends RuntimeException {

  private static final long serialVersionUID = -6112780192479692859L;

  private String id;

  public UserNotExistException(String id) {
    super("user not exist");
    this.id = id;
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

}

我们在服务里面抛出这个异常

代码语言:javascript
复制
  @GetMapping("{id:\\d+}")
  @JsonView(User.UserDetailView.class)
  public User getUserInfo(@PathVariable(name = "id") String id){
        throw new UserNotExistException(id);
  }

用我们postman访问:

代码语言:javascript
复制
{
    "timestamp": 1584870909493,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "com.zhaohong.exception.UserNotExistException",
    "message": "user not exist",
    "path": "/user/1"
}

我们可以看到异常变了,是UserNotExistException,由于默认情况下,返回的异常不会去读message之外的信息,所以返回的结果中并没有包含用户的id,那么如何把这个id返回给前台。

下面我们自定义一个异常处理器。

代码语言:javascript
复制
@ControllerAdvice
public class ControllerExceptionHandler {

  @ExceptionHandler(UserNotExistException.class)
  @ResponseBody
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  public Map<String, Object> handleUserNotExistException(UserNotExistException ex) {
    Map<String, Object> result = new HashMap<>();
    result.put("id", ex.getId());
    result.put("message", ex.getMessage());
    return result;
  }

}

@ExceptionHandler指定了要捕获的异常,@ResponseStatus指定返回的状态码。

我们再次反问服务,结果是返回:

代码语言:javascript
复制
{
    "id": "user not exist",
    "message": "user not exist"
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java患者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 进入到服务里面抛出异常的处理机制
  • 浏览器端自定义错误处理机制
  • 其他的客户端自定义错误处理机制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档