若依前后端分离版分页数据 knife4j 文档响应参数查看不到类型说明

2024-08-29T15:51:00

前言

自从接入了 Knife4(swagger 增强版) 后,前端同事对于接口的要求就提高了。要求参数是否必要的属性,要标注准确。这个好解决,多定义几个 DTOVO 之类的,一个请求响应定义一个 VODTO 肯定能解决。后面发现有的接口返回数据(data)没有参数类型说明,主要集中在使用 AjaxResult 的静态方法返回数据时出现。

后来发现,使用 R 的静态方法返回数据就可以正常显示。对比了一下,两者返回的内容都差不多,所以可以使用 RAjaxResult 返回类型进行替换。

但后面发现一个 TableDataInfo,主要通过 getDataTable(List<?> list) 来添加行数等信息:

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected TableDataInfo getDataTable(List<?> list)
    {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }

这个 getDataTable 与封装的 startPage 都是成对出现,配合使用。用的也是 PageHelper 分页插件。

之前的分页服务层返回 PageInfo.of(list) 数据,控制器再使用这个 R.ok(list) 包一下完全没问题。舍弃若依封装好的方法,似乎可以解决这个问题。

但还是决定研究一下为什么 AjaxResultTableDataInfo 之类的定义的响应数据结构不能被 swagger 识别,而 R 可以。

研究过程

其实从返回类型的定义上差别就很清楚了。普通的返回类型为类型本身,而 R 可以额外定义内部使用的范型类型,比如: R<Integer>

Swagger 整合 Knife4j 增强遇到的问题:接口文档没有字段说明 中解释了两种不显示参数说明可能的原因:

统一返回封装类是 Map 类型:因为无论是 Map 还是 HashMap 等,这些类型对于 Swagger 来说都是未定义结构的数据,而其只认定义好的类-属性,所以同时如果是 Object 这个顶级父类也不行。

类定义了泛型但属性不是泛型,同时需要自动生成 get、set 方法,插件才会将代码生成返回 Object

并且,还需要 接口层强指定泛型类型才生效

所以现在要做的,就是改写分页数据对象,还有 BaseController 中定义的工厂方法 getDataTable

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected <T> TableDataInfo<T> getDataTable(List<T> list)
    {
        TableDataInfo<T> rspData = new TableDataInfo<>();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }

TableDataInfo 类修改:

...
public class TableDataInfo<T> implements Serializable
...

    /** 列表数据 */
    private List<T> rows;
...

    /**
     * 分页
     * 
     * @param list 列表数据
     * @param total 总记录数
     */
    public TableDataInfo(List<T> list, int total)
    {
        this.rows = list;
        this.total = total;
    }

...

    public List<T> getRows()
    {
        return rows;
    }

    public void setRows(List<T> rows)
    {
        this.rows = rows;
    }

其中部分范型类型为 List<?> 也统一改成 List<T>,据说会有影响。

最后,是接口层强指定泛型类型:

    public TableDataInfo<DetailDTO> details(DetailVO detailVO)
    {
        startPage();
        List<DetailDTO> list = bizDeviceService.storageDetails(detailVO);
        return getDataTable(list);
    }

结尾

对于 Java 的高级编程部分早忘干净了,现在一点一点的熟悉补回来。

? 和 T 的 关联和区别

在 Java 中,? 和 T 通常不单独使用,它们被用作泛型的一部分。T 通常用来表示类型参数,而 ? 则用来表示不确定的类型。

泛型是Java SE 1.5的新特性,全称为Parameterized Type(参数化类型)。在泛型出现之前,对于类似List这样的集合类,我们通常会使用Object类型来进行存储,这样一来,取出来的时候就需要进行类型的强制转换,这种转换是不安全的,可能会引发ClassCastException异常。

泛型的出现,就是为了解决这个问题。我们可以在创建集合的时候,指定集合中元素的类型。

有时候,我们可能希望创建一个可以持有不同类型参数的集合,这时候,我们可以使用通配符?。

T 是一个具体的类型,它在使用泛型的时候确定下来。

? 表示不确定的类型,它可以匹配任何类型。

注意:? 和 T 可以结合使用,例如 ? extends T 和 ? super T,表示上界和下界。

—— 摘自百度AI智能回答

当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »