前言:
Metersphere 官网支持IDEA插件可以一键导入到MS当中,但一些项目当中自己定义的注解并不支持解析,所以基于这个场景的考虑,自己准备适配一下自定义插件的解析。
官网插件地址:https://github.com/metersphere/metersphere-idea-plugin
去官网看到插件的结构,是通过java编写,gradle作为构建工具。平时使用Maven比较多,所以这边从0开始搭建一个插件环境。
![image.png](https://img-blog.csdnimg.cn/img_convert/3669572d76bc374c5767a50be4fcf838.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=264&id=u15a5d437&margin=[object Object]&name=image.png&originHeight=264&originWidth=678&originalType=binary&ratio=1&rotation=0&showTitle=false&size=20721&status=done&style=none&taskId=u4b1f3662-830e-4a81-84ae-b1e11114527&title=&width=678)
vi ~/.zshrc (我本地安装了item2,所以是这个文件。)
![image.png](https://img-blog.csdnimg.cn/img_convert/ef3d4bdde0ac04e6bcc8c3eb46740494.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=178&id=u6f51b3c7&margin=[object Object]&name=image.png&originHeight=178&originWidth=782&originalType=binary&ratio=1&rotation=0&showTitle=false&size=39100&status=done&style=none&taskId=udd245d3d-01e0-4999-ab3a-bb7e4024b6b&title=&width=782)
验证 gradle --version
![image.png](https://img-blog.csdnimg.cn/img_convert/f8c139a0328e21c5f83092d3c9405904.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=692&id=u64d90d99&margin=[object Object]&name=image.png&originHeight=692&originWidth=736&originalType=binary&ratio=1&rotation=0&showTitle=false&size=76102&status=done&style=none&taskId=u923677c1-1a9b-4a7e-899c-452665eed48&title=&width=736)
注意:安装gradle先安装jdk,安装jdk网上资料很多。
具体的用法不在这里介绍了,直接查看官网即可。
参考:
https://docs.gradle.org/7.4.2/userguide/what_is_gradle.html
https://www.iteye.com/blog/shmilyaw-hotmail-com-2345439
![image.png](https://img-blog.csdnimg.cn/img_convert/51006e44b6b8ca10d6bcaae900369e6f.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=598&id=ub29d539b&margin=[object Object]&name=image.png&originHeight=598&originWidth=915&originalType=binary&ratio=1&rotation=0&showTitle=false&size=130965&status=done&style=none&taskId=uef761640-a770-4e19-b457-098a661a649&title=&width=915)
官网模板是kotlin写的。
可以先看下整体的目录结构
.
├── .github/ GitHub Actions workflows and Dependabot configuration files
├── .run/ Predefined Run/Debug Configurations
├── gradle
│ └── wrapper/ Gradle Wrapper
├── build/ Output build directory
├── src Plugin sources
│ └── main
│ ├── kotlin/ Kotlin production sources 存放项目的源码
│ └── resources/ Resources - plugin.xml, icons, messages 存放项目的资源配置,图标,信息等
│ └── test
│ ├── kotlin/ Kotlin test sources
│ └── testData/ Test data used by tests
├── .gitignore Git ignoring rules
├── build.gradle.kts Gradle configuration
├── CHANGELOG.md Full change history
├── gradle.properties Gradle configuration properties
├── gradlew *nix Gradle Wrapper script
├── gradlew.bat Windows Gradle Wrapper script
├── LICENSE License, MIT by default
├── qodana.yml Qodana configuration file
├── README.md README
└── settings.gradle.kts Gradle project settings
plunig.xml
![image.png](https://img-blog.csdnimg.cn/img_convert/0457f1225a8f78ba154c0608938e23a4.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=706&id=u1da3d7a2&margin=[object Object]&name=image.png&originHeight=706&originWidth=1619&originalType=binary&ratio=1&rotation=0&showTitle=false&size=170116&status=done&style=none&taskId=uf82281f2-628c-43f3-bd57-8bef5dc9ca0&title=&width=1619)
<idea-plugin>
<id>org.jetbrains.plugins.template</id>
<name>Template</name>
<vendor>JetBrains</vendor>
<depends>com.intellij.modules.platform</depends>
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="..."/>
<projectService serviceImplementation="..."/>
</extensions>
<projectListeners>
<listener class="..." topic="..."/>
</projectListeners>
</idea-plugin>
了解了项目架构之后,开始自己搭建一个环境。
![image.png](https://img-blog.csdnimg.cn/img_convert/c771cab3d42c81ba6b2de63e2b877346.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=764&id=u5a38f55c&margin=[object Object]&name=image.png&originHeight=764&originWidth=823&originalType=binary&ratio=1&rotation=0&showTitle=false&size=122313&status=done&style=none&taskId=u6e8c8d34-a8e9-460a-8631-525f0532f81&title=&width=823)
新建之后的目录结构是这样子的:
![image.png](https://img-blog.csdnimg.cn/img_convert/71e67bc60626e62ac9008167f76aa5c7.png#clientId=u10e27521-f96f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=399&id=u24c91a51&margin=[object Object]&name=image.png&originHeight=399&originWidth=381&originalType=binary&ratio=1&rotation=0&showTitle=false&size=30610&status=done&style=none&taskId=u738d367a-1d19-4ef3-a9dc-953ae89ab13&title=&width=381)
src
--main
--java // 一般我们写的java文件都会放到这个里面。
--resources
--META-INF
--plugin.xml // 插件的配置文件
build.gradle // 构建gradle的配置文件,相当于maven里面的pom.xml文件,我们所需要的依赖信息都会放到这里面来。
**plugin.xml **
<idea-plugin>
<!-- 插件名称,别人在官方插件库搜索你的插件时使用的名称 -->
<name>MyPlugin</name>
<!-- 插件唯一id,不能和其他插件项目重复,所以推荐使用com.xxx.xxx的格式
插件不同版本之间不能更改,若没有指定,则与插件名称相同 -->
<id>com.example.plugin.myplugin</id>
<!-- 插件的描述 -->
<description>my plugin description</description>
<!-- 插件版本变更信息,支持HTML标签;
将展示在 settings | Plugins 对话框和插件仓库的Web页面 -->
<change-notes>Initial release of the plugin.</change-notes>
<!-- 插件版本 -->
<version>1.0</version>
<!-- 供应商主页和email-->
<vendor url="http://www.jetbrains.com" email="support@jetbrains.com" />
<!-- 插件所依赖的其他插件的id -->
<depends>MyFirstPlugin</depends>
<!-- 插件兼容IDEA的最大和最小 build 号,两个属性可以任选一个或者同时使用
官网详细介绍:http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html-->
<idea-version since-build="3000" until-build="3999"/>
<!-- application components -->
<application-components>
<component>
<!-- 组件接口 -->
<interface-class>com.foo.Component1Interface</interface-class>
<!-- 组件的实现类 -->
<implementation-class>com.foo.impl.Component1Impl</implementation-class>
</component>
</application-components>
<!-- project components -->
<project-components>
<component>
<!-- 接口和实现类相同 -->
<interface-class>com.foo.Component2</interface-class>
</component>
</project-components>
<!-- module components -->
<module-components>
<component>
<interface-class>com.foo.Component3</interface-class>
</component>
</module-components>
<!-- Actions -->
<actions>
...
</actions>
<!-- 插件定义的扩展点,以供其他插件扩展该插件 -->
<extensionPoints>
...
</extensionPoints>
<!-- 声明该插件对IDEA core或其他插件的扩展 -->
<extensions xmlns="com.intellij">
...
</extensions>
</idea-plugin>
到此,插件的环境已经搭建好了。
IDEA 插件官方提供了一些PSI接口,可以方便我们分析源代码文件。
![image.png](https://img-blog.csdnimg.cn/img_convert/883f22489a4da2f51b71edb1a1f0c53b.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=524&id=u56693021&margin=[object Object]&name=image.png&originHeight=524&originWidth=891&originalType=binary&ratio=1&rotation=0&showTitle=false&size=61072&status=done&style=none&taskId=ue0fd94f4-5ef6-44f6-9dbc-c8cf9eae1dc&title=&width=891)
官方介绍: 程序结构接口,通常被称为PSI,是IntelliJ 平台中负责解析文件和创建语法和语义代码模型的层,改模型支持平台的许多功能。
简单理解就是我们要想分析源代码文件的内容,就需要PSI的帮助。
我们知道,JVM在加载类之前,首先需要读取Class文件,并将Class文件解析成一个结构体对象,对应的是Class文件结构。与JVM解析Class文件不同的是,IDEA解析的Java的源代码,但IDEA也是将Java文件解析为一个结构体对象。
请记住一句话,对于任何拥有固定结构的文件或者代码,都可以使用访问者模式。
不仅Java文件,任何代码文件都会有一定的结构,否则编译器也不能识别,也是因为如此,IDEA实现的PSI与Java字节码操作工具ASM有非常多的相似之处,除了都是将文件解析成结构外,也都支持使用访问者模式编辑文件,一个大的结构下面包含许多小的结构,小的结构也支持使用访问者模式编辑。
因为很相似,所以我们可以用学习使用 ASM 工具分析、创建、或改写Class文件的思维去学习PSI。
由于不同的编程语言编写的代码文件有不同的结构,IDEA将文件结构抽象为接口,叫程序结构接口文件(PSI File),不同类型的文件解析后生成不同的PsiFile接口的实现类实例,这也是IDEA能够扩展支持多语言的基础。
一个文件就是一个PsiFile,也是一个文件的结构树的根节点,PsiFile是一个接口,如果文件是一个.java文件,那么解析生成的PsiFile就是PsiJavaFile对象,如果是一个Xml文件,则解析后生成的是XmlFile对象。
Class文件结构包含字段表、属性表、方法表等,每个字段、方法也都有属性表,但在PSI中,总体上只有PsiFile和PsiElement。
Element即元素,一个PsiFile(本身也是PsiElement)由许多的PsiElement构成,每个PsiElement也可以由许多的PsiElement构成。
PsiElement用于描述源代码的内部结构,不同的结构对应不同的实现类。
对应Java文件的PsiElement种类有:PsiClass、PsiField、PsiMethod、PsiCodeBlock、PsiStatement、PsiMethodCallExpression等等。其中,PsiField、PsiMethod都是PsiClass的子元素,PsiCodeBlock是PsiMethod的子元素,PsiMethodCallExpression是PsiCodeBlock的子元素,正是这种关系构造成了一棵树。
解析一个Java文件有上百种类型的PsiElement,对于一个新手,我们如何才能快速的认识对应Java代码文件中的每行代码都会解析生成呢?好在IDEA提供了PSI视图查看器。
如果你正在编写插件,那么IDEA会自动在“工具”菜单中显示“查看PSI结构”的选项,否则,我们需要修改IDEA的配置文件才能在“工具”菜单中看到这个选项。
工具
![image.png](https://img-blog.csdnimg.cn/img_convert/9ff52646579175364b8f57b926b4f173.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=232&id=u773fd499&margin=[object Object]&name=image.png&originHeight=232&originWidth=1080&originalType=binary&ratio=1&rotation=0&showTitle=false&size=44279&status=done&style=none&taskId=u8c581cb9-d367-462f-9e0f-73092145907&title=&width=1080)
配置文件在IDEA安装路径的bin目录下,找到idea.properties文件,如下图所示。
![image.png](https://img-blog.csdnimg.cn/img_convert/04dd6a99d859649e5667add5a67ff2b6.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=866&id=u68a3f9c6&margin=[object Object]&name=image.png&originHeight=866&originWidth=1670&originalType=binary&ratio=1&rotation=0&showTitle=false&size=537693&status=done&style=none&taskId=uf9dd44fd-2628-44b9-a7ea-07554ba4f6a&title=&width=1670)
添加配置后重启IDEA就能看到tools菜单下新加了两个选择,如下图所示。
![image.png](https://img-blog.csdnimg.cn/img_convert/651d77c73f2a770c27a3579d514ecf63.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=532&id=u8af15b18&margin=[object Object]&name=image.png&originHeight=532&originWidth=948&originalType=binary&ratio=1&rotation=0&showTitle=false&size=502552&status=done&style=none&taskId=u5c38f75c-b5cc-4e92-852e-56f9e5b4f99&title=&width=948)
其中View PSI Structure of Current File是将当前查看的文件解析为结构树,选中选项后弹出如下图所示的窗口。
![image.png](https://img-blog.csdnimg.cn/img_convert/7a56cafd86307c351124d43abd8ca07e.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=813&id=ub0e82473&margin=[object Object]&name=image.png&originHeight=813&originWidth=1380&originalType=binary&ratio=1&rotation=0&showTitle=false&size=143767&status=done&style=none&taskId=u886de55c-548e-4e77-aa38-2042a4e711b&title=&width=1380)
![image.png](https://img-blog.csdnimg.cn/img_convert/7fbb507620283b8cd8f11ffcc46753dc.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=827&id=u6f0d475b&margin=[object Object]&name=image.png&originHeight=827&originWidth=1388&originalType=binary&ratio=1&rotation=0&showTitle=false&size=138855&status=done&style=none&taskId=ubbbe7d94-c1f1-4076-ba29-1dcff86d66a&title=&width=1388)
当我们选中源码时,IDEA会找到对应的PsiElement标志为选中状态,如上图左侧的PSI Tree窗口所示
这个小工具可以帮我们刚好的理解PSI的源码
一个PsiReference表示代码中某个PsiElement链接到相应的声明。
简单理解,PsiReference就是我们选中鼠标右键弹出菜单中Go To的Declaration or Usages、或者按住command键+鼠标点击后能够跳转到相应声明的依据。
![image.png](https://img-blog.csdnimg.cn/img_convert/d6f8672cb60a77e92c16f3f6eb7d3e28.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=348&id=uf62d2b9f&margin=[object Object]&name=image.png&originHeight=348&originWidth=1080&originalType=binary&ratio=1&rotation=0&showTitle=false&size=96035&status=done&style=none&taskId=ue0772e6d-af7b-4945-9a9e-5b0d680a5e6&title=&width=1080)
理解了核心的几个接口,在IDEA的PSI中,有很多工具类可以帮助我们在写插件的时候事半功倍。
![image.png](https://img-blog.csdnimg.cn/img_convert/681eb19ff47f24e53fa9255f4667b7c5.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=683&id=u85be3658&margin=[object Object]&name=image.png&originHeight=683&originWidth=478&originalType=binary&ratio=1&rotation=0&showTitle=false&size=101227&status=done&style=none&taskId=ue5d44e50-b808-4b4a-830e-f45a25f537c&title=&width=478)
源码当中写的都比较清楚。具体的可以研究下。
在介绍MS分析源码之前先看下效果。
具体用法参考官网
https://github.com/metersphere/metersphere-idea-plugin
![image.png](https://img-blog.csdnimg.cn/img_convert/9f92bfc76ca2a2dd13b02d24fd9a8982.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=729&id=ud7b5e8df&margin=[object Object]&name=image.png&originHeight=729&originWidth=833&originalType=binary&ratio=1&rotation=0&showTitle=false&size=119500&status=done&style=none&taskId=u4410f8ce-c90c-41e2-b4f3-9c905b0b37f&title=&width=833)
![image.png](https://img-blog.csdnimg.cn/img_convert/371edec532cf4402b99ea5326795de35.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=685&id=ueb67ae19&margin=[object Object]&name=image.png&originHeight=685&originWidth=1519&originalType=binary&ratio=1&rotation=0&showTitle=false&size=75238&status=done&style=none&taskId=u3895d3e4-bcd0-4b69-abca-89494fe2ea4&title=&width=1519)
![image.png](https://img-blog.csdnimg.cn/img_convert/da28ec1082fb644332d123aa5f4f13e0.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=852&id=u739054ee&margin=[object Object]&name=image.png&originHeight=852&originWidth=892&originalType=binary&ratio=1&rotation=0&showTitle=false&size=232892&status=done&style=none&taskId=u5859b66f-afaf-4f1b-8f7a-09682f4569f&title=&width=892)
结果
![image.png](https://img-blog.csdnimg.cn/img_convert/548e88b57992276f6263a2014b39214f.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=640&id=ufdec84f5&margin=[object Object]&name=image.png&originHeight=640&originWidth=445&originalType=binary&ratio=1&rotation=0&showTitle=false&size=80863&status=done&style=none&taskId=u999a19ea-d444-4bf6-9dfb-6f549354a74&title=&width=445)
针对业务开发人员来讲,就是一个idea的插件,通过对接Metersphere,将项目中的Controller 一键导出到Metersphere当中,完美的融化了开发部门和测试部门的配合。
首先去官网clone 到本地 https://github.com/metersphere/metersphere-idea-plugin
项目结构:
![image.png](https://img-blog.csdnimg.cn/img_convert/0d9d018f927df5d24844fafd4311a10f.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=984&id=uf01533e0&margin=[object Object]&name=image.png&originHeight=984&originWidth=404&originalType=binary&ratio=1&rotation=0&showTitle=false&size=89880&status=done&style=none&taskId=ufd9115e2-b30c-41cb-85c9-cfc7fad3f09&title=&width=404)
目前MS支持两种导出方式:1. postman 2. metersphere
![image.png](https://img-blog.csdnimg.cn/img_convert/3fbd5b87265f05dd1a4acd8d0325bbc4.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=871&id=u196e080b&margin=[object Object]&name=image.png&originHeight=871&originWidth=1761&originalType=binary&ratio=1&rotation=0&showTitle=false&size=290636&status=done&style=none&taskId=uf75a24f4-fffe-452a-aa71-9fc0582f996&title=&width=1761)
这个配置文件是这个插件的整体配置信息,可以从中获取到插件的ID,名称,邮箱等基本信息和Action以及扩展插件的信息,具体意思参考上面的本地环境搭建。
�![image.png](https://img-blog.csdnimg.cn/img_convert/71a6193fd3d64e2d680de0bd5ce8c5b1.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=772&id=uf4c3976a&margin=[object Object]&name=image.png&originHeight=772&originWidth=1368&originalType=binary&ratio=1&rotation=0&showTitle=false&size=193674&status=done&style=none&taskId=u234678a4-a3cc-4c89-9351-e212d3931ba&title=&width=1368)
�
![image.png](https://img-blog.csdnimg.cn/img_convert/3c639d67f607d981b7e669431b8edb3b.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=893&id=u4be3e427&margin=[object Object]&name=image.png&originHeight=893&originWidth=1387&originalType=binary&ratio=1&rotation=0&showTitle=false&size=236721&status=done&style=none&taskId=uca0d9bcb-3dd1-495f-b1d4-b8534009e16&title=&width=1387)�
![image.png](https://img-blog.csdnimg.cn/img_convert/ca0db8f1d266e17de74e2b7d4a7201fc.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=849&id=u080b9824&margin=[object Object]&name=image.png&originHeight=849&originWidth=1705&originalType=binary&ratio=1&rotation=0&showTitle=false&size=201461&status=done&style=none&taskId=u2b46d721-d6dc-4a2a-a8bc-20abc853424&title=&width=1705)
![image.png](https://img-blog.csdnimg.cn/img_convert/dbaafad427c4769e989f89265814e66d.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=835&id=u69421449&margin=[object Object]&name=image.png&originHeight=835&originWidth=1601&originalType=binary&ratio=1&rotation=0&showTitle=false&size=252002&status=done&style=none&taskId=u5d526681-eebd-4cbe-b058-769e911288b&title=&width=1601)
![image.png](https://img-blog.csdnimg.cn/img_convert/900c5f93fb3b58857cdcc473b2eec86e.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=830&id=u1ced80cb&margin=[object Object]&name=image.png&originHeight=830&originWidth=1199&originalType=binary&ratio=1&rotation=0&showTitle=false&size=160485&status=done&style=none&taskId=uaa5af9c9-ac2f-4001-9823-863edd44a9c&title=&width=1199)
�1. AppSettingComponent() 这个方法是个构造方法,其中initData(appSettingState)是初始化配置信息的方法,可以看到里面很多Listener,这些个Listener是对gui填写内容的监听,每个类型的Listener不同,但监听原理是相同的。都是当内容发生的时候,触发的动作。
![image.png](https://img-blog.csdnimg.cn/img_convert/1907d63f0922570dd234e3c00266ecb8.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=367&id=uaf2167fb&margin=[object Object]&name=image.png&originHeight=367&originWidth=1307&originalType=binary&ratio=1&rotation=0&showTitle=false&size=71684&status=done&style=none&taskId=u27a5d67e-0234-491a-a98e-068c05f177f&title=&width=1307)�
�
继承了�CommonAction
�![image.png](https://img-blog.csdnimg.cn/img_convert/1ae28e2332acb50da65d5200f4b44cea.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=665&id=u3af70da6&margin=[object Object]&name=image.png&originHeight=665&originWidth=972&originalType=binary&ratio=1&rotation=0&showTitle=false&size=131181&status=done&style=none&taskId=uf9b59e48-d069-4a18-97bd-dcb519e8fe2&title=&width=972)
![image.png](https://img-blog.csdnimg.cn/img_convert/c9a41161a7d5bc92117b787fb477a95b.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=418&id=u6dca968a&margin=[object Object]&name=image.png&originHeight=418&originWidth=1067&originalType=binary&ratio=1&rotation=0&showTitle=false&size=84348&status=done&style=none&taskId=ub7daa61b-da30-47f0-92a9-7ac978b64e6&title=&width=1067)
所以核心类就是MeterSphereExporter这个类
![image.png](https://img-blog.csdnimg.cn/img_convert/5d243c5bdbf0118e3cc99909282b13a5.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=874&id=u7a66796c&margin=[object Object]&name=image.png&originHeight=874&originWidth=1367&originalType=binary&ratio=1&rotation=0&showTitle=false&size=212659&status=done&style=none&taskId=u46194604-9917-4da6-b6d3-eb7b447bd02&title=&width=1367)
这个方法的整体逻辑就是
![image.png](https://img-blog.csdnimg.cn/img_convert/43d98217988e81cc16faa8a8d467a01e.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=883&id=u6b653d4c&margin=[object Object]&name=image.png&originHeight=883&originWidth=1460&originalType=binary&ratio=1&rotation=0&showTitle=false&size=187564&status=done&style=none&taskId=u50e55415-f78d-4516-88be-be6f3c11adf&title=&width=1460)
![image.png](https://img-blog.csdnimg.cn/img_convert/c787e0550b9f8f55a8dde915ca0416eb.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=775&id=u1a12c145&margin=[object Object]&name=image.png&originHeight=775&originWidth=1515&originalType=binary&ratio=1&rotation=0&showTitle=false&size=161681&status=done&style=none&taskId=u0fbd23d7-55e8-4a09-bb8c-fbec402d18f&title=&width=1515)
![image.png](https://img-blog.csdnimg.cn/img_convert/f92cfe3ea3903dc7fe4e3acafa8ab917.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=884&id=ucefecb06&margin=[object Object]&name=image.png&originHeight=884&originWidth=1412&originalType=binary&ratio=1&rotation=0&showTitle=false&size=183241&status=done&style=none&taskId=u1a685844-4d79-412b-a8e2-985a8aa07b6&title=&width=1412)
![image.png](https://img-blog.csdnimg.cn/img_convert/947721b9ab55c52c270733e875cf6efc.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=813&id=u5f7ad926&margin=[object Object]&name=image.png&originHeight=813&originWidth=1194&originalType=binary&ratio=1&rotation=0&showTitle=false&size=171672&status=done&style=none&taskId=ucf651936-4f2a-4694-8fe2-63227c6276e&title=&width=1194)
![image.png](https://img-blog.csdnimg.cn/img_convert/f0944df4903a722c50df6e2404ff0cab.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=953&id=ue61c01d4&margin=[object Object]&name=image.png&originHeight=953&originWidth=1442&originalType=binary&ratio=1&rotation=0&showTitle=false&size=246181&status=done&style=none&taskId=u506d0750-4c5d-4771-a552-5cbadd3b6c2&title=&width=1442)
参考链接:Json Schema 官方网站 中文文档 生成Json Schema 工具
![image.png](https://img-blog.csdnimg.cn/img_convert/40057f50ea35c5d48acec4ea29ebae24.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=729&id=uae73e3a3&margin=[object Object]&name=image.png&originHeight=729&originWidth=1567&originalType=binary&ratio=1&rotation=0&showTitle=false&size=210295&status=done&style=none&taskId=u8642ea32-fafa-4ec5-a1ac-14744a4313d&title=&width=1567)
![image.png](https://img-blog.csdnimg.cn/img_convert/52c50e9d897220f0089df57aac90464d.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=375&id=u04d03b03&margin=[object Object]&name=image.png&originHeight=375&originWidth=1406&originalType=binary&ratio=1&rotation=0&showTitle=false&size=76563&status=done&style=none&taskId=udd2c50b4-e36f-4c94-91d8-f99da92da1c&title=&width=1406)
![image.png](https://img-blog.csdnimg.cn/img_convert/d26baf9f55b33f3f1c909debb0f9bd83.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=561&id=ufd8e0c2a&margin=[object Object]&name=image.png&originHeight=561&originWidth=1189&originalType=binary&ratio=1&rotation=0&showTitle=false&size=111366&status=done&style=none&taskId=u53cc07cb-e09b-479a-921c-df86a00b66a&title=&width=1189)
![image.png](https://img-blog.csdnimg.cn/img_convert/d3684c067d2f0952228b582994b8d075.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=948&id=u2d65a80e&margin=[object Object]&name=image.png&originHeight=948&originWidth=1489&originalType=binary&ratio=1&rotation=0&showTitle=false&size=248172&status=done&style=none&taskId=u947c12d8-2f78-4db9-a917-ba612e4b66c&title=&width=1489)
![image.png](https://img-blog.csdnimg.cn/img_convert/061cb98269ec4f1d1722b69560b76169.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=756&id=u44a78202&margin=[object Object]&name=image.png&originHeight=756&originWidth=1572&originalType=binary&ratio=1&rotation=0&showTitle=false&size=172767&status=done&style=none&taskId=u782872ae-a7af-4295-9d2e-68b63228b15&title=&width=1572)
![image.png](https://img-blog.csdnimg.cn/img_convert/2d8539af0b57a9f48597a200e7bbf1c0.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=775&id=u81d73afe&margin=[object Object]&name=image.png&originHeight=775&originWidth=1345&originalType=binary&ratio=1&rotation=0&showTitle=false&size=173660&status=done&style=none&taskId=u8df8060d-8796-46c8-a164-94361d7a9a0&title=&width=1345)
当前测试下来,自定义注解是不支持的,还有复杂的泛型嵌套,也是不支持的。所以基于客户的需求,重构了一下代码。
![image.png](https://img-blog.csdnimg.cn/img_convert/3608bab411c104c298ef0b41fae37fe5.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=978&id=u954940aa&margin=[object Object]&name=image.png&originHeight=978&originWidth=1763&originalType=binary&ratio=1&rotation=0&showTitle=false&size=302585&status=done&style=none&taskId=uf57424a7-7afa-4d78-9027-3a3ab58ea05&title=&width=1763)
![image.png](https://img-blog.csdnimg.cn/img_convert/c1b23c081d449ffe53e3e218afaba290.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=828&id=u5eb879d9&margin=[object Object]&name=image.png&originHeight=828&originWidth=1360&originalType=binary&ratio=1&rotation=0&showTitle=false&size=226853&status=done&style=none&taskId=u73000708-ac00-4da7-97ea-608bb03b694&title=&width=1360)
![image.png](https://img-blog.csdnimg.cn/img_convert/3a98c3872b3329669806a05ad8311a52.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=595&id=ucaacb2e3&margin=[object Object]&name=image.png&originHeight=595&originWidth=1197&originalType=binary&ratio=1&rotation=0&showTitle=false&size=99019&status=done&style=none&taskId=u86d15b1b-58a3-4859-b34e-9a86c28bcb1&title=&width=1197)![image.png](https://img-blog.csdnimg.cn/img_convert/33d89c507f8eb077f80b0ed031d6c5f5.png#clientId=uc20870b0-2696-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=276&id=u52317765&margin=[object Object]&name=image.png&originHeight=276&originWidth=715&originalType=binary&ratio=1&rotation=0&showTitle=false&size=35601&status=done&style=none&taskId=uead7a2d8-2dc6-42e8-a073-d38c1e6defb&title=&width=715)
经过一番改造后,最后终于支持自定义注解了,并且支持复杂的泛型嵌套。比如