From 9cd5d1a65df55c5c7b39fc8a4e7f7a3acb55885a Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Thu, 24 Apr 2025 10:55:00 +0800 Subject: [PATCH] 'commit' --- dsBase/pom.xml | 7 + .../base/Base/Controller/BaseController.java | 2 + .../com/dsideal/base/JApiDocsGenerator.java | 194 ++++++++++++++++++ .../base/Menu/Controller/MenuController.java | 45 +--- .../dsideal/base/Plugin/PostmanDocPlugin.java | 48 +++++ .../base/fay/tree/domain/FayTreeNode.java | 80 -------- .../base/fay/tree/domain/MenuBean.java | 69 ------- .../base/fay/tree/service/IFayTree.java | 11 - .../base/fay/tree/service/IFayTreeNode.java | 6 - .../base/fay/tree/service/impl/FayTree.java | 84 -------- .../base/fay/tree/util/FayTreeUtil.java | 27 --- 11 files changed, 252 insertions(+), 321 deletions(-) create mode 100644 dsBase/src/main/java/com/dsideal/base/JApiDocsGenerator.java create mode 100644 dsBase/src/main/java/com/dsideal/base/Plugin/PostmanDocPlugin.java delete mode 100644 dsBase/src/main/java/com/dsideal/base/fay/tree/domain/FayTreeNode.java delete mode 100644 dsBase/src/main/java/com/dsideal/base/fay/tree/domain/MenuBean.java delete mode 100644 dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTree.java delete mode 100644 dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTreeNode.java delete mode 100644 dsBase/src/main/java/com/dsideal/base/fay/tree/service/impl/FayTree.java delete mode 100644 dsBase/src/main/java/com/dsideal/base/fay/tree/util/FayTreeUtil.java diff --git a/dsBase/pom.xml b/dsBase/pom.xml index fe41b438..02ab14da 100644 --- a/dsBase/pom.xml +++ b/dsBase/pom.xml @@ -56,6 +56,13 @@ ${minio.version} + + + io.github.yedaxia + japidocs + 1.4.4 + + javax.xml.bind jaxb-api diff --git a/dsBase/src/main/java/com/dsideal/base/Base/Controller/BaseController.java b/dsBase/src/main/java/com/dsideal/base/Base/Controller/BaseController.java index 077fed8a..9d2f68a4 100644 --- a/dsBase/src/main/java/com/dsideal/base/Base/Controller/BaseController.java +++ b/dsBase/src/main/java/com/dsideal/base/Base/Controller/BaseController.java @@ -14,6 +14,7 @@ import com.dsideal.base.Util.CommonUtil; import com.dsideal.base.Util.ExcelCommonUtil; import com.dsideal.base.Util.FileUtil; import com.dsideal.base.Interceptor.*; +import io.github.yedaxia.apidocs.ApiDoc; import net.sf.json.JSONArray; import org.apache.commons.lang.StringUtils; @@ -21,6 +22,7 @@ import java.io.File; import java.util.*; import java.util.stream.Collectors; +@ApiDoc public class BaseController extends Controller { //实例化model BaseModel model = new BaseModel(); diff --git a/dsBase/src/main/java/com/dsideal/base/JApiDocsGenerator.java b/dsBase/src/main/java/com/dsideal/base/JApiDocsGenerator.java new file mode 100644 index 00000000..bc91cbb4 --- /dev/null +++ b/dsBase/src/main/java/com/dsideal/base/JApiDocsGenerator.java @@ -0,0 +1,194 @@ +package com.dsideal.base; + +import cn.hutool.core.io.FileUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.dsideal.base.Plugin.PostmanDocPlugin; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.jfinal.aop.Before; +import com.jfinal.core.Controller; +import com.jfinal.ext.interceptor.GET; +import com.jfinal.ext.interceptor.POST; +import com.jfinal.kit.PropKit; +import io.github.yedaxia.apidocs.DocContext; +import io.github.yedaxia.apidocs.Docs; +import io.github.yedaxia.apidocs.DocsConfig; + +import java.io.File; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; + +/** + * JApiDocs 无需额外注解的 API 文档生成工具 + *

+ * 源码 https://github.com/YeDaxia/JApiDocs + * 文档 https://japidocs.agilestudio.cn/#/zh-cn/ + * + * @author zxd 2022-02-17 + */ +public class JApiDocsGenerator { + + private static String getHttpType(Before before) { + if (before.value().length > 0) { + for (Class interceptClass : before.value()) { + if (interceptClass.equals(GET.class)) { + return "GET"; + } else if (interceptClass.equals(POST.class)) { + return "POST"; + } + } + } + return "UNKNOWN"; + } + + /** + * 获取指定目录下所有JAVA文件 + * @param directory 指定目录 + * @return 所有Java文件 + */ + public static List findJavaFiles(File directory) { + List javaFiles = new ArrayList<>(); + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + javaFiles.addAll(findJavaFiles(file)); // 递归遍历子目录 + } else if (file.getName().endsWith(".java")) { + javaFiles.add(file); // 添加Java文件 + } + } + } + return javaFiles; + } + + /** + * 功能:获取所有 Controller 名称 + * + * @param sourceJava JAVA目录 + * @return Controller名称集合 + */ + public static Map getControllMap(String sourceJava) { + Map res = new HashMap<>(); + List files = findJavaFiles(new File(sourceJava)); + for (File file : files) { + String className = file.getAbsolutePath().replace("\\", "/").replace(sourceJava + "/", ""); + className = className.replace("/", "."); + className = className.replace(".java", ""); + try { + // 去掉.class后缀并加载类 + Class cls = Class.forName(className); + if (Controller.class.isAssignableFrom(cls) && !Modifier.isAbstract(cls.getModifiers())) { + // 获取类上的所有方法 + Method[] methods = cls.getDeclaredMethods(); + for (Method method : methods) { + // 检查方法上是否有@Before注解 + var before = method.getAnnotation(Before.class); + if (before != null) { + String httpType = getHttpType(before); + res.put(cls.getSimpleName() + "." + method.getName(), httpType); + } + } + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + return res; + } + + /** + * JApiDocs 生成器 + * 如果报错,做如下检查: + * 1 javadoc @param 后是否有注释 + * 2 src.main.java 目录中非 .java 扩展名文件的内容要 // 注释起来 + * 3 删除 config.setDocsPath 目录中的文件,再生成试试 + *

+ * 如果生成的 api 文档不是预期的,作如下检查: + * 1 必须在 configRoute(Routes me) 中已该方式 me.add("/xx/yy", xx.class, "/"); 定义 Controller + * 2 在需要生成 api 的 Controller 中添加 @ApiDoc 注解 + * 3 如果要忽略某 action,在 action 上添加 @Ignore + * https://jfinal.com/share/2528 + *

+ * 在需要生成Doc文档的Controller类上面加上@ApiDoc注解 + *

+ * https://japidocs.agilestudio.cn/#/zh-cn/ + */ + public static void main(String[] args) { + PropKit.use("application_dev.properties"); + //可以限制只生成哪个接口,数组内容为空,则表示生成全部 + String[] generateInterfacesList = {}; + //String[] generateInterfacesList = {"getImportTemplate","uploadExcel"}; + + String projectPath = System.getProperty("user.dir"); + projectPath = projectPath.replace("\\", "/"); + String projectName = projectPath.substring(projectPath.lastIndexOf("/") + 1); + DocsConfig config = new DocsConfig(); + String sourceJava = projectPath + "/src/main/java"; + config.setProjectPath(sourceJava); // root project path + config.setProjectName(projectName); // project name + String version = "v1.0"; + config.setApiVersion(version); // api version + String docPath = projectPath + "/Doc"; + config.setDocsPath(docPath); // api docs target path + config.addPlugin(new PostmanDocPlugin()); + config.setAutoGenerate(Boolean.FALSE); // auto generate + config.setMvcFramework("JFinal"); + Docs.buildHtmlDocs(config); // execute to generate + + // 获取项目路径 + Map map = getControllMap(sourceJava); + //修正一下 postman 的请求方式 + String docFileName = String.format("%s-%s-api-docs.json", DocContext.getDocsConfig().getProjectName(), DocContext.getDocsConfig().getApiVersion()); + String jsonPath = docPath + "/" + version + "/" + docFileName; + String jsonContent = FileUtil.readUtf8String(jsonPath); + JSONObject jo = JSONObject.parseObject(jsonContent); + //第一层item + for (Object item : jo.getJSONArray("item")) { + JSONObject j2 = (JSONObject) item; + //Controller类名 + String className = j2.getString("name"); + //第二层item + for (Object o : j2.getJSONArray("item")) { + JSONObject j3 = (JSONObject) o; + JSONObject jRequest = j3.getJSONObject("request"); + String x = jRequest.getJSONObject("url").getString("raw"); + x = x.substring(x.lastIndexOf("/") + 1); + jRequest.put("method", map.get(className + "." + x)); + } + } + //限制只生成哪个接口 + Set _set = new HashSet<>(); + Collections.addAll(_set, generateInterfacesList); + + // 获取JSONArray + jo = jo.getJSONArray("item").getJSONObject(0); + JSONArray jsonArray = jo.getJSONArray("item"); + + if (!_set.isEmpty()) { + // 遍历JSONArray + for (int i = 0; i < jsonArray.size(); i++) { + // 获取当前的JSONObject + JSONObject obj = jsonArray.getJSONObject(i); + JSONObject jRequest = obj.getJSONObject("request"); + // 检查条件,例如,如果名字不是"John",则删除这个条目 + String x = jRequest.getJSONObject("url").getString("raw"); + x = x.substring(x.lastIndexOf("/") + 1); + if (!_set.contains(x)) { + // 从JSONArray中移除当前条目 + jsonArray.remove(i); + // 由于移除操作会改变数组的长度和索引,所以i需要减1以保持正确的索引位置 + i--; + } + } + // 将修改后的JSONArray重新设置回JSONObject + jo.put("item", jsonArray); + } + //美化JSON格式化保存 + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String jsonString = gson.toJson(jo); + FileUtil.writeUtf8String(jsonString, jsonPath); + System.out.println("恭喜,文档JSON处理完成!"); + } +} \ No newline at end of file diff --git a/dsBase/src/main/java/com/dsideal/base/Menu/Controller/MenuController.java b/dsBase/src/main/java/com/dsideal/base/Menu/Controller/MenuController.java index 313092c9..8af6c108 100644 --- a/dsBase/src/main/java/com/dsideal/base/Menu/Controller/MenuController.java +++ b/dsBase/src/main/java/com/dsideal/base/Menu/Controller/MenuController.java @@ -8,9 +8,6 @@ import com.dsideal.base.Util.CommonUtil; import com.dsideal.base.Menu.Model.MenuModel; import com.dsideal.base.Util.JwtUtil; import com.dsideal.base.Util.RetKit; -import com.dsideal.base.fay.tree.domain.MenuBean; -import com.dsideal.base.fay.tree.service.IFayTreeNode; -import com.dsideal.base.fay.tree.util.FayTreeUtil; import com.jfinal.aop.Before; import com.jfinal.core.Controller; import com.jfinal.ext.interceptor.GET; @@ -102,47 +99,7 @@ public class MenuController extends Controller { renderJson(CommonUtil.renderJsonForLayUI(dt, dt.size())); } - /** - * 功能:获取指定人员下的菜单 - * 作者:黄海 - * 时间:2018-12-22 - */ - @Before({GET.class}) - public void selectMenuByPerson() { - //当前登录的人员 - int identity_id = Integer.parseInt(getCookie("identity_id").trim()); - String person_id = getCookie("person_id").trim(); - //获取单位管理员菜单 - if (identity_id < 5) { //1,2,3,4 - Page page = model.selectBureauMenuByPersonId(identity_id, person_id); - List list = new ArrayList<>(); - for (int i = 0; i < page.getList().size(); i++) { - Record r = page.getList().get(i); - MenuBean m = new MenuBean(r.getStr("menu_id"), r.getStr("parent_id"), r.getStr("menu_name"), - r.getStr("url"), r.getStr("type")); - list.add(m); - } - Object data = FayTreeUtil.getTreeInJsonObject(list); - //如果是超级管理员,那么应该有配置菜单的功能返回,或者默认就必须有这个返回 - Kv kv = Kv.by("success", true); - kv.set("data", data); - renderJson(kv); - return; - } - //5,6 角色,就是教师,学生 - List menu_list = model.selectMenuByPersonId(person_id); - List list = new ArrayList<>(); - for (int i = 0; i < menu_list.size(); i++) { - Record r = menu_list.get(i); - MenuBean m = new MenuBean(r.getStr("menu_id"), r.getStr("parent_id"), r.getStr("menu_name"), - r.getStr("url"), r.getStr("type")); - list.add(m); - } - Object data = FayTreeUtil.getTreeInJsonObject(list); - Kv kv = Kv.by("success", true); - kv.set("data", data); - renderJson(kv); - } + /** * 功能:增加菜单 diff --git a/dsBase/src/main/java/com/dsideal/base/Plugin/PostmanDocPlugin.java b/dsBase/src/main/java/com/dsideal/base/Plugin/PostmanDocPlugin.java new file mode 100644 index 00000000..60c9b0ba --- /dev/null +++ b/dsBase/src/main/java/com/dsideal/base/Plugin/PostmanDocPlugin.java @@ -0,0 +1,48 @@ +package com.dsideal.base.Plugin; + +import freemarker.template.Template; +import freemarker.template.TemplateException; +import io.github.yedaxia.apidocs.DocContext; +import io.github.yedaxia.apidocs.IPluginSupport; +import io.github.yedaxia.apidocs.Resources; +import io.github.yedaxia.apidocs.Utils; +import io.github.yedaxia.apidocs.parser.ControllerNode; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PostmanDocPlugin implements IPluginSupport { + public PostmanDocPlugin() { + } + + public void execute(List controllerNodeList) { + FileWriter docFileWriter = null; + + try { + Template ctrlTemplate = this.getDocTpl(); + + String docFileName = String.format("%s-%s-api-docs.json", DocContext.getDocsConfig().getProjectName(), DocContext.getDocsConfig().getApiVersion()); + File docFile = new File(DocContext.getDocPath(), docFileName); + docFileWriter = new FileWriter(docFile); + Map data = new HashMap(); + data.put("controllerNodes", controllerNodeList); + data.put("currentApiVersion", DocContext.getCurrentApiVersion()); + data.put("projectName", DocContext.getDocsConfig().getProjectName()); + data.put("i18n", DocContext.getI18n()); + ctrlTemplate.process(data, docFileWriter); + + } catch (IOException | TemplateException var10) { + var10.printStackTrace(); + } finally { + Utils.closeSilently(docFileWriter); + } + } + + private Template getDocTpl() throws IOException { + return Resources.getFreemarkerTemplate("postman-doc.json.ftl"); + } +} \ No newline at end of file diff --git a/dsBase/src/main/java/com/dsideal/base/fay/tree/domain/FayTreeNode.java b/dsBase/src/main/java/com/dsideal/base/fay/tree/domain/FayTreeNode.java deleted file mode 100644 index e279ef9f..00000000 --- a/dsBase/src/main/java/com/dsideal/base/fay/tree/domain/FayTreeNode.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.dsideal.base.fay.tree.domain; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.fastjson.annotation.JSONField; -import com.dsideal.base.fay.tree.service.IFayTreeNode; - -public class FayTreeNode { - - @JSONField(ordinal=1) - private String nodeId; - - @JSONField(ordinal=3) - private String parentNodeId; - - private FayTreeNode parent; - - private IFayTreeNode treeObject; - - @JSONField(ordinal=6) - private List children = new ArrayList(); - - private List allChildren = new ArrayList(); - - public FayTreeNode(IFayTreeNode obj){ - this.nodeId = obj.getNodeId(); - this.parentNodeId = obj.getNodeParentId(); - this.treeObject = obj; - } - public void addChild(FayTreeNode treeNode){ - this.children.add(treeNode); - } - public void removeChild(FayTreeNode treeNode){ - this.children.remove(treeNode); - } - public String getNodeId() { - return nodeId; - } - public void setNodeId(String nodeId) { - this.nodeId = nodeId; - } - public String getParentNodeId() { - return parentNodeId; - } - public void setParentNodeId(String parentNodeId) { - this.parentNodeId = parentNodeId; - } - public FayTreeNode getParent() { - return parent; - } - public void setParent(FayTreeNode parent) { - this.parent = parent; - } - public List getChildren() { - if(children == null || children.isEmpty()) return null; - return children; - } - public void setChildren(List children) { - this.children = children; - } - - public IFayTreeNode getTreeObject() { - return treeObject; - } - - public void setTreeObject(IFayTreeNode treeObject) { - this.treeObject = treeObject; - } - - public List getAllChildren() { - if(this.allChildren.isEmpty()){ - for(FayTreeNode treeNode : this.children){ - this.allChildren.add(treeNode); - this.allChildren.addAll(treeNode.getAllChildren()); - } - } - return this.allChildren; - } -} diff --git a/dsBase/src/main/java/com/dsideal/base/fay/tree/domain/MenuBean.java b/dsBase/src/main/java/com/dsideal/base/fay/tree/domain/MenuBean.java deleted file mode 100644 index 571f360f..00000000 --- a/dsBase/src/main/java/com/dsideal/base/fay/tree/domain/MenuBean.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.dsideal.base.fay.tree.domain; - -import com.dsideal.base.fay.tree.service.IFayTreeNode; - -public class MenuBean implements IFayTreeNode { - private String menu_id; - private String parentId; - private String menu_name; - private String url; - private String memo; - - public MenuBean(String menu_id, String parentId, String menu_name, String url, String type) { - this.menu_id = menu_id; - this.parentId = parentId; - this.menu_name = menu_name; - this.url = url; - this.memo = type; - } - - @Override - public String getNodeId() { - return this.menu_id; - } - - @Override - public String getNodeParentId() { - return this.parentId; - } - - public String getMenu_id() { - return menu_id; - } - - public void setMenu_id(String menu_id) { - this.menu_id = menu_id; - } - - public String getParentId() { - return parentId; - } - - public void setParentId(String parentId) { - this.parentId = parentId; - } - - public String getMenu_name() { - return menu_name; - } - - public void setMenu_name(String menu_name) { - this.menu_name = menu_name; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getMemo() { - return memo; - } - - public void setMemo(String memo) { - this.memo = memo; - } -} diff --git a/dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTree.java b/dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTree.java deleted file mode 100644 index fcf7ba26..00000000 --- a/dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTree.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dsideal.base.fay.tree.service; - -import java.util.List; - -import com.dsideal.base.fay.tree.domain.FayTreeNode; - -public interface IFayTree { - List getTree(); - List getRoot(); - FayTreeNode getFayTreeNode(String nodeId); -} diff --git a/dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTreeNode.java b/dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTreeNode.java deleted file mode 100644 index 4272f743..00000000 --- a/dsBase/src/main/java/com/dsideal/base/fay/tree/service/IFayTreeNode.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dsideal.base.fay.tree.service; - -public interface IFayTreeNode { - String getNodeId(); - String getNodeParentId(); -} diff --git a/dsBase/src/main/java/com/dsideal/base/fay/tree/service/impl/FayTree.java b/dsBase/src/main/java/com/dsideal/base/fay/tree/service/impl/FayTree.java deleted file mode 100644 index 91ec9e55..00000000 --- a/dsBase/src/main/java/com/dsideal/base/fay/tree/service/impl/FayTree.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dsideal.base.fay.tree.service.impl; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; - -import com.dsideal.base.fay.tree.domain.FayTreeNode; -import com.dsideal.base.fay.tree.service.IFayTree; -import com.dsideal.base.fay.tree.service.IFayTreeNode; - -public class FayTree implements IFayTree { - private HashMap treeNodesMap = new LinkedHashMap(); - private List treeNodesList = new ArrayList(); - - public FayTree(List list){ - initTreeNodeMap(list); - initTreeNodeList(); - } - - private void initTreeNodeMap(List list){ - FayTreeNode treeNode = null; - for(IFayTreeNode item : list){ - treeNode = new FayTreeNode(item); - treeNodesMap.put(treeNode.getNodeId(), treeNode); - } - - Iterator iter = treeNodesMap.values().iterator(); - FayTreeNode parentTreeNode = null; - while(iter.hasNext()){ - treeNode = iter.next(); - if(treeNode.getParentNodeId() == null || treeNode.getParentNodeId() == ""){ - continue; - } - - parentTreeNode = treeNodesMap.get(treeNode.getParentNodeId()); - if(parentTreeNode != null){ - treeNode.setParent(parentTreeNode); - parentTreeNode.addChild(treeNode); - } - } - } - - private void initTreeNodeList(){ - if(treeNodesList.size() > 0){ - return; - } - if(treeNodesMap.size() == 0){ - return; - } - Iterator iter = treeNodesMap.values().iterator(); - FayTreeNode treeNode = null; - while(iter.hasNext()){ - treeNode = iter.next(); - if(treeNode.getParent() == null){ - this.treeNodesList.add(treeNode); - this.treeNodesList.addAll(treeNode.getAllChildren()); - } - } - } - - @Override - public List getTree() { - return this.treeNodesList; - } - - @Override - public List getRoot() { - List rootList = new ArrayList(); - if (this.treeNodesList.size() > 0) { - for (FayTreeNode node : treeNodesList) { - if (node.getParent() == null) - rootList.add(node); - } - } - return rootList; - } - - @Override - public FayTreeNode getFayTreeNode(String nodeId) { - return this.treeNodesMap.get(nodeId); - } -} diff --git a/dsBase/src/main/java/com/dsideal/base/fay/tree/util/FayTreeUtil.java b/dsBase/src/main/java/com/dsideal/base/fay/tree/util/FayTreeUtil.java deleted file mode 100644 index 2ed7b55f..00000000 --- a/dsBase/src/main/java/com/dsideal/base/fay/tree/util/FayTreeUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dsideal.base.fay.tree.util; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.serializer.SimplePropertyPreFilter; -import com.dsideal.base.fay.tree.service.IFayTreeNode; -import com.dsideal.base.fay.tree.service.impl.FayTree; - -public class FayTreeUtil { - - public static Object getTreeInJsonObject(List list){ - if(list == null || list.isEmpty()){ - return new ArrayList<>(); - } - FayTree tree = new FayTree(new ArrayList<>(list)); - SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); // 构造方法里,也可以直接传需要序列化的属性名字 - filter.getExcludes().add("parent"); - filter.getExcludes().add("allChildren"); - filter.getExcludes().add("parentNodeId"); - filter.getExcludes().add("nodeId"); - String treeJsonString = JSONObject.toJSONString(tree.getRoot(), filter); - Object data = JSONObject.parse(treeJsonString); - return data; - } -}