Struct Util 是一个 Java 语言开发的结构化数据映射处理工具。Struct Util 主要解决两个方面的问题。第一个方面将*.xls, *.csv 等配置友好型数据源转换为业务侧友好型的 bean 结构,对配置数据和使用数据进行解耦,让开发和运营、策划三方实现共赢。第二方面解决了数据表热重载,数据有条件过滤,表结构跨表引用等等应用相关的问题。
点击阅读Struct Util 权威指南 - 通过 SPI 实现自定义扩展
Struct Util 是一个 Java 语言开发的结构化数据映射处理工具。Struct Util 主要解决两个方面的问题。第一个方面将*.xls, *.csv 等配置友好型数据源转换为业务侧友好型的 bean 结构,对配置数据和使用数据进行解耦,让开发和运营、策划三方实现共赢。第二方面解决了数据表热重载,数据有条件过滤,表结构跨表引用等等应用相关的问题。
StructUtil是博主个人作品, 稍微有自吹自擂的嫌疑, 欢迎收藏。哈哈, 因为是个人作品,应该是足够”权威”了。嘻嘻~~
SPI 扩展
Struct Util 提供了 Converters
, Converter
, StructFactoryBean
, StructHandler
四个扩展点,允许用户进行功能扩展。
EnhancedServiceLoader
相比于 JDK 内置的 SPI 功能解决了加载异常处理,懒加载等问题。核心加载代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void handleDefinitionFile(String dir, ClassLoader classLoader, List<ExtensionDefinition> output) throws IOException {
String fileName = dir + this.service.getName();
Enumeration<URL> urls = classLoader != null
? classLoader.getResources(fileName)
: ClassLoader.getSystemResources(fileName);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) {
String line = null;
while (null != (line = reader.readLine())) {
line = line.trim();
if (line.length() > 0) {
try {
output.add(this.createExtensionDefinition(line, classLoader));
} catch (LinkageError | ClassNotFoundException e) {
LOGGER.warn("load [{}] class failure. {}", line, e.getMessage());
}
}
}
} catch (Throwable e) {
LOGGER.warn("handle extension definition file error.", e);
}
}
}
ExtensionDefinition createExtensionDefinition(String clzName, ClassLoader loader) throws ClassNotFoundException {
Class<?> clzOfService = Class.forName(clzName, true, loader);
String name = null;
int order = 0;
SPI anno = AnnotationUtils.findAnnotation(SPI.class, clzOfService);
if (anno != null) {
name = anno.name();
order = anno.order();
}
return new ExtensionDefinition(name, clzOfService, order);
}
自定义 Converter
Struct Util内置了常用的类型转换器, 当用户有特殊转换需求时,可以通过扩展 Converter
接口实现转换业务,并通过 SPI
机制自动注册到系统中。以下是一个简单的字符串转数组的转换器实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class StringToArrayConverter implements Converter {
@Override
public Object convert(Object originValue, Class<?> targetType) {
if (!targetType.isArray() || String.class != originValue.getClass()) {
return null;
}
String content = (String) originValue;
Class<?> componentType = targetType.getComponentType();
String[] data = content.split(separator);
if (exceptBlank) {
data = Arrays.stream(data)
.map(String::trim)
.filter(s -> !s.isEmpty())
.toArray(String[]::new);
}
Object array = Array.newInstance(componentType, data.length);
for (int i = 0; i < data.length; i++) {
Array.set(array, i, ConverterUtil.covert(data[i], componentType));
}
return array;
}
}
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 TinyZ Zzh (包含链接: https://tinyzzh.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。 如有任何疑问,请 与我联系 (tinyzzh815@gmail.com) 。
评论