spring boot 统一结果封装

为什么要统一返回值

在我们做前后端应用的时候 , 前后端分离的情况下 , 我们经常会定义一个数据格式,通常会包含code , message, data 这三个不可少的信息来方便我们的交流

创建Result 来包装我的数据

@Data
public class Result {
    private Integer code;
    private String message;
    private Object data;
}

创建测试Controller

@RestController
public class TestController {

    @GetMapping("test")
    public Result test(){

        Map<String, Object> map = new HashMap<>();
        map.put("test",2 );

        Result result = new Result();
        result.setCode(200);
        result.setMessage("成功");
        result.setData(map);
        return result;
    }
}

请求 /test 返回结果如下

{
  "code": 200,
  "message": "成功",
  "data": {
    "test": 2
  }
}

这样写没什么问题 , 但是我们需要在每个方法中都这样写、这样比较繁琐,我们把Result 类重构下

@Data
public class Result {
    private Integer code;
    private String message;
    private Object data;

    public Result(Integer code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static Result success() {
        return new Result(200,"成功",null);
    }

    public static Result success(Object data) {
        return new Result(200,"成功",data);
    }

    public static Result error() {
        return new Result(201,"失败");
    }
}

重构Controller

@RestController
public class TestController {

    @GetMapping("test")
    public Result test(){

        Map<String, Object> map = new HashMap<>();
        map.put("test",2 );
        return Result.success(map);
    }
}

访问

{
  "code": 200,
  "message": "成功",
  "data": {
    "test": 2
  }
}

结果是一样的,但是controller中的代码量变少了 ,到这里我们发现 code都是直接定义的没有一个统一管理的地方
我们新建一个 ResultCode 来管理所有结果码和对应的信息

@Getter
public enum ResultCode {
    //成功返回结果
    SERVICE_OK(200,"成功!"),
    //返回失败结果
    SERVICE_ERR(201,"失败");

    private String msg;
    private int code;

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

在重构下Result

@Data
public class Result {
    private Integer code;
    private String message;
    private Object data;

    public Result() {
    }

    public Result(ResultCode apiCode, Object data) {
        this.code = apiCode.getCode();
        this.message = apiCode.getMsg();
        this.data = data;
    }

    public Result(ResultCode apiCode) {
        this.code = apiCode.getCode();
        this.message = apiCode.getMsg();
    }

    public static Result success() {
        return new Result(ResultCode.SERVICE_OK);
    }

    public static Result success(Object data) {
        return new Result(ResultCode.SERVICE_OK, data);
    }

    public static Result error(ResultCode apiCode) {
        return new Result(apiCode);
    }
}

重构Controller

@RestController
public class TestController {

    @GetMapping("test")
    public Result test(){
        Map<String, Object> map = new HashMap<>();
        map.put("test",2 );
        return Result.success(map);
    }

    @GetMapping("test2")
    public Result test2(){
        return Result.error(ResultCode.SERVICE_ERR);
    }
}

访问 /test

{
  "code": 200,
  "message": "成功!",
  "data": {
    "test": 2
  }
}

访问/test2

{
  "code": 201,
  "message": "失败",
  "data": null
}

到这里感觉大功告成了 , 其实不然,请看如下代码

@RestController
public class TestController {

    @GetMapping("test")
    public Result test(){
        Map<String, Object> map = new HashMap<>();
        map.put("test",2 );
        return Result.success(map);
    }

    @GetMapping("test2")
    public Result test2(){
        Integer.parseInt("sdf1");
        return Result.error(ResultCode.SERVICE_ERR);
    }
}

访问/test2


image.png

我们用 Integer.parseInt("sdf1"); 来模拟开发中service 的异常。 当然我们可以使用try{}catch 来把异常拦截掉。每个Controller的方法都需要 try catch 代码重复率其实很高的,也不方便后期维护。

要解决这个问题就需要使用我们今天的主角了@ControllerAdvice

首先新建 ResultException 自定义异常

@ControllerAdvice
public class ExceptionHandle {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result handle(Exception e) {
        if (e instanceof ResultException) {
            ResultException resultException = (ResultException) e;
            return Result.error(resultException.getResultCode());
        }else {
            return Result.error(ResultCode.SERVICE_ERR);
        }
    }
}

新建 ExceptionHandle

@ControllerAdvice
public class ExceptionHandle {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result handle(Exception e) {
        if (e instanceof ResultException) {
            ResultException resultException = (ResultException) e;
            return Result.error(resultException.getResultCode());
        }else {
            return Result.error(ResultCode.SERVICE_ERR);
        }
    }
}

我们在把Controller 重构下

@GetMapping("test2")
    public Result test2(){
        Integer.parseInt("sdf1");
        return null;
    }

请求/test2

{
  "code": 201,
  "message": "失败",
  "data": null
}

我们看到结果 统一异常拦截器把我们的异常拦截返回了我们统一封装类信息

我们在把Controller 重构下

@RestController
public class TestController {

    @GetMapping("test2")
    public Result test2(){
        throw new ResultException(ResultCode.SERVICE_ERR);
    }
}

这次我们主动把异常抛出,指定我们的状态码

{
  "code": 201,
  "message": "失败",
  "data": null
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容