当前位置: 首页 > news >正文

02.SpringBoot常用Utils工具类详解

文章目录

    • 1. BeanUtils详解
      • 1.1 什么是BeanUtils?
      • 1.2 主要的BeanUtils实现
        • 1.2.1 Spring BeanUtils
        • 1.2.2 Apache Commons BeanUtils
        • 1.2.3 其他实现
      • 1.3 Spring BeanUtils详细使用
        • 1.3.1 基本用法
        • 1.3.2 指定忽略属性
        • 1.3.3 批量拷贝(列表转换)
      • 1.4 自定义BeanUtils工具类
      • 1.5 BeanUtils的局限性和注意事项
        • 1.5.1 深拷贝 vs 浅拷贝
        • 1.5.2 类型转换问题
      • 1.6 BeanUtils性能对比
    • 2. StringUtils详解
      • 2.1 什么是StringUtils?
      • 2.2 Apache Commons StringUtils
        • 2.2.1 基本判断方法
        • 2.2.2 字符串操作方法
        • 2.2.3 字符串查找和替换
        • 2.2.4 字符串分割和连接
        • 2.2.5 字符串去除和修剪
        • 2.2.6 字符串比较
      • 2.3 Spring StringUtils
    • 3. CollectionUtils详解
      • 3.1 什么是CollectionUtils?
      • 3.2 Apache Commons CollectionUtils
        • 3.2.1 基本集合操作
        • 3.2.2 集合转换和过滤
        • 3.2.3 集合统计和分组
      • 3.3 Spring CollectionUtils
    • 4. DateUtils详解
      • 4.1 什么是DateUtils?
      • 4.2 Apache Commons DateUtils
        • 4.2.1 日期基本操作
        • 4.2.2 日期解析和格式化
        • 4.2.3 日期比较和判断
      • 4.3 Java 8+ 时间API工具类
    • 5. JsonUtils详解
      • 5.1 什么是JsonUtils?
      • 5.2 基于Jackson的JsonUtils
      • 5.3 配置化的JsonUtils
    • 6. FileUtils详解
      • 6.1 什么是FileUtils?
      • 6.2 Apache Commons IO FileUtils
        • 6.2.1 文件基本操作
        • 6.2.2 高级文件操作
      • 6.3 文件工具类实战
    • 7. ValidateUtils详解
      • 7.1 什么是ValidateUtils?
      • 7.2 基本参数验证
      • 7.3 业务验证工具类
    • 8. EncryptUtils详解
      • 8.1 什么是EncryptUtils?
      • 8.2 常用加密算法实现
    • 9. ReflectionUtils详解
      • 9.1 什么是ReflectionUtils?
      • 9.2 Spring ReflectionUtils使用
    • 10. 自定义工具类实践
      • 10.1 综合工具类
    • 11. 总结与最佳实践
      • 11.1 工具类使用原则
      • 11.2 开发建议

1. BeanUtils详解

1.1 什么是BeanUtils?

BeanUtils是一个非常重要的工具类,主要用于JavaBean之间的属性拷贝。在实际开发中,我们经常需要在不同的对象之间复制属性值,比如Entity转DTO、VO转DTO等场景。

1.2 主要的BeanUtils实现

1.2.1 Spring BeanUtils

Spring框架提供的BeanUtils,性能较好,是最常用的选择。

1.2.2 Apache Commons BeanUtils

Apache提供的BeanUtils,功能更强大但性能相对较差。

1.2.3 其他实现
  • Dozer
  • MapStruct(编译时生成代码,性能最佳)
  • ModelMapper

1.3 Spring BeanUtils详细使用

