实用工具:FastDoc 文档提取工具

news2024/11/20 10:32:34

实用工具:FastDoc 文档提取工具

简单、实用的 HTTP API 文档生成工具,支持 Spring MVC/Spring Boot 下的控制器信息提取,类似 Swagger 但稍有不同的机制。

example2

在线演示地址在 https://framework.ajaxjs.com/demo/fast-doc/。

关于研发者这工具的动机,请参考我博客《写文档是件大事情,怎么弄好它?》。

文档的信息来自哪里?换句话说,根据哪些的信息,才能形成文档?笔者愚以为,来自下面几个方面:

  • Spring MVC 各种注解,定义了这个控制器大体如何,如 @GetMapping("/test/{id}"),告诉了你是 GET 方法和接口地址
  • Java 的注释。前面我的博文说过,基于 Java 本身的注释就够了,不是基于 Swagger 那样的自定义注解
  • 前两者是主要的信息提供者。若不够或者不满足,就来像 Swagger 那样子采取自定义注解的方式。但这种方式不会太多。

有人疑问,既然有了 Swagger 注解为什么还要 Java 的注释呢?——因为没有了 Java 注释,你编码的时候就没有语法提示呀,IDE 又不会智能到可以提取注解的信息。当然,你可以复制一份到 Java 注释,但岂不是重复了么,而且手工复制?——那不符合我们程序员“懒”的追求哦。——呃~重复不是问题~~你有代码生成器?再加上,,我控制器方法不需要给其他 Java 代码提示啊~~——呃~那好吧。

Anyway,综上,笔者编写了这个小巧的工具,不仅代码行数少,精简、轻量级,而且非入侵,不会影响你原有的工程依赖,无论使用还是部署也很方便。

尽管这一个小小的工具,但不例外地,也是由前、后端两部分程序所组成。但这所谓的“后端”并不是一个 Web 程序,严格说只是一个 main() 函数或者单元测试就能运行的 Java 程序,目的是生成供给前端渲染的 JSON,这个 JSON 就包含了所有文档信息。

  • 前端源码在 https://gitee.com/sp42_admin/ajaxjs/tree/master/aj-ui-widget/fast-doc。
  • 生成 JSON 程序,其实是 AJAXJS Framework 的一部分,源码在 https://gitee.com/sp42_admin/ajaxjs/tree/master/aj-framework/src/main/java/com/ajaxjs/fast_doc。

使用方法

前端网页

前端网页很简单,能读取 json.js 就能解析了。你甚至可以把网页直接用浏览器 file:// 方式打开,当然更常见的是放在 Nginx/Tomcat 上面。

在这里插入图片描述

注意 fast-doc 是里面那层目录,外面一层还有与之平级的 libscommon 的依赖。

另外,还有一个地方要配置,就是接口地址的前缀,更改你具体的地址。用于显示这里:

在这里插入图片描述

你要进入源码简单改下,编辑 doc.htm 文件约第 197 行,修改 data.root 即可。

在这里插入图片描述

生成 JSON

添加依赖

在你的项目工程中,添加下面两个依赖:

<dependency>
    <groupId>com.ajaxjs</groupId>
    <artifactId>ajaxjs-framework</artifactId>
    <version>1.0.7</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>com.ajaxjs</groupId>
    <artifactId>ajaxjs-javadoc</artifactId>
    <version>1.0.2</version>
    <scope>test</scope>
</dependency>

使用 test 的 scope 即可,这是非入侵的。然后新建一个 JUnit 单元测试(虽然 main() 函数执行也可以,但是前面已经是 test 的 Maven 依赖了,故无法 main())。

调用方法

新建单测方法,配置参数 FastDocRun 并运行 FastDoc.run(run)

FastDocRun run = new FastDocRun();
run.sourceDir = "D:\\code\\ajaxjs\\aj-framework\\aj-framework\\src\\test\\java\\"; // 源码目录,到 java 那一层
run.beanClasses = new Class<?>[] { FooBean.class, BarBean.class, InnerClass.class }; // 有哪些 Java Bean,都列出来
run.controllerClasses = new Class<?>[] { FooController.class }; // 有哪些 Spring MVC 控制器类,都列出来
run.jsonDir = "D:\\code\\ajaxjs\\aj-framework\\aj-ui-widget\\fast-doc\\json.js"; // 最终 JSON 保存的地方

