若依前后端分离版分页数据 knife4j 文档响应参数查看不到类型说明
前言
自从接入了 Knife4(swagger 增强版) 后,前端同事对于接口的要求就提高了。要求参数是否必要的属性,要标注准确。这个好解决,多定义几个 DTO
、VO
之类的,一个请求响应定义一个 VO
和 DTO
肯定能解决。后面发现有的接口返回数据(data
)没有参数类型说明,主要集中在使用 AjaxResult
的静态方法返回数据时出现。
后来发现,使用 R
的静态方法返回数据就可以正常显示。对比了一下,两者返回的内容都差不多,所以可以使用 R
对 AjaxResult
返回类型进行替换。
但后面发现一个 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)
包一下完全没问题。舍弃若依封装好的方法,似乎可以解决这个问题。
但还是决定研究一下为什么 AjaxResult
、TableDataInfo
之类的定义的响应数据结构不能被 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智能回答