一、接口展示中的问题

  现在大部分前后端的数据交互都是采用json格式,如我们经常用一个大的json包裹着数据发送的,但是在Swagger中,如果直接返回这个类对象,是展示不了data里面的数据的,更谈不上嵌套的json了,所以,为了让它能展示出data中的数据类型及格式,我们可以使用Java的泛型来做。

{
  "code": 0,
  "data": {},
  "msg": "string"
}

二、BaseResult工具类

  首先,我们要制定一个用于所有返回数据的最外层json框架的工具类,但是这个时候不能直接写这个类了,因为我们想在Swagger中显示内层数据的格式。Swagger是通过反射机制来展现类内部信息的,如果它只会返回一层数据的详细类型,即使类里面包含了其他类的对象,也不会再深入展示了,所以为了让它知道内部还有一个类对象要展示,那要传入这个对象的类型信息,所以要用到泛型。

package com.sc.springboot.utils;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;

//和以前唯一不一样的地方就是加了一个泛型T
@ApiModel("通用返回对象")  //注释这个类的信息
public class BaseResult<T> implements Serializable {
    //解释各字段的意思
    @ApiModelProperty(value = "返回码", dataType = "String")
    private int code;
    @ApiModelProperty(value = "提示信息", dataType = "String")
    private String msg;
    @ApiModelProperty(value = "返回值", dataType = "String")
    private T data;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    //几种构造方法
    public BaseResult() {
    }

    public BaseResult(BaseResult.Type type, String msg) {
        this.code = type.value;
        this.msg = msg;
    }

    public BaseResult(BaseResult.Type type, String msg, T data) {
        this.code = type.value;
        this.msg = msg;
        if (data != null) {
            this.data = data;
        }

    }
    //静态方法要使用泛型参数的话,要声明其为泛型方法
    public static <T> BaseResult<T> success() {
        return success("操作成功");
    }

    public  static <T> BaseResult<T> success(T data) {
        return success("操作成功", data);
    }

    public static <T> BaseResult<T> success(String msg) {
        return success(msg, (T) null);
    }

    public static <T> BaseResult<T> success(String msg, T data) {
        return new BaseResult<T>(BaseResult.Type.SUCCESS, msg, data);
    }

    public static <T> BaseResult<T> warn(String msg) {
        return warn(msg, (T) null);
    }

    public static <T> BaseResult<T> warn(String msg, T data) {
        return new BaseResult<T>(BaseResult.Type.WARN, msg, data);
    }


    public static <T> BaseResult<T> unAuth() {
        return new BaseResult<T>(Type.UNAUTH, "未登陆", (T)null);
    }

    public static <T> BaseResult<T> error() {
        return error("操作失败");
    }

    public static <T> BaseResult<T> error(String msg) {
        return error(msg, (T)null);
    }

    public static <T> BaseResult<T> error(String msg, T data) {
        return new BaseResult<T>(BaseResult.Type.ERROR, msg, data);
    }

    public static enum Type {
        SUCCESS(200),
        WARN(402),
        UNAUTH(401),
        ERROR(500);

        private final int value;

        private Type(int value) {
            this.value = value;
        }

        public int value() {
            return this.value;
        }
    }
}

这里编写的BaseResult类可以直接在工程中使用,和以前唯一的不同就是,在BaseResult返回值上带一个具体的data类型

三、使用BaseResult

1. 对应一个url该怎么返回数据

  唯一的变化就是,在返回的BaseResult需要加上你要返回的泛型参数即可

@ApiOperation("获取登录用户信息")
@ApiImplicitParams({
        @ApiImplicitParam(name = "token", value = "token信息", paramType = "header")
})
@ApiResponses({
        @ApiResponse(code=200,message = "请求成功"),
        @ApiResponse(code=401,message = "未登陆"),
})
@GetMapping("getuserinfo")
public BaseResult<Supplier> getUserOfLogin(HttpServletRequest request) throws UnsupportedEncodingException {
    //获取Headers中的参数
    String token = request.getHeader("token");
    //获取header,这是从Redis中获取登录信息
    Supplier user = (Supplier) redisTemplate.opsForValue().get(token);
    if(user != null){
        return BaseResult.success(user);
    }
    return BaseResult.unAuth();
}
2. swagger中的数据展示

