美文网首页
六、springBoot 全局异常处理

六、springBoot 全局异常处理

作者: 茶铺里的水 | 来源:发表于2018-05-21 18:09 被阅读151次

我们每次写一个接口,如果抛出一个异常给前端,会造成很不好的体验。如果每个接口都用try...catch包起来,工作量也非常大。

一、ErrorController 的应用

  • 首先,我们先模拟异常场景,直接写了个接口,抛出空指针异常
package com.springboot.my.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class HelloController {

    @RequestMapping("/")
    public String index(){
        log.info("index ...........");
        return "Greetings from Spring Boot!";
    }

    @RequestMapping("/exception")
    public String exception(){
        throw new NullPointerException();
    }
}
  • postman验证,服务端抛出了一次,但是客户端返回了正常的结果。
服务端日志 客户端接收结果1

这是因为 SpringBoot 默认提供了一个 /error 的映射,该映射被注册为 Servlet 容器中的一个全局错误页面用来合理处理所有的异常情况。

  • 自定义ErrorController
    默认的异常响应报文不符合我们定义的数据规范,我们可以自己定义一个新的 ErrorController,代码如下
    Result.java
package com.springboot.my.model;

import lombok.Data;

@Data
public class Result {
    private int code;
    private String msg;
    private Object data;

    public Result(int code,String msg){
        this.code = code;
        this.msg = msg;
    }
}

MExceptionController.java

package com.springboot.my.controller;

import com.springboot.my.model.Result;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class MExceptionController implements ErrorController{
    @Override
    public String getErrorPath() {
        return "/error";
    }
    @RequestMapping
    @ResponseBody
    public Result doHandleError() {
        return new Result(200,"服务器繁忙");
    }
}

postman再次验证返回如下,验证成功:

客户端接口结果2

二、ExceptionHandler 的使用

  • 我们可以在一个controller中加入如下代码,实现异常的捕捉,经postman验证成功
    @ExceptionHandler(Exception.class)
    public Result doHandleError() {
        return new Result(200,"服务器繁忙");
    }
  • 当然,如果每个controller都写一遍也很累,所以,我们可以定义一个BaseController,所有其他controller都要继承该父类即可。
package com.springboot.my.controller;

import com.springboot.my.model.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;

public class BaseController {

    @ExceptionHandler(Exception.class)
    public Result doHandleError() {
        return new Result(200,"服务器繁忙");
    }
}
  • 但是这样还有一个问题,万一哪次忘记继承BaseController了,异常信息又会再次暴露给用户,针对这种问题,我们可以使用注解***@ControllerAdvice ***来解决。代码示例如下,经postman验证通过。
package com.springboot.my.controller;

import com.springboot.my.model.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
@ResponseBody
public class BaseController {

    @ExceptionHandler(Exception.class)
    public Result doHandleError(Exception e) {
        e.printStackTrace();
        return new Result(200,"服务器繁忙");
    }
}

@ControllerAdvice
该注解是spring2.3以后新增的一个注解,主要是用来Controller的一些公共的需求的低侵入性增强提供辅助。

@ExceptionHandler
该注解是配合@ExceptionHandler一起使用的注解,自定义错误处理器,可自己组装json字符串,并返回到页面。

:我们可以在@ControllerAdice定义的类中,通过定义多个@ExceptionHandler捕捉不同的异常来实现不同的异常处理

相关文章

网友评论

      本文标题:六、springBoot 全局异常处理

      本文链接:https://www.haomeiwen.com/subject/okdqjftx.html