生成kafka内部请求与响应的接口文档
生成kafka内部请求与响应的接口文档
/**
*/
package com.code260.ss.kafka10demo;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.kafka.common.protocol.types.BoundField;
import org.apache.kafka.common.protocol.types.Schema;
import org.apache.kafka.common.requests.AbstractRequest;
import org.apache.kafka.common.requests.AbstractResponse;
/**
* @since 2019-08-07
*
*/
public class GenKafkaRequestDoc {
/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
collect(AbstractRequest.class);
System.out.println("=======");
collect(AbstractResponse.class);
}
/**
* @param sedClazz
* @throws IOException
* @throws ClassNotFoundException
*/
public static void collect(Class<?> sedClazz) throws IOException, ClassNotFoundException {
List<Class<?>> children = getAllChildrenClass("org.apache.kafka", sedClazz);
List<Class<?>> childrenOfAbstractRequest = filter(children, sedClazz);
for (Class<?> rquestClazz : childrenOfAbstractRequest) {
System.out.println("\n## " + rquestClazz.getSimpleName());
try {
Schema[] schemas = (Schema[]) rquestClazz.getDeclaredMethod("schemaVersions").invoke(null);
for (int i = 0; i < schemas.length; i++) {
Schema schema = schemas[i];
System.out.println("\n### version:" + i);
StringBuffer sb = new StringBuffer();
sb.append(
"<table><tr><td style=\"width:160px\">name</td><td>type</td><td style=\"width:80px\">defaultValue</td><td>docString</td></tr>");
for (int j = 0; j < schema.fields().length; j++) {
BoundField field = schema.fields()[j];
sb.append("<tr><td>").append(field.def.name).append("</td>");
sb.append("<td>").append(field.def.type).append("</td>");
sb.append("<td>").append(field.def.defaultValue).append("</td>");
sb.append("<td>").append(field.def.docString).append("</td></tr>").append("\n");
}
sb.append("</table> \n \n ");
System.out.println(sb.toString());
}
// System.out.println(schemas);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
private static List<Class<?>> filter(List<Class<?>> children, Class<?> parentClazz) {
List<Class<?>> result = new ArrayList<Class<?>>();
if (children == null || children.isEmpty()) {
return result;
}
for (Class<?> child : children) {
if (isAssignedFrom(child, parentClazz)) {
result.add(child);
}
}
return result;
}
private static boolean isAssignedFrom(Class<?> currentClazz, Class<?> targetParentClazz) {
if (targetParentClazz == null || currentClazz == null) {
return false;
}
// Class<?>[] parentInterfaces = currentClazz.getInterfaces();
Class<?> parentClazz = currentClazz.getSuperclass();
while (parentClazz != null) {
if (parentClazz.equals(targetParentClazz)) {
return true;
} else {
parentClazz = parentClazz.getSuperclass();
}
}
Class<?>[] parentInterfaces = currentClazz.getInterfaces();
return isAssignedFrom(parentInterfaces, targetParentClazz);
}
private static boolean isAssignedFrom(Class<?>[] parentInterfaces, Class<?> targetParentClazz) {
if (parentInterfaces == null) {
return false;
}
for (Class<?> ppInterface : parentInterfaces) {
if (ppInterface != null && ppInterface.equals(targetParentClazz)) {
return true;
} else {
boolean result = isAssignedFrom(ppInterface.getInterfaces(), targetParentClazz);
if (result) {
return true;
}
}
}
return false;
}
private static List<Class<?>> getAllChildrenClass(String scanPackageStr, Class<?> parentClazz)
throws IOException, ClassNotFoundException {
List<Class<?>> children = new ArrayList<Class<?>>();
Enumeration<URL> packageLocations = parentClazz.getClassLoader().getResources(scanPackageStr.replace(".", "/"));
while (packageLocations.hasMoreElements()) {
URL packageLocation = packageLocations.nextElement();
String protocol = packageLocation.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(packageLocation.getFile(), "UTF-8");
findAndAddClassesInPackageByFile(filePath, scanPackageStr, children);
} else if ("jar".equals(protocol)) {
findAndAddClassesInPackageByJar(packageLocation.getPath(), scanPackageStr, children);
}
}
return children;
}
private static void findAndAddClassesInPackageByJar(String packageLocation, String packageName,
List<Class<?>> clazzList) throws IOException, ClassNotFoundException {
String[] segs = packageLocation.split("!");
String jarFilePath = segs[0].substring(segs[0].indexOf("/"));
jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
String packagePath = segs[1].substring(1);
JarFile jarFile = null;
try {
jarFile = new JarFile(jarFilePath);
Enumeration<JarEntry> entrys = jarFile.entries();
while (entrys.hasMoreElements()) {
JarEntry jarEntry = entrys.nextElement();
String entryName = jarEntry.getName();
if (entryName.endsWith(".class")) {
if (entryName.startsWith(packagePath)) {
entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(entryName);
clazzList.add(clazz);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (jarFile != null) {
jarFile.close();
}
}
}
private static void findAndAddClassesInPackageByFile(String filePath, String packageName,
List<Class<?>> clazzList) {
File file = new File(filePath);
File[] children = file.listFiles();
for (File child : children) {
if (child.isDirectory()) {
findAndAddClassesInPackageByFile(child.getAbsolutePath(), packageName + "." + child.getName(),
clazzList);
}
if (child.isFile()) {
if (!child.getName().endsWith(".class")) {
continue;
}
}
String childName = child.getName();
if (!childName.endsWith(".class")) {
continue;
}
String className = packageName + "." + childName.substring(0, childName.length() - ".class".length());
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
clazzList.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
生成kafka内部请求与响应的接口文档的更多相关文章
- Swagger 接口文档规范
导语: 相信无论是前端还是后端开发,都或多或少地被接口文档折磨过.前端经常抱怨后端给的接口文档与实际情况不一致.后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新.其实无论是前端调用后端,还是 ...
- Markdown写接口文档,自动添加TOC
上回说到,用Impress.js代替PPT来做项目展示.这回换Markdown来做接口文档好了.(不敢说代替Word,只能说个人感觉更为方便)当然,还要辅之以Git,来方便版本管理. Markdown ...
- Django框架深入了解_05 (Django中的缓存、Django解决跨域流程(非简单请求,简单请求)、自动生成接口文档)
一.Django中的缓存: 前戏: 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的时候,每一 ...
- SpringBoot整合knife4j框架(可生成离线接口文档),并设置接口请求头token默认值
功能和swagger类似 官网地址:https://doc.xiaominfo.com/knife4j/ 这个框架可以设置返回字段的描述 引入依赖 <dependency> <gro ...
- drf07 过滤 排序 分页 异常处理 自动生成接口文档
4. 过滤Filtering 对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持. pip install django-filter 在配置文件sett ...
- spring boot:用swagger3生成接口文档,支持全局通用参数(swagger 3.0.0 / spring boot 2.3.2)
一,什么是swagger? 1, Swagger 是一个规范和完整的文档框架, 用于生成.描述.调用和可视化 RESTful 风格的 Web 服务文档 官方网站: https://swagger.i ...
- day74:drf:drf其他功能:认证/权限/限流/过滤/排序/分页/异常处理&自动生成接口文档
目录 1.django-admin 2.认证:Authentication 3.权限:Permissions 4.限流:Throttling 5.过滤:Filtering 6.排序:OrderingF ...
- SpringBoot接口 - 如何生成接口文档之非侵入方式(通过注释生成)Smart-Doc?
通过Swagger系列可以快速生成API文档,但是这种API文档生成是需要在接口上添加注解等,这表明这是一种侵入式方式: 那么有没有非侵入式方式呢, 比如通过注释生成文档? 本文主要介绍非侵入式的方式 ...
- asp.net core 使用 swagger 生成接口文档
参考地址:http://www.cnblogs.com/daxnet/p/6181366.html http://www.jianshu.com/p/fa5a9b76f3ed 微软参考文档:https ...
随机推荐
- [并发编程] -- ThreadPoolExecutor篇
Executor框架 Executor框架的两级调度模型(基于HotSpot) 在上层,Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定 ...
- Ubuntu安装Docker(官方文档翻译)
翻译自Docker官方文档 https://docs.docker.com/engine/installation/linux/ubuntulinux/ 之前因为看不懂官方文档,卡在某个步骤无法完成安 ...
- React Native 中使用Redux
参考https://jspang.com/detailed?id=48和印度同事的代码简单整理一下在RN中使用Redux的步骤 1. 首先我们应该先了解Redux是什么,什么情况下需要用到它 在Red ...
- 基于MySql主从分离的代码层实现
前言 该文是基于上篇<MySQL主从分离的实现>的代码层实现,所以本文配置的主数据库和从数据库的数据源都是在上篇博文中已经介绍了的. 动态选择数据源的配置 由于我们在写数据的时候需 ...
- 再见了Antirez永远的Redis之神
其实antirez(Redis作者)退出Redis维护一发布我就在很多咨询网站上面看到了,当时也没太多感慨. 今天比较有空想去看看霉霉Twitter的,然后看到了antirez,我就又一次回顾了他的退 ...
- 自制廉价的LED+LCD型投影仪
文档标识符:PROJECTOR_T-D-P6 作者:DLHC 最后修改日期:2020.7.30 本文链接:https://www.cnblogs.com/DLHC-TECH/p/PROJECTOR_T ...
- 5.15 牛客挑战赛40 C 小V和字符串 数位dp 计数问题
LINK:小V和字符串 容易想到只有1个数相同的 才能有贡献. 知道两个01串 那么容易得到最小步数 大体上就是 第一个串的最前的1和第二个串最前的1进行匹配. 容易想到设f[i][j]表示 前i位1 ...
- 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治
LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...
- 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点
容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...
- 剑指 Offer 58 - I. 翻转单词顺序
本题 题目链接 题目描述 我的题解 方法一:库函数split() 要注意str.split()函数: 字符串str前有 n 个空格时,分割出来的字符串列表中会多出 n 个空字符串: 字符串str某两个 ...