Skip to content

Hutool

测试代码在sl-express-ms-base-service的测试用例中,点击查看

树结构工具-TreeUtil

构建Tree示例

java
package com.sl.transport.common.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.List;

@Slf4j
class TreeUtilTest {

    @Test
    void treeTest() {
        // 构建node列表
        List<TreeNode<String>> nodeList = CollUtil.newArrayList();

        nodeList.add(new TreeNode<>("1", "0", "系统管理", 5));
        nodeList.add(new TreeNode<>("11", "1", "用户管理", 222222));
        nodeList.add(new TreeNode<>("111", "11", "用户添加", 0));
        nodeList.add(new TreeNode<>("2", "0", "店铺管理", 1));
        nodeList.add(new TreeNode<>("21", "2", "商品管理", 44));
        nodeList.add(new TreeNode<>("221", "2", "添加商品", 2));

        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        treeNodeConfig.setWeightKey("weight");
        treeNodeConfig.setIdKey("id");
        // 最大递归深度
        treeNodeConfig.setDeep(3);
        //构造树结构
        List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0",
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.putAll(BeanUtil.beanToMap(treeNode));
                    tree.remove("bid");
                });
        
        log.info("treeNodes {}", JSONUtil.toJsonStr(treeNodes));
    }
}

输出结果

json
[{
	"id": "2",
	"parentId": "0",
	"name": "店铺管理",
	"weight": 1,
	"children": [{
		"id": "221",
		"parentId": "2",
		"name": "添加商品",
		"weight": 2
	}, {
		"id": "21",
		"parentId": "2",
		"name": "商品管理",
		"weight": 44
	}]
}, {
	"id": "1",
	"parentId": "0",
	"name": "系统管理",
	"weight": 5,
	"children": [{
		"id": "11",
		"parentId": "1",
		"name": "用户管理",
		"weight": 222222,
		"children": [{
			"id": "111",
			"parentId": "11",
			"name": "用户添加",
			"weight": 0
		}]
	}]
}]

Bean工具-BeanUtil

对象转Bean

java
@Slf4j
public class BeanUtilTest {
    
    @Getter
    @Setter
    public static class SubPerson extends Person {
    
        public static final String SUBNAME = "TEST";
        
        private UUID id;
        private String subName;
        private Boolean slow;
        private LocalDateTime date;
        private LocalDate date2;
    }
    
    @Getter
    @Setter
    public static class Person {
        private String name;
        private int age;
        private String openid;
    }
    
    /**
    * 对象转Bean
    */
    @Test
    public void toBeanTest() {
        SubPerson person = new SubPerson();
        person.setAge(14);
        person.setOpenid("11213232");
        person.setName("测试A11");
        person.setSubName("sub名字");
        
        Map<?, ?> map = BeanUtil.toBean(person, Map.class);
        Assert.assertEquals("测试A11", map.get("name"));
        Assert.assertEquals(14, map.get("age"));
        Assert.assertEquals("11213232", map.get("openid"));
        // static属性应被忽略
        log.info("map是否包含名为SUBNAME的key {}", map.containsKey("SUBNAME"));
    }
}

输出结果

map是否包含名为SUBNAME的key false

验证码工具-CaptchaUtil

生成验证码

java
package com.sl.transport.common.util;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;

/**
* 直线干扰验证码单元测试
*
* @author looly
*/
@Slf4j
public class CaptchaTest {

    /**
    * 生成验证码
    */
    @Test
    public void lineCaptchaTest1() {
        // 定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        Assert.assertNotNull(lineCaptcha.getCode());
        log.info("直线干扰验证码: {}", lineCaptcha.getCode());
        log.info("直线干扰验证码验证结果: {}",lineCaptcha.verify(lineCaptcha.getCode()));
    }
}

输出结果

直线干扰验证码: 5ku0o
直线干扰验证码验证结果: true

类型转换工具类-Convert

转换值为指定类型

java
/**
* 转换值为指定类型
*/
@Test
public void toObjectTest() {
    final Object result = Convert.convert(Object.class, "aaaa");
    log.info(result + "");
}

输出结果

aaaa

对象工具-ObjectUtil

对象相等

java
/**
* 比较两个对象是否相等
*/
@Test
public void equalsTest() {
    Object a = null;
    Object b = null;
    log.info("是否相等:{}" , ObjectUtil.equals(a, b));
}

输出结果

是否相等:true

数字工具-NumberUtil

加法运算

java
/**
* 提供精确的加法运算
*/
@Test
public void addTest() {
    final Float a = 3.15f;
    final Double b = 4.22;
    final double result = NumberUtil.add(a, b).doubleValue();
    log.info(result + "");
}

输出结果

7.37

日期时间工具-DateUtil

当前时间

