Spring boot的异常处理

微信公众号:Java患者
专注Java领域技术分享

Spring boot的默认异常处理机制

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

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

  // 如果请求头中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里面来告诉我们客户端哪些字段有问题,问题是什么。

{
    "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模拟其他的渠道,返回的是:

{
    "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。

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


}

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

  @GetMapping("{id:\\d+}")
  @JsonView(User.UserDetailView.class)
  public User getUserInfo(@PathVariable(name = "id") String id){
        throw new UserNotExistException(id);
  }

用我们postman访问:

{
    "timestamp": 1584870909493,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "com.zhaohong.exception.UserNotExistException",
    "message": "user not exist",
    "path": "/user/1"
}

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

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

@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指定返回的状态码。

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

{
    "id": "user not exist",
    "message": "user not exist"
}

查看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值