异常这样处理,对用户更友好

856 阅读2分钟

在项目中,经常有一些业务需要抛出异常,但是如果后台直接抛出throw new Exception的话,前端就很难看,对用户提示也不够友好,今天我们就来解决这个问题。

先建立一个工程,模拟将异常抛出。如下:

@RestController
public class DemoController {

    @GetMapping("test")
    public String test() throws Exception{
        if(true){
            throw new Exception("error");
        }
        return "ok";
    }
}

前端用浏览器请求下,看看界面什么样子:

@ControllerAdvice@ExceptionHandler

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
        @ExceptionHandler
        @ResponseBody
        @ResponseStatus(HttpStatus.OK)
        public ResultDto globalException(HttpServletResponse response, Exception ex){
                log.info("ExceptionHandler...");
                log.info("错误代码:"  + response.getStatus());
                ResultDto resultDto = new ResultDto();
                resultDto.setCode(0);
                resultDto.setMsg(ex.getMessage());
                resultDto.setData(null);
                return resultDto;
        }
}

定义个返回到前端的通用结构体

@Data
public class ResultDto {
    //请求结果0表示失败,其他是成功
    private int code;
    //失败的消息
    private String msg;
    //实际返回到前端的数据
    private Object data;
}

然后我们写一个controller模拟抛出异常

@GetMapping("test1")
public String test1() throws Exception{
    if(true){
        throw new NullPointerException("NullPointerException");
    }
    return "ok";
}

@GetMapping("test2")
public String test2() throws Exception{
    if(true){
        throw new RuntimeException("RuntimeException");
    }
    return "ok";
}

@GetMapping("test3")
public String test3() throws MyException{
    if(true){
        //不能直接拋Exception 否则不能捕获,可以自己定义一个异常
        throw new MyException("MyException");
    }
    return "ok";
}

请求下,看看postman返回的是什么

{
    "code": 0,
    "msg": "NullPointerException",
    "data": null
}

在实际业务中我们通常返回自定义的异常,那么我接下来定义一个自己的异常,并对自己的异常进行单独的处理:

public class MyException extends Exception {
    public MyException() {
        super();
    }

    public MyException(String message) {
        super(message);
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }

    public MyException(Throwable cause) {
        super(cause);
    }

    protected MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

然后在GlobalExceptionHandler中增加对MyException的处理:

@ExceptionHandler(MyException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ResultDto myException(HttpServletResponse response, MyException ex){
        log.info("MyExceptionHandler...");
        log.info("错误代码:"  + response.getStatus());
        ResultDto resultDto = new ResultDto();
        resultDto.setCode(0);
        resultDto.setMsg(ex.getMessage());
        resultDto.setData(null);
        return resultDto;
}

请求http://localhost:8080/test3看看输出到前端的是什么

{
    "code": 0,
    "msg": "MyException",
    "data": null
}

这里其实看不出来到底走的是myException还是globalException但是如果你看后台日志输出就能清晰的看到。因此我们在对多种异常进行处理的时候springboot会优先处理子类异常。

更多java原创阅读:javawu.com