统一异常处理和统一返回格式@RestControllerAdvice

闲来无事,自己的模块写完了,就看了看项目框架。之前有个大佬说很多公司都没做统一异常处理和统一返回处理,我现在公司做了,所以就看看。 首先,咱们了解一下什么是统一返回,统一返回就是一种规范,咱们自定义这种规范,从后端返回的数据都按这种规范来,这样前端更容易处理。一般都是用类,这种类都命名为Result

	//主要属性:
	@ApiModelProperty(notes = "状态")
    private int code;
    @ApiModelProperty(notes = "提示信息")
    private String message;
    @ApiModelProperty(notes = "返回内容")
    private T data;
    
    //然后自己定义一些构造方法如下:
    public Result() {
        this(SUCCESS, "success!");
    }

    public Result(int code, String message, T content) {
        this.code = code;
        this.message = message;
        this.data = content;
    }

    public Result(int code, String message) {
        this(code, message, null);
    }

    public static <T> Result<T> error() {
        return error(ERROR, "error!");
    }

    public static <T> Result<T> error(String msg) {
        return error(ERROR, msg);
    }

    public static <T> Result<T> error(int code, String msg) {
        return new Result<>(code, msg);
    }

    public static <T> Result<T> error(String msg, T content) {
        return new Result<>(ERROR, msg, content);
    }

    public static <T> Result<T> error(int code, String msg, T content) {
        return new Result<>(code, msg, content);
    }

    public static <T> Result<T> ok() {
        return new Result<>();
    }

    public static <T> Result<T> ok(String message) {
        return new Result<>(SUCCESS, message);
    }

    public static <T> Result<T> ok(T content) {
        return new Result<>(SUCCESS, "success!", content);
    }

    public static <T> Result<T> ok(int status, T content) {
        return new Result<>(status, "success!", content);
    }

    public static <T> Result<T> ok(int status, String message, T content) {
        return new Result<>(status, message, content);
    }

    @Override
    public boolean matching() {
        return this.code == 0;
    }
复制代码

定义好返回的类后,就可以开始编写统一返回处理了,在编写统一返回处理之前我们得了解一个接口类ResponseBodyAdvice,这个接口类如其名,主要是对ResponseBody的一个处理,也是就controller的响应进行一个处理。 它有两个方法,第一个方法,这里有两个参数,大家可以自行去了解一下哈,我只用到了returnType.getGenericParameterType(),这个方法是得到返回的数据类型,因此我们就可以判断返回的类型是不是我们规定的了。

 boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
复制代码

这个方法主要是判断需要不需要第二个方法beforeBodyWrite。

如果supports返回的true,就会执行第二个方法,如果返回false就不会执行第二个方法。所以第一个supports,能在定位到包的基础上更精确的处理一些返回值。

至于对返回值的统一处理就靠我们第二方法了。 方法中的body就是相应的返回值了,而returnType.getGenericParameterType()可以获取返回值的类型

  T beforeBodyWrite(T body, MethodParameter returnType, MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response);

复制代码

我们实现这个接口类,重写这两个方法,并且类上打上注解@RestControllerAdvice(basePackages = "XXX") 这个注解是拦截controller的,输入包路径后,就是指定的包路径了。 第一个方法,我们实现主要是判断返回类型是不是我们的规范类型,如果不是就返回true,就会执行第二个方法。 第二个方法就可以对数据进行一个处理了,我们就进行一个封装,这样返回类型就是统一规范了。如下:

   if (body == null) {
            return Result.ok();
        }
        if (body instanceof Result) {
            return body;
        }
        if (returnType.getGenericParameterType().equals(String.class)) {
            return body;
        }
        return Result.ok(body);
        
复制代码

完成上述步骤后,即使返回的为空,只要没报错都会有个状态码,和状态,以上就是返回统一格式。

接下来是统一异常处理,统一异常处理,也要用到@RestControllerAdvice注解,拦截所有controller,还有 @ExceptionHandler(),参数是指定异常类型,主要是用这两个注解。代码如下:

    public ResponseEntity<Object> customExceptionHandler(BaseCustomException exception) {
        log.error(exception.getLogMessage());
        return new ResponseEntity<>(Result.error(exception.getErrorCode(), exception.getMessage()), exception.getHttpStatus());
    }
复制代码
完成上述代码,这样遇到异常就能按我们的格式抛来了。自定义一个异常,这样就完成自定义异常处理了。
复制代码

猜你喜欢

转载自juejin.im/post/7036258117805408269