java
/**
* 当前时间
*/
@Test
public void nowTest() {
    // 当前时间
    final Date date = DateUtil.date();
    Assert.assertNotNull(date);
    // 当前时间
    final Date date2 = DateUtil.date(Calendar.getInstance());
    Assert.assertNotNull(date2);
    // 当前时间
    final Date date3 = DateUtil.date(System.currentTimeMillis());
    Assert.assertNotNull(date3);

    // 当前日期字符串,格式:yyyy-MM-dd HH:mm:ss
    final String now = DateUtil.now();
    Assert.assertNotNull(now);
    // 当前日期字符串,格式:yyyy-MM-dd
    final String today = DateUtil.today();
    log.info(today);
}

输出结果

2023-03-10

集合工具-CollUtil

自定义函数判断集合是否包含某类值

java
/**
* 自定义函数判断集合是否包含某类值
*/
@Test
public void testPredicateContains() {
    final ArrayList<String> list = CollUtil.newArrayList("bbbbb", "aaaaa", "ccccc");
    log.info( "" + CollUtil.contains(list, s -> s.startsWith("a")));
    log.info( "" + CollUtil.contains(list, s -> s.startsWith("d")));
}

输出结果

true
false

集合串行流工具-CollStreamUtil

将Collection转化为map

java
/**
* 将Collection转化为map(value类型与collection的泛型不同)
*/
@Test
public void testToMap() {
    Map<Long, String> map = CollStreamUtil.toMap(null, Student::getStudentId, Student::getName);
    Assert.assertEquals(map, Collections.EMPTY_MAP);
    List<Student> list = new ArrayList<>();
    map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
    Assert.assertEquals(map, Collections.EMPTY_MAP);
    list.add(new Student(1, 1, 1, "张三"));
    list.add(new Student(1, 1, 2, "李四"));
    list.add(new Student(1, 1, 3, "王五"));
    map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
    Assert.assertEquals(map.get(1L), "张三");
    Assert.assertEquals(map.get(2L), "李四");
    Assert.assertEquals(map.get(3L), "王五");
    Assert.assertNull(map.get(4L));

    // 测试value为空时
    list.add(new Student(1, 1, 4, null));
    map = CollStreamUtil.toMap(list, Student::getStudentId, Student::getName);
    log.info(map.get(4L));
}

输出结果

null

JSON工具-JSONUtil

JSON字符串转JSONObject对象

java
/**
* JSON字符串转JSONObject对象
*/
@Test
public void toJsonStrTest2() {
    final Map<String, Object> model = new HashMap<>();
    model.put("mobile", "17610836523");
    model.put("type", 1);

    final Map<String, Object> data = new HashMap<>();
    data.put("model", model);
    data.put("model2", model);

    final JSONObject jsonObject = JSONUtil.parseObj(data);

    log.info("是否相等{}", ObjectUtil.equals( "17610836523", jsonObject.getJSONObject("model").getStr("mobile")));
}

输出结果

是否相等true

唯一ID工具-IdUtil

获取随机UUID

java
/**
*获取随机UUID
*/
@Test
public void randomUUIDTest() {
    String randomUUID = IdUtil.randomUUID();
    log.info(randomUUID);
}

输出结果

e514518b-21d7-4918-9b34-792b21b0b64f

枚举工具-EnumUtil

枚举类中所有枚举对象的name列表

java
public enum TestEnum{
    TEST1("type1"), TEST2("type2"), TEST3("type3");

    TestEnum(String type) {
        this.type = type;
    }

    private final String type;
    @SuppressWarnings("unused")
    private String name;

    public String getType() {
        return this.type;
    }

    public String getName() {
        return this.name;
    }
}

/**
* 枚举类中所有枚举对象的name列表
*/
@Test
public void getNamesTest() {
    List<String> names = EnumUtil.getNames(TestEnum.class);
    boolean equalList = CollUtil.isEqualList(CollUtil.newArrayList("TEST1", "TEST2", "TEST3"), names);
    log.info(equalList + "");
}

输出结果

true

了解权限管家

介绍

公司有多个业务系统,这些业务系统的公共部分包括组织、用户、权限等系统管理: image-20220228161416340.png 这个公共的系统管理,可以剥离出一套基础组件服务,即权限管家。

传智权限管家是一个通用的权限管理中台服务,在神领物流项目中,我们使用权限系统管理企业内部员工,比如:快递员、司机、管理员等。

在权限管家中可以管理用户,管理后台系统的菜单,以及角色的管理。

逻辑模型

权限管家的接口根据管理范围分为公司级、应用级和系统接口,如下图:

部署安装

参考:https://sl-express.itheima.net/#/zh-cn/base-service?id=权限管家

登录

登录地址:http://auth.sl-express.com/api/authority/static/index.html#/login

用户名密码:admin/123456

image-20220729150005960.png

image-20220729150028329.png

应用管理

权限管家是一个多应用的管理系统,所以要接入权限管家首先需要创建应用。

【应用管理】 => 【添加应用】 image-20220729150644377.png

创建成功:

image-20220729151041632.png

查看应用所对应的ID和CODE: image-20220729151124872.png

组织管理

