SpringBoot学习

SpringBoot 统一异常处理

2018-10-10  本文已影响0人  weisen

一、什么是异常处理

异常(exception) 是程序运行过程中发生的事件, 该事件可以中断程序指令的正常执行流程.
1当Java程序运行时出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象
2:然后把该异常对象提交给JAVA虚拟机
3:JAVA虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则程序终止
4:程序员可以自己编写代码来扑捉可能出现的异常,并编写代码来处理相应的异常.

二、实现方法

1、通过@ControllerAdvice@ExceptionHandler实现处理controller层的异常

@ControllerAdvice
@ResponseBody  //表示返回的对象,Spring会自动把该对象进行json转化,最后写入到Response中。
public class GlobalExceptionHandler {
​
    @ExceptionHandler(Exception.class) //表示让Spring捕获到所有抛出的SignException异常,并交由这个被注解的方法处理。
    @ResponseStatus(HttpStatus.BAD_REQUEST)  //表示设置状态码。
    String handleException(){
        return "Exception Deal!";
    }
}

这样方法 handleException() 就会处理所有 Controller 层抛出的 Exception 及其子类的异常。
又因为service层的异常会抛出到controller层,所以service层抛出的异常也会被handleException处理.

2、异常是处理了,但是希望前端页面能够看到统一的返回结果,如下:

{
    "code": "33316",
    "msg": "This is NullPointerException.",
    "data": null
}

创建统一的JSON返回对象,code:消息类型,message:消息内容,url:请求的url,data:请求返回的数据
如创建类ResponseDto,无论正确的返回还是异常返回,都返回这个类对象

public class ResponseDto<T> {
    //错误码
    private String code;
    //提示信息
    private String msg;
    //具体的内容
    private T data;
    public ResponseDto() {
    }
    public ResponseDto(String code, String msg) {
        this.code = code;
        this.msg = msg;
        this.data = null;
    }
    //getter和setter方法。。。
}

controller中,都返回这个对象,如下:

@RequestMapping(value = "/getUser")
    public ResponseDto getUser(String id){
        ResponseDto dto  = new ResponseDto();
        dto.setCode("10000");
        dto.setMsg("操作成功");
        dto.setData(userServiceImpl.getUser(id));
        return dto;
    }
​
    @RequestMapping(value = "/listUser")
    public ResponseDto getUser(){
        ResponseDto dto  = new ResponseDto();
        dto.setCode("10000");
        dto.setMsg("操作成功");
        dto.setData(userServiceImpl.listUser());
        return dto;
    }

看到有重复代码,那就需要将重复代码提取出来,写一个工具类ResultUtil,在类中定义方法

 public static ResponseDto success(Object object){
        ResponseDto result = new ResponseDto();
        result.setCode("10000");
        result.setMsg("操作成功");
        result.setData(object);
        return result;
    }

这样controller中的方法就可以改为:

    @RequestMapping(value = "/getUser")
    public ResponseDto getUser(String id){
        return ResultUtil.success(userServiceImpl.getUser(id));
    }
​
    @RequestMapping(value = "/listUser")
    public ResponseDto getUser(){
        return ResultUtil.success(userServiceImpl.listUser());
    }

异常处理的handleException方法也要做出对应的修改,这样处理异常的返回才能是对应的格式

    @ExceptionHandler(Exception.class) //表示让Spring捕获到所有抛出的SignException异常,并交由这个被注解的方法处理。
    @ResponseBody  //表示返回的对象,Spring会自动把该对象进行json转化,最后写入到Response中。
    @ResponseStatus(HttpStatus.BAD_REQUEST)  //表示设置状态码。
    String handleException(){
        logger.error("Exception Deal!") ;
        return ResultUtil.error(CommonConstant.RESPONSE_CODE_UNKNOW_EXCEPTION,e.getMessage());
    }

三、对参数进行校验。

 //添加全局异常处理流程,根据需要设置需要处理的异常,本文以MethodArgumentNotValidException为例
    @ExceptionHandler(value=MethodArgumentNotValidException.class)
    public Object MethodArgumentNotValidHandler(HttpServletRequest request,
                                                MethodArgumentNotValidException exception) {
        List<ObjectError> errors =exception.getBindingResult().getAllErrors();
        StringBuffer errorMsg=new StringBuffer();
        errors.stream().forEach(x -> errorMsg.append(x.getDefaultMessage()).append(";"));
        logger.error("---MethodArgumentNotValidException Handler--- ERROR: {}", errorMsg.toString());
        respBean.setRespCode(RespCodeConstant.VALIDATE_ERROR);
        respBean.setRespDesc(RespCodeConstant.VALIDATE_ERROR_DESC);
        respBean.setRespData(errorMsg.toString());
        return respBean;
    }

在contorller中的方法中添加@Validated校验

public RespBean getWeeklyVisitTrend(@RequestBody @Validated ParamsDto dto) {

在ParamsDto 里面的字段添加上具体的校验,以及出错时打印的信息

@NotBlank(message = "params.dto.begin.date.null")
    private String begin_date;
上一篇 下一篇

猜你喜欢

热点阅读