通用工具包(Commons)
常用的工具类库封装,是在开发 YMP 框架过程中积累下来的一些非常实用的辅助工具,其中主要涉及 HttpClient 请求包装器、JSON 包装器、文件及资源管理、数据导入与导出、视频图片处理、二维码、序列化、类、日期时间、数学、经纬度、字符串加解密、运行时环境、网络、线程操作等。
Maven包依赖
<dependency>
<groupId>net.ymate.platform</groupId>
<artifactId>ymate-platform-commons</artifactId>
<version>2.1.4-dev</version>
</dependency>
基础类型(Lang)
提供了针对任意对象之间 的类型转换、组合和无限层级树型结构的支持。
模糊对象(BlurObject)
BlurObject 是一个用于任意类型对象之间转换的工具类,基本涵盖日常使用的数据类型。通过 IConverter 接口可以实现自定义转换器,并支持手动注册或 SPI 机制自动注册。
核心特性
- 类型安全转换:支持各种基本数据类型、包装类型、集合类型之间的自动转换
- 智能类型推断:自动识别源类型并进行相应的转换处理
- 可扩展性:通过
IConverter接口支持自定义类型转换 - SPI 自动注册:支持通过 SPI 机制自动发现和注册转换器
创建 BlurObject 实例
// 使用静态 bind 方法创建
BlurObject blurObject = BlurObject.bind("123.4");
// 使用构造方法创建
BlurObject blurObject = new BlurObject(123);
// 绑定 null 值
BlurObject blurObject = BlurObject.bind(null);
基本数据类型转换
BlurObject 提供了丰富的方法用于基本数据类型转换:
| 方法 | 返回类型 | 说明 |
|---|---|---|
toBoolean() / toBooleanValue() | Boolean / boolean | 转换为布尔值 |
toInteger() / toIntValue() | Integer / int | 转换为整数 |
toLong() / toLongValue() | Long / long | 转换为长整型 |
toFloat() / toFloatValue() | Float / float | 转换为浮点数 |
toDouble() / toDoubleValue() | Double / double | 转换为双精度浮点数 |
toShort() / toShortValue() | Short / short | 转换为短整型 |
toByte() / toByteValue() | Byte / byte | 转换为字节 |
toStringValue() | String | 转换为字符串 |
toCharValue() | char | 转换为字符 |
示例: 基本数据类型转换
Object targetObj = "123.4";
BlurObject blurObject = BlurObject.bind(targetObj);
// 转换为整数(自动解析字符串)
int intValue = blurObject.toIntValue(); // 123
// 转换为双精度浮点数
double doubleValue = blurObject.toDoubleValue(); // 123.4
// 转换为浮点数
float floatValue = blurObject.toFloatValue(); // 123.4f
// 转换为字符串
String stringValue = blurObject.toStringValue(); // "123.4"
// 转换为布尔值
BlurObject boolObj = BlurObject.bind("true");
boolean boolValue = boolObj.toBooleanValue(); // true
集合类型转换
BlurObject 支持将对象转换为各种集合类型:
| 方法 | 返回类型 | 说明 |
|---|---|---|
toMapValue() | Map<?, ?> | 转换为 Map |
toListValue() | List<?> | 转换为 List |
toSetValue() | Set<?> | 转换为 Set |
示例: 集合类型转换
// Map 转换
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", 123);
BlurObject blurObject = BlurObject.bind(map);
Map<?, ?> resultMap = blurObject.toMapValue();
// List 转换
List<String> list = Arrays.asList("a", "b", "c");
BlurObject blurObject = BlurObject.bind(list);
List<?> resultList = blurObject.toListValue();
// 非集合类型会自动包装为单元素集合
BlurObject singleObj = BlurObject.bind("single");
List<?> singleList = singleObj.toListValue(); // ["single"]
字节数组转换
BlurObject 支持字节数组和包装类型的转换:
| 方法 | 返回类型 | 说明 |
|---|---|---|
toBytes() | Byte[] | 转换为 Byte 数组(包装类型) |
toBytesValue() | byte[] | 转换为 byte 数组(基本类型) |
示例: 字节数组转换
// byte[] 转换
byte[] bytes = {1, 2, 3, 4, 5};
BlurObject blurObject = BlurObject.bind(bytes);
byte[] result = blurObject.toBytesValue();
// Byte[] 转换
Byte[] byteObjects = {1, 2, 3, 4, 5};
BlurObject blurObject = BlurObject.bind(byteObjects);
byte[] result = blurObject.toBytesValue();
指定类型转换
使用 toObjectValue(Class<?> clazz) 方法可以将对象转换为指定类型:
BlurObject blurObject = BlurObject.bind("123");
// 转换为指定类型
Integer intObj = (Integer) blurObject.toObjectValue(Integer.class);
Double doubleObj = (Double) blurObject.toObjectValue(Double.class);
String strObj = (String) blurObject.toObjectValue(String.class);
自定义类型转换器
通过实现 IConverter 接口并配合 @Converter 注解,可以创建自定义类型转换器。
示例: 自定义类型转换器的注册与使用
// 自定义类型转换器,通过注解明确从...到...类型之间的转换
// 此类可以通过 SPI 方式被自动注册
@Converter(from = {java.util.Date.class}, to = java.sql.Date.class)
public class DateConverter implements IConverter<java.sql.Date> {
@Override
public java.sql.Date convert(Object target) {
return new java.sql.Date(((java.util.Date) target).getTime());
}
}
// 手动注册转换器
BlurObject.registerConverter(java.util.Date.class, java.sql.Date.class, new DateConverter());
// 执行转换
java.util.Date date = new java.util.Date();
java.sql.Date sqlDate = BlurObject.bind(date).toObjectValue(java.sql.Date.class);
SPI 自动注册
转换器可以通过 SPI 机制自动注册,只需在 META-INF/services/net.ymate.platform.commons.lang.IConverter 文件中添加转换器类的全限定名:
com.example.converter.DateConverter
com.example.converter.TimestampConverter
特殊类型处理
BlurObject 对一些特殊类型提供了专门的处理:
| 源类型 | 处理方式 |
|---|---|
Clob | 读取字符流并转换为字符串 |
Blob | 读取二进制流并转换为字节数组 |
Date / Calendar | 转换为时间戳(Long) |
LocalDate / LocalDateTime / ZonedDateTime | 转换为时间戳(Long) |
| 枚举类型 | 通过名称匹配进行转换 |
Object[] | 使用 | 连接为字符串 |
示例: 日期时间转换
// Date 转换为 Long(时间戳)
java.util.Date date = new java.util.Date();
BlurObject blurObject = BlurObject.bind(date);
long timestamp = blurObject.toLongValue();
// LocalDateTime 转换为 Long
LocalDateTime localDateTime = LocalDateTime.now();
BlurObject blurObject = BlurObject.bind(localDateTime);
long timestamp = blurObject.toLongValue();
最佳实践
-
优先使用带默认值的方法:如
toIntValue()、toBooleanValue()等,避免处理 null 值时的空指针异常 -
合理使用类型转换:了解各种类型之间的转换规则,避免精度丢失或数据截断
-
自定义转换器:对于复杂的类型转换需求,建议实现
IConverter接口进行封装 -
SPI 自动注册:对于通用的转换器,使用 SPI 机制自动注册,减少手动配置
结对对象(PairObject)
PairObject<K, V> 是一个通用的键值对容器类,用于将任意两种类型的对象以 <K, V> 的形式组合在一起。它实现了 Serializable 接口,支持序列化操作。
核心特性
- 泛型支持:支持任意类型的键和值组合
- 链式调用:setter 方法支持链式调用,方便构建对象
- 空值检查:提供便捷的空值检查方法
- 序列化支持:实现
Serializable接口,支持对象序列化
创建 PairObject 实例
PairObject 提供了多种创建实例的方式:
| 方法 | 说明 |
|---|---|
PairObject() | 默认构造方法,创建空的结对对象 |
PairObject(K key) | 使用键创建结对对象,值为 null |
PairObject(K key, V value) | 使用键和值创建结对对象 |
PairObject.bind(K key) | 静态方法,使用键创建结对对象 |
PairObject.bind(K key, V value) | 静态方法,使用键和值创建结对对象 |
示例: 创建结对对象
// 使用静态 bind 方法创建(推荐)
PairObject<String, Integer> pairObject1 = PairObject.bind("suninformation", 18);
// 使用构造方法创建
PairObject<String, Integer> pairObject2 = new PairObject<>("suninformation", 18);
// 只设置键,值为 null
PairObject<String, Integer> pairObject3 = PairObject.bind("key");
// 使用默认构造方法,然后通过 setter 设置
PairObject<String, Integer> pairObject4 = new PairObject<>();
pairObject4.setKey("suninformation").setValue(18);
常用方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
getKey() | K | 获取键 |
setKey(K key) | PairObject<K, V> | 设置键,支持链式调用 |
getValue() | V | 获取值 |
setValue(V value) | PairObject<K, V> | 设置值,支持链式调用 |
isEmpty() | boolean | 检查键和值是否都为 null |
isAnyEmpty() | boolean | 检查键或值是否为 null |
使用示例
示例一: 基本类型结对
String name = "suninformation";
int age = 18;
PairObject<String, Integer> pairObject = PairObject.bind(name, age);
// 获取键和值
String key = pairObject.getKey(); // "suninformation"
Integer value = pairObject.getValue(); // 18
// 检查是否为空
boolean empty = pairObject.isEmpty(); // false
boolean anyEmpty = pairObject.isAnyEmpty(); // false
示例二: 复杂类型结对
// 使用集合类型作为键和值
List<String> keyList = new ArrayList<>();
keyList.add("item1");
keyList.add("item2");
Map<String, String> valueMap = new HashMap<>();
valueMap.put("key1", "value1");
valueMap.put("key2", "value2");
PairObject<List<String>, Map<String, String>> pairObject =
new PairObject<>(keyList, valueMap);
// 获取键和值
List<String> keys = pairObject.getKey();
Map<String, String> values = pairObject.getValue();
示例三: 链式调用
PairObject<String, Integer> pairObject = new PairObject<>()
.setKey("age")
.setValue(25);
// 修改值
pairObject.setValue(26);
示例四: 空值检查
// 创建空的结对对象
PairObject<String, Integer> emptyPair = new PairObject<>();
// 检查是否为空
boolean isEmpty = emptyPair.isEmpty(); // true
boolean isAnyEmpty = emptyPair.isAnyEmpty(); // true
// 创建只有键的结对对象
PairObject<String, Integer> keyOnlyPair = PairObject.bind("key");
boolean isEmpty2 = keyOnlyPair.isEmpty(); // false(键不为null)
boolean isAnyEmpty2 = keyOnlyPair.isAnyEmpty(); // true(值为null)
示例五: 在集合中使用
// 创建结对对象列表
List<PairObject<String, Integer>> pairList = new ArrayList<>();
pairList.add(PairObject.bind("Alice", 25));
pairList.add(PairObject.bind("Bob", 30));
pairList.add(PairObject.bind("Charlie", 35));
// 遍历并输出
for (PairObject<String, Integer> pair : pairList) {
System.out.println(pair.getKey() + ": " + pair.getValue());
}
// 使用 Map 存储结对对象
Map<String, PairObject<String, Integer>> pairMap = new HashMap<>();
pairMap.put("user1", PairObject.bind("Alice", 25));
pairMap.put("user2", PairObject.bind("Bob", 30));
最佳实践
-
优先使用静态 bind 方法:代码更简洁,意图更明确
-
使用泛型确保类型安全:在创建
PairObject时明确指定键和值的类型 -
合理使用空值检查:在获取值之前使用
isEmpty()或isAnyEmpty()进行检查 -
链式调用简化代码:在需要连续设置多个属性时使用链式调用
-
作为方法返回值:当方法需要返回两个相关联的值时,可以使用
PairObject作为返回类型
// 作为方法返回值
public PairObject<String, Integer> getUserInfo() {
String name = getUserName();
int age = getUserAge();
return PairObject.bind(name, age);
}
树型对象(TreeObject)
使用级联方式存储各种数据类型,不限层级深度。
TreeObject 是一个功能强大的树形数据结构,支持以下特性:
- 支持三种存储模式:值模式、映射模式和数组集合模式
- 支持多种数据类型,包括基本类型、字符串、数组、集合等
- 支持 JSON 和 XML 的序列化与反序列化
- 提供丰富的类型转换和取值方法
- 支持通过默认值避免空指针异常
存储模式
TreeObject 支持三种存储模式:
| 常量 | 值 | 说明 |
|---|---|---|
| MODE_VALUE | 1 | 值模式,用于存储单个值 |
| MODE_MAP | 2 | 映射模式,用于存储键值对 |
| MODE_ARRAY | 3 | 数组集合模式,用于存储有序列表 |