FastDoc.run(run);

jsonDir 就是你前端要读取 json.js 文件的那个地方。运行通过之后,你要手动复制 json.js 到前端覆盖。

提示:如果 class 太多怎么办?可以通过 FastDoc.findAndAddClassesInPackageByFile() 指定某个目录返回目录下所有的类。返回的数组太多,可以通过实用工具 ListUtils.addAll(T[]... arrays) 合并为一个数组然后传到方法中。

高级用法

如果你使用 Swagger 的注解,或者自定义的注解声明文档信息,可以通过自定义提取器的方式生成 JSON。

下面假设 @Doc 是你自定义的注解,我们通过新建 DashuAnnotationParser 来提取它。

import com.ajaxjs.fast_doc.Model;
import com.ajaxjs.fast_doc.annotation.SpringMvcAnnotationParser;
import com.ajaxjs.spring.easy_controller.ControllerMethod;
import com.dashu.lazyapidoc.annotation.Doc;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class DashuAnnotationParser extends SpringMvcAnnotationParser {
    @Override
    public void onClzInfo(Model.ControllerInfo ci, Class<?> clz) {
        Doc doc = clz.getAnnotation(Doc.class);
        if (doc != null) {
            ci.description = doc.value();
        }
    }

    @Override
    public void getMethodInfo(Model.Item item, Method method) {
        Doc[] annotationsByType = method.getAnnotationsByType(Doc.class);

        if (annotationsByType != null) {
            if (annotationsByType.length == 1) {
                Doc doc = annotationsByType[0];
                item.name = doc.value();

                if (StringUtils.hasText(doc.remark()))
                    item.description = doc.remark();

                return;
            }

            // 多个,name 为空的那个就是
            for (Doc doc : annotationsByType) {
                if (StringUtils.isEmpty(doc.name())) {
                    item.name = doc.value();

                    if (StringUtils.hasText(doc.remark()))
                        item.description = doc.remark();

                    break;
                }
            }
        }
    }

    @Override
    public void getArgs(Model.Item item, Method method, Parameter param, Model.ArgInfo arg) {
        Doc[] annotationsByType = method.getAnnotationsByType(Doc.class);

        if (ObjectUtils.isEmpty(annotationsByType))
            return;

        for (Doc doc : annotationsByType) {
            String argName = doc.name();

            if (StringUtils.hasText(argName) && argName.equals(arg.name)) {
                arg.description = doc.value();

                if (StringUtils.hasText(doc.remark()))
                    arg.description += "。" + doc.remark();

                break;
            }
        }
    }
}

DashuAnnotationParser 继承于 SpringMvcAnnotationParser,覆盖了相关的模板方法(又称虚方法),分别对应获取类信息、方法信息和金额参数信息的时候。

这样,调用 FastDoc 的方法有所不同,如下是:

Class<?>[] beans = FastDoc.findAndAddClassesInPackageByFile("org.basecode.protocol.sys.model", "C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\org\\basecode\\protocol\\sys\\model");
Class<?>[] dtos = FastDoc.findAndAddClassesInPackageByFile("org.basecode.protocol.sys.dto", "C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\org\\basecode\\protocol\\sys\\dto");
Class<?>[] vos = FastDoc.findAndAddClassesInPackageByFile("org.basecode.protocol.sys.vo", "C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\org\\basecode\\protocol\\sys\\vo");
Class<?>[] forms = FastDoc.findAndAddClassesInPackageByFile("org.basecode.protocol.sys.form", "C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\org\\basecode\\protocol\\sys\\form");

Class<?>[] all = ListUtils.concat(ListUtils.concat(beans, dtos), vos);
all = ListUtils.concat(all, forms);

FastDoc.loadBeans("C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\",
        all);

Class<?>[] services = FastDoc.findAndAddClassesInPackageByFile("org.basecode.protocol.sys.service", "C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\org\\basecode\\protocol\\sys\\service");
FastDoc.loadControllersDoc(DashuAnnotationParser.class, "C:\\code\\auth-git\\security-console-parent\\security-console-service-protocol\\src\\main\\java\\",
        services);

