springboot3,knife4j结合javadoc,无需注解就可以生成满意的swagger-ui文档!
在springboot3中,我们一般使用kneif4j来集成springdoc,进而swagger-ui。swagger-ui需要在我们的类上增加很多注解,但我们通常开发是使用javadoc来完成注释的。幸运的是,springdoc也可以解析javadoc自动生成相关内容,不再需要增加额外的注解。该功能可以解析model类上面的注释,字段的注释,controller类上面的注释,方法上的注释,包括
在springboot3中,我们一般使用knife4j来集成springdoc,进而集成swagger-ui。
可swagger-ui需要在我们的类上增加很多注解,而我们通常开发是使用javadoc来完成注释的。
幸运的是,springdoc也可以解析javadoc自动生成相关内容,不再需要增加额外的注解。
该功能可以解析model类上面的注释,字段的注释,controller类上面的注释,方法上的注释,包括方法javadoc里面的 @param和 @return 都可以解析。
下面是具体是使用方案.
使用方案
首先引入knife4j,为了集成javadoc,还要引入therapi-runtime-javadoc
,注意 maven-compiler-plugin
也要做修改,pom参考:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-3</name>
<description>springboot-3</description>
<properties>
<java.version>17</java.version>
<knife4j.version>4.5.0</knife4j.version>
<therapi-runtime-javadoc.version>0.15.0</therapi-runtime-javadoc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.27</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>com.github.therapi</groupId>
<artifactId>therapi-runtime-javadoc</artifactId>
<version>${therapi-runtime-javadoc.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>com.github.therapi</groupId>
<artifactId>therapi-runtime-javadoc-scribe</artifactId>
<version>${therapi-runtime-javadoc.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
然后,我们在application.yaml里面启用knife4j:
knife4j:
enable: true
编写一个TestController,看看生成的api文档是否可以解析javadoc:
/**
* 测试接口集合
*/
@RestController
public class TestController {
/**
* 测试接口
* @param testParam 测试参数
* @return 测试返回值
*/
@GetMapping("/test")
public String test(String testParam) {
return testParam;
}
}
访问 http://localhost:8080/doc.html :
可以看到,我们写的javadoc已经被解析成功。
但是,美中不足的是,我们在controller类上面写的注释,没有被识别成组,如图箭头所示。这个是因为springdoc解析controller上面的注释时,把他映射成@Tag的description
属性,而name
则使用类名生成。而knife4j显示的是name
字段,这个可以通过访问 http://localhost:8080/swagger-ui.html 验证:
那么,我们有没有什么办法把它的description
字段写到name
上,让knife4j显示的更加友好呢?
增强方案
springdoc提供了修改器,可以修改生成后的api,我们自定义一个修改器,发现name
是snake格式,并且description
字段有值的Tag,就把他的description
改到name
字段上,参考代码如下:
@Component
@Slf4j
public class TagJavadocOpenApiCustomizer implements GlobalOpenApiCustomizer {
private static final Logger log = LoggerFactory.getLogger(TagJavadocOpenApiCustomizer.class);
private Predicate<String> snakeNameMatcher = Pattern.compile("^[a-zA-Z0-9-]+$").asPredicate();
@Override
public void customise(OpenAPI openApi) {
log.info("TagJavadocOpenApi OpenApiCustomizer");
// 把 controller上面的注释 生成TAG
// 官方默认是把注释弄成了description,但是我们希望他的变成tag
if (openApi.getTags() == null) {
return;
}
List<Tag> tags = openApi.getTags();
for (Tag tag : tags) {
if (snakeNameMatcher.test(tag.getName()) && StringUtils.isNotEmpty(tag.getDescription())) {
String newName = tag.getDescription();
// 同步修改映射关系
openApi.getPaths().forEach((s, pathItem) -> {
List<Operation> operations = new ArrayList<>();
addIfNotNull(operations, pathItem.getGet());
addIfNotNull(operations, pathItem.getDelete());
addIfNotNull(operations, pathItem.getDelete());
addIfNotNull(operations, pathItem.getOptions());
addIfNotNull(operations, pathItem.getPatch());
addIfNotNull(operations, pathItem.getPost());
addIfNotNull(operations, pathItem.getPut());
addIfNotNull(operations, pathItem.getTrace());
for (Operation operation : operations) {
for (int i = 0; i < operation.getTags().size(); i++) {
if (operation.getTags().get(i).equals(tag.getName())) {
operation.getTags().set(i, newName);
}
}
}
});
tag.name(newName);
}
}
}
private <T> void addIfNotNull(List<T> original, T itemsToAdd) {
if (itemsToAdd != null) {
original.add(itemsToAdd);
}
}
}
自定义的Customizer,只要注册成spring的bean,就会被自动应用。修改后结果如下:
可以看到,我们的注释都已经被成功解析了。

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)