一般公司会设置不同的组织结构用来管理人员,比如:总部、分公司、人事部、行政部、财务部、物流部、物流转运等。

image.png

添加组织,组织是一颗树,所以需要选择上级组织:

image.png

添加完成:

image.png

进入应用

对于应用的操作需要进入到应用中才能操作:

image.png

进入应用后,可以看到左侧菜单有3项管理:【用户管理】、【菜单管理】、【角色管理】

image.png

对应的后台系统的菜单列表:(不要修改)

image.png

应用中的角色:

image.png

新增用户

新增用户需要【返回权限管家】进行操作,在【用户管理】中【新增用户】:

image.pngimage.png

新增用户:

image.png

添加成功:

image.png

分配角色

现在为【test01】分配快递员角色,怎么操作呢?

首先需要进入到【神领物流】应用,在【用户管理】中分配角色:

image.png

image.png

image.png

这样,test01就拥有了【快递员】角色了。

同理,可以添加其他的用户了。

SDK使用说明

关于authority-sdk

authority-sdk是基于authority-sdk的restful接口实现的Java SDK的封装,实现了token、组织、菜单、角色等功能。

快速集成使用

authority-sdk提供了两种方式与业务系统对接,分别是:

  • java sdk方式
  • Spring Boot集成方式

使用方法

java sdk方式

第一步,导入maven依赖

xml
<dependency>
    <groupId>com.itheima.em.auth</groupId>
    <artifactId>authority-sdk</artifactId>
    <version>{version}</version>
</dependency>

第二步,实例化AuthTemplate对象

java
String host = "127.0.0.1"; //Authority服务地址
int port = 8764; //Authority服务端口
int timeout = 1000; //http请求的超时时间,不传值默认为10S
        
//token,非登录请求都需要带上,一般情况下登录成功后将该数据放入缓存中        
String token = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYWNjb3VudCI6ImFkbWluIiwibmFtZSI6IuW5s-WPsOeuoeeQhuWRmCIsIm9yZ2lkIjo4NzQyMjc2MTUxNzM0NDk4MjUsInN0YXRpb25pZCI6ODU3OTQwMTU3NDYwOTU3NTM3LCJhZG1pbmlzdHJhdG9yIjp0cnVlLCJleHAiOjE2NTEyNTkyODB9.anqT0MD9zAr13KG9OE4mqHHK2UMCOXUjeMrEsN1wy9_a14zFbjPkiDZ8dM7JirsAgj61yvshoP6pqBImdmyilQN-iFSa_ci15Ii4HhfFE1mcaRon3ojX_T9ncjHKuF9Y9ZPKT68NOzOfCwvhDrG_sDiaI1C-TwEJmhLM78FhwAI";
//应用ID,非登录请求都需要带上,该参数表示你需要查询哪个应用相关数据,一般情况下置于配置文件中
Long applicationId = 1L;
//登录获取token
AuthTemplate authTemplate = new AuthTemplate(host,port,TIME_OUT);
Result<LoginDTO> result = authTemplate.opsForLogin().token("admin","123456");

//后续基于AuthTemplate可以调用各种服务
AuthTemplate authTemplate = new AuthTemplate(host,port,TIME_OUT,token,applicationId);
Result<List<MenuDTO>> result = authTemplate.opsForPermission().getMenu();
log.info("菜单:{}", JSONObject.toJSONString(result));

Spring Boot集成方式

第一步,导入maven依赖

xml
<dependency>
    <groupId>com.itheima.em.auth</groupId>
    <artifactId>itcast-auth-spring-boot-starter</artifactId>
    <version>1.0</version>
</dependency>

<!-- 如果是SNAPSHOT版本,如要在项目的pom.xml文件中引入快照版源 -->
<repositories>
    <repository>
        <id>sonatypeSnapshots</id>
        <name>Sonatype Snapshots</name>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
    </repository>
</repositories>

第二步,配置application.yml文件

yaml
itcast:
  authority:
    host: 127.0.0.1 #authority服务地址,根据实际情况更改
    port: 8764 #authority服务端口
    timeout: 10000 #http请求的超时时间

第三步,使用用例

java
package com.example.demo.service;

import com.alibaba.fastjson.JSONObject;
import com.itheima.auth.sdk.AuthTemplate;
import com.itheima.auth.sdk.common.Result;
import com.itheima.auth.sdk.dto.LoginDTO;
import com.itheima.auth.sdk.dto.MenuDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class AuthService {

    @Value("${itcast.authority.host}")
    private String host;

    @Value("${itcast.authority.port}")
    private int port;

    private final static int TIME_OUT = 10000;

    /**
     * 登录获取token
     * @param account
     * @param password
     */
    public void login(String account, String password) {
        AuthTemplate authTemplate = new AuthTemplate(host,port);
        Result<LoginDTO> loginDTO = authTemplate.opsForLogin().token(account, password);
        log.info("登录结果:{}", JSONObject.toJSONString(loginDTO));
    }
}