FastDoc.saveToDisk("C:\\code\\aj\\aj-all\\ajaxjs\\aj-ui-widget\\fast-doc\\json.js");

FAQ 答疑

  • 如果出现如下图所示,只有成员的名称、类型等的信息,而没有注释信息,是什么原因?
    输入图片说明

配置有问题。能提取成员的名称、类型等的信息,已说明 classPath 配置正确,但没配置好所需的 sourcePath。你想想看,编译好的 .class 哪里有注释?肯定在 .java 文件里面才有。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163019.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二三层转发原理

二层转发原理 数据帧 二层即数据链路层的转发是以数据帧的格式进行转发&#xff0c;数据帧的格式如下&#xff1a; 目的地址(Destination Address,DA) &#xff1a;可以是单独的地址,或者是广播或组播MAC地址。 源地址(Source Address,SA) &#xff1a;用来识别发送没备,在S…

听说你想用开发者工具调试我的网站?挺可以的啊。25

本篇博客重点为大家介绍&#xff0c;如何禁止用户在浏览器中查看源码&#xff0c;禁用开发者工具调试等前端需求 案例已更新到 爬虫训练场 文章目录禁用右键&#xff0c;禁用 F12禁用 ctrl U 查看源代码&#xff0c;禁用 ctrl shift i 打开开发者工具实现开发者工具无限 deb…

arcgis使用Python脚本进行批量截图

arcgis使用Python脚本进行批量截图 介绍 最近公司数据部那边有个需求&#xff0c;需要结合矢量数据和影像数据&#xff0c;进行批量截图&#xff0c;并且截图中只能有一个图斑&#xff0c;还要添加上相应的水印。 思路 一开始我是准备使用QGIS直接进行批量出图&#xff0c;…

Ant Design在处理业务表单中的一些实践

文章目录前言表单处理实践Modal 清空旧数据使用Form.create和getFieldDecorator对Form进行包装表单控件是switch自定义表单控件Table列表SelectshowSearch 用于在选择框中显示搜索框其他需要注意的组件Tabs其它前言 目前&#xff0c;很多中小企业前端实现采用了react&#xff…

二、总线控制

文章目录一、引子二、总线判优控制1.基本概念2.方式&#xff08;1&#xff09;集中式①链式查询方式②计数器定时查询方式③独立请求方式&#xff08;2&#xff09;分布式三、总线通信控制1.基本概念2.方式&#xff08;1&#xff09;同步通信①介绍②同步式数据输入③同步数据输…

数据结构与算法学习推荐

推荐&#xff1a;官网地址&#xff1a;http://localhost:8000/algorithm/github&#xff1a;https://github.com/paiDaXing-web/You-Dont-Know-Algorithm 点star 大话搜索搜索一般指在有限的状态空间中进行枚举&#xff0c;通过穷尽所有的可能来找到符合条件的解或者解的个数。…

佳能C5235彩色激光复印机复印有底灰

故障描述&#xff1a; 佳能C5235彩色激光复印机&#xff0c;复印的时候有不同颜色的底灰问题&#xff1b; 检测分析&#xff1a; 打印不同纯色的纸张进行测试发现每张纸的上面都有不同颜色的底灰&#xff1b; 拆机进行检测吧&#xff0c;先打开前盖&#xff0c;拧下左右两边的螺…

CMake基础教程

CMake最大优势是跨平台&#xff0c;可以根据不同的平台生成Makefile文件&#xff0c;看下CMake的基础使用。 cmake&#xff08;单目录单文件&#xff09; 第一个最简单的cmake构建。 demo1.cpp代码&#xff1a; #include <iostream>using namespace std;int main(int…

【基于机械臂触觉伺服的物体操控研究】UR5e动力学建模及代码实现

我的毕设题目定为《基于机械臂触觉伺服的物体操控研究》&#xff0c;这个系列主要用于记录做毕设的过程。 前言&#xff1a;UR系列是优傲公司的代表产品&#xff0c;也是目前比较通用的产品级机械臂。所以我打算用该机械臂进行毕设的仿真实现。关于其动力学建模&#xff0c;网…

