Knife4j @ApiModelProperty position不生效--避坑

443 阅读1分钟

Knife4j底层基于swagger,做了许多增强,UI比swagger更友好。

我在项目中使用了Knife4j-3.0.3,官方文档说是基于swagger2-2.10.5,我实际调试时应该引用的是swagger2-3.0.0

在给DTO注解@ApiModelProperty时,默认UI端看到的Model字段是按照字母顺序排列的。但是有时候我们想将一些重要的字段放在前面,这时候就何以指定position值。

@Data
@ApiModel(value = "测试参数DTO")
public class ParamDto{

    @ApiModelProperty(value = "id", position = 1)
    private Integer id;

    @ApiModelProperty(value = "名称", position = 2)
    private String name;

    @ApiModelProperty(value = "年龄", position = 3)
    private Integer age;

    @ApiModelProperty(value = "地址", position = 4)
    private String addr;
}

然鹅,,,

添加图片注释,不超过 140 字(可选)

实际测试发现position根本不生效,官方GitHub的issue中有人提到这个bug,作者说版本2.4.9版本就修复了,但是还是有人提到这个bug依然存在。找了很久都没有解决,包括一些博客说的重新实现ModelPropertyBuilderPlugin和OperationBuilderPlugin类。

无奈看了半天源码,终于在springfox.documentation.swagger2.mappers.CompatibilityModelMapper类中找到问题:

package springfox.documentation.swagger2.mappers;

@Mapper(
    componentModel = "spring"
)
public abstract class CompatibilityModelMapper {
    @Autowired
    @Value("${springfox.documentation.swagger.v2.use-model-v3:true}")
    private boolean useModelV3;

    public CompatibilityModelMapper() {
    }

    Map<String, Model> modelsFromApiListings(Map<String, List<ApiListing>> apiListings) {
        if (this.useModelV3) {
            return ((ModelSpecificationMapper)Mappers.getMapper(ModelSpecificationMapper.class)).modelsFromApiListings(apiListings);
        } else {
            Map<String, springfox.documentation.schema.Model> definitions = new TreeMap();
            apiListings.values().stream().flatMap(Collection::stream).forEachOrdered((each) -> {
                definitions.putAll(each.getModels());
            });
            return ((ModelMapper)Mappers.getMapper(ModelMapper.class)).mapModels(definitions);
        }
    }
}

其中useModelV3这个配置属性默认true,分支走到ModelSpecificationMapper,这个类中对Model属性做排序时用的Comparator::naturalOrder(),就是按照字母表顺序排列。而下面的分支ModelMapper才是使用的先position后name的排序方式。

总结:修改配置

application.properties:

springfox.documentation.swagger.v2.use-model-v3=false

application.yml:

springfox:
  documentation:
    swagger:
      v2:
        use-model-v3: false