利用javadoc注釋自動生成Swagger注解
目的
可視化接口管理平臺,通過接口管理平臺一目了然知道接口的作用,接口上面擴展了哪些功能,從而做到對應用程序代碼零侵入
現(xiàn)狀
由于現(xiàn)在controller方法上面沒有swagger注解,只能拿到接口url地址,無法獲得接口功能描述。
值得慶幸的是我們的代碼非常規(guī)范每個方法都有標準的javadoc注釋,于是就想到了獲取javadoc注釋的描述自動生成swagger注解
思路
1,AOP切面,你會發(fā)現(xiàn)根本無法獲取javadoc,這個方案就直接pass掉了
2,讀文件流獲取文件內(nèi)容解析出想要的數(shù)據(jù),雖然可以但是費時費力,不是最優(yōu)的方案
3,使用開源的javaparser難道不香嗎,非常香就它了
javaparser
<dependency> <groupId>com.github.javaparser</groupId> <artifactId>javaparser-core</artifactId> <version>3.25.4</version> </dependency>
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import com.fuchuang.scm.common.util.ScmAssert;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/**
* 通過javadoc注釋自動生成Swagger注解
*
* @author xiongyan
* @date 2023/7/7
*/
public class Sw {
public static void main(String[] args) throws Exception {
String clientPath = "/Users/xiongyan/Documents/work/fc-cdc/fc-cdc-api/src/main/java/com/fc/cdc/controller";
String controllerPath = "/Users/xiongyan/Documents/work/fc-cdc/fc-cdc-api/src/main/java/com/fc/cdc/controller";
Map<String, ClassOrInterfaceDeclaration> clientMap = Sw.clientMap(clientPath);
File project = new File(controllerPath);
ScmAssert.isTrue(project.exists(), "項目路徑不存在");
for (File file : project.listFiles()) {
CompilationUnit cu = StaticJavaParser.parse(file);
ClassOrInterfaceDeclaration classDeclaration = cu.findFirst(ClassOrInterfaceDeclaration.class).orElse(null);
if (null == classDeclaration) {
continue;
}
String classComment = null;
Map<String, String> methodCommentMap = new HashMap<>();
if (classDeclaration.getImplementedTypes().size() > 0) {
String interfaceName = classDeclaration.getImplementedTypes(0).getNameAsString();
ClassOrInterfaceDeclaration interfaceDeclaration = clientMap.get(interfaceName);
if (null == interfaceDeclaration) {
continue;
}
if (interfaceDeclaration.getJavadoc().isPresent()) {
classComment = interfaceDeclaration.getJavadoc().get().getDescription().toText();
}
for (MethodDeclaration method : interfaceDeclaration.getMethods()) {
if (!method.getJavadoc().isPresent()) {
continue;
}
methodCommentMap.put(method.getNameAsString(), method.getJavadoc().get().getDescription().toText());
}
}
if (StrUtil.isEmpty(classComment)) {
if (classDeclaration.getJavadoc().isPresent()) {
classComment = classDeclaration.getJavadoc().get().getDescription().toText();
} else {
classComment = classDeclaration.getNameAsString();
}
}
if (!classDeclaration.getAnnotationByClass(Api.class).isPresent()) {
classDeclaration.addAndGetAnnotation(Api.class).addPair("value", "\"" + classComment + "\"");
}
for (MethodDeclaration method : classDeclaration.getMethods()) {
if (method.getAnnotationByClass(ApiOperation.class).isPresent()) {
continue;
}
String methodComment = methodCommentMap.get(method.getNameAsString());
if (StrUtil.isEmpty(methodComment)) {
if (method.getJavadoc().isPresent()) {
methodComment = method.getJavadoc().get().getDescription().toText();
} else {
methodComment = method.getNameAsString();
}
}
method.addAndGetAnnotation(ApiOperation.class).addPair("value", "\"" + classComment + "-" + methodComment + "\"");
}
FileOutputStream outputStream = new FileOutputStream(file);
outputStream.write(cu.toString().getBytes());
}
}
private static Map<String, ClassOrInterfaceDeclaration> clientMap(String path) throws FileNotFoundException {
File project = new File(path);
ScmAssert.isTrue(project.exists(), "項目路徑不存在");
Map<String, ClassOrInterfaceDeclaration> clientMap = new HashMap<>();
for (File file : project.listFiles()) {
CompilationUnit cu = StaticJavaParser.parse(file);
if (null == cu) {
continue;
}
ClassOrInterfaceDeclaration classDeclaration = cu.findFirst(ClassOrInterfaceDeclaration.class).orElse(null);
if (null != classDeclaration && classDeclaration.isInterface()) {
clientMap.put(classDeclaration.getNameAsString(), classDeclaration);
}
}
return clientMap;
}
}效果
/**
* 數(shù)據(jù)庫管理
*
* @author xiongyan
* @date 2023/03/13
*/
@RestController
@RequestMapping("/web/database")
public class WebDatabaseController {
/**
* 分頁列表
*
* @param request
* @return
*/
@PostMapping("/page")
public ScmResponse<ScmPage<DatabaseDto>> page(@RequestBody DatabaseRequest request) {
return ScmResponseUtil.success();
}
}/**
* 數(shù)據(jù)庫管理
*
* @author xiongyan
* @date 2023/03/13
*/
@RestController
@RequestMapping("/web/database")
@Api(value = "數(shù)據(jù)庫管理")
public class WebDatabaseController {
/**
* 分頁列表
*
* @param request
* @return
*/
@PostMapping("/page")
@ApiOperation(value = "數(shù)據(jù)庫管理-分頁列表")
public ScmResponse<ScmPage<DatabaseDto>> page(@RequestBody DatabaseRequest request) {
return ScmResponseUtil.success();
}
}可以看到通過javadoc自動生成了swagger注解,尤其是對于我們這樣微服務拆分很細的,應用非常多,接口更是多的,通過這種方式效率最高的
接口文檔
服務器啟動就可以把 接口應用名稱,接口URL地址,接口請求方式,接口描述,接口請求結構,接口響應結構 數(shù)據(jù)收集進行注冊自動生成接口文檔
接口擴展
1,數(shù)據(jù)脫敏
2,操作日志
3,防重復提交
4,接口冪等
5,接口限流
6,黑白名單
7,權限控制
8,。。。。。
到此這篇關于利用javadoc注釋自動生成Swagger注解的文章就介紹到這了,更多相關javadoc生成Swagger注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用通過ARP類似P2P終結者實現(xiàn)數(shù)據(jù)封包
目前網(wǎng)絡上類似P2P終結者這類軟件,主要都是基于ARP欺騙實現(xiàn)的,網(wǎng)絡上到處都有關于ARP的介紹,不過為了本文讀者不需要再去查找,我就在這里大概講解一下2012-12-12
確保SpringBoot定時任務只執(zhí)行一次的常見方法小結
在Spring Boot項目中,確保定時任務只執(zhí)行一次是一個常見的需求,這種需求可以通過多種方式來實現(xiàn),以下是一些常見的方法,它們各具特點,可以根據(jù)項目的實際需求來選擇最合適的方法,需要的朋友可以參考下2024-10-10
SpringBoot和MyBatis環(huán)境下實現(xiàn)動態(tài)數(shù)據(jù)源切換過程
dynamic-datasource-spring-boot-starter?是一個用于在SpringBoot和MyBatis環(huán)境下實現(xiàn)動態(tài)數(shù)據(jù)源切換的工具,它簡化了配置和切換邏輯,通過引入依賴,配置數(shù)據(jù)源和使用@DS注解,可以輕松實現(xiàn)數(shù)據(jù)源的動態(tài)切換2025-10-10