1.3.1 基本用法
import org.springframework.beans.BeanUtils;/*** 用户实体类*/
public class User {private Long id;private String username;private String email;private String phone;private Integer age;private Date createTime;// 构造方法public User() {}public User(Long id, String username, String email, String phone, Integer age) {this.id = id;this.username = username;this.email = email;this.phone = phone;this.age = age;this.createTime = new Date();}// getter和setter方法...public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getPhone() { return phone; }public void setPhone(String phone) { this.phone = phone; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }public Date getCreateTime() { return createTime; }public void setCreateTime(Date createTime) { this.createTime = createTime; }@Overridepublic String toString() {return "User{id=" + id + ", username='" + username + "', email='" + email + "', phone='" + phone + "', age=" + age + ", createTime=" + createTime + '}';}
}/*** 用户DTO类*/
public class UserDTO {private Long id;private String username;private String email;private String phone;private Integer age;private String createTimeStr; // 注意:这个字段名不同// 构造方法public UserDTO() {}// getter和setter方法...public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getPhone() { return phone; }public void setPhone(String phone) { this.phone = phone; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }public String getCreateTimeStr() { return createTimeStr; }public void setCreateTimeStr(String createTimeStr) { this.createTimeStr = createTimeStr; }@Overridepublic String toString() {return "UserDTO{id=" + id + ", username='" + username + "', email='" + email + "', phone='" + phone + "', age=" + age + ", createTimeStr='" + createTimeStr + "'}";}
}/*** 基本拷贝示例*/
public class BeanUtilsExample {public static void main(String[] args) {// 创建源对象User user = new User(1L, "张三", "zhangsan@example.com", "13800138000", 25);System.out.println("源对象:" + user);// 创建目标对象UserDTO userDTO = new UserDTO();// 执行属性拷贝BeanUtils.copyProperties(user, userDTO);System.out.println("拷贝后的目标对象:" + userDTO);System.out.println("注意:createTime没有被拷贝,因为目标对象中对应的是createTimeStr");}
}
1.3.2 指定忽略属性
public class BeanUtilsIgnoreExample {public static void main(String[] args) {User user = new User(1L, "李四", "lisi@example.com", "13900139000", 30);UserDTO userDTO = new UserDTO();// 拷贝时忽略指定属性BeanUtils.copyProperties(user, userDTO, "email", "phone");System.out.println("忽略email和phone后的拷贝结果:" + userDTO);// 输出:UserDTO{id=1, username='李四', email='null', phone='null', age=30, createTimeStr='null'}}
}
1.3.3 批量拷贝(列表转换)
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;public class BeanUtilsBatchExample {/*** 批量拷贝方法*/public static <T> List<T> copyList(List<?> sourceList, Class<T> targetClass) {if (sourceList == null || sourceList.isEmpty()) {return new ArrayList<>();}return sourceList.stream().map(source -> {try {T target = targetClass.newInstance();BeanUtils.copyProperties(source, target);return target;} catch (Exception e) {throw new RuntimeException("对象拷贝失败", e);}}).collect(Collectors.toList());}public static void main(String[] args) {// 创建用户列表List<User> userList = new ArrayList<>();userList.add(new User(1L, "张三", "zhangsan@example.com", "13800138000", 25));userList.add(new User(2L, "李四", "lisi@example.com", "13900139000", 30));userList.add(new User(3L, "王五", "wangwu@example.com", "13700137000", 28));System.out.println("原始用户列表:");userList.forEach(System.out::println);// 批量转换为DTOList<UserDTO> userDTOList = copyList(userList, UserDTO.class);System.out.println("\n转换后的DTO列表:");userDTOList.forEach(System.out::println);}
}

1.4 自定义BeanUtils工具类

import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;/*** 自定义Bean拷贝工具类*/
public class BeanCopyUtils {/*** 单个对象拷贝* @param source 源对象* @param targetSupplier 目标对象供应器* @param <T> 目标对象类型* @return 拷贝后的目标对象*/public static <T> T copyBean(Object source, Supplier<T> targetSupplier) {if (source == null) {return null;}T target = targetSupplier.get();BeanUtils.copyProperties(source, target);return target;}/*** 单个对象拷贝(指定忽略属性)* @param source 源对象* @param targetSupplier 目标对象供应器* @param ignoreProperties 忽略的属性名* @param <T> 目标对象类型* @return 拷贝后的目标对象*/public static <T> T copyBean(Object source, Supplier<T> targetSupplier, String... ignoreProperties) {if (source == null) {return null;}T target = targetSupplier.get();BeanUtils.copyProperties(source, target, ignoreProperties);return target;}/*** 列表对象拷贝* @param sourceList 源对象列表* @param targetSupplier 目标对象供应器* @param <T> 目标对象类型* @return 拷贝后的目标对象列表*/public static <T> List<T> copyBeanList(List<?> sourceList, Supplier<T> targetSupplier) {if (CollectionUtils.isEmpty(sourceList)) {return new ArrayList<>();}List<T> targetList = new ArrayList<>(sourceList.size());for (Object source : sourceList) {T target = copyBean(source, targetSupplier);targetList.add(target);}return targetList;}/*** 列表对象拷贝(指定忽略属性)* @param sourceList 源对象列表* @param targetSupplier 目标对象供应器* @param ignoreProperties 忽略的属性名* @param <T> 目标对象类型* @return 拷贝后的目标对象列表*/public static <T> List<T> copyBeanList(List<?> sourceList, Supplier<T> targetSupplier, String... ignoreProperties) {if (CollectionUtils.isEmpty(sourceList)) {return new ArrayList<>();}List<T> targetList = new ArrayList<>(sourceList.size());for (Object source : sourceList) {T target = copyBean(source, targetSupplier, ignoreProperties);targetList.add(target);}return targetList;}
}/*** 使用示例*/
public class BeanCopyUtilsExample {public static void main(String[] args) {// 单个对象拷贝User user = new User(1L, "张三", "zhangsan@example.com", "13800138000", 25);UserDTO userDTO = BeanCopyUtils.copyBean(user, UserDTO::new);System.out.println("单个对象拷贝:" + userDTO);// 单个对象拷贝(忽略属性)UserDTO userDTO2 = BeanCopyUtils.copyBean(user, UserDTO::new, "email", "phone");System.out.println("忽略属性拷贝:" + userDTO2);// 列表拷贝List<User> userList = new ArrayList<>();userList.add(new User(1L, "张三", "zhangsan@example.com", "13800138000", 25));userList.add(new User(2L, "李四", "lisi@example.com", "13900139000", 30));List<UserDTO> userDTOList = BeanCopyUtils.copyBeanList(userList, UserDTO::new);System.out.println("列表拷贝:");userDTOList.forEach(System.out::println);}
}

1.5 BeanUtils的局限性和注意事项

1.5.1 深拷贝 vs 浅拷贝
import java.util.List;
import java.util.ArrayList;/*** 演示BeanUtils的浅拷贝特性*/
public class User {private Long id;private String username;private List<String> hobbies; // 引用类型private Address address; // 自定义引用类型// 构造方法和getter/setter...public User() {}public User(Long id, String username) {this.id = id;this.username = username;this.hobbies = new ArrayList<>();this.address = new Address();}// getter和setter方法public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public List<String> getHobbies() { return hobbies; }public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }public Address getAddress() { return address; }public void setAddress(Address address) { this.address = address; }
}class Address {private String province;private String city;public Address() {}public Address(String province, String city) {this.province = province;this.city = city;}// getter和setterpublic String getProvince() { return province; }public void setProvince(String province) { this.province = province; }public String getCity() { return city; }public void setCity(String city) { this.city = city; }@Overridepublic String toString() {return "Address{province='" + province + "', city='" + city + "'}";}
}public class ShallowCopyExample {public static void main(String[] args) {// 创建源对象User sourceUser = new User(1L, "张三");sourceUser.getHobbies().add("篮球");sourceUser.getHobbies().add("足球");sourceUser.setAddress(new Address("北京", "北京市"));// 拷贝对象User targetUser = new User();BeanUtils.copyProperties(sourceUser, targetUser);System.out.println("拷贝前:");System.out.println("源对象地址:" + sourceUser.getAddress());System.out.println("目标对象地址:" + targetUser.getAddress());System.out.println("地址对象是否相同:" + (sourceUser.getAddress() == targetUser.getAddress()));// 修改源对象的引用类型属性sourceUser.getAddress().setCity("上海市");sourceUser.getHobbies().add("游泳");System.out.println("\n修改源对象后:");System.out.println("源对象地址:" + sourceUser.getAddress());System.out.println("目标对象地址:" + targetUser.getAddress());System.out.println("目标对象的地址也被修改了!这就是浅拷贝的问题");}
}
1.5.2 类型转换问题
/*** 演示类型转换问题*/
public class TypeConversionExample {static class SourceBean {private String id; // String类型private String age; // String类型private Date createTime;public SourceBean(String id, String age, Date createTime) {this.id = id;this.age = age;this.createTime = createTime;}// getter和setter...public String getId() { return id; }public void setId(String id) { this.id = id; }public String getAge() { return age; }public void setAge(String age) { this.age = age; }public Date getCreateTime() { return createTime; }public void setCreateTime(Date createTime) { this.createTime = createTime; }}static class TargetBean {private Long id; // Long类型private Integer age; // Integer类型private String createTime; // String类型// getter和setter...public Long getId() { return id; }public void setId(Long id) { this.id = id; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }public String getCreateTime() { return createTime; }public void setCreateTime(String createTime) { this.createTime = createTime; }@Overridepublic String toString() {return "TargetBean{id=" + id + ", age=" + age + ", createTime='" + createTime + "'}";}}public static void main(String[] args) {SourceBean source = new SourceBean("123", "25", new Date());TargetBean target = new TargetBean();// BeanUtils不会进行类型转换BeanUtils.copyProperties(source, target);System.out.println("拷贝结果:" + target);// 输出:TargetBean{id=null, age=null, createTime='null'}// 所有属性都为null,因为类型不匹配System.out.println("String类型的id无法直接拷贝到Long类型");System.out.println("需要手动进行类型转换");}
}

1.6 BeanUtils性能对比

import org.springframework.beans.BeanUtils;
import org.apache.commons.beanutils.BeanUtils as ApacheBeanUtils;/*** BeanUtils性能测试*/
public class BeanUtilsPerformanceTest {private static final int TEST_COUNT = 100000;public static void main(String[] args) throws Exception {User sourceUser = new User(1L, "张三", "zhangsan@example.com", "13800138000", 25);// Spring BeanUtils性能测试long startTime = System.currentTimeMillis();for (int i = 0; i < TEST_COUNT; i++) {UserDTO target = new UserDTO();BeanUtils.copyProperties(sourceUser, target);}long springTime = System.currentTimeMillis() - startTime;System.out.println("Spring BeanUtils耗时:" + springTime + "ms");// Apache BeanUtils性能测试startTime = System.currentTimeMillis();for (int i = 0; i < TEST_COUNT; i++) {UserDTO target = new UserDTO();ApacheBeanUtils.copyProperties(target, sourceUser);}long apacheTime = System.currentTimeMillis() - startTime;System.out.println("Apache BeanUtils耗时:" + apacheTime + "ms");// 手动拷贝性能测试startTime = System.currentTimeMillis();for (int i = 0; i < TEST_COUNT; i++) {UserDTO target = new UserDTO();target.setId(sourceUser.getId());target.setUsername(sourceUser.getUsername());target.setEmail(sourceUser.getEmail());target.setPhone(sourceUser.getPhone());target.setAge(sourceUser.getAge());}long manualTime = System.currentTimeMillis() - startTime;System.out.println("手动拷贝耗时:" + manualTime + "ms");System.out.println("\n性能对比:");System.out.println("Spring BeanUtils vs 手动拷贝:" + (springTime / (double) manualTime) + " 倍");System.out.println("Apache BeanUtils vs 手动拷贝:" + (apacheTime / (double) manualTime) + " 倍");}
}

2. StringUtils详解

2.1 什么是StringUtils?

StringUtils是处理字符串的工具类,提供了大量便捷的字符串操作方法。主要有Apache Commons Lang的StringUtils和Spring的StringUtils。

2.2 Apache Commons StringUtils

2.2.1 基本判断方法
import org.apache.commons.lang3.StringUtils;/*** StringUtils基本判断方法示例*/
public class StringUtilsBasicExample {public static void main(String[] args) {String str1 = null;String str2 = "";String str3 = "   ";String str4 = "hello";String str5 = "Hello World";System.out.println("=== 空值判断 ===");// isEmpty: 判断字符串是否为null或空字符串System.out.println("StringUtils.isEmpty(null): " + StringUtils.isEmpty(str1)); // trueSystem.out.println("StringUtils.isEmpty(\"\"): " + StringUtils.isEmpty(str2)); // trueSystem.out.println("StringUtils.isEmpty(\"   \"): " + StringUtils.isEmpty(str3)); // falseSystem.out.println("StringUtils.isEmpty(\"hello\"): " + StringUtils.isEmpty(str4)); // false// isNotEmpty: 判断字符串是否不为null且不为空字符串System.out.println("StringUtils.isNotEmpty(\"hello\"): " + StringUtils.isNotEmpty(str4)); // true// isBlank: 判断字符串是否为null、空字符串或只包含空白字符System.out.println("\n=== 空白判断 ===");System.out.println("StringUtils.isBlank(null): " + StringUtils.isBlank(str1)); // trueSystem.out.println("StringUtils.isBlank(\"\"): " + StringUtils.isBlank(str2)); // trueSystem.out.println("StringUtils.isBlank(\"   \"): " + StringUtils.isBlank(str3)); // trueSystem.out.println("StringUtils.isBlank(\"hello\"): " + StringUtils.isBlank(str4)); // false// isNotBlank: 判断字符串是否不为空白System.out.println("StringUtils.isNotBlank(\"hello\"): " + StringUtils.isNotBlank(str4)); // trueSystem.out.println("StringUtils.isNotBlank(\"   \"): " + StringUtils.isNotBlank(str3)); // falseSystem.out.println("\n=== 实际应用场景 ===");// 在实际开发中的应用String username = getUserInput(); // 模拟用户输入if (StringUtils.isNotBlank(username)) {System.out.println("用户名有效:" + username.trim());} else {System.out.println("请输入有效的用户名");}}private static String getUserInput() {// 模拟用户输入,可能为空或包含空格return "  admin  ";}
}
2.2.2 字符串操作方法
/*** StringUtils字符串操作方法示例*/
public class StringUtilsOperationExample {public static void main(String[] args) {String str = "Hello World Java Programming";System.out.println("=== 字符串截取和填充 ===");// 安全的截取字符串(不会抛出IndexOutOfBoundsException)System.out.println("substring(str, 0, 5): " + StringUtils.substring(str, 0, 5)); // "Hello"System.out.println("substring(str, 6, 11): " + StringUtils.substring(str, 6, 11)); // "World"System.out.println("substring(str, 100): " + StringUtils.substring(str, 100)); // "" (不会报错)// 左填充和右填充String shortStr = "123";System.out.println("leftPad(\"123\", 8, '0'): " + StringUtils.leftPad(shortStr, 8, '0')); // "00000123"System.out.println("rightPad(\"123\", 8, '*'): " + StringUtils.rightPad(shortStr, 8, '*')); // "123*****"System.out.println("center(\"123\", 10, '-'): " + StringUtils.center(shortStr, 10, '-')); // "---123----"System.out.println("\n=== 字符串重复和反转 ===");// 重复字符串System.out.println("repeat(\"abc\", 3): " + StringUtils.repeat("abc", 3)); // "abcabcabc"System.out.println("repeat(\"*\", 10): " + StringUtils.repeat("*", 10)); // "**********"// 反转字符串System.out.println("reverse(\"hello\"): " + StringUtils.reverse("hello")); // "olleh"System.out.println("\n=== 大小写转换 ===");String mixedCase = "hELLo WoRLd";System.out.println("capitalize(str): " + StringUtils.capitalize(mixedCase)); // "HELLo WoRLd"System.out.println("uncapitalize(str): " + StringUtils.uncapitalize(mixedCase)); // "hELLo WoRLd"System.out.println("swapCase(str): " + StringUtils.swapCase(mixedCase)); // "HellO wOrld"System.out.println("\n=== 实际应用示例 ===");// 格式化订单号String orderNumber = "123";String formattedOrderNumber = StringUtils.leftPad(orderNumber, 10, '0');System.out.println("订单号格式化:" + formattedOrderNumber); // "0000000123"// 生成分隔线String separator = StringUtils.repeat("=", 50);System.out.println(separator);System.out.println(StringUtils.center("系统公告", 50, '='));System.out.println(separator);}
}
2.2.3 字符串查找和替换
/*** StringUtils查找和替换方法示例*/
public class StringUtilsSearchReplaceExample {public static void main(String[] args) {String text = "Java is great, Java is powerful, Java is everywhere";System.out.println("=== 字符串查找 ===");// 查找子字符串System.out.println("contains(text, \"Java\"): " + StringUtils.contains(text, "Java")); // trueSystem.out.println("containsIgnoreCase(text, \"java\"): " + StringUtils.containsIgnoreCase(text, "java")); // true// 统计子字符串出现次数System.out.println("countMatches(text, \"Java\"): " + StringUtils.countMatches(text, "Java")); // 3System.out.println("countMatches(text, \"is\"): " + StringUtils.countMatches(text, "is")); // 3// 查找位置System.out.println("indexOf(text, \"great\"): " + StringUtils.indexOf(text, "great")); // 8System.out.println("lastIndexOf(text, \"Java\"): " + StringUtils.lastIndexOf(text, "Java")); // 45System.out.println("\n=== 字符串替换 ===");// 替换所有匹配项String replaced1 = StringUtils.replace(text, "Java", "Python");System.out.println("replace Java with Python: " + replaced1);// 只替换前n个匹配项String replaced2 = StringUtils.replace(text, "Java", "Python", 2);System.out.println("replace first 2 Java with Python: " + replaced2);// 忽略大小写替换String replaced3 = StringUtils.replaceIgnoreCase(text, "java", "C++");System.out.println("replaceIgnoreCase java with C++: " + replaced3);System.out.println("\n=== 批量替换 ===");// 批量替换String[] searchArray = {"Java", "great", "powerful"};String[] replaceArray = {"Python", "awesome", "amazing"};String batchReplaced = StringUtils.replaceEach(text, searchArray, replaceArray);System.out.println("批量替换结果: " + batchReplaced);System.out.println("\n=== 实际应用示例 ===");// 敏感词过滤String userInput = "这是一个该死的测试文本,包含一些脏话";String[] sensitiveWords = {"该死", "脏话"};String[] replacements = {"***", "**"};String filteredText = StringUtils.replaceEach(userInput, sensitiveWords, replacements);System.out.println("敏感词过滤后: " + filteredText);// URL参数替换String urlTemplate = "https://api.example.com/users/{userId}/posts/{postId}";String finalUrl = StringUtils.replace(urlTemplate, "{userId}", "123");finalUrl = StringUtils.replace(finalUrl, "{postId}", "456");System.out.println("URL模板替换: " + finalUrl);}
}
2.2.4 字符串分割和连接
import java.util.Arrays;/*** StringUtils分割和连接方法示例*/
public class StringUtilsSplitJoinExample {public static void main(String[] args) {System.out.println("=== 字符串分割 ===");String csv = "apple,banana,orange,grape";String[] fruits = StringUtils.split(csv, ",");System.out.println("split CSV: " + Arrays.toString(fruits));// 按多个分隔符分割String mixedSeparators = "apple,banana;orange:grape";String[] mixedFruits = StringUtils.split(mixedSeparators, ",;:");System.out.println("split by multiple separators: " + Arrays.toString(mixedFruits));// 分割并限制结果数量String longText = "one,two,three,four,five";String[] limitedSplit = StringUtils.split(longText, ",", 3);System.out.println("split with limit 3: " + Arrays.toString(limitedSplit));// 按空白字符分割String sentence = "Hello   world    java   programming";String[] words = StringUtils.split(sentence);System.out.println("split by whitespace: " + Arrays.toString(words));System.out.println("\n=== 字符串连接 ===");// 简单连接String[] animals = {"cat", "dog", "bird", "fish"};String joined1 = StringUtils.join(animals, ", ");System.out.println("join with comma: " + joined1);// 连接数组的部分元素String joined2 = StringUtils.join(animals, " | ", 1, 3);System.out.println("join partial array: " + joined2); // "dog | bird"// 连接集合java.util.List<String> list = Arrays.asList("red", "green", "blue");String joined3 = StringUtils.join(list, " - ");System.out.println("join list: " + joined3);System.out.println("\n=== 实际应用示例 ===");// 处理用户输入的标签String userTags = "Java, Spring,   MyBatis,  ,   Redis,";String[] tagArray = StringUtils.split(userTags, ",");// 清理空白和空字符串java.util.List<String> cleanTags = new java.util.ArrayList<>();for (String tag : tagArray) {String cleanTag = StringUtils.trim(tag);if (StringUtils.isNotBlank(cleanTag)) {cleanTags.add(cleanTag);}}String finalTags = StringUtils.join(cleanTags, ", ");System.out.println("清理后的标签: " + finalTags);// 构建SQL IN查询String[] userIds = {"1", "2", "3", "4", "5"};String inClause = "'" + StringUtils.join(userIds, "', '") + "'";String sql = "SELECT * FROM users WHERE id IN (" + inClause + ")";System.out.println("生成的SQL: " + sql);}
}
2.2.5 字符串去除和修剪
/*** StringUtils去除和修剪方法示例*/
public class StringUtilsTrimExample {public static void main(String[] args) {System.out.println("=== 基本修剪操作 ===");String str1 = "   hello world   ";String str2 = "\t\n  hello world  \r\n";String str3 = null;// 安全的trim(处理null值)System.out.println("trim(\"   hello world   \"): '" + StringUtils.trim(str1) + "'");System.out.println("trim(null): '" + StringUtils.trim(str3) + "'"); // nullSystem.out.println("trimToEmpty(null): '" + StringUtils.trimToEmpty(str3) + "'"); // ""System.out.println("trimToNull(\"   \"): " + StringUtils.trimToNull("   ")); // null// 去除所有空白字符System.out.println("deleteWhitespace(str): '" + StringUtils.deleteWhitespace(str2) + "'"); // "helloworld"System.out.println("\n=== 自定义字符去除 ===");String str4 = "xxxhello worldxxx";String str5 = "abc123def";// 去除指定字符System.out.println("strip(\"xxxhello worldxxx\", \"x\"): '" + StringUtils.strip(str4, "x") + "'");System.out.println("stripStart(\"xxxhello worldxxx\", \"x\"): '" + StringUtils.stripStart(str4, "x") + "'");System.out.println("stripEnd(\"xxxhello worldxxx\", \"x\"): '" + StringUtils.stripEnd(str4, "x") + "'");// 去除数字System.out.println("stripDigits(\"abc123def\"): '" + removeDigits(str5) + "'");System.out.println("\n=== 实际应用示例 ===");// 清理用户输入String userInput = "  admin@example.com  ";String cleanEmail = StringUtils.trimToEmpty(userInput).toLowerCase();System.out.println("清理后的邮箱: '" + cleanEmail + "'");// 清理文件路径String filePath = "///path//to///file.txt///";String cleanPath = StringUtils.strip(filePath, "/");System.out.println("清理后的路径: '" + cleanPath + "'");}private static String removeDigits(String str) {if (str == null) return null;return str.replaceAll("\\d", "");}
}
2.2.6 字符串比较
/*** StringUtils比较方法示例*/
public class StringUtilsCompareExample {public static void main(String[] args) {String str1 = "hello";String str2 = "Hello";String str3 = "hello";String str4 = null;String str5 = "";System.out.println("=== 基本比较 ===");// 安全的equals比较(处理null)System.out.println("equals(\"hello\", \"hello\"): " + StringUtils.equals(str1, str3)); // trueSystem.out.println("equals(\"hello\", \"Hello\"): " + StringUtils.equals(str1, str2)); // falseSystem.out.println("equals(null, null): " + StringUtils.equals(str4, str4)); // trueSystem.out.println("equals(\"hello\", null): " + StringUtils.equals(str1, str4)); // false// 忽略大小写比较System.out.println("equalsIgnoreCase(\"hello\", \"Hello\"): " + StringUtils.equalsIgnoreCase(str1, str2)); // true// 比较任意一个System.out.println("equalsAny(\"hello\", \"world\", \"hello\", \"java\"): " + StringUtils.equalsAny(str1, "world", "hello", "java")); // trueSystem.out.println("\n=== 字符串相似度 ===");String text1 = "programming";String text2 = "programing"; // 少了一个mString text3 = "program";// 计算编辑距离int distance1 = StringUtils.getLevenshteinDistance(text1, text2);int distance2 = StringUtils.getLevenshteinDistance(text1, text3);System.out.println("编辑距离 \"programming\" vs \"programing\": " + distance1); // 1System.out.println("编辑距离 \"programming\" vs \"program\": " + distance2); // 4// 获取相同前缀String prefix = StringUtils.getCommonPrefix("hello", "help", "healthy");System.out.println("共同前缀: '" + prefix + "'"); // "hel"System.out.println("\n=== 实际应用示例 ===");// 用户名验证String inputUsername = "Admin";String[] existingUsers = {"admin", "user1", "test"};boolean userExists = false;for (String existing : existingUsers) {if (StringUtils.equalsIgnoreCase(inputUsername, existing)) {userExists = true;break;}}System.out.println("用户名 '" + inputUsername + "' 是否存在: " + userExists);// 模糊搜索建议String searchTerm = "jav";String[] technologies = {"Java", "JavaScript", "Python", "C++", "Ruby"};System.out.println("搜索建议(包含 '" + searchTerm + "'):");for (String tech : technologies) {if (StringUtils.containsIgnoreCase(tech, searchTerm)) {System.out.println("  - " + tech);}}}
}

2.3 Spring StringUtils

import org.springframework.util.StringUtils;/*** Spring StringUtils示例*/
public class SpringStringUtilsExample {public static void main(String[] args) {System.out.println("=== Spring StringUtils基本方法 ===");String str1 = "hello,world,java";String str2 = "  hello world  ";String str3 = "user/profile/settings";// 判断是否有文本(相当于Apache的isNotBlank)System.out.println("hasText(\"  hello world  \"): " + StringUtils.hasText(str2)); // trueSystem.out.println("hasText(\"   \"): " + StringUtils.hasText("   ")); // falseSystem.out.println("hasText(null): " + StringUtils.hasText(null)); // false// 判断是否有长度(相当于Apache的isNotEmpty)System.out.println("hasLength(\"\"): " + StringUtils.hasLength("")); // falseSystem.out.println("hasLength(\"hello\"): " + StringUtils.hasLength("hello")); // true// 字符串分割(返回数组)String[] tokens1 = StringUtils.commaDelimitedListToStringArray(str1);System.out.println("commaDelimitedListToStringArray: " + java.util.Arrays.toString(tokens1));// 字符串分割(指定分隔符)String[] tokens2 = StringUtils.delimitedListToStringArray(str3, "/");System.out.println("delimitedListToStringArray: " + java.util.Arrays.toString(tokens2));// 数组转逗号分隔字符串String[] array = {"apple", "banana", "orange"};String joined = StringUtils.arrayToCommaDelimitedString(array);System.out.println("arrayToCommaDelimitedString: " + joined);System.out.println("\n=== 路径和文件操作 ===");String filePath = "/path/to/file.txt";String fileName = "document.pdf";String extension = ".java";// 获取文件名System.out.println("getFilename(\"/path/to/file.txt\"): " + StringUtils.getFilename(filePath));// 获取文件扩展名System.out.println("getFilenameExtension(\"document.pdf\"): " + StringUtils.getFilenameExtension(fileName));// 去除文件扩展名System.out.println("stripFilenameExtension(\"document.pdf\"): " + StringUtils.stripFilenameExtension(fileName));// 清理路径String messyPath = "/path/../to/./file.txt";System.out.println("cleanPath: " + StringUtils.cleanPath(messyPath));System.out.println("\n=== 实际应用示例 ===");// 配置解析String configValue = "jdbc.driver, jdbc.url, jdbc.username, jdbc.password";String[] configKeys = StringUtils.commaDelimitedListToStringArray(configValue);System.out.println("配置项解析:");for (String key : configKeys) {System.out.println("  - " + key.trim());}// 文件上传处理String uploadFileName = "user_avatar.png";String fileExtension = StringUtils.getFilenameExtension(uploadFileName);if (StringUtils.hasText(fileExtension)) {if ("jpg,jpeg,png,gif".contains(fileExtension.toLowerCase())) {System.out.println("文件类型有效: " + fileExtension);} else {System.out.println("不支持的文件类型: " + fileExtension);}}}
}

3. CollectionUtils详解

3.1 什么是CollectionUtils?

CollectionUtils是用于处理集合(Collection)的工具类,提供了许多便捷的集合操作方法。主要有Apache Commons Collections和Spring的CollectionUtils。

3.2 Apache Commons CollectionUtils

3.2.1 基本集合操作
import org.apache.commons.collections4.CollectionUtils;
import java.util.*;/*** CollectionUtils基本操作示例*/
public class CollectionUtilsBasicExample {public static void main(String[] args) {List<String> list1 = Arrays.asList("a", "b", "c", "d");List<String> list2 = Arrays.asList("c", "d", "e", "f");List<String> emptyList = new ArrayList<>();List<String> nullList = null;System.out.println("=== 集合判断 ===");// 判断集合是否为空System.out.println("isEmpty(emptyList): " + CollectionUtils.isEmpty(emptyList)); // trueSystem.out.println("isEmpty(nullList): " + CollectionUtils.isEmpty(nullList)); // trueSystem.out.println("isEmpty(list1): " + CollectionUtils.isEmpty(list1)); // false// 判断集合是否不为空System.out.println("isNotEmpty(list1): " + CollectionUtils.isNotEmpty(list1)); // true// 获取集合大小(安全)System.out.println("size(list1): " + CollectionUtils.size(list1)); // 4System.out.println("size(nullList): " + CollectionUtils.size(nullList)); // 0System.out.println("\n=== 集合运算 ===");// 交集Collection<String> intersection = CollectionUtils.intersection(list1, list2);System.out.println("交集 list1 ∩ list2: " + intersection); // [c, d]// 并集Collection<String> union = CollectionUtils.union(list1, list2);System.out.println("并集 list1 ∪ list2: " + union); // [a, b, c, d, e, f]// 差集(list1中有但list2中没有的元素)Collection<String> subtract = CollectionUtils.subtract(list1, list2);System.out.println("差集 list1 - list2: " + subtract); // [a, b]// 对称差集(两个集合中不共同拥有的元素)Collection<String> disjunction = CollectionUtils.disjunction(list1, list2);System.out.println("对称差集: " + disjunction); // [a, b, e, f]System.out.println("\n=== 实际应用示例 ===");// 用户权限管理List<String> userPermissions = Arrays.asList("read", "write", "delete");List<String> requiredPermissions = Arrays.asList("read", "write");// 检查用户是否拥有所需权限boolean hasAllPermissions = CollectionUtils.containsAll(userPermissions, requiredPermissions);System.out.println("用户是否拥有所需权限: " + hasAllPermissions);// 找出缺少的权限Collection<String> missingPermissions = CollectionUtils.subtract(requiredPermissions, userPermissions);if (CollectionUtils.isNotEmpty(missingPermissions)) {System.out.println("缺少权限: " + missingPermissions);} else {System.out.println("权限充足");}// 商品标签管理List<String> productTags = Arrays.asList("electronics", "mobile", "smartphone", "android");List<String> searchTags = Arrays.asList("mobile", "ios");Collection<String> matchedTags = CollectionUtils.intersection(productTags, searchTags);System.out.println("匹配的标签: " + matchedTags);if (CollectionUtils.isNotEmpty(matchedTags)) {System.out.println("商品与搜索条件匹配");} else {System.out.println("商品与搜索条件不匹配");}}
}
3.2.2 集合转换和过滤
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import java.util.*;/*** CollectionUtils转换和过滤示例*/
public class CollectionUtilsTransformExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);List<String> words = Arrays.asList("hello", "world", "java", "programming", "collection");System.out.println("=== 集合过滤 ===");// 过滤偶数Collection<Integer> evenNumbers = CollectionUtils.select(numbers, new Predicate<Integer>() {@Overridepublic boolean evaluate(Integer number) {return number % 2 == 0;}});System.out.println("偶数: " + evenNumbers); // [2, 4, 6, 8, 10]// 使用Lambda表达式(Java 8+)List<Integer> oddNumbers = new ArrayList<>();CollectionUtils.select(numbers, n -> n % 2 == 1, oddNumbers);System.out.println("奇数: " + oddNumbers); // [1, 3, 5, 7, 9]// 过滤长度大于4的单词Collection<String> longWords = CollectionUtils.select(words, new Predicate<String>() {@Overridepublic boolean evaluate(String word) {return word.length() > 4;}});System.out.println("长单词: " + longWords); // [hello, world, programming, collection]System.out.println("\n=== 集合转换 ===");// 数字平方转换Collection<Integer> squares = CollectionUtils.collect(numbers, new Transformer<Integer, Integer>() {@Overridepublic Integer transform(Integer number) {return number * number;}});System.out.println("平方数: " + squares); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]// 字符串转大写Collection<String> upperWords = CollectionUtils.collect(words, new Transformer<String, String>() {@Overridepublic String transform(String word) {return word.toUpperCase();}});System.out.println("大写单词: " + upperWords);System.out.println("\n=== 组合操作 ===");// 先过滤再转换:获取偶数的平方Collection<Integer> evenSquares = CollectionUtils.collect(CollectionUtils.select(numbers, n -> n % 2 == 0),n -> n * n);System.out.println("偶数的平方: " + evenSquares); // [4, 16, 36, 64, 100]System.out.println("\n=== 实际应用示例 ===");// 用户数据处理List<User> users = createSampleUsers();// 过滤成年用户Collection<User> adults = CollectionUtils.select(users, user -> user.getAge() >= 18);System.out.println("成年用户数量: " + adults.size());// 提取用户名Collection<String> usernames = CollectionUtils.collect(users, User::getUsername);System.out.println("用户名列表: " + usernames);// 获取成年用户的邮箱Collection<String> adultEmails = CollectionUtils.collect(CollectionUtils.select(users, user -> user.getAge() >= 18),User::getEmail);System.out.println("成年用户邮箱: " + adultEmails);}private static List<User> createSampleUsers() {List<User> users = new ArrayList<>();users.add(new User(1L, "张三", "zhangsan@example.com", 25));users.add(new User(2L, "李四", "lisi@example.com", 17));users.add(new User(3L, "王五", "wangwu@example.com", 30));users.add(new User(4L, "赵六", "zhaoliu@example.com", 16));return users;}static class User {private Long id;private String username;private String email;private Integer age;public User(Long id, String username, String email, Integer age) {this.id = id;this.username = username;this.email = email;this.age = age;}// getterspublic Long getId() { return id; }public String getUsername() { return username; }public String getEmail() { return email; }public Integer getAge() { return age; }@Overridepublic String toString() {return "User{id=" + id + ", username='" + username + "', email='" + email + "', age=" + age + '}';}}
}
3.2.3 集合统计和分组
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.collections4.Bag;
import java.util.*;/*** CollectionUtils统计和分组示例*/
public class CollectionUtilsStatisticsExample {public static void main(String[] args) {List<String> fruits = Arrays.asList("apple", "banana", "apple", "orange", "banana", "apple", "grape");List<Integer> scores = Arrays.asList(85, 92, 78, 96, 88, 92, 85, 78, 96);System.out.println("=== 元素计数 ===");// 使用Bag进行计数Bag<String> fruitBag = new HashBag<>(fruits);System.out.println("水果统计:");for (String fruit : fruitBag.uniqueSet()) {System.out.println("  " + fruit + ": " + fruitBag.getCount(fruit));}// 手动计数Map<Integer, Integer> scoreCount = new HashMap<>();for (Integer score : scores) {scoreCount.put(score, scoreCount.getOrDefault(score, 0) + 1);}System.out.println("\n分数统计: " + scoreCount);System.out.println("\n=== 集合比较 ===");List<String> list1 = Arrays.asList("a", "b", "c");List<String> list2 = Arrays.asList("a", "b", "c");List<String> list3 = Arrays.asList("a", "b", "d");// 集合相等比较System.out.println("isEqualCollection(list1, list2): " + CollectionUtils.isEqualCollection(list1, list2)); // trueSystem.out.println("isEqualCollection(list1, list3): " + CollectionUtils.isEqualCollection(list1, list3)); // false// 获取基数(去重后的大小)System.out.println("fruits cardinality: " + CollectionUtils.cardinality("apple", fruits)); // 3System.out.println("\n=== 实际应用示例 ===");// 电商订单统计List<Order> orders = createSampleOrders();// 按状态分组统计Map<String, Integer> statusCount = new HashMap<>();for (Order order : orders) {statusCount.put(order.getStatus(), statusCount.getOrDefault(order.getStatus(), 0) + 1);}System.out.println("订单状态统计: " + statusCount);// 统计总金额double totalAmount = orders.stream().mapToDouble(Order::getAmount).sum();System.out.println("订单总金额: " + totalAmount);// 按金额范围分组Map<String, List<Order>> amountGroups = new HashMap<>();amountGroups.put("low", new ArrayList<>());    // 0-100amountGroups.put("medium", new ArrayList<>());  // 100-500amountGroups.put("high", new ArrayList<>());    // 500+for (Order order : orders) {if (order.getAmount() < 100) {amountGroups.get("low").add(order);} else if (order.getAmount() < 500) {amountGroups.get("medium").add(order);} else {amountGroups.get("high").add(order);}}System.out.println("订单金额分组:");for (Map.Entry<String, List<Order>> entry : amountGroups.entrySet()) {System.out.println("  " + entry.getKey() + ": " + entry.getValue().size() + " 个订单");}}private static List<Order> createSampleOrders() {List<Order> orders = new ArrayList<>();orders.add(new Order(1L, "pending", 89.99));orders.add(new Order(2L, "completed", 299.99));orders.add(new Order(3L, "pending", 159.99));orders.add(new Order(4L, "cancelled", 599.99));orders.add(new Order(5L, "completed", 79.99));orders.add(new Order(6L, "completed", 899.99));return orders;}static class Order {private Long id;private String status;private Double amount;public Order(Long id, String status, Double amount) {this.id = id;this.status = status;this.amount = amount;}public Long getId() { return id; }public String getStatus() { return status; }public Double getAmount() { return amount; }@Overridepublic String toString() {return "Order{id=" + id + ", status='" + status + "', amount=" + amount + '}';}}
}

3.3 Spring CollectionUtils

import org.springframework.util.CollectionUtils;
import java.util.*;/*** Spring CollectionUtils示例*/
public class SpringCollectionUtilsExample {public static void main(String[] args) {List<String> list1 = Arrays.asList("a", "b", "c");List<String> list2 = Arrays.asList("c", "d", "e");List<String> emptyList = new ArrayList<>();List<String> nullList = null;System.out.println("=== 基本判断 ===");// 判断集合是否为空System.out.println("isEmpty(emptyList): " + CollectionUtils.isEmpty(emptyList)); // trueSystem.out.println("isEmpty(nullList): " + CollectionUtils.isEmpty(nullList)); // trueSystem.out.println("isEmpty(list1): " + CollectionUtils.isEmpty(list1)); // falseSystem.out.println("\n=== 集合合并 ===");// 合并数组到集合String[] array = {"x", "y", "z"};List<String> mergedList = new ArrayList<>(list1);CollectionUtils.mergeArrayIntoCollection(array, mergedList);System.out.println("合并后的集合: " + mergedList); // [a, b, c, x, y, z]// 合并PropertiesProperties props1 = new Properties();props1.setProperty("key1", "value1");props1.setProperty("key2", "value2");Properties props2 = new Properties();props2.setProperty("key2", "newValue2"); // 会覆盖props2.setProperty("key3", "value3");CollectionUtils.mergePropertiesIntoMap(props1, props2);System.out.println("合并后的Properties: " + props2);System.out.println("\n=== 集合转换 ===");// 集合转数组String[] arrayFromList = list1.toArray(new String[0]);System.out.println("集合转数组: " + Arrays.toString(arrayFromList));System.out.println("\n=== 实际应用示例 ===");// 配置管理Properties defaultConfig = new Properties();defaultConfig.setProperty("timeout", "30");defaultConfig.setProperty("retries", "3");defaultConfig.setProperty("debug", "false");Properties userConfig = new Properties();userConfig.setProperty("timeout", "60"); // 用户自定义超时时间userConfig.setProperty("host", "localhost"); // 用户添加的配置// 合并配置(用户配置优先)Properties finalConfig = new Properties();CollectionUtils.mergePropertiesIntoMap(defaultConfig, finalConfig);CollectionUtils.mergePropertiesIntoMap(userConfig, finalConfig);System.out.println("最终配置:");for (Object key : finalConfig.keySet()) {System.out.println("  " + key + " = " + finalConfig.getProperty((String) key));}// 数据验证List<String> requiredFields = Arrays.asList("username", "email", "password");Map<String, String> formData = new HashMap<>();formData.put("username", "admin");formData.put("email", "admin@example.com");// 缺少password字段List<String> missingFields = new ArrayList<>();for (String field : requiredFields) {if (!formData.containsKey(field) || formData.get(field) == null || formData.get(field).trim().isEmpty()) {missingFields.add(field);}}if (CollectionUtils.isEmpty(missingFields)) {System.out.println("表单验证通过");} else {System.out.println("缺少必填字段: " + missingFields);}}
}

4. DateUtils详解

4.1 什么是DateUtils?

DateUtils是用于处理日期和时间的工具类。Java 8之前主要使用Apache Commons Lang的DateUtils,Java 8之后推荐使用新的时间API(LocalDate、LocalDateTime等)。

4.2 Apache Commons DateUtils

4.2.1 日期基本操作
import org.apache.commons.lang3.time.DateUtils;
import java.util.Date;
import java.util.Calendar;
import java.text.SimpleDateFormat;/*** DateUtils基本操作示例*/
public class DateUtilsBasicExample {private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) throws Exception {Date now = new Date();System.out.println("当前时间: " + sdf.format(now));System.out.println("\n=== 日期加减操作 ===");// 添加天数Date tomorrow = DateUtils.addDays(now, 1);Date yesterday = DateUtils.addDays(now, -1);System.out.println("明天: " + sdf.format(tomorrow));System.out.println("昨天: " + sdf.format(yesterday));// 添加小时Date nextHour = DateUtils.addHours(now, 1);Date prevHour = DateUtils.addHours(now, -1);System.out.println("一小时后: " + sdf.format(nextHour));System.out.println("一小时前: " + sdf.format(prevHour));// 添加月份Date nextMonth = DateUtils.addMonths(now, 1);Date lastMonth = DateUtils.addMonths(now, -1);System.out.println("下个月: " + sdf.format(nextMonth));System.out.println("上个月: " + sdf.format(lastMonth));// 添加年份Date nextYear = DateUtils.addYears(now, 1);System.out.println("明年: " + sdf.format(nextYear));System.out.println("\n=== 日期设置操作 ===");// 设置时间为当天开始(00:00:00)Date startOfDay = DateUtils.truncate(now, Calendar.DAY_OF_MONTH);System.out.println("今天开始: " + sdf.format(startOfDay));// 设置为当月开始Date startOfMonth = DateUtils.truncate(now, Calendar.MONTH);System.out.println("本月开始: " + sdf.format(startOfMonth));// 设置为当年开始Date startOfYear = DateUtils.truncate(now, Calendar.YEAR);System.out.println("今年开始: " + sdf.format(startOfYear));// 设置具体时间Date specificTime = DateUtils.setHours(now, 14);specificTime = DateUtils.setMinutes(specificTime, 30);specificTime = DateUtils.setSeconds(specificTime, 0);System.out.println("设置为14:30:00: " + sdf.format(specificTime));System.out.println("\n=== 实际应用示例 ===");// 计算生日是否在本月Date birthday = sdf.parse("1990-03-15 10:30:00");Date birthdayThisYear = DateUtils.setYears(birthday, Calendar.getInstance().get(Calendar.YEAR));Date startOfThisMonth = DateUtils.truncate(now, Calendar.MONTH);Date endOfThisMonth = DateUtils.addMonths(startOfThisMonth, 1);boolean birthdayThisMonth = birthdayThisYear.after(startOfThisMonth) && birthdayThisYear.before(endOfThisMonth);System.out.println("生日是否在本月: " + birthdayThisMonth);// 计算工作日(简单示例:排除周末)Date checkDate = DateUtils.addDays(now, 1);Calendar cal = Calendar.getInstance();cal.setTime(checkDate);int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);boolean isWorkday = dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY;System.out.println("明天是否为工作日: " + isWorkday);}
}
4.2.2 日期解析和格式化
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.util.Date;
import java.text.ParseException;/*** DateUtils解析和格式化示例*/
public class DateUtilsParseExample {public static void main(String[] args) throws ParseException {System.out.println("=== 日期解析 ===");// 解析多种格式的日期字符串String[] parsePatterns = {"yyyy-MM-dd","yyyy/MM/dd","yyyy-MM-dd HH:mm:ss","yyyy/MM/dd HH:mm:ss","dd/MM/yyyy","MM/dd/yyyy"};String[] dateStrings = {"2023-12-25","2023/12/25","2023-12-25 15:30:45","2023/12/25 15:30:45","25/12/2023","12/25/2023"};for (String dateStr : dateStrings) {try {Date parsedDate = DateUtils.parseDate(dateStr, parsePatterns);System.out.println("解析 '" + dateStr + "' -> " + DateFormatUtils.format(parsedDate, "yyyy-MM-dd HH:mm:ss"));} catch (ParseException e) {System.out.println("无法解析: " + dateStr);}}System.out.println("\n=== 日期格式化 ===");Date now = new Date();// 常用格式化System.out.println("标准格式: " + DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss"));System.out.println("日期格式: " + DateFormatUtils.format(now, "yyyy年MM月dd日"));System.out.println("时间格式: " + DateFormatUtils.format(now, "HH:mm:ss"));System.out.println("ISO格式: " + DateFormatUtils.ISO_DATETIME_FORMAT.format(now));System.out.println("RFC822格式: " + DateFormatUtils.SMTP_DATETIME_FORMAT.format(now));System.out.println("\n=== 实际应用示例 ===");// 用户输入的日期解析String userInput = "2023-12-25";try {Date userDate = DateUtils.parseDate(userInput, parsePatterns);System.out.println("用户输入日期: " + DateFormatUtils.format(userDate, "yyyy年MM月dd日"));// 检查是否是未来日期if (userDate.after(new Date())) {System.out.println("这是一个未来日期");} else {System.out.println("这是一个过去日期");}} catch (ParseException e) {System.out.println("日期格式错误,请使用正确格式");}// 日志文件名生成String logFileName = "app_" + DateFormatUtils.format(now, "yyyyMMdd_HHmmss") + ".log";System.out.println("日志文件名: " + logFileName);}
}
4.2.3 日期比较和判断
/*** DateUtils比较和判断示例*/
public class DateUtilsCompareExample {public static void main(String[] args) throws ParseException {Date now = new Date();Date yesterday = DateUtils.addDays(now, -1);Date tomorrow = DateUtils.addDays(now, 1);Date sameDay = DateUtils.truncate(now, Calendar.DAY_OF_MONTH);System.out.println("=== 日期相等判断 ===");// 判断是否是同一天(忽略时分秒)System.out.println("今天和昨天是同一天: " + DateUtils.isSameDay(now, yesterday)); // falseSystem.out.println("今天和今天是同一天: " + DateUtils.isSameDay(now, sameDay)); // true// 判断是否是同一时刻System.out.println("现在和截取后的时间相等: " + (now.getTime() == sameDay.getTime())); // falseSystem.out.println("\n=== 日期范围判断 ===");// 创建日期范围Date startDate = DateUtils.parseDate("2023-01-01", "yyyy-MM-dd");Date endDate = DateUtils.parseDate("2023-12-31", "yyyy-MM-dd");Date testDate = DateUtils.parseDate("2023-06-15", "yyyy-MM-dd");boolean inRange = testDate.after(startDate) && testDate.before(endDate);System.out.println("测试日期是否在范围内: " + inRange);System.out.println("\n=== 年龄计算 ===");Date birthDate = DateUtils.parseDate("1990-05-15", "yyyy-MM-dd");long ageInMillis = now.getTime() - birthDate.getTime();long ageInDays = ageInMillis / (24 * 60 * 60 * 1000);int ageInYears = (int) (ageInDays / 365.25);System.out.println("年龄: " + ageInYears + " 岁");System.out.println("\n=== 实际应用示例 ===");// 会员有效期检查Date membershipExpiry = DateUtils.parseDate("2024-01-01", "yyyy-MM-dd");if (now.before(membershipExpiry)) {long daysLeft = (membershipExpiry.getTime() - now.getTime()) / (24 * 60 * 60 * 1000);System.out.println("会员有效,还剩 " + daysLeft + " 天");} else {System.out.println("会员已过期");}// 促销活动时间检查Date promotionStart = DateUtils.parseDate("2023-11-01 00:00:00", "yyyy-MM-dd HH:mm:ss");Date promotionEnd = DateUtils.parseDate("2023-11-30 23:59:59", "yyyy-MM-dd HH:mm:ss");if (now.after(promotionStart) && now.before(promotionEnd)) {System.out.println("促销活动进行中");} else if (now.before(promotionStart)) {System.out.println("促销活动尚未开始");} else {System.out.println("促销活动已结束");}}
}

4.3 Java 8+ 时间API工具类

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;/*** Java 8+ 时间API工具类*/
public class ModernDateTimeUtils {public static final DateTimeFormatter DEFAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");public static final DateTimeFormatter DEFAULT_DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");public static final DateTimeFormatter CHINESE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy年MM月dd日");/*** 获取当前日期*/public static LocalDate getCurrentDate() {return LocalDate.now();}/*** 获取当前时间*/public static LocalDateTime getCurrentDateTime() {return LocalDateTime.now();}/*** 字符串转LocalDate*/public static LocalDate parseDate(String dateStr) {return LocalDate.parse(dateStr, DEFAULT_DATE_FORMAT);}/*** 字符串转LocalDateTime*/public static LocalDateTime parseDateTime(String dateTimeStr) {return LocalDateTime.parse(dateTimeStr, DEFAULT_DATETIME_FORMAT);}/*** LocalDate转字符串*/public static String formatDate(LocalDate date) {return date.format(DEFAULT_DATE_FORMAT);}/*** LocalDateTime转字符串*/public static String formatDateTime(LocalDateTime dateTime) {return dateTime.format(DEFAULT_DATETIME_FORMAT);}/*** 计算两个日期之间的天数差*/public static long daysBetween(LocalDate startDate, LocalDate endDate) {return ChronoUnit.DAYS.between(startDate, endDate);}/*** 计算年龄*/public static int calculateAge(LocalDate birthDate) {return Period.between(birthDate, LocalDate.now()).getYears();}/*** 获取月份的第一天*/public static LocalDate getFirstDayOfMonth(LocalDate date) {return date.withDayOfMonth(1);}/*** 获取月份的最后一天*/public static LocalDate getLastDayOfMonth(LocalDate date) {return date.withDayOfMonth(date.lengthOfMonth());}/*** 判断是否是工作日*/public static boolean isWorkday(LocalDate date) {DayOfWeek dayOfWeek = date.getDayOfWeek();return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;}/*** Date转LocalDateTime*/public static LocalDateTime dateToLocalDateTime(Date date) {return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());}/*** LocalDateTime转Date*/public static Date localDateTimeToDate(LocalDateTime localDateTime) {return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());}public static void main(String[] args) {System.out.println("=== Java 8+ 时间API示例 ===");LocalDate today = getCurrentDate();LocalDateTime now = getCurrentDateTime();System.out.println("今天: " + formatDate(today));System.out.println("现在: " + formatDateTime(now));System.out.println("中文格式: " + today.format(CHINESE_DATE_FORMAT));// 日期计算LocalDate birthday = parseDate("1990-05-15");int age = calculateAge(birthday);System.out.println("年龄: " + age + " 岁");// 月份操作LocalDate firstDay = getFirstDayOfMonth(today);LocalDate lastDay = getLastDayOfMonth(today);System.out.println("本月第一天: " + formatDate(firstDay));System.out.println("本月最后一天: " + formatDate(lastDay));// 工作日判断System.out.println("今天是工作日: " + isWorkday(today));// 时间范围LocalDate startDate = today.minusDays(30);long daysDiff = daysBetween(startDate, today);System.out.println("30天前到今天共 " + daysDiff + " 天");// 与Date的转换Date oldDate = new Date();LocalDateTime converted = dateToLocalDateTime(oldDate);System.out.println("Date转换为LocalDateTime: " + formatDateTime(converted));}
}

5. JsonUtils详解

5.1 什么是JsonUtils?

JsonUtils是用于处理JSON数据的工具类,主要基于Jackson、Gson、Fastjson等JSON库实现。在SpringBoot中,默认使用Jackson库。

5.2 基于Jackson的JsonUtils

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.util.List;
import java.util.Map;/*** 基于Jackson的JSON工具类*/
public class JsonUtils {private static final ObjectMapper objectMapper = new ObjectMapper();/*** 对象转JSON字符串*/public static String toJson(Object obj) {try {return objectMapper.writeValueAsString(obj);} catch (JsonProcessingException e) {throw new RuntimeException("对象转JSON失败", e);}}/*** 对象转格式化的JSON字符串*/public static String toPrettyJson(Object obj) {try {return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);} catch (JsonProcessingException e) {throw new RuntimeException("对象转JSON失败", e);}}/*** JSON字符串转对象*/public static <T> T fromJson(String json, Class<T> clazz) {try {return objectMapper.readValue(json, clazz);} catch (JsonProcessingException e) {throw new RuntimeException("JSON转对象失败", e);}}/*** JSON字符串转List*/public static <T> List<T> fromJsonToList(String json, Class<T> clazz) {try {CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);return objectMapper.readValue(json, listType);} catch (JsonProcessingException e) {throw new RuntimeException("JSON转List失败", e);}}/*** JSON字符串转Map*/public static Map<String, Object> fromJsonToMap(String json) {try {return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});} catch (JsonProcessingException e) {throw new RuntimeException("JSON转Map失败", e);}}/*** 对象转Map*/public static Map<String, Object> objectToMap(Object obj) {return objectMapper.convertValue(obj, new TypeReference<Map<String, Object>>() {});}/*** Map转对象*/public static <T> T mapToObject(Map<String, Object> map, Class<T> clazz) {return objectMapper.convertValue(map, clazz);}/*** 读取JSON节点*/public static JsonNode readTree(String json) {try {return objectMapper.readTree(json);} catch (JsonProcessingException e) {throw new RuntimeException("解析JSON树失败", e);}}/*** 检查是否是有效的JSON*/public static boolean isValidJson(String json) {try {objectMapper.readTree(json);return true;} catch (JsonProcessingException e) {return false;}}/*** 使用示例*/public static void main(String[] args) {System.out.println("=== JSON工具类示例 ===");// 创建测试对象User user = new User(1L, "张三", "zhangsan@example.com", 25);// 对象转JSONString json = toJson(user);System.out.println("对象转JSON: " + json);// 格式化JSONString prettyJson = toPrettyJson(user);System.out.println("格式化JSON:\n" + prettyJson);// JSON转对象User parsedUser = fromJson(json, User.class);System.out.println("JSON转对象: " + parsedUser);// 对象转MapMap<String, Object> userMap = objectToMap(user);System.out.println("对象转Map: " + userMap);// Map转对象User userFromMap = mapToObject(userMap, User.class);System.out.println("Map转对象: " + userFromMap);// JSON数组处理List<User> userList = List.of(new User(1L, "张三", "zhangsan@example.com", 25),new User(2L, "李四", "lisi@example.com", 30));String listJson = toJson(userList);System.out.println("List转JSON: " + listJson);List<User> parsedList = fromJsonToList(listJson, User.class);System.out.println("JSON转List: " + parsedList);// JSON节点读取JsonNode rootNode = readTree(json);System.out.println("读取用户名: " + rootNode.get("username").asText());System.out.println("读取年龄: " + rootNode.get("age").asInt());// JSON有效性检查System.out.println("有效JSON: " + isValidJson(json));System.out.println("无效JSON: " + isValidJson("{invalid json}"));}static class User {private Long id;private String username;private String email;private Integer age;public User() {}public User(Long id, String username, String email, Integer age) {this.id = id;this.username = username;this.email = email;this.age = age;}// getters and setterspublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }@Overridepublic String toString() {return "User{id=" + id + ", username='" + username + "', email='" + email + "', age=" + age + '}';}}
}

5.3 配置化的JsonUtils

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.LocalDateTime;
import java.util.List;/*** 配置化的JSON工具类*/
public class ConfigurableJsonUtils {private static final ObjectMapper objectMapper;static {objectMapper = new ObjectMapper();// 配置时间模块objectMapper.registerModule(new JavaTimeModule());// 配置序列化选项objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);// 配置反序列化选项objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);}/*** 获取配置的ObjectMapper实例*/public static ObjectMapper getObjectMapper() {return objectMapper;}/*** 对象转JSON(不包含null值)*/public static String toJsonExcludeNull(Object obj) {try {ObjectMapper mapper = objectMapper.copy();mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);return mapper.writeValueAsString(obj);} catch (Exception e) {throw new RuntimeException("JSON转换失败", e);}}/*** 对象转JSON(不包含空值)*/public static String toJsonExcludeEmpty(Object obj) {try {ObjectMapper mapper = objectMapper.copy();mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);return mapper.writeValueAsString(obj);} catch (Exception e) {throw new RuntimeException("JSON转换失败", e);}}/*** 容错的JSON解析*/public static <T> T fromJsonTolerant(String json, Class<T> clazz) {try {ObjectMapper mapper = objectMapper.copy();mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);mapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);return mapper.readValue(json, clazz);} catch (Exception e) {throw new RuntimeException("JSON解析失败", e);}}public static void main(String[] args) {System.out.println("=== 配置化JSON工具类示例 ===");// 测试时间序列化UserWithTime user = new UserWithTime();user.setId(1L);user.setUsername("张三");user.setEmail(null); // null值user.setDescription(""); // 空字符串user.setCreateTime(LocalDateTime.now());System.out.println("包含null值: " + JsonUtils.toJson(user));System.out.println("排除null值: " + toJsonExcludeNull(user));System.out.println("排除空值: " + toJsonExcludeEmpty(user));// 测试容错解析String invalidJson = "{\"id\":1,\"username\":\"张三\",\"unknownField\":\"value\",\"age\":\"not_a_number\"}";try {UserWithTime parsed = fromJsonTolerant(invalidJson, UserWithTime.class);System.out.println("容错解析结果: " + parsed);} catch (Exception e) {System.out.println("解析失败: " + e.getMessage());}}static class UserWithTime {private Long id;private String username;private String email;private String description;private LocalDateTime createTime;private Integer age;// getters and setterspublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getDescription() { return description; }public void setDescription(String description) { this.description = description; }public LocalDateTime getCreateTime() { return createTime; }public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }@Overridepublic String toString() {return "UserWithTime{id=" + id + ", username='" + username + "', email='" + email + "', description='" + description + "', createTime=" + createTime + ", age=" + age + '}';}}
}

6. FileUtils详解

6.1 什么是FileUtils?

FileUtils是用于处理文件和目录操作的工具类,主要基于Apache Commons IO实现,提供了丰富的文件操作方法。

6.2 Apache Commons IO FileUtils

6.2.1 文件基本操作
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;/*** FileUtils基本操作示例*/
public class FileUtilsBasicExample {public static void main(String[] args) throws IOException {System.out.println("=== 文件读写操作 ===");File testFile = new File("test.txt");String content = "Hello, FileUtils!\n这是测试内容。\n中文支持测试。";// 写入文件FileUtils.writeStringToFile(testFile, content, StandardCharsets.UTF_8);System.out.println("文件写入成功: " + testFile.getAbsolutePath());// 读取文件String readContent = FileUtils.readFileToString(testFile, StandardCharsets.UTF_8);System.out.println("文件内容: " + readContent);// 按行读取List<String> lines = FileUtils.readLines(testFile, StandardCharsets.UTF_8);System.out.println("文件行数: " + lines.size());for (int i = 0; i < lines.size(); i++) {System.out.println("第" + (i + 1) + "行: " + lines.get(i));}System.out.println("\n=== 文件信息 ===");// 文件大小long fileSize = FileUtils.sizeOf(testFile);System.out.println("文件大小: " + fileSize + " 字节");System.out.println("文件大小(可读): " + FileUtils.byteCountToDisplaySize(fileSize));// 文件时间System.out.println("最后修改时间: " + new java.util.Date(testFile.lastModified()));System.out.println("\n=== 文件复制和移动 ===");File copyFile = new File("test_copy.txt");File moveFile = new File("test_moved.txt");// 复制文件FileUtils.copyFile(testFile, copyFile);System.out.println("文件复制成功: " + copyFile.getAbsolutePath());// 移动文件FileUtils.moveFile(copyFile, moveFile);System.out.println("文件移动成功: " + moveFile.getAbsolutePath());System.out.println("\n=== 目录操作 ===");File testDir = new File("testDir");File subDir = new File(testDir, "subDir");// 创建目录FileUtils.forceMkdir(subDir);System.out.println("目录创建成功: " + subDir.getAbsolutePath());// 复制文件到目录FileUtils.copyFileToDirectory(testFile, testDir);System.out.println("文件复制到目录成功");// 列出目录中的文件Collection<File> files = FileUtils.listFiles(testDir, new String[]{"txt"}, true);System.out.println("目录中的txt文件:");for (File file : files) {System.out.println("  " + file.getName());}// 计算目录大小long dirSize = FileUtils.sizeOfDirectory(testDir);System.out.println("目录大小: " + FileUtils.byteCountToDisplaySize(dirSize));System.out.println("\n=== 清理 ===");// 删除文件和目录FileUtils.deleteQuietly(testFile);FileUtils.deleteQuietly(moveFile);FileUtils.deleteDirectory(testDir);System.out.println("清理完成");}
}
6.2.2 高级文件操作
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.*;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;/*** FileUtils高级操作示例*/
public class FileUtilsAdvancedExample {public static void main(String[] args) throws IOException {System.out.println("=== 文件过滤 ===");// 创建测试文件结构createTestStructure();File rootDir = new File("fileTest");// 按扩展名过滤Collection<File> javaFiles = FileUtils.listFiles(rootDir, new String[]{"java", "class"}, true);System.out.println("Java相关文件:");javaFiles.forEach(file -> System.out.println("  " + file.getName()));// 按大小过滤Collection<File> largeFiles = FileUtils.listFiles(rootDir, new SizeFileFilter(100), // 大于100字节TrueFileFilter.INSTANCE);System.out.println("大文件:");largeFiles.forEach(file -> System.out.println("  " + file.getName() + " (" + FileUtils.byteCountToDisplaySize(file.length()) + ")"));// 按修改时间过滤long oneHourAgo = System.currentTimeMillis() - (60 * 60 * 1000);Collection<File> recentFiles = FileUtils.listFiles(rootDir,new AgeFileFilter(oneHourAgo, false), // 最近一小时内修改的TrueFileFilter.INSTANCE);System.out.println("最近修改的文件:");recentFiles.forEach(file -> System.out.println("  " + file.getName()));// 组合过滤器IOFileFilter combinedFilter = new AndFileFilter(new SuffixFileFilter(".txt"),new SizeFileFilter(50, true) // 小于50字节的txt文件);Collection<File> filteredFiles = FileUtils.listFiles(rootDir, combinedFilter, TrueFileFilter.INSTANCE);System.out.println("小txt文件:");filteredFiles.forEach(file -> System.out.println("  " + file.getName()));System.out.println("\n=== 文件监控 ===");// 文件迭代器Iterator<File> fileIterator = FileUtils.iterateFiles(rootDir, null, true);System.out.println("所有文件:");while (fileIterator.hasNext()) {File file = fileIterator.next();System.out.println("  " + file.getPath() + " (" + FileUtils.byteCountToDisplaySize(file.length()) + ")");}System.out.println("\n=== 文件名操作 ===");String filePath = "/path/to/document.pdf";System.out.println("完整路径: " + filePath);System.out.println("文件名: " + FilenameUtils.getName(filePath));System.out.println("基础名: " + FilenameUtils.getBaseName(filePath));System.out.println("扩展名: " + FilenameUtils.getExtension(filePath));System.out.println("路径: " + FilenameUtils.getPath(filePath));System.out.println("父路径: " + FilenameUtils.getFullPath(filePath));// 路径标准化String messyPath = "/path/../to/./document.pdf";System.out.println("混乱路径: " + messyPath);System.out.println("标准化路径: " + FilenameUtils.normalize(messyPath));// 清理FileUtils.deleteDirectory(rootDir);System.out.println("\n清理完成");}private static void createTestStructure() throws IOException {File rootDir = new File("fileTest");FileUtils.forceMkdir(rootDir);// 创建不同类型的文件FileUtils.writeStringToFile(new File(rootDir, "test.txt"), "这是一个文本文件", StandardCharsets.UTF_8);FileUtils.writeStringToFile(new File(rootDir, "README.md"), "# 这是README文件\n这是一个较长的文件内容,用于测试文件大小过滤功能。", StandardCharsets.UTF_8);FileUtils.writeStringToFile(new File(rootDir, "Main.java"), "public class Main { public static void main(String[] args) {} }", StandardCharsets.UTF_8);// 创建子目录File subDir = new File(rootDir, "subdir");FileUtils.forceMkdir(subDir);FileUtils.writeStringToFile(new File(subDir, "data.xml"), "<root><data>test</data></root>", StandardCharsets.UTF_8);FileUtils.writeStringToFile(new File(subDir, "config.properties"), "app.name=test\napp.version=1.0", StandardCharsets.UTF_8);}
}

6.3 文件工具类实战

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;/*** 实用文件工具类*/
public class PracticalFileUtils {/*** 安全地读取文件内容*/public static String readFileContent(String filePath) {try {File file = new File(filePath);if (!file.exists() || !file.isFile()) {return null;}return FileUtils.readFileToString(file, StandardCharsets.UTF_8);} catch (IOException e) {throw new RuntimeException("读取文件失败: " + filePath, e);}}/*** 安全地写入文件内容*/public static boolean writeFileContent(String filePath, String content) {try {File file = new File(filePath);FileUtils.forceMkdirParent(file); // 确保父目录存在FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8);return true;} catch (IOException e) {System.err.println("写入文件失败: " + filePath + ", " + e.getMessage());return false;}}/*** 备份文件*/public static boolean backupFile(String filePath, String backupDir) {try {File sourceFile = new File(filePath);if (!sourceFile.exists()) {return false;}File backupDirectory = new File(backupDir);FileUtils.forceMkdir(backupDirectory);String timestamp = String.valueOf(System.currentTimeMillis());String backupName = FilenameUtils.getBaseName(filePath) + "_" + timestamp + "." + FilenameUtils.getExtension(filePath);File backupFile = new File(backupDirectory, backupName);FileUtils.copyFile(sourceFile, backupFile);return true;} catch (IOException e) {System.err.println("备份文件失败: " + e.getMessage());return false;}}/*** 压缩文件夹*/public static boolean zipDirectory(String sourceDir, String zipFilePath) {try {File source = new File(sourceDir);if (!source.exists() || !source.isDirectory()) {return false;}FileUtils.forceMkdirParent(new File(zipFilePath));try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilePath))) {Path sourcePath = source.toPath();Files.walk(sourcePath).filter(path -> !Files.isDirectory(path)).forEach(path -> {try {String entryName = sourcePath.relativize(path).toString();ZipEntry entry = new ZipEntry(entryName);zos.putNextEntry(entry);Files.copy(path, zos);zos.closeEntry();} catch (IOException e) {throw new RuntimeException("压缩文件失败", e);}});}return true;} catch (Exception e) {System.err.println("压缩目录失败: " + e.getMessage());return false;}}/*** 获取文件的MD5值*/public static String getFileMD5(String filePath) {try {File file = new File(filePath);if (!file.exists()) {return null;}java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");try (FileInputStream fis = new FileInputStream(file)) {byte[] buffer = new byte[8192];int length;while ((length = fis.read(buffer)) != -1) {md.update(buffer, 0, length);}}byte[] digest = md.digest();StringBuilder sb = new StringBuilder();for (byte b : digest) {sb.append(String.format("%02x", b));}return sb.toString();} catch (Exception e) {System.err.println("计算MD5失败: " + e.getMessage());return null;}}/*** 清理临时文件*/public static int cleanupTempFiles(String tempDir, long maxAgeMillis) {try {File dir = new File(tempDir);if (!dir.exists() || !dir.isDirectory()) {return 0;}long cutoffTime = System.currentTimeMillis() - maxAgeMillis;int deletedCount = 0;File[] files = dir.listFiles();if (files != null) {for (File file : files) {if (file.lastModified() < cutoffTime) {if (FileUtils.deleteQuietly(file)) {deletedCount++;}}}}return deletedCount;} catch (Exception e) {System.err.println("清理临时文件失败: " + e.getMessage());return 0;}}/*** 监控目录变化*/public static void watchDirectory(String dirPath) {try {Path path = Paths.get(dirPath);WatchService watchService = FileSystems.getDefault().newWatchService();path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY);System.out.println("开始监控目录: " + dirPath);WatchKey key;while ((key = watchService.take()) != null) {for (WatchEvent<?> event : key.pollEvents()) {WatchEvent.Kind<?> kind = event.kind();Path filePath = (Path) event.context();System.out.println("文件变化: " + kind.name() + " -> " + filePath);}key.reset();}} catch (Exception e) {System.err.println("目录监控失败: " + e.getMessage());}}public static void main(String[] args) throws IOException {System.out.println("=== 实用文件工具类示例 ===");// 创建测试环境String testContent = "这是测试文件内容\n包含多行文本\n用于测试各种文件操作";String testFile = "practical_test.txt";// 写入文件boolean writeSuccess = writeFileContent(testFile, testContent);System.out.println("文件写入: " + (writeSuccess ? "成功" : "失败"));// 读取文件String content = readFileContent(testFile);System.out.println("文件内容: " + (content != null ? "读取成功" : "读取失败"));// 备份文件boolean backupSuccess = backupFile(testFile, "backup");System.out.println("文件备份: " + (backupSuccess ? "成功" : "失败"));// 计算MD5String md5 = getFileMD5(testFile);System.out.println("文件MD5: " + md5);// 创建测试目录结构并压缩File testDir = new File("zipTest");FileUtils.forceMkdir(testDir);FileUtils.writeStringToFile(new File(testDir, "file1.txt"), "文件1内容", StandardCharsets.UTF_8);FileUtils.writeStringToFile(new File(testDir, "file2.txt"), "文件2内容", StandardCharsets.UTF_8);boolean zipSuccess = zipDirectory("zipTest", "test.zip");System.out.println("目录压缩: " + (zipSuccess ? "成功" : "失败"));// 清理FileUtils.deleteQuietly(new File(testFile));FileUtils.deleteQuietly(new File("backup"));FileUtils.deleteQuietly(new File("zipTest"));FileUtils.deleteQuietly(new File("test.zip"));System.out.println("清理完成");}
}

7. ValidateUtils详解

7.1 什么是ValidateUtils?

ValidateUtils是用于数据验证的工具类,提供了多种验证方法,包括参数校验、格式验证、业务规则验证等。在实际开发中,数据验证是保证系统安全性和数据完整性的重要环节。

7.2 基本参数验证

import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.regex.Pattern;/*** 基础验证工具类*/
public class ValidateUtils {// 常用正则表达式private static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");private static final Pattern ID_CARD_PATTERN = Pattern.compile("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$");private static final Pattern CHINESE_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5]+$");private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]{3,20}$");/*** 验证字符串不为空*/public static boolean isNotBlank(String str) {return StringUtils.hasText(str);}/*** 验证字符串为空*/public static boolean isBlank(String str) {return !StringUtils.hasText(str);}/*** 验证集合不为空*/public static boolean isNotEmpty(Collection<?> collection) {return collection != null && !collection.isEmpty();}/*** 验证对象不为空*/public static boolean isNotNull(Object obj) {return obj != null;}/*** 验证邮箱格式*/public static boolean isValidEmail(String email) {if (isBlank(email)) {return false;}return EMAIL_PATTERN.matcher(email).matches();}/*** 验证手机号格式*/public static boolean isValidPhone(String phone) {if (isBlank(phone)) {return false;}return PHONE_PATTERN.matcher(phone).matches();}/*** 验证身份证号格式*/public static boolean isValidIdCard(String idCard) {if (isBlank(idCard)) {return false;}return ID_CARD_PATTERN.matcher(idCard).matches();}/*** 验证用户名格式(字母、数字、下划线,3-20位)*/public static boolean isValidUsername(String username) {if (isBlank(username)) {return false;}return USERNAME_PATTERN.matcher(username).matches();}/*** 验证是否为中文*/public static boolean isChinese(String str) {if (isBlank(str)) {return false;}return CHINESE_PATTERN.matcher(str).matches();}/*** 验证数字范围*/public static boolean isInRange(Number number, Number min, Number max) {if (number == null || min == null || max == null) {return false;}double value = number.doubleValue();return value >= min.doubleValue() && value <= max.doubleValue();}/*** 验证字符串长度*/public static boolean isLengthValid(String str, int minLength, int maxLength) {if (str == null) {return false;}int length = str.length();return length >= minLength && length <= maxLength;}/*** 验证密码强度(至少包含大写字母、小写字母、数字,长度8-20位)*/public static boolean isStrongPassword(String password) {if (isBlank(password) || !isLengthValid(password, 8, 20)) {return false;}boolean hasUpper = password.matches(".*[A-Z].*");boolean hasLower = password.matches(".*[a-z].*");boolean hasDigit = password.matches(".*\\d.*");return hasUpper && hasLower && hasDigit;}/*** 验证URL格式*/public static boolean isValidUrl(String url) {if (isBlank(url)) {return false;}try {new java.net.URL(url);return true;} catch (java.net.MalformedURLException e) {return false;}}/*** 验证IP地址格式*/public static boolean isValidIpAddress(String ip) {if (isBlank(ip)) {return false;}String ipPattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";return Pattern.matches(ipPattern, ip);}public static void main(String[] args) {System.out.println("=== 验证工具类示例 ===");// 邮箱验证System.out.println("邮箱验证:");System.out.println("  admin@example.com: " + isValidEmail("admin@example.com"));System.out.println("  invalid-email: " + isValidEmail("invalid-email"));// 手机号验证System.out.println("\n手机号验证:");System.out.println("  13800138000: " + isValidPhone("13800138000"));System.out.println("  12345678901: " + isValidPhone("12345678901"));// 密码强度验证System.out.println("\n密码强度验证:");System.out.println("  Password123: " + isStrongPassword("Password123"));System.out.println("  password: " + isStrongPassword("password"));System.out.println("  123456: " + isStrongPassword("123456"));// 用户名验证System.out.println("\n用户名验证:");System.out.println("  admin_123: " + isValidUsername("admin_123"));System.out.println("  ab: " + isValidUsername("ab")); // 太短System.out.println("  user@name: " + isValidUsername("user@name")); // 包含特殊字符// 数字范围验证System.out.println("\n数字范围验证:");System.out.println("  25 in (18, 60): " + isInRange(25, 18, 60));System.out.println("  15 in (18, 60): " + isInRange(15, 18, 60));}
}

7.3 业务验证工具类

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;/*** 业务验证工具类*/
public class BusinessValidateUtils {/*** 验证用户注册信息*/public static ValidationResult validateUserRegistration(UserRegistrationRequest request) {ValidationResult result = new ValidationResult();// 验证用户名if (ValidateUtils.isBlank(request.getUsername())) {result.addError("username", "用户名不能为空");} else if (!ValidateUtils.isValidUsername(request.getUsername())) {result.addError("username", "用户名格式不正确,只能包含字母、数字、下划线,长度3-20位");}// 验证邮箱if (ValidateUtils.isBlank(request.getEmail())) {result.addError("email", "邮箱不能为空");} else if (!ValidateUtils.isValidEmail(request.getEmail())) {result.addError("email", "邮箱格式不正确");}// 验证密码if (ValidateUtils.isBlank(request.getPassword())) {result.addError("password", "密码不能为空");} else if (!ValidateUtils.isStrongPassword(request.getPassword())) {result.addError("password", "密码强度不够,需包含大写字母、小写字母、数字,长度8-20位");}// 验证确认密码if (!request.getPassword().equals(request.getConfirmPassword())) {result.addError("confirmPassword", "两次输入的密码不一致");}// 验证手机号if (ValidateUtils.isNotBlank(request.getPhone()) && !ValidateUtils.isValidPhone(request.getPhone())) {result.addError("phone", "手机号格式不正确");}// 验证年龄if (request.getAge() != null && !ValidateUtils.isInRange(request.getAge(), 1, 150)) {result.addError("age", "年龄必须在1-150之间");}return result;}/*** 验证订单信息*/public static ValidationResult validateOrder(OrderRequest request) {ValidationResult result = new ValidationResult();// 验证商品列表if (ValidateUtils.isNotEmpty(request.getItems())) {for (int i = 0; i < request.getItems().size(); i++) {OrderItemRequest item = request.getItems().get(i);String prefix = "items[" + i + "]";if (item.getProductId() == null || item.getProductId() <= 0) {result.addError(prefix + ".productId", "商品ID无效");}if (item.getQuantity() == null || item.getQuantity() <= 0) {result.addError(prefix + ".quantity", "商品数量必须大于0");}if (item.getPrice() == null || item.getPrice().compareTo(java.math.BigDecimal.ZERO) <= 0) {result.addError(prefix + ".price", "商品价格必须大于0");}}} else {result.addError("items", "订单商品列表不能为空");}// 验证收货地址if (ValidateUtils.isBlank(request.getShippingAddress())) {result.addError("shippingAddress", "收货地址不能为空");}// 验证联系电话if (ValidateUtils.isBlank(request.getContactPhone())) {result.addError("contactPhone", "联系电话不能为空");} else if (!ValidateUtils.isValidPhone(request.getContactPhone())) {result.addError("contactPhone", "联系电话格式不正确");}return result;}/*** 验证文件上传*/public static ValidationResult validateFileUpload(String fileName, long fileSize, byte[] fileContent) {ValidationResult result = new ValidationResult();// 验证文件名if (ValidateUtils.isBlank(fileName)) {result.addError("fileName", "文件名不能为空");return result;}// 验证文件扩展名String extension = getFileExtension(fileName);List<String> allowedExtensions = Arrays.asList("jpg", "jpeg", "png", "gif", "pdf", "doc", "docx");if (!allowedExtensions.contains(extension.toLowerCase())) {result.addError("fileName", "不支持的文件类型,支持的类型:" + String.join(", ", allowedExtensions));}// 验证文件大小(10MB)long maxSize = 10 * 1024 * 1024;if (fileSize > maxSize) {result.addError("fileSize", "文件大小不能超过10MB");}// 验证文件内容if (fileContent == null || fileContent.length == 0) {result.addError("fileContent", "文件内容不能为空");}return result;}private static String getFileExtension(String fileName) {int lastDotIndex = fileName.lastIndexOf('.');if (lastDotIndex == -1) {return "";}return fileName.substring(lastDotIndex + 1);}/*** 验证结果类*/public static class ValidationResult {private boolean valid = true;private java.util.Map<String, String> errors = new java.util.HashMap<>();public void addError(String field, String message) {this.valid = false;this.errors.put(field, message);}public boolean isValid() {return valid;}public java.util.Map<String, String> getErrors() {return errors;}public String getErrorMessage() {if (valid) {return null;}return String.join("; ", errors.values());}}// 请求类示例static class UserRegistrationRequest {private String username;private String email;private String password;private String confirmPassword;private String phone;private Integer age;// getters and setterspublic String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getPassword() { return password; }public void setPassword(String password) { this.password = password; }public String getConfirmPassword() { return confirmPassword; }public void setConfirmPassword(String confirmPassword) { this.confirmPassword = confirmPassword; }public String getPhone() { return phone; }public void setPhone(String phone) { this.phone = phone; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }}static class OrderRequest {private List<OrderItemRequest> items;private String shippingAddress;private String contactPhone;// getters and setterspublic List<OrderItemRequest> getItems() { return items; }public void setItems(List<OrderItemRequest> items) { this.items = items; }public String getShippingAddress() { return shippingAddress; }public void setShippingAddress(String shippingAddress) { this.shippingAddress = shippingAddress; }public String getContactPhone() { return contactPhone; }public void setContactPhone(String contactPhone) { this.contactPhone = contactPhone; }}static class OrderItemRequest {private Long productId;private Integer quantity;private java.math.BigDecimal price;// getters and setterspublic Long getProductId() { return productId; }public void setProductId(Long productId) { this.productId = productId; }public Integer getQuantity() { return quantity; }public void setQuantity(Integer quantity) { this.quantity = quantity; }public java.math.BigDecimal getPrice() { return price; }public void setPrice(java.math.BigDecimal price) { this.price = price; }}public static void main(String[] args) {System.out.println("=== 业务验证工具类示例 ===");// 测试用户注册验证UserRegistrationRequest userRequest = new UserRegistrationRequest();userRequest.setUsername("admin");userRequest.setEmail("admin@example.com");userRequest.setPassword("Password123");userRequest.setConfirmPassword("Password123");userRequest.setPhone("13800138000");userRequest.setAge(25);ValidationResult userResult = validateUserRegistration(userRequest);System.out.println("用户注册验证: " + (userResult.isValid() ? "通过" : "失败"));if (!userResult.isValid()) {System.out.println("错误信息: " + userResult.getErrorMessage());}// 测试文件上传验证ValidationResult fileResult = validateFileUpload("test.jpg", 1024 * 1024, new byte[]{1, 2, 3});System.out.println("文件上传验证: " + (fileResult.isValid() ? "通过" : "失败"));if (!fileResult.isValid()) {System.out.println("错误信息: " + fileResult.getErrorMessage());}}
}

8. EncryptUtils详解

8.1 什么是EncryptUtils?

EncryptUtils是用于加密和解密操作的工具类,提供了多种加密算法的实现,包括MD5、SHA、AES、RSA等常用加密方式。

8.2 常用加密算法实现

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;/*** 加密工具类*/
public class EncryptUtils {private static final String AES_ALGORITHM = "AES";private static final String AES_TRANSFORMATION = "AES/ECB/PKCS5Padding";/*** MD5加密*/public static String md5(String input) {try {MessageDigest md = MessageDigest.getInstance("MD5");byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));return bytesToHex(digest);} catch (Exception e) {throw new RuntimeException("MD5加密失败", e);}}/*** SHA-256加密*/public static String sha256(String input) {try {MessageDigest sha = MessageDigest.getInstance("SHA-256");byte[] digest = sha.digest(input.getBytes(StandardCharsets.UTF_8));return bytesToHex(digest);} catch (Exception e) {throw new RuntimeException("SHA-256加密失败", e);}}/*** 生成随机盐值*/public static String generateSalt() {SecureRandom random = new SecureRandom();byte[] salt = new byte[16];random.nextBytes(salt);return bytesToHex(salt);}/*** 密码加盐哈希*/public static String hashPasswordWithSalt(String password, String salt) {return sha256(password + salt);}/*** 验证密码*/public static boolean verifyPassword(String password, String salt, String hashedPassword) {String computedHash = hashPasswordWithSalt(password, salt);return computedHash.equals(hashedPassword);}/*** 生成AES密钥*/public static String generateAESKey() {try {KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);keyGenerator.init(256);SecretKey secretKey = keyGenerator.generateKey();return Base64.getEncoder().encodeToString(secretKey.getEncoded());} catch (Exception e) {throw new RuntimeException("生成AES密钥失败", e);}}/*** AES加密*/public static String aesEncrypt(String plainText, String base64Key) {try {byte[] keyBytes = Base64.getDecoder().decode(base64Key);SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES_ALGORITHM);Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION);cipher.init(Cipher.ENCRYPT_MODE, keySpec);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(encryptedBytes);} catch (Exception e) {throw new RuntimeException("AES加密失败", e);}}/*** AES解密*/public static String aesDecrypt(String encryptedText, String base64Key) {try {byte[] keyBytes = Base64.getDecoder().decode(base64Key);SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES_ALGORITHM);Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION);cipher.init(Cipher.DECRYPT_MODE, keySpec);byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);byte[] decryptedBytes = cipher.doFinal(encryptedBytes);return new String(decryptedBytes, StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException("AES解密失败", e);}}/*** Base64编码*/public static String base64Encode(String input) {return Base64.getEncoder().encodeToString(input.getBytes(StandardCharsets.UTF_8));}/*** Base64解码*/public static String base64Decode(String encoded) {byte[] decodedBytes = Base64.getDecoder().decode(encoded);return new String(decodedBytes, StandardCharsets.UTF_8);}/*** 字节数组转十六进制字符串*/private static String bytesToHex(byte[] bytes) {StringBuilder result = new StringBuilder();for (byte b : bytes) {result.append(String.format("%02x", b));}return result.toString();}public static void main(String[] args) {System.out.println("=== 加密工具类示例 ===");String originalText = "Hello, 这是需要加密的文本!";System.out.println("原文: " + originalText);// MD5加密String md5Hash = md5(originalText);System.out.println("MD5: " + md5Hash);// SHA-256加密String sha256Hash = sha256(originalText);System.out.println("SHA-256: " + sha256Hash);// 密码加盐哈希String password = "MyPassword123";String salt = generateSalt();String hashedPassword = hashPasswordWithSalt(password, salt);System.out.println("\n密码加盐哈希:");System.out.println("密码: " + password);System.out.println("盐值: " + salt);System.out.println("哈希: " + hashedPassword);// 验证密码boolean isValid = verifyPassword(password, salt, hashedPassword);System.out.println("密码验证: " + (isValid ? "通过" : "失败"));// AES加密解密String aesKey = generateAESKey();String encrypted = aesEncrypt(originalText, aesKey);String decrypted = aesDecrypt(encrypted, aesKey);System.out.println("\nAES加密解密:");System.out.println("密钥: " + aesKey);System.out.println("加密: " + encrypted);System.out.println("解密: " + decrypted);// Base64编码解码String encoded = base64Encode(originalText);String decoded = base64Decode(encoded);System.out.println("\nBase64编码解码:");System.out.println("编码: " + encoded);System.out.println("解码: " + decoded);}
}

9. ReflectionUtils详解

9.1 什么是ReflectionUtils?

ReflectionUtils是用于反射操作的工具类,提供了便捷的反射方法,用于动态获取类信息、调用方法、访问字段等操作。

9.2 Spring ReflectionUtils使用

import org.springframework.util.ReflectionUtils;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;/*** 反射工具类示例*/
public class ReflectionUtilsExample {/*** 获取类的所有字段(包括私有字段)*/public static List<Field> getAllFields(Class<?> clazz) {List<Field> fields = new ArrayList<>();ReflectionUtils.doWithFields(clazz, fields::add);return fields;}/*** 获取类的所有方法(包括私有方法)*/public static List<Method> getAllMethods(Class<?> clazz) {List<Method> methods = new ArrayList<>();ReflectionUtils.doWithMethods(clazz, methods::add);return methods;}/*** 根据字段名获取字段值*/public static Object getFieldValue(Object obj, String fieldName) {try {Field field = ReflectionUtils.findField(obj.getClass(), fieldName);if (field == null) {throw new IllegalArgumentException("字段不存在: " + fieldName);}ReflectionUtils.makeAccessible(field);return ReflectionUtils.getField(field, obj);} catch (Exception e) {throw new RuntimeException("获取字段值失败", e);}}/*** 根据字段名设置字段值*/public static void setFieldValue(Object obj, String fieldName, Object value) {try {Field field = ReflectionUtils.findField(obj.getClass(), fieldName);if (field == null) {throw new IllegalArgumentException("字段不存在: " + fieldName);}ReflectionUtils.makeAccessible(field);ReflectionUtils.setField(field, obj, value);} catch (Exception e) {throw new RuntimeException("设置字段值失败", e);}}/*** 调用对象的方法*/public static Object invokeMethod(Object obj, String methodName, Object... args) {try {Class<?>[] paramTypes = new Class<?>[args.length];for (int i = 0; i < args.length; i++) {paramTypes[i] = args[i].getClass();}Method method = ReflectionUtils.findMethod(obj.getClass(), methodName, paramTypes);if (method == null) {throw new IllegalArgumentException("方法不存在: " + methodName);}ReflectionUtils.makeAccessible(method);return ReflectionUtils.invokeMethod(method, obj, args);} catch (Exception e) {throw new RuntimeException("调用方法失败", e);}}/*** 创建对象实例*/@SuppressWarnings("unchecked")public static <T> T createInstance(Class<T> clazz) {try {Constructor<T> constructor = clazz.getDeclaredConstructor();constructor.setAccessible(true);return constructor.newInstance();} catch (Exception e) {throw new RuntimeException("创建实例失败", e);}}/*** 复制对象属性*/public static void copyProperties(Object source, Object target) {Class<?> sourceClass = source.getClass();Class<?> targetClass = target.getClass();ReflectionUtils.doWithFields(sourceClass, field -> {ReflectionUtils.makeAccessible(field);Object value = ReflectionUtils.getField(field, source);Field targetField = ReflectionUtils.findField(targetClass, field.getName());if (targetField != null && targetField.getType().equals(field.getType())) {ReflectionUtils.makeAccessible(targetField);ReflectionUtils.setField(targetField, target, value);}});}/*** 检查类是否包含指定注解*/public static boolean hasAnnotation(Class<?> clazz, Class<? extends java.lang.annotation.Annotation> annotationClass) {return clazz.isAnnotationPresent(annotationClass);}/*** 获取带有指定注解的字段*/public static List<Field> getFieldsWithAnnotation(Class<?> clazz, Class<? extends java.lang.annotation.Annotation> annotationClass) {List<Field> annotatedFields = new ArrayList<>();ReflectionUtils.doWithFields(clazz, field -> {if (field.isAnnotationPresent(annotationClass)) {annotatedFields.add(field);}});return annotatedFields;}/*** 获取带有指定注解的方法*/public static List<Method> getMethodsWithAnnotation(Class<?> clazz, Class<? extends java.lang.annotation.Annotation> annotationClass) {List<Method> annotatedMethods = new ArrayList<>();ReflectionUtils.doWithMethods(clazz, method -> {if (method.isAnnotationPresent(annotationClass)) {annotatedMethods.add(method);}});return annotatedMethods;}public static void main(String[] args) {System.out.println("=== 反射工具类示例 ===");// 创建测试对象TestUser user = new TestUser();user.setId(1L);user.setUsername("admin");user.setEmail("admin@example.com");user.setAge(25);System.out.println("原始对象: " + user);// 获取字段值Object username = getFieldValue(user, "username");System.out.println("获取用户名: " + username);// 设置字段值setFieldValue(user, "username", "new_admin");System.out.println("修改用户名后: " + user);// 调用方法Object result = invokeMethod(user, "getDisplayName");System.out.println("调用getDisplayName方法: " + result);// 获取所有字段List<Field> fields = getAllFields(TestUser.class);System.out.println("\n所有字段:");for (Field field : fields) {System.out.println("  " + field.getName() + " (" + field.getType().getSimpleName() + ")");}// 获取所有方法List<Method> methods = getAllMethods(TestUser.class);System.out.println("\n所有方法:");for (Method method : methods) {if (method.getDeclaringClass() == TestUser.class) { // 只显示当前类的方法System.out.println("  " + method.getName());}}// 创建新实例并复制属性TestUser newUser = createInstance(TestUser.class);copyProperties(user, newUser);System.out.println("\n复制后的新对象: " + newUser);}/*** 测试用户类*/static class TestUser {private Long id;private String username;private String email;private Integer age;public TestUser() {}// getters and setterspublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }public String getDisplayName() {return username + " (" + email + ")";}@Overridepublic String toString() {return "TestUser{id=" + id + ", username='" + username + "', email='" + email + "', age=" + age + '}';}}
}

10. 自定义工具类实践

10.1 综合工具类

import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;/*** 综合工具类,整合常用功能*/
public class CommonUtils {/*** 判断字符串是否为空或空白*/public static boolean isBlank(String str) {return str == null || str.trim().isEmpty();}/*** 判断字符串是否不为空且不为空白*/public static boolean isNotBlank(String str) {return !isBlank(str);}/*** 安全的字符串转换*/public static String safeToString(Object obj) {return obj == null ? "" : obj.toString();}/*** 安全的数字转换*/public static Integer safeToInteger(String str, Integer defaultValue) {try {return isBlank(str) ? defaultValue : Integer.parseInt(str.trim());} catch (NumberFormatException e) {return defaultValue;}}/*** 安全的长整型转换*/public static Long safeToLong(String str, Long defaultValue) {try {return isBlank(str) ? defaultValue : Long.parseLong(str.trim());} catch (NumberFormatException e) {return defaultValue;}}/*** 安全的双精度浮点数转换*/public static Double safeToDouble(String str, Double defaultValue) {try {return isBlank(str) ? defaultValue : Double.parseDouble(str.trim());} catch (NumberFormatException e) {return defaultValue;}}/*** 对象拷贝*/public static <T> T copyBean(Object source, Supplier<T> targetSupplier) {if (source == null) {return null;}T target = targetSupplier.get();BeanUtils.copyProperties(source, target);return target;}/*** 列表拷贝*/public static <T> List<T> copyBeanList(List<?> sourceList, Supplier<T> targetSupplier) {if (CollectionUtils.isEmpty(sourceList)) {return new ArrayList<>();}return sourceList.stream().map(source -> copyBean(source, targetSupplier)).collect(Collectors.toList());}/*** 获取文件扩展名*/public static String getFileExtension(String fileName) {if (isBlank(fileName)) {return "";}int lastDotIndex = fileName.lastIndexOf('.');return lastDotIndex == -1 ? "" : fileName.substring(lastDotIndex + 1).toLowerCase();}/*** 生成随机字符串*/public static String generateRandomString(int length) {String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";StringBuilder sb = new StringBuilder();java.util.Random random = new java.util.Random();for (int i = 0; i < length; i++) {sb.append(chars.charAt(random.nextInt(chars.length())));}return sb.toString();}/*** 脱敏手机号*/public static String maskPhone(String phone) {if (isBlank(phone) || phone.length() != 11) {return phone;}return phone.substring(0, 3) + "****" + phone.substring(7);}/*** 脱敏邮箱*/public static String maskEmail(String email) {if (isBlank(email) || !email.contains("@")) {return email;}String[] parts = email.split("@");String localPart = parts[0];String domainPart = parts[1];if (localPart.length() <= 2) {return email;}String maskedLocal = localPart.substring(0, 1) + "****" + localPart.substring(localPart.length() - 1);return maskedLocal + "@" + domainPart;}/*** 脱敏身份证号*/public static String maskIdCard(String idCard) {if (isBlank(idCard) || idCard.length() != 18) {return idCard;}return idCard.substring(0, 6) + "********" + idCard.substring(14);}public static void main(String[] args) {System.out.println("=== 综合工具类示例 ===");// 字符串处理System.out.println("空字符串检查: " + isBlank("   "));System.out.println("安全转换: " + safeToInteger("abc", 0));// 数据脱敏System.out.println("手机号脱敏: " + maskPhone("13800138000"));System.out.println("邮箱脱敏: " + maskEmail("admin@example.com"));System.out.println("身份证脱敏: " + maskIdCard("110101199001011234"));// 随机字符串System.out.println("随机字符串: " + generateRandomString(10));// 文件扩展名System.out.println("文件扩展名: " + getFileExtension("test.jpg"));}
}

11. 总结与最佳实践

11.1 工具类使用原则

  1. 静态方法设计:工具类的方法应设计为静态方法,方便调用
  2. 线程安全:确保工具类的方法是线程安全的
  3. 异常处理:妥善处理可能出现的异常,提供有意义的错误信息
  4. 参数验证:对输入参数进行必要的验证
  5. 性能考虑:避免在工具类中进行耗时操作

11.2 开发建议

  1. 合理选择工具类:根据项目需求选择合适的工具类
  2. 统一工具类规范:在团队中建立统一的工具类使用规范
  3. 避免重复造轮子:优先使用成熟的工具类库
  4. 适当封装:对常用操作进行封装,提高代码复用性
  5. 文档完善:为自定义工具类编写详细的文档和示例

通过学习和掌握这些工具类,可以大大提高SpringBoot项目的开发效率,减少重复代码,提升代码质量。在实际开发中,建议根据项目需求选择合适的工具类,并建立团队统一的使用规范。

http://www.lryc.cn/news/578581.html

相关文章:

  • pytorch学习—7.处理多维特征的输入
  • 通达信【极弱强势指标与股道波段交易系统】幅图
  • 【学习笔记】Python中主函数调用的方式
  • 修改Spatial-MLLM项目,使其专注于无人机航拍视频的空间理解
  • Electron 应用中的内容安全策略 (CSP) 全面指南
  • AbMole| H₂DCFDA(M9096;活性氧(ROS)探针)
  • 医学编码:临床试验数据标准化的关键
  • Next.js 安装使用教程
  • 多容器应用与编排——AI教你学Docker
  • Web性能测试常用指标(转自百度AI)
  • 开关电源和线性电源Multisim电路仿真实验汇总——硬件工程师笔记
  • 暖通锅炉的智能管控:物联网实现节能又舒适​
  • grom使用mysql快速上手
  • [论文阅读] 人工智能 + 软件工程 | 从软件工程视角看大语言模型:挑战与未来之路
  • 使用 icinga2 写入 TDengine
  • 基于ApachePOI实现百度POI分类快速导入PostgreSQL数据库实战
  • SpringBoot计时一次请求耗时
  • 基于netmiko模块实现支持SSH or Telnet的多线程多厂商网络设备自动化巡检脚本
  • 浏览器F12开发者工具的使用
  • [Python] -基础篇7-新手常见Python语法错误及解决方案
  • Qt时间显示按钮功能详解
  • openlayers根据图层名称判断图层是否在视口内
  • js代码09
  • Maven安装使用教程
  • java web2(黑马)
  • 阿里云-云效自动部署spring boot项目
  • vue + element-ui实现可拖拽表格
  • Windows VMWare Centos Docker部署Springboot + mybatis + MySql应用
  • 学习昇腾开发的第12天--安装第三方依赖
  • 飞算 JavaAI:我的编程强力助推引擎