在这里插入图片描述
在这里插入图片描述

  这样的返回信息,已经很棒了,但是有时候我们的json有会嵌套很多层,那么我们就需要嵌套多层泛型。

四、多层嵌套

1. 嵌入一层列表

  比如,我们返回的不知一个用户信息了,想返回一个列表,可以直接用泛型表示列表就行了

@GetMapping("/getuserlist")
private BaseResult<List<Supplier> > getUser(){
    List<Supplier> supplier = new LinkedList<>();
    return BaseResult.success(supplier);
}

在这里插入图片描述
在这里插入图片描述

2. 返回分页信息

  这种情况很常见,比如,我们要给数据分页,就得给出一个列表和一些页数信息,当前页,最大页等。
  我们可以单独创建一个分页类

package com.lonelyzhe.sc.bean;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel("分页类型")
public class DivPage<T> {
    @ApiModelProperty(value = "当前页数", dataType = "Integer")
    private Integer current_page;
    @ApiModelProperty(value = "最大页数", dataType = "Integer")
    private Integer max_page;
    @ApiModelProperty(value = "当前内容", dataType = "List")
    private T content;
    //省去了set、get方法,可以写上,或者用注解都行
}

  返回的时候,填写DivPage的泛型参数就行了

@GetMapping("/getpagelist")
private BaseResult<DivPage<List<Supplier>> > getUser(){
    List<Supplier> supplier = new LinkedList<>();
    DivPage<List<Supplier>> divPage = new DivPage<>();
    divPage.setCurrent_page(1);
    divPage.setMax_page(20);
    divPage.setContent(supplier);

    return BaseResult.success(divPage);
}

在这里插入图片描述
在这里插入图片描述

3. 对象里有另外的对象

  这种情况其实也挺多的,比如我们的用户有一个公司属性,但这个公司属性也是个对象,有公司id,公司名等,现在也要完整展示公司的信息,相当于嵌套里面有嵌套,其实和分页差不多,只是分页用的List本身就是泛型的,所以为了展示我们自己对象里的对象,需要把第一层对象设置为泛型。
(1)添加一个Company类

package com.lonelyzhe.sc.bean;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "公司")
public class Company {
    @ApiModelProperty(value = "公司id", dataType = "Integer")
    private Integer id;
    @ApiModelProperty(value = "公司名", dataType = "String")
    private String name;
    //省略get、set方法
}

(2)修改Supplier类,使其接收泛型参数

package com.lonelyzhe.jedisdemo.bean;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "供应商信息")
public class Supplier<T>{  //这里多加一个泛型参数
    @ApiModelProperty(value = "供应商id", dataType = "int")
    private Integer supplier_id;
    @ApiModelProperty(value = "供应商名称", dataType = "String")
    private String supplier_name;
    @ApiModelProperty(value = "一级分类", dataType = "String")
    private String primary_supplier;
    @ApiModelProperty(value = "二级分类", dataType = "String")
    private String secondary_supplier;
    @ApiModelProperty(value = "三级分类", dataType = "String")
    private String tertiary_supplier;
    @ApiModelProperty(value = "所属公司", dataType = "Company")
    private Company company;
}

(3)返回结果
在这里插入图片描述
在这里插入图片描述
  如果有很多层对象封装的话,那么每一层都需要泛型参数,如果一层中有多个封装的对象,那么可能要传入多个泛型参数。

五、总结

  刚开始接触swagger有点懵,为啥返回不了里面的类的字段呀,后来查阅了很多资料,说得用泛型,又回想到Java编程思量里管理泛型和反射的章节,感觉swagger返回参数的时候应该是只读取了一层类型,如果类里面还包含其他的类对象,它就不知道具体类型是什么,此时需要用泛型去指定这个参数,让它知道类内部对象的类型才行。
  当然,这只是最近研究的方法,如果有更好的方法就好,毕竟给每个类都加上泛型,还是麻烦的,增加了开发成本,不过相较于最后的自动Api结果,依然是真香!

GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 4 个月前
8c391e04 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