clay commit : tree=util使用,sentinel dashboard简介
continuous-integration/drone/push Build is passing Details

This commit is contained in:
clay 2022-11-17 12:18:38 +08:00
parent eee3ad9298
commit fe7b21ba53
5 changed files with 192 additions and 1 deletions

View File

@ -31,7 +31,7 @@ module.exports = {
// 设置侧边栏内容 // 设置侧边栏内容
sidebar: [ sidebar: [
{ {
title: '教程', title: '本文档使用教程',
collapsable: false, collapsable: false,
children: [ children: [
'/document/', '/document/',
@ -59,6 +59,13 @@ module.exports = {
'/use/spring-amin/', '/use/spring-amin/',
] // 根据自己的需求来订对应自己在docs下的文件夹名默认首页是README.md ] // 根据自己的需求来订对应自己在docs下的文件夹名默认首页是README.md
}, },
{
title: '工具类使用',
collapsable: false,
children: [
'/util/tree-util/',
] // 根据自己的需求来订对应自己在docs下的文件夹名默认首页是README.md
},
// { // {
// title: '模块介绍', // title: '模块介绍',

View File

@ -0,0 +1,36 @@
# sentinel dashboard 限流模块
> sentinel dashboard可以通过页面图形化的方式监控机器以及服务的运行情况和配置复杂的各种流控、降级等规则以保证线上服务的稳定运行本篇文章主要是介绍控制台参数意义和使用规则达到快速使用的目的
## 具体实现
security cloud 有两个sentinel dashboard模块,一个是官方给的完整版,另外一个为集成了nacos持久化,适合生产环境使用
### 官方提供
- xml
```xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
```
- 添加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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

0
docs/util/README.md Normal file
View File

View File

@ -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 <T>
* @return
*/
public static <T> List<T> build(List<?> list, Class<T> 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<Object, List<Object>> listMap = list.stream().collect(Collectors.groupingBy(object -> getParentId(object)));
//最终开始进行tree的构建
return getChildren(listMap, minPid);
}
/**
* 获取到子节点
*
* @param listMap
* @param parentId
* @param <T>
* @return
*/
private static <T> List<T> getChildren(Map<Object, List<Object>> listMap, Object parentId) {
//获取到缓存中的list
List<?> objects = listMap.get(parentId);
if (chickList(objects)) {
return null;
}
listMap.remove(parentId);
//遍历数组,并将对象一一的转换
List<Object> collect = objects.stream().map(object ->
conversion(object, listMap)).collect(Collectors.toList());
return (List<T>) collect;
}
/**
* 对象直接的字段进行转换
*
* @param object
* @param listMap
* @param <T>
* @return
*/
private static <T> T conversion(Object object, Map<Object, List<Object>> listMap) {
try {
Object targetObject = targetClass.newInstance();
//相同字段名称直接赋值
if (config.isCopy()){
BeanUtils.copyProperties(object, targetObject);
}
//不同字段名进行赋值
for (Map.Entry<String, String> 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<Object> 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<DeptVo> selectDeptTree(String deptName, Integer state) {
List<Dept> deptList = deptMapper.selectDeptList(deptName, state);
return TreeUtil.build(deptList,DeptVo.class,(config)->{
config.setIdField("deptId");
config.setMapper("key","deptId");
config.setExclude("phone");
});
}
```