台阶问题-

台阶问题 题目描述 有NNN级的台阶&#xff0c;你一开始在底部&#xff0c;每次可以向上迈最多KKK级台阶&#xff08;最少111级&#xff09;&#xff0c;问到达第NNN级台阶有多少种不同方式。 输入格式 两个正整数N&#xff0c;K。 输出格式 一个正整数&#xff0c;为不同…

JVM(一)——架构基础

JVM java虚拟机 java gc 主要回收的是 方法区 和 堆中的内容&#xff0c;以下架构图是重点&#xff1a; 方法区和堆是线程共享&#xff0c;java栈、本机方法栈、程序计数器是线程私有。 运行时数据区可以用Runtime.getRuntime()获取 字节码执行引擎&#xff0c;修改程序计数器…

不要怀疑了,个人也是可以做好跨境电商的!

近几年随着跨境电商卖家们赚得盆满钵满&#xff0c;许多人都想从中分一杯羹&#xff0c;进而入住了跨境电商市场&#xff0c;有人与一些公司企业合作&#xff0c;也有人选择了自己做跨境电商平台&#xff0c;个人做的优劣势又有哪些呢&#xff1f; 个人做跨境电商平台最明显突…

A V L树

概念 在之前介绍了搜索二叉树&#xff0c;但是当我们插入的数据若是有序或者接近于有序&#xff0c;那么此时查找的效率底下&#xff0c;于是俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法&#xff1a;当向二叉搜索树中插入新结点后&am…

javaEE学生教学实习计划申报系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 javaEE学生教学实习计划申报系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&…

正点原子【第四期】手把手教你学 Linux之驱动开发篇-01

学习目的 了解驱动开发和应用开发的过程&#xff0c;具有一定的基础就行 第一讲&#xff1a;linux驱动开发与裸机开发区别 刚开始听不懂很正常&#xff0c;等之后学了一点你就会知道它说啥了 第二讲&#xff1a;字符设备驱动开发基础 字符设备驱动是最简单的&#xff0c;块设…

C++ 移动语义

从拷贝说起我们知道&#xff0c;C中有拷贝构造函数和拷贝赋值运算符。那既然是拷贝&#xff0c;听上去就是开销很大的操作。没错&#xff0c;所谓拷贝&#xff0c;就是申请一块新的内存空间&#xff0c;然后将数据复制到新的内存空间中。如果一个对象中都是一些基本类型的数据的…

【Unity3D】绘制物体外框线条盒子

1 需求描述 点选物体、框选物体、绘制外边框 中介绍了物体投影到屏幕上的二维外框绘制方法&#xff0c;本文将介绍物体外框线条盒子绘制方法。 内框&#xff1a;选中物体后&#xff0c;绘制物体的内框&#xff08;紧贴物体、并与物体姿态一致的内框盒子&#xff09;外框&#…

Python与C++语法比较--字符串篇

tags: C Python 写在前面 刷lc从Python转向C, 不只是语法层面, 还要改变很多的API, 这次记录一下C和Python在字符串方面的一些区别, 供参考. 基本区别 Python字符串是不可变类型, 而C的String为容器(本质上是一个类的别名, 说容器有点不合适, 因为容器内的元素类型已经被指…

Kotlin中的Lambda编程

文章目录1.集合的创建与遍历2.集合的函数式API3.Java函数式API的使用1.集合的创建与遍历 传统意义上的集合主要是List和Set&#xff0c;再广泛一点的话&#xff0c;像Map这样的键值对数据结构也可以包含进来。List&#xff0c;Set和Map再Java中都是接口&#xff0c;List主要的…

Java设计模式-命令模式Command

介绍 命令模式&#xff08;Command Pattern&#xff09;&#xff1a;在软件设计中&#xff0c;我们经常需要向某些对象发送请求&#xff0c;但是并不知道请求的接收 者是谁&#xff0c;也不知道被请求的操作是哪个&#xff0c; 我们只需在程序运行时指定具体的请求接收者即可&…