此系列主要盘点 spring-core
下的通用工具类(指与 Spring 的特性比如 bean
等 无关),因为现在大多数 java
开发基于 Spring 体系,那么这些工具类其实可以被认为标准 API 来直接调用了
Spring 5.2.x
Spring 提供了三个 IdGenerator 的实现类用来生成 UUID,有少许 安全性、性能 上的差距,不讨论
static void testIdGenerator() {
// 内部维护原子变量递增,可以使用其单例
System.out.println(new SimpleIdGenerator().generateId());
// UUID.randomUUID()
System.out.println(new JdkIdGenerator().generateId());
// 推荐使用
System.out.println(new AlternativeJdkIdGenerator().generateId());
}
结果:
00000000-0000-0000-0000-000000000001
d50aaaee-6cab-4f11-a4ee-2c3c11351a3b
317fd6b1-42e1-c806-193b-caffaf7c41e0
Ant 风格路径正则匹配,不会还有人在自己手动匹配 url
路径吧?不会吧不会吧?
static void testAntPathMatcher() {
// 可以指定分隔符,默认就是 "/"
System.out.println(new AntPathMatcher("/")
.match("com/t?st.jsp", "com/test.jsp")); // true
System.out.println(new AntPathMatcher("/")
.match("com/*.jsp", "com/test.jsp")); // true
System.out.println(new AntPathMatcher("/")
.match("com/**/test.jsp", "com/test.jsp")); // true
}
类似与 junit
的断言
一个很有意思的 ArrayList,允许指定一个生成器 ElementFactory,在 get(int index)
方法没有指定元素时,则由 ElementFactory 生成一个对应的元素,默认为 ReflectiveElementFactory 基于 反射 生成,即 new
一个
static void testAutoPopulatingList() {
class A {
int i;
public A() {
}
public A(int i) {
this.i = i;
}
@Override
public String toString() {
return "A{" +
"i=" + i +
'}';
}
}
// 默认 ElementFactory,即 new A() -> A{i=0}
System.out.println(new AutoPopulatingList<A>(A.class).get(0));
// 指定 ElementFactory -> A{i=1}
System.out.println(new AutoPopulatingList<A>(i -> new A(i)).get(1));
}
Base64 加解密封装工具类
static void testBase64Utils() {
System.out.println(
new String(
// 解密
Base64Utils.decode(
// 加密
Base64Utils.encode("test".getBytes()))));
} // test
封装了 Class 相关的大量方法,Spring 内部关于 反射 其实提供了很多对应的工具类,因此 duck不必 再手写 反射 代码了
interface A {
void a();
}
class AImpl implements A {
@Override
public void a() {
}
}
static void testClassUtils() {
// A
for (Class<?> c : ClassUtils.getAllInterfacesForClass(AImpl.class)) {
System.out.println(c.getSimpleName());
}
// public void com.xsn.util.test.TestUtils$AImpl.a()
System.out.println(
// 获取 AImpl 中对应 A 的方法 a
ClassUtils.getMostSpecificMethod(
// 获取指定方法
ClassUtils.getMethod(A.class, "a")
, AImpl.class));
}
集合工具类,最常用的应该也就是 isEmpty(Collection> collection)
isEmpty(Map, ?> map)
方法
Properties 文件读写操作工具类,SpringBoot 时代下应该不常用了
摘要 生成工具类,可用于文件的 防篡改
static void testDigestUtils() throws IOException {
System.out.println(
// 文件一旦被改写,摘要就会发生变化
DigestUtils.md5DigestAsHex(
new FileInputStream("F://1.txt")));
}
文件复制工具类,适用于 web
编程
static void testFileCopyUtils() throws IOException {
// byte[] 复制到 文件
FileCopyUtils.copy(
// 文件 复制到 byte[]
FileCopyUtils.copyToByteArray(new File("F://1.txt"))
, new File("F://2.txt")
);
}
文件操作工具类,提供了递归 删除、复制 文件的方法
static void testFileSystemUtils() throws IOException {
// 递归复制 F://test 下的文件到 F://test1
FileSystemUtils.copyRecursively(
new File("F://test")
, new File("F://test1")
);
}
一个不区分大小写的 Map
static void testLinkedCaseInsensitiveMap() {
LinkedCaseInsensitiveMap<String> linkedCaseInsensitiveMap
= new LinkedCaseInsensitiveMap<String>();
linkedCaseInsensitiveMap.put("a", "1");
linkedCaseInsensitiveMap.put("A", "2");
System.out.println(linkedCaseInsensitiveMap.get("a")); // 2
}
Spring 提供了一个 MultiValueMap 接口,为 Map 接口拓展了 add
方法支持一个 key
对应多个 value
,并提供了实现类 LinkedMultiValueMap
static void testLinkedMultiValueMap() {
LinkedMultiValueMap<String, String> linkedMultiValueMap =
new LinkedMultiValueMap<String, String>();
linkedMultiValueMap.add("1", "a");
linkedMultiValueMap.add("1", "b");
System.out.println(linkedMultiValueMap.get("1")); // [a, b]
}
数字相关工具类,提供 convertNumberToTargetClass(Number number, Class
数字类型转换、parseNumber(String text, Class
字符串解析为数字 等方法,感觉实用性不大
Object 相关工具类,示例其中几个常用的方法
static void testObjectUtils() {
System.out.println(
ObjectUtils.isArray(new int[]{})); // true
System.out.println(
ObjectUtils.isEmpty(new ArrayList<>())); // true
System.out.println(
ObjectUtils.isCheckedException(new RuntimeException())); // false
}
PatternMatchUtils,针对形如 *x
x*
x*y
的 正则 进行匹配的工具类
static void testPatternMatchUtils() {
System.out.println(
PatternMatchUtils.simpleMatch("*h", "match")); // true
System.out.println(
PatternMatchUtils.simpleMatch("m*h", "batch")); // false
}
PropertyPlaceholderHelper,支持 占位符 的解析,提供了 replacePlaceholders(String value, final Properties properties)
方法支持从 Properties 文件取值,也可以自定义 PlaceholderResolver 解析策略,见示例从 map
中解析占位符
static void testPropertyPlaceholderHelper() {
System.out.println(
// 指定占位符前后缀
new PropertyPlaceholderHelper("<", ">")
.replacePlaceholders(
"c"
// 参数 PlaceholderResolver 是个函数式接口
, new HashMap<String, String>() {
{
put("a", "A");
put("b", "B");
put("c", "C");
}
}::get
));
}
结果:ABc
Spring 提供的反射工具类,除了基础的反射相关方法外,还提供了诸如 doWithMethods
等好用的方法,见示例
static void testReflectionUtils() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
class A {
Integer a;
public A(Integer a) {
this.a = a;
}
void a() {
}
@Override
public String toString() {
return "A{" +
"a=" + a +
'}';
}
}
// 构造 -> A{a=1}
System.out.println(
ReflectionUtils.accessibleConstructor(A.class, Integer.class)
.newInstance(1));
// 属性获取
System.out.println(
ReflectionUtils.findField(A.class, "a"));
// 方法获取
System.out.println(
ReflectionUtils.findMethod(A.class, "a"));
// 打印 name 为 a 的方法
ReflectionUtils.doWithMethods(
A.class
, System.out::println
, m -> m.getName().equals("a")
);
}
记录程序运行时间的工具类,可以指定任务名称,分析运行时间占比等,监控程序性能十分有用
static void testStopWatch() throws InterruptedException {
StopWatch stopWatch = new StopWatch();
stopWatch.start("testTask");
TimeUnit.SECONDS.sleep(1);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}
结果:
StopWatch '': running time = 999796800 ns
---------------------------------------------
ns % Task name
---------------------------------------------
999796800 100% testTask
流操作相关工具类,之前介绍的 FileCopyUtils 的若干方法便是委托给 StreamUtils 来实现
static void testStreamUtils() throws IOException {
System.out.println(
StreamUtils.copyToByteArray(
new FileInputStream("F://1.txt")));
}
StringUtils,提供了大量 String 相关的工具方法
static void testStringUtils() {
System.out.println(StringUtils.isEmpty("")); // true
System.out.println(StringUtils.isEmpty(" ")); // false
System.out.println(StringUtils.hasLength("")); // false
System.out.println(StringUtils.hasLength(" ")); // true
System.out.println(StringUtils.hasText("")); // false
System.out.println(StringUtils.hasText(" ")); // false
System.out.println(StringUtils.capitalize("aaaaa")); // Aaaaa
System.out.println(StringUtils.uncapitalize("AAAAA")); // aAAAA
System.out.println(StringUtils.applyRelativePath("D://a/b/", "../")); // D://a/b/../
System.out.println(StringUtils.cleanPath("D://a/b/../")); // D://a/
System.out.println(StringUtils.pathEquals("D://a/", "D://a/b/../")); // true
System.out.println(StringUtils.getFilename("D://a/b/1.txt")); // 1.txt
System.out.println(StringUtils.getFilenameExtension("D://a/b/1.txt")); // txt
System.out.println(StringUtils.arrayToCommaDelimitedString(
new String[]{"1", "2"}
)); // 1,2
for (String s : StringUtils.commaDelimitedListToStringArray("1,2")) {
System.out.print(s);
} // 12
System.out.println(StringUtils.arrayToDelimitedString(
new String[]{"1", "2"}
, "%"
)); // 1%2
System.out.println(StringUtils.quote("test")); // 'test'
}
支持从系统变量中解析 占位符,前后缀固定位 ${}
static void testSystemPropertyUtils() {
System.out.println(SystemPropertyUtils.resolvePlaceholders("${user.dir}"));
}
本章节盘点了很多 Spring 提供的通用工具类,可以大大提升我们开发的效率