前言
swagger接口文档侵入性比较强, 本来计划基于java注释做一个开源组件。经过调研选择了 JavaParser
, 奈何解决不了jar包的注释问题, 所以最终放弃了, 仅记录下调研过程中的单元测试~
基于javaparser-core实现
maven依赖
1 2 3 4 5
| <dependency> <groupId>com.github.javaparser</groupId> <artifactId>javaparser-core</artifactId> <version>3.22.1</version> </dependency>
|
提取注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| package cn.idea360.docs;
import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.javadoc.Javadoc; import com.github.javaparser.javadoc.JavadocBlockTag; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test;
import java.io.File; import java.util.List; import java.util.Optional;
public class JavaParserTest {
CompilationUnit cu; @BeforeEach public void runBeforeTestMethod() throws Exception{ File javaFile = new File("/Users/cuishiying/work/rest-docs/src/main/java/cn/idea360/docs/controller/UserController.java"); JavaParser javaParser = new JavaParser(); ParseResult<CompilationUnit> parseResult = javaParser.parse(javaFile); parseResult.ifSuccessful(compilationUnit -> { cu = compilationUnit; });
}
@Test void t1() { List<Comment> comments = cu.getComments(); System.out.println(comments); }
@Test void t2() { for (Comment comment : cu.getAllContainedComments()) { String content = comment.getContent(); System.out.println(content); } }
@Test void t3() { for (Comment comment : cu.getAllContainedComments()) { Javadoc parse = comment.asJavadocComment().parse(); String methodDesc = parse.getDescription().toText(); System.out.println("方法注释:" + methodDesc); List<JavadocBlockTag> blockTags = parse.getBlockTags(); for (JavadocBlockTag javadocBlockTag: blockTags) { Optional<String> name = javadocBlockTag.getName(); name.ifPresent(k -> { String text = javadocBlockTag.getContent().getElements().get(0).toText(); System.out.println("参数注释: " + k + ":" + text); }); } } }
@Test void t4() { Optional<ClassOrInterfaceDeclaration> userController = cu.getClassByName("UserController"); userController.ifPresent(c -> { c.getJavadoc().ifPresent(javadoc -> { String methodDesc = javadoc.getDescription().toText(); System.out.println("方法注释:" + methodDesc); List<JavadocBlockTag> blockTags = javadoc.getBlockTags(); for (JavadocBlockTag javadocBlockTag: blockTags) { String name = javadocBlockTag.getTagName(); String content = javadocBlockTag.getContent().toText(); System.out.println("参数注释: " + name + ":" + content); } }); }); }
}
|
基于therapi-runtime-javadoc实现
maven依赖
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>com.github.therapi</groupId> <artifactId>therapi-runtime-javadoc</artifactId> <version>0.12.0</version> </dependency> <dependency> <groupId>com.github.therapi</groupId> <artifactId>therapi-runtime-javadoc-scribe</artifactId> <version>0.12.0</version> </dependency>
|
示例controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package cn.idea360.docs.controller;
import cn.idea360.docs.model.User; import org.springframework.web.bind.annotation.*;
@RestController public class ExampleController {
@GetMapping("/example/{id}") public String exampleMethod(@PathVariable Long id, @RequestParam String name, @RequestParam int age, @RequestBody User user) { return "Hello " + name + ", age " + age; } }
|
注释提取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| package cn.idea360.docs;
import cn.idea360.docs.controller.ExampleController; import com.github.therapi.runtimejavadoc.ClassJavadoc; import com.github.therapi.runtimejavadoc.MethodJavadoc; import com.github.therapi.runtimejavadoc.ParamJavadoc; import com.github.therapi.runtimejavadoc.RuntimeJavadoc; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.StandardReflectionParameterNameDiscoverer; import org.springframework.web.bind.annotation.GetMapping;
import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors;
public class ApiDocGenerator {
public static void main(String[] args) { try { Class<?> clazz = ExampleController.class; ClassJavadoc classJavadoc = RuntimeJavadoc.getJavadoc(clazz); System.out.println("Class: " + classJavadoc.getComment()); System.out.println();
for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(GetMapping.class)) { MethodJavadoc methodJavadoc = RuntimeJavadoc.getJavadoc(method);
System.out.println("Method: " + method.getName());
System.out.println("Description: " + methodJavadoc.getComment()); System.out.println();
ParameterNameDiscoverer parameterNameDiscoverer = new StandardReflectionParameterNameDiscoverer(); String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
Parameter[] parameters = method.getParameters();
if (parameterNames != null && parameters.length == parameterNames.length) { for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; String parameterName = parameterNames[i]; System.out.println("Parameter name: " + parameterName); System.out.println("Parameter type: " + parameter.getType().getName()); Map<String, ParamJavadoc> paramJavadocMap = methodJavadoc.getParams().stream().collect(Collectors.toMap(ParamJavadoc::getName, Function.identity())); System.out.println("Parameter description: " + (Objects.isNull(paramJavadocMap.get(parameterName)) ? "No description" : paramJavadocMap.get(parameterName).getComment())); System.out.println(); } } else { System.out.println("No parameter names found or parameters length mismatch."); } } } } catch (Exception e) { e.printStackTrace(); } } }
|
最后
本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】支持一下。