diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index c2a0c63..248bff5 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -31,7 +31,7 @@ module.exports = { // 设置侧边栏内容 sidebar: [ { - title: '教程', + title: '本文档使用教程', collapsable: false, children: [ '/document/', @@ -59,6 +59,13 @@ module.exports = { '/use/spring-amin/', ] // 根据自己的需求来订,对应自己在docs下的文件夹名,默认首页是README.md }, + { + title: '工具类使用', + collapsable: false, + children: [ + '/util/tree-util/', + ] // 根据自己的需求来订,对应自己在docs下的文件夹名,默认首页是README.md + }, // { // title: '模块介绍', diff --git a/docs/use/sentinel-dashboard/README.md b/docs/use/sentinel-dashboard/README.md new file mode 100644 index 0000000..c48bcd5 --- /dev/null +++ b/docs/use/sentinel-dashboard/README.md @@ -0,0 +1,36 @@ +# sentinel dashboard 限流模块 +> sentinel dashboard可以通过页面图形化的方式监控机器以及服务的运行情况和配置复杂的各种流控、降级等规则,以保证线上服务的稳定运行,本篇文章主要是介绍控制台参数意义和使用规则,达到快速使用的目的 + +## 具体实现 +security cloud 有两个sentinel dashboard模块,一个是官方给的完整版,另外一个为集成了nacos持久化,适合生产环境使用 + +### 官方提供 + +- xml +```xml + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + +``` + +- 添加yaml配置文件到client服务中 + +```yaml +spring: + cloud: + sentinel: + transport: + # sentinel dashboard服务地址 + dashboard: localhost:5000 +``` + +### nacos升级 +- 配置数据持久化到nacos +- client注册到sentinel dashboard时,sentinel dashboard将nacos上对应的配置文件初始化给client +- 支持配置设置针对单一client设置配置文件还是集群内全部服务设置配置 + +> 配置与上方相同,只需要添加nacos的配置中心信息即可 + +![](./sentinel.png) + diff --git a/docs/use/sentinel-dashboard/sentinel.png b/docs/use/sentinel-dashboard/sentinel.png new file mode 100644 index 0000000..f8ae443 Binary files /dev/null and b/docs/use/sentinel-dashboard/sentinel.png differ diff --git a/docs/util/README.md b/docs/util/README.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/util/tree-util/README.md b/docs/util/tree-util/README.md new file mode 100644 index 0000000..33d6ad2 --- /dev/null +++ b/docs/util/tree-util/README.md @@ -0,0 +1,148 @@ +# 树形结构转换工具类 + +## 功能介绍 +- 将 A类的List数组快速转换为 B类型 List 的树形结构列表 + +## 实现原理 +- 主要使用到Java反射机制,将A类中的字段拷贝到B类中,并且根据A类中id 与 pid之间的关系快速构建树形结构 +- 设置配置类,更方便的实现A类与B类之前转换的需要,配置类包含有id字段与pid字段之间自定义设置,A类中需要转换到B类中的字段,以及是需要Spring 中 BeanUtils直接copy,以及如果使用了BeanUtil后需要排除的字段 + +## 代码展示 +```java +/** + * @author Clay + * @date 2022/11/16 + */ +public class TreeUtil { + + private static TreeConfig config; + + private static Class targetClass; + + /** + * 构建tree结构 + * + * @param list + * @param target + * @param node + * @param + * @return + */ + public static List build(List list, Class target, Node node) { + //初始化config + config = new TreeConfig(); + //将目标class对象设置为全局对象 + TreeUtil.targetClass = target; + //提供给实现类对config进行修改 + node.build(config); + //获取到最小的 + Object min = list.stream().min(Comparator.comparing(object -> getParentId(object).toString())).get(); + //获取到最小的父级id + Object minPid = getParentId(min); + //将数据通过他们的各自的父id进行分组 + Map> listMap = list.stream().collect(Collectors.groupingBy(object -> getParentId(object))); + //最终开始进行tree的构建 + return getChildren(listMap, minPid); + } + + /** + * 获取到子节点 + * + * @param listMap + * @param parentId + * @param + * @return + */ + private static List getChildren(Map> listMap, Object parentId) { + //获取到缓存中的list + List objects = listMap.get(parentId); + if (chickList(objects)) { + return null; + } + listMap.remove(parentId); + //遍历数组,并将对象一一的转换 + List collect = objects.stream().map(object -> + conversion(object, listMap)).collect(Collectors.toList()); + return (List) collect; + } + + /** + * 对象直接的字段进行转换 + * + * @param object + * @param listMap + * @param + * @return + */ + private static T conversion(Object object, Map> listMap) { + try { + Object targetObject = targetClass.newInstance(); + //相同字段名称直接赋值 + if (config.isCopy()){ + BeanUtils.copyProperties(object, targetObject); + } + //不同字段名进行赋值 + for (Map.Entry entry : config.getMapper().entrySet()) { + String targetKey = entry.getKey(); + String sourceKey = entry.getValue(); + Object value = ReflectUtils.invokeGetter(object, sourceKey); + Object[] args = new Object[]{value}; + ReflectUtils.invokeSetter(targetObject, targetKey, args); + } + //设置子节点 + Object id = ReflectUtils.invokeGetter(object, config.getIdField()); + List children = getChildren(listMap, id); + if (!chickList(children)) { + ReflectUtils.invokeSetter(targetObject, config.getChildrenField(), new Object[]{children}); + } + //设置完毕后,将需要排除的字段进行置空 + for (String key : config.getExclude()) { + ReflectUtils.invokeSetNull(targetObject, key); + } + //返回结果 + return (T) targetObject; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 检查list是否为空 + * + * @param objects + * @return + */ + private static boolean chickList(List objects) { + return null == objects || objects.isEmpty(); + } + + /** + * 获取到父级id + * + * @param object + * @return + */ + private static Object getParentId(Object object) { + try { + return ReflectUtils.invokeGetter(object, config.getParentField()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} +``` +## 使用demo +```java +@Override +public List selectDeptTree(String deptName, Integer state) { + List deptList = deptMapper.selectDeptList(deptName, state); + return TreeUtil.build(deptList,DeptVo.class,(config)->{ + config.setIdField("deptId"); + config.setMapper("key","deptId"); + config.setExclude("phone"); + }); +} +``` + +