Apache Commons工具类
学习目标
- 理解Apache Commons系列库的作用和价值
- 掌握Commons Lang3的常用工具类(StringUtils、ObjectUtils等)
- 熟练使用Commons Collections4进行集合操作
- 掌握Commons IO进行文件和流操作
- 掌握Commons BeanUtils进行对象操作
- 了解其他常用Commons组件
- 能够在实际项目中应用这些工具类提升开发效率
一、为什么需要Apache Commons?
1.1 Apache Commons简介
Apache Commons是Apache软件基金会的一个项目,提供了大量可重用的Java组件。这些组件经过充分测试,性能优秀,可以大大提高开发效率。
Apache Commons核心组件
├── Commons Lang3 - 核心工具类(字符串、对象、数组等)
├── Commons Collections4 - 集合工具类
├── Commons IO - IO操作工具类
├── Commons BeanUtils - Bean操作工具类
├── Commons Codec - 编码解码工具类
├── Commons FileUpload - 文件上传工具类
└── Commons Math3 - 数学计算工具类
1.2 为什么要使用Commons?
问题场景:
// 场景1:判断字符串是否为空
// ❌ 原生写法:繁琐且容易出错
if (str != null && !str.trim().isEmpty()) {
// 处理逻辑
}
// ✓ 使用Commons:简洁且安全
if (StringUtils.isNotBlank(str)) {
// 处理逻辑
}
// 场景2:数组判空
// ❌ 原生写法
if (array != null && array.length > 0) {
// 处理逻辑
}
// ✓ 使用Commons
if (ArrayUtils.isNotEmpty(array)) {
// 处理逻辑
}
// 场景3:对象属性拷贝
// ❌ 原生写法:需要手动set每个属性
UserVO vo = new UserVO();
vo.setId(user.getId());
vo.setUsername(user.getUsername());
vo.setNickname(user.getNickname());
// ... 更多属性
// ✓ 使用Commons:一行代码搞定
BeanUtils.copyProperties(user, vo);
使用Commons的优势:
- 提高开发效率:减少重复代码,专注业务逻辑
- 代码更简洁:一行代码完成复杂操作
- 更加安全:处理了各种边界情况,避免NPE
- 性能优秀:经过充分优化和测试
- 社区支持:文档完善,使用广泛
1.3 Maven依赖配置
<!-- pom.xml -->
<dependencies>
<!-- Commons Lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- Commons Collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<!-- Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- Commons BeanUtils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<!-- Commons Codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
</dependencies>
二、Commons Lang3 - 核心工具类
2.1 StringUtils - 字符串工具类
StringUtils是最常用的工具类之一,提供了大量字符串操作方法。
2.1.1 判空操作
import org.apache.commons.lang3.StringUtils;
public class StringUtilsDemo {
public static void main(String[] args) {
String str1 = null;
String str2 = "";
String str3 = " ";
String str4 = "hello";
// isEmpty:判断是否为null或空字符串
System.out.println(StringUtils.isEmpty(str1)); // true
System.out.println(StringUtils.isEmpty(str2)); // true
System.out.println(StringUtils.isEmpty(str3)); // false(空格不算空)
System.out.println(StringUtils.isEmpty(str4)); // false
// isBlank:判断是否为null、空字符串或只包含空白字符
System.out.println(StringUtils.isBlank(str1)); // true
System.out.println(StringUtils.isBlank(str2)); // true
System.out.println(StringUtils.isBlank(str3)); // true(空格算空)
System.out.println(StringUtils.isBlank(str4)); // false
// isNotEmpty / isNotBlank:取反
System.out.println(StringUtils.isNotEmpty(str4)); // true
System.out.println(StringUtils.isNotBlank(str4)); // true
}
}
isEmpty vs isBlank 对比:
┌──────────────┬──────────┬──────────┐
│ 输入值 │ isEmpty │ isBlank │
├──────────────┼──────────┼──────────┤
│ null │ true │ true │
│ "" │ true │ true │
│ " " │ false │ true │
│ "hello" │ false │ false │
└──────────────┴──────────┴──────────┘
使用建议:
- isEmpty:只判断null和空字符串
- isBlank:判断null、空字符串和空白字符(推荐使用)
2.1.2 默认值处理
// defaultString:如果为null则返回默认值
String str = null;
String result = StringUtils.defaultString(str); // ""
String result2 = StringUtils.defaultString(str, "默认值"); // "默认值"
// defaultIfBlank:如果为blank则返回默认值
String str2 = " ";
String result3 = StringUtils.defaultIfBlank(str2, "默认值"); // "默认值"
// defaultIfEmpty:如果为empty则返回默认值
String str3 = "";
String result4 = StringUtils.defaultIfEmpty(str3, "默认值"); // "默认值"
// 实际应用:处理用户输入
public String getUserNickname(String nickname) {
// 如果用户没有输入昵称,使用默认昵称
return StringUtils.defaultIfBlank(nickname, "匿名用户");
}
2.1.3 字符串截取和填充
// substring:安全的字符串截取(不会抛出IndexOutOfBoundsException)
String str = "hello world";
String sub1 = StringUtils.substring(str, 0, 5); // "hello"
String sub2 = StringUtils.substring(str, 6); // "world"
String sub3 = StringUtils.substring(str, 0, 100); // "hello world"(不会越界)
// left/right/mid:从左/右/中间截取
String left = StringUtils.left(str, 5); // "hello"
String right = StringUtils.right(str, 5); // "world"
String mid = StringUtils.mid(str, 6, 5); // "world"
// substringBefore/After:根据分隔符截取
String email = "user@example.com";
String username = StringUtils.substringBefore(email, "@"); // "user"
String domain = StringUtils.substringAfter(email, "@"); // "example.com"
// leftPad/rightPad:填充字符串到指定长度
String num = "123";
String padded1 = StringUtils.leftPad(num, 6, '0'); // "000123"
String padded2 = StringUtils.rightPad(num, 6, '0'); // "123000"
// center:居中对齐
String centered = StringUtils.center("hello", 11, '*'); // "***hello***"
2.1.4 字符串比较
// equals:安全的字符串比较(处理null)
String str1 = null;
String str2 = "hello";
boolean result1 = StringUtils.equals(str1, str2); // false(不会NPE)
// equalsIgnoreCase:忽略大小写比较
boolean result2 = StringUtils.equalsIgnoreCase("Hello", "hello"); // true
// equalsAny:判断是否等于任意一个值
boolean result3 = StringUtils.equalsAny("apple", "apple", "banana", "orange"); // true
// compare:字符串比较(处理null)
int result4 = StringUtils.compare(str1, str2); // -1(null小于非null)
// 实际应用:验证用户输入
public boolean isValidStatus(String status) {
// 判断状态是否为有效值
return StringUtils.equalsAnyIgnoreCase(status, "ACTIVE", "INACTIVE", "PENDING");
}
2.1.5 字符串查找和替换
String str = "hello world, hello java";
// contains:判断是否包含子串
boolean contains1 = StringUtils.contains(str, "world"); // true
boolean contains2 = StringUtils.containsIgnoreCase(str, "WORLD"); // true
// containsAny:判断是否包含任意一个字符
boolean contains3 = StringUtils.containsAny(str, 'a', 'b', 'c'); // true(包含'a')
// indexOf/lastIndexOf:查找子串位置
int index1 = StringUtils.indexOf(str, "hello"); // 0
int index2 = StringUtils.lastIndexOf(str, "hello"); // 13
// replace:替换字符串
String replaced1 = StringUtils.replace(str, "hello", "hi"); // "hi world, hi java"
// replaceOnce:只替换第一个匹配项
String replaced2 = StringUtils.replaceOnce(str, "hello", "hi"); // "hi world, hello java"
// remove:删除子串
String removed = StringUtils.remove(str, "hello "); // "world, java"
// 实际应用:敏感词过滤
public String filterSensitiveWords(String content) {
String filtered = content;
filtered = StringUtils.replace(filtered, "敏感词1", "***");
filtered = StringUtils.replace(filtered, "敏感词2", "***");
return filtered;
}
2.1.6 字符串分割和连接
// split:分割字符串(处理null和空字符串)
String str = "apple,banana,orange";
String[] arr1 = StringUtils.split(str, ","); // ["apple", "banana", "orange"]
// 处理多个分隔符
String str2 = "apple,banana;orange";
String[] arr2 = StringUtils.split(str2, ",;"); // ["apple", "banana", "orange"]
// splitByWholeSeparator:按完整分隔符分割
String str3 = "apple::banana::orange";
String[] arr3 = StringUtils.splitByWholeSeparator(str3, "::");
// ["apple", "banana", "orange"]
// join:连接字符串数组
String[] array = {"apple", "banana", "orange"};
String joined1 = StringUtils.join(array, ","); // "apple,banana,orange"
// join集合
List<String> list = Arrays.asList("apple", "banana", "orange");
String joined2 = StringUtils.join(list, ","); // "apple,banana,orange"
// 实际应用:构建SQL的IN子句
public String buildInClause(List<Long> ids) {
if (CollectionUtils.isEmpty(ids)) {
return "";
}
return "id IN (" + StringUtils.join(ids, ",") + ")";
}
2.1.7 字符串转换
// capitalize:首字母大写
String str1 = StringUtils.capitalize("hello"); // "Hello"
// uncapitalize:首字母小写
String str2 = StringUtils.uncapitalize("Hello"); // "hello"
// upperCase/lowerCase:大小写转换(处理null)
String str3 = StringUtils.upperCase("hello"); // "HELLO"
String str4 = StringUtils.lowerCase("HELLO"); // "hello"
// swapCase:大小写互换
String str5 = StringUtils.swapCase("Hello World"); // "hELLO wORLD"
// reverse:反转字符串
String str6 = StringUtils.reverse("hello"); // "olleh"
// repeat:重复字符串
String str7 = StringUtils.repeat("*", 5); // "*****"
String str8 = StringUtils.repeat("ab", 3); // "ababab"
// 实际应用:生成分隔线
public String generateSeparator(int length) {
return StringUtils.repeat("-", length);
}
2.2 ObjectUtils - 对象工具类
import org.apache.commons.lang3.ObjectUtils;
public class ObjectUtilsDemo {
public static void main(String[] args) {
// defaultIfNull:如果为null则返回默认值
String str = null;
String result = ObjectUtils.defaultIfNull(str, "默认值"); // "默认值"
// isEmpty:判断对象是否为空
System.out.println(ObjectUtils.isEmpty(null)); // true
System.out.println(ObjectUtils.isEmpty("")); // true
System.out.println(ObjectUtils.isEmpty(new int[0])); // true
System.out.println(ObjectUtils.isEmpty("hello")); // false
// isNotEmpty:判断对象是否非空
System.out.println(ObjectUtils.isNotEmpty("hello")); // true
// compare:比较两个对象
Integer a = 10;
Integer b = 20;
int result2 = ObjectUtils.compare(a, b); // -1(a < b)
// min/max:获取最小/最大值
Integer min = ObjectUtils.min(10, 20, 5, 30); // 5
Integer max = ObjectUtils.max(10, 20, 5, 30); // 30
// clone:克隆对象(对象需要实现Cloneable接口)
User user = new User("张三", 20);
User cloned = ObjectUtils.clone(user);
}
}
// 实际应用:处理可能为null的对象
public class UserService {
public String getUserNickname(User user) {
// 如果user为null或nickname为null,返回默认昵称
return ObjectUtils.defaultIfNull(
user != null ? user.getNickname() : null,
"匿名用户"
);
}
public int getUserAge(User user) {
// 如果user为null或age为null,返回默认年龄
Integer age = user != null ? user.getAge() : null;
return ObjectUtils.defaultIfNull(age, 0);
}
}
2.3 ArrayUtils - 数组工具类
import org.apache.commons.lang3.ArrayUtils;
public class ArrayUtilsDemo {
public static void main(String[] args) {
// isEmpty/isNotEmpty:判断数组是否为空
int[] arr1 = null;
int[] arr2 = new int[0];
int[] arr3 = {1, 2, 3};
System.out.println(ArrayUtils.isEmpty(arr1)); // true
System.out.println(ArrayUtils.isEmpty(arr2)); // true
System.out.println(ArrayUtils.isEmpty(arr3)); // false
System.out.println(ArrayUtils.isNotEmpty(arr3)); // true
// contains:判断数组是否包含某个元素
boolean contains = ArrayUtils.contains(arr3, 2); // true
// indexOf:查找元素位置
int index = ArrayUtils.indexOf(arr3, 2); // 1
// add:添加元素(返回新数组)
int[] arr4 = ArrayUtils.add(arr3, 4); // {1, 2, 3, 4}
// addAll:合并数组
int[] arr5 = {4, 5, 6};
int[] arr6 = ArrayUtils.addAll(arr3, arr5); // {1, 2, 3, 4, 5, 6}
// remove:删除指定位置的元素
int[] arr7 = ArrayUtils.remove(arr3, 1); // {1, 3}
// removeElement:删除指定元素
int[] arr8 = ArrayUtils.removeElement(arr3, 2); // {1, 3}
// reverse:反转数组
int[] arr9 = {1, 2, 3, 4, 5};
ArrayUtils.reverse(arr9); // {5, 4, 3, 2, 1}
// subarray:截取子数组
int[] arr10 = ArrayUtils.subarray(arr3, 0, 2); // {1, 2}
// toString:数组转字符串
String str = ArrayUtils.toString(arr3); // "{1,2,3}"
// toObject/toPrimitive:基本类型数组和包装类型数组互转
int[] primitiveArray = {1, 2, 3};
Integer[] objectArray = ArrayUtils.toObject(primitiveArray);
int[] primitiveArray2 = ArrayUtils.toPrimitive(objectArray);
}
}
// 实际应用:处理数组参数
public class ProductService {
public List<Product> findByIds(Long[] ids) {
// 判断数组是否为空
if (ArrayUtils.isEmpty(ids)) {
return Collections.emptyList();
}
// 查询数据库
return productMapper.selectByIds(Arrays.asList(ids));
}
public List<Product> findByCategories(String... categories) {
// 判断可变参数是否为空
if (ArrayUtils.isEmpty(categories)) {
return Collections.emptyList();
}
// 查询数据库
return productMapper.selectByCategories(Arrays.asList(categories));
}
}
2.4 NumberUtils - 数字工具类
import org.apache.commons.lang3.math.NumberUtils;
public class NumberUtilsDemo {
public static void main(String[] args) {
// toInt/toLong/toFloat/toDouble:字符串转数字(安全转换)
int num1 = NumberUtils.toInt("123"); // 123
int num2 = NumberUtils.toInt("abc"); // 0(转换失败返回0)
int num3 = NumberUtils.toInt("abc", -1); // -1(转换失败返回默认值)
long num4 = NumberUtils.toLong("123456"); // 123456
float num5 = NumberUtils.toFloat("123.45"); // 123.45
double num6 = NumberUtils.toDouble("123.45"); // 123.45
// isDigits:判断字符串是否全为数字
boolean isDigits1 = NumberUtils.isDigits("123"); // true
boolean isDigits2 = NumberUtils.isDigits("12.3"); // false
boolean isDigits3 = NumberUtils.isDigits("abc"); // false
// isCreatable:判断字符串是否可以转换为数字
boolean isCreatable1 = NumberUtils.isCreatable("123"); // true
boolean isCreatable2 = NumberUtils.isCreatable("12.3"); // true
boolean isCreatable3 = NumberUtils.isCreatable("0x10"); // true(十六进制)
boolean isCreatable4 = NumberUtils.isCreatable("abc"); // false
// min/max:获取最小/最大值
int min = NumberUtils.min(10, 20, 5, 30); // 5
int max = NumberUtils.max(10, 20, 5, 30); // 30
// compare:比较两个数字
int result = NumberUtils.compare(10, 20); // -1(10 < 20)
}
}
// 实际应用:处理用户输入的数字
public class OrderService {
public void createOrder(String quantityStr, String priceStr) {
// 安全地将字符串转换为数字
int quantity = NumberUtils.toInt(quantityStr, 1); // 默认数量为1
double price = NumberUtils.toDouble(priceStr, 0.0); // 默认价格为0
// 验证数字是否有效
if (quantity <= 0 || price <= 0) {
throw new IllegalArgumentException("数量和价格必须大于0");
}
// 创建订单
Order order = new Order();
order.setQuantity(quantity);
order.setPrice(price);
order.setTotalAmount(quantity * price);
orderMapper.insert(order);
}
}
2.5 RandomUtils - 随机数工具类
import org.apache.commons.lang3.RandomUtils;
public class RandomUtilsDemo {
public static void main(String[] args) {
// nextInt:生成随机整数
int randomInt1 = RandomUtils.nextInt(); // 随机int
int randomInt2 = RandomUtils.nextInt(1, 100); // 1到99之间的随机数
// nextLong:生成随机长整数
long randomLong = RandomUtils.nextLong(1L, 1000L);
// nextDouble:生成随机浮点数
double randomDouble = RandomUtils.nextDouble(0.0, 1.0);
// nextBoolean:生成随机布尔值
boolean randomBoolean = RandomUtils.nextBoolean();
// nextBytes:生成随机字节数组
byte[] randomBytes = RandomUtils.nextBytes(16);
}
}
// 实际应用:生成随机验证码
public class SmsService {
public String generateVerificationCode() {
// 生成6位随机验证码
int code = RandomUtils.nextInt(100000, 999999);
return String.valueOf(code);
}
public String generateOrderNo() {
// 生成订单号:时间戳 + 6位随机数
long timestamp = System.currentTimeMillis();
int random = RandomUtils.nextInt(100000, 999999);
return timestamp + String.valueOf(random);
}
}
三、Commons Collections4 - 集合工具类
3.1 CollectionUtils - 集合工具类
import org.apache.commons.collections4.CollectionUtils;
public class CollectionUtilsDemo {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("a", "b", "c");
List<String> list2 = Arrays.asList("b", "c", "d");
// isEmpty/isNotEmpty:判断集合是否为空
System.out.println(CollectionUtils.isEmpty(null)); // true
System.out.println(CollectionUtils.isEmpty(new ArrayList<>())); // true
System.out.println(CollectionUtils.isNotEmpty(list1)); // true
// union:并集
Collection<String> union = CollectionUtils.union(list1, list2);
// [a, b, c, d]
// intersection:交集
Collection<String> intersection = CollectionUtils.intersection(list1, list2);
// [b, c]
// disjunction:差集(对称差集)
Collection<String> disjunction = CollectionUtils.disjunction(list1, list2);
// [a, d]
// subtract:差集(list1 - list2)
Collection<String> subtract = CollectionUtils.subtract(list1, list2);
// [a]
// isEqualCollection:判断两个集合是否相等(忽略顺序)
boolean isEqual = CollectionUtils.isEqualCollection(list1, list2); // false
// containsAny:判断是否包含任意一个元素
boolean containsAny = CollectionUtils.containsAny(list1, list2); // true
// containsAll:判断是否包含所有元素
boolean containsAll = CollectionUtils.containsAll(list1, list2); // false
// addAll:添加所有元素
List<String> list3 = new ArrayList<>();
CollectionUtils.addAll(list3, "a", "b", "c");
// filter:过滤集合
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
CollectionUtils.filter(numbers, num -> num % 2 == 0);
// numbers现在是[2, 4, 6]
// select:选择符合条件的元素(返回新集合)
Collection<Integer> evenNumbers = CollectionUtils.select(
Arrays.asList(1, 2, 3, 4, 5, 6),
num -> num % 2 == 0
);
// [2, 4, 6]
// transform:转换集合元素
Collection<String> transformed = CollectionUtils.collect(
Arrays.asList(1, 2, 3),
num -> "num_" + num
);
// ["num_1", "num_2", "num_3"]
}
}
// 实际应用:处理集合操作
public class UserService {
public List<User> findCommonFriends(Long userId1, Long userId2) {
// 获取两个用户的好友列表
List<User> friends1 = userMapper.selectFriendsByUserId(userId1);
List<User> friends2 = userMapper.selectFriendsByUserId(userId2);
// 判断是否为空
if (CollectionUtils.isEmpty(friends1) || CollectionUtils.isEmpty(friends2)) {
return Collections.emptyList();
}
// 获取共同好友(交集)
Collection<User> commonFriends = CollectionUtils.intersection(friends1, friends2);
return new ArrayList<>(commonFriends);
}
public List<User> findActiveUsers(List<User> users) {
// 判断集合是否为空
if (CollectionUtils.isEmpty(users)) {
return Collections.emptyList();
}
// 过滤出活跃用户
return CollectionUtils.select(users, user -> "ACTIVE".equals(user.getStatus()))
.stream()
.collect(Collectors.toList());
}
}
3.2 MapUtils - Map工具类
import org.apache.commons.collections4.MapUtils;
public class MapUtilsDemo {
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 20);
map.put("score", 85.5);
// isEmpty/isNotEmpty:判断Map是否为空
System.out.println(MapUtils.isEmpty(null)); // true
System.out.println(MapUtils.isEmpty(new HashMap<>())); // true
System.out.println(MapUtils.isNotEmpty(map)); // true
// getString:获取String类型的值
String name = MapUtils.getString(map, "name"); // "张三"
String gender = MapUtils.getString(map, "gender", "未知"); // "未知"(默认值)
// getInteger:获取Integer类型的值
Integer age = MapUtils.getInteger(map, "age"); // 20
Integer height = MapUtils.getInteger(map, "height", 170); // 170(默认值)
// getDouble:获取Double类型的值
Double score = MapUtils.getDouble(map, "score"); // 85.5
// getBoolean:获取Boolean类型的值
Boolean isActive = MapUtils.getBoolean(map, "isActive", true); // true(默认值)
// getLong:获取Long类型的值
Long id = MapUtils.getLong(map, "id", 0L); // 0L(默认值)
// safeAddToMap:安全地添加元素到Map
MapUtils.safeAddToMap(map, "city", "北京");
// invertMap:反转Map(key和value互换)
Map<String, Integer> original = new HashMap<>();
original.put("apple", 1);
original.put("banana", 2);
Map<Integer, String> inverted = MapUtils.invertMap(original);
// {1=apple, 2=banana}
// debugPrint:打印Map内容(用于调试)
MapUtils.debugPrint(System.out, "用户信息", map);
}
}
// 实际应用:处理配置参数
public class ConfigService {
public void processConfig(Map<String, Object> config) {
// 判断配置是否为空
if (MapUtils.isEmpty(config)) {
throw new IllegalArgumentException("配置不能为空");
}
// 安全地获取配置值
String appName = MapUtils.getString(config, "app.name", "默认应用");
Integer port = MapUtils.getInteger(config, "server.port", 8080);
Boolean enableCache = MapUtils.getBoolean(config, "cache.enabled", false);
// 使用配置
System.out.println("应用名称:" + appName);
System.out.println("端口:" + port);
System.out.println("是否启用缓存:" + enableCache);
}
}
3.3 ListUtils - List工具类
import org.apache.commons.collections4.ListUtils;
public class ListUtilsDemo {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);
// union:并集
List<Integer> union = ListUtils.union(list1, list2);
// [1, 2, 3, 4, 5, 4, 5, 6, 7, 8](保留重复元素)
// intersection:交集
List<Integer> intersection = ListUtils.intersection(list1, list2);
// [4, 5]
// subtract:差集
List<Integer> subtract = ListUtils.subtract(list1, list2);
// [1, 2, 3]
// partition:分区(将大List分成多个小List)
List<Integer> bigList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<List<Integer>> partitions = ListUtils.partition(bigList, 3);
// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
// defaultIfNull:如果为null则返回空List
List<String> list3 = null;
List<String> result = ListUtils.defaultIfNull(list3, Collections.emptyList());
// emptyIfNull:如果为null则返回空List
List<String> result2 = ListUtils.emptyIfNull(list3);
}
}
// 实际应用:批量处理数据
public class OrderService {
public void batchProcessOrders(List<Order> orders) {
// 判断订单列表是否为空
if (CollectionUtils.isEmpty(orders)) {
return;
}
// 将订单列表分成每批100个
List<List<Order>> batches = ListUtils.partition(orders, 100);
// 批量处理每一批订单
for (List<Order> batch : batches) {
processBatch(batch);
}
}
private void processBatch(List<Order> batch) {
// 批量更新订单状态
orderMapper.batchUpdate(batch);
}
}
四、Commons IO - IO操作工具类
4.1 FileUtils - 文件工具类
import org.apache.commons.io.FileUtils;
public class FileUtilsDemo {
public static void main(String[] args) throws IOException {
File file = new File("test.txt");
File dir = new File("testDir");
// readFileToString:读取文件内容为字符串
String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
// readLines:读取文件内容为行列表
List<String> lines = FileUtils.readLines(file, StandardCharsets.UTF_8);
// writeStringToFile:写入字符串到文件
FileUtils.writeStringToFile(file, "Hello World", StandardCharsets.UTF_8);
// writeLines:写入行列表到文件
List<String> linesToWrite = Arrays.asList("line1", "line2", "line3");
FileUtils.writeLines(file, linesToWrite);
// copyFile:复制文件
File destFile = new File("test_copy.txt");
FileUtils.copyFile(file, destFile);
// copyDirectory:复制目录
File destDir = new File("testDir_copy");
FileUtils.copyDirectory(dir, destDir);
// moveFile:移动文件
File movedFile = new File("test_moved.txt");
FileUtils.moveFile(file, movedFile);
// deleteQuietly:删除文件(不抛异常)
FileUtils.deleteQuietly(file);
// deleteDirectory:删除目录
FileUtils.deleteDirectory(dir);
// sizeOf:获取文件大小
long size = FileUtils.sizeOf(file);
// sizeOfDirectory:获取目录大小
long dirSize = FileUtils.sizeOfDirectory(dir);
// listFiles:列出目录下的文件
Collection<File> files = FileUtils.listFiles(
dir,
new String[]{"txt", "java"}, // 文件扩展名
true // 是否递归
);
// touch:创建文件(如果不存在)或更新修改时间
FileUtils.touch(file);
// forceMkdir:强制创建目录
FileUtils.forceMkdir(dir);
}
}
// 实际应用:文件操作
public class FileService {
private static final String UPLOAD_DIR = "/data/uploads/";
public void saveFile(MultipartFile file, String filename) throws IOException {
// 创建上传目录
File uploadDir = new File(UPLOAD_DIR);
FileUtils.forceMkdir(uploadDir);
// 保存文件
File destFile = new File(uploadDir, filename);
FileUtils.copyInputStreamToFile(file.getInputStream(), destFile);
}
public String readFileContent(String filename) throws IOException {
File file = new File(UPLOAD_DIR + filename);
// 判断文件是否存在
if (!file.exists()) {
throw new FileNotFoundException("文件不存在:" + filename);
}
// 读取文件内容
return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}
public void deleteFile(String filename) {
File file = new File(UPLOAD_DIR + filename);
// 安全删除文件(不抛异常)
FileUtils.deleteQuietly(file);
}
public long getDirectorySize() {
File dir = new File(UPLOAD_DIR);
// 获取目录大小
return FileUtils.sizeOfDirectory(dir);
}
}
4.2 IOUtils - IO流工具类
import org.apache.commons.io.IOUtils;
public class IOUtilsDemo {
public static void main(String[] args) throws IOException {
// toString:将InputStream转换为字符串
InputStream is = new FileInputStream("test.txt");
String content = IOUtils.toString(is, StandardCharsets.UTF_8);
IOUtils.closeQuietly(is);
// toByteArray:将InputStream转换为字节数组
is = new FileInputStream("test.txt");
byte[] bytes = IOUtils.toByteArray(is);
IOUtils.closeQuietly(is);
// copy:复制流
InputStream input = new FileInputStream("source.txt");
OutputStream output = new FileOutputStream("dest.txt");
IOUtils.copy(input, output);
IOUtils.closeQuietly(input, output);
// readLines:读取流内容为行列表
is = new FileInputStream("test.txt");
List<String> lines = IOUtils.readLines(is, StandardCharsets.UTF_8);
IOUtils.closeQuietly(is);
// writeLines:写入行列表到流
OutputStream os = new FileOutputStream("test.txt");
List<String> linesToWrite = Arrays.asList("line1", "line2", "line3");
IOUtils.writeLines(linesToWrite, "\n", os, StandardCharsets.UTF_8);
IOUtils.closeQuietly(os);
// closeQuietly:安全关闭流(不抛异常)
IOUtils.closeQuietly(is, os);
}
}
// 实际应用:处理HTTP响应流
public class HttpService {
public String downloadContent(String url) throws IOException {
HttpURLConnection conn = null;
InputStream is = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.connect();
is = conn.getInputStream();
// 将响应流转换为字符串
return IOUtils.toString(is, StandardCharsets.UTF_8);
} finally {
// 安全关闭流
IOUtils.closeQuietly(is);
if (conn != null) {
conn.disconnect();
}
}
}
public void downloadFile(String url, String destFile) throws IOException {
HttpURLConnection conn = null;
InputStream is = null;
OutputStream os = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.connect();
is = conn.getInputStream();
os = new FileOutputStream(destFile);
// 复制流
IOUtils.copy(is, os);
} finally {
// 安全关闭流
IOUtils.closeQuietly(is, os);
if (conn != null) {
conn.disconnect();
}
}
}
}
4.3 FilenameUtils - 文件名工具类
import org.apache.commons.io.FilenameUtils;
public class FilenameUtilsDemo {
public static void main(String[] args) {
String filename = "/home/user/documents/test.txt";
// getName:获取文件名
String name = FilenameUtils.getName(filename); // "test.txt"
// getBaseName:获取文件名(不含扩展名)
String baseName = FilenameUtils.getBaseName(filename); // "test"
// getExtension:获取文件扩展名
String extension = FilenameUtils.getExtension(filename); // "txt"
// getPath:获取文件路径(不含文件名)
String path = FilenameUtils.getPath(filename); // "/home/user/documents/"
// getFullPath:获取完整路径(不含文件名)
String fullPath = FilenameUtils.getFullPath(filename); // "/home/user/documents/"
// normalize:规范化路径
String normalized = FilenameUtils.normalize("/home/user/../user/documents/./test.txt");
// "/home/user/documents/test.txt"
// concat:连接路径
String concatenated = FilenameUtils.concat("/home/user", "documents/test.txt");
// "/home/user/documents/test.txt"
// removeExtension:移除扩展名
String noExt = FilenameUtils.removeExtension(filename);
// "/home/user/documents/test"
// isExtension:判断是否为指定扩展名
boolean isTxt = FilenameUtils.isExtension(filename, "txt"); // true
boolean isImage = FilenameUtils.isExtension(filename, new String[]{"jpg", "png", "gif"}); // false
}
}
// 实际应用:文件上传处理
public class FileUploadService {
private static final List<String> ALLOWED_EXTENSIONS =
Arrays.asList("jpg", "jpeg", "png", "gif", "pdf", "doc", "docx");
public String uploadFile(MultipartFile file) throws IOException {
// 获取原始文件名
String originalFilename = file.getOriginalFilename();
// 获取文件扩展名
String extension = FilenameUtils.getExtension(originalFilename);
// 验证文件扩展名
if (!ALLOWED_EXTENSIONS.contains(extension.toLowerCase())) {
throw new IllegalArgumentException("不支持的文件类型:" + extension);
}
// 生成新文件名:UUID + 扩展名
String newFilename = UUID.randomUUID().toString() + "." + extension;
// 保存文件
String uploadPath = "/data/uploads/";
File destFile = new File(uploadPath + newFilename);
FileUtils.copyInputStreamToFile(file.getInputStream(), destFile);
return newFilename;
}
}
五、Commons BeanUtils - Bean操作工具类
5.1 BeanUtils - Bean属性操作
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class BeanUtilsDemo {
public static void main(String[] args) throws Exception {
User user = new User();
user.setId(1L);
user.setUsername("zhangsan");
user.setAge(20);
// copyProperties:复制属性
UserVO vo = new UserVO();
BeanUtils.copyProperties(vo, user);
// vo现在拥有user的所有属性值
// getProperty:获取属性值(返回String)
String username = BeanUtils.getProperty(user, "username"); // "zhangsan"
String age = BeanUtils.getProperty(user, "age"); // "20"(注意是String)
// setProperty:设置属性值(自动类型转换)
BeanUtils.setProperty(user, "age", "25"); // 字符串"25"会自动转换为int
// describe:将Bean转换为Map
Map<String, String> map = BeanUtils.describe(user);
// {id=1, username=zhangsan, age=25, class=class User}
// populate:从Map填充Bean
Map<String, Object> properties = new HashMap<>();
properties.put("username", "lisi");
properties.put("age", 30);
BeanUtils.populate(user, properties);
// cloneBean:克隆Bean
User cloned = (User) BeanUtils.cloneBean(user);
}
}
// PropertyUtils:更强大的属性操作(保留类型)
public class PropertyUtilsDemo {
public static void main(String[] args) throws Exception {
User user = new User();
// getProperty:获取属性值(保留原始类型)
Integer age = (Integer) PropertyUtils.getProperty(user, "age");
// setProperty:设置属性值(不进行类型转换)
PropertyUtils.setProperty(user, "age", 25); // 必须传入Integer类型
// getPropertyType:获取属性类型
Class<?> ageType = PropertyUtils.getPropertyType(user, "age"); // Integer.class
// isReadable/isWriteable:判断属性是否可读/可写
boolean readable = PropertyUtils.isReadable(user, "username"); // true
boolean writeable = PropertyUtils.isWriteable(user, "username"); // true
}
}
// 实际应用:DTO和Entity互转
public class UserService {
public UserVO convertToVO(User user) {
if (user == null) {
return null;
}
UserVO vo = new UserVO();
try {
// 复制属性
BeanUtils.copyProperties(vo, user);
} catch (Exception e) {
log.error("属性复制失败", e);
throw new RuntimeException("属性复制失败", e);
}
return vo;
}
public User convertToEntity(UserDTO dto) {
if (dto == null) {
return null;
}
User user = new User();
try {
// 复制属性
BeanUtils.copyProperties(user, dto);
} catch (Exception e) {
log.error("属性复制失败", e);
throw new RuntimeException("属性复制失败", e);
}
return user;
}
public void updateUser(Long userId, Map<String, Object> updates) {
// 查询用户
User user = userMapper.selectById(userId);
if (user == null) {
throw new UserNotFoundException("用户不存在");
}
try {
// 从Map更新Bean属性
BeanUtils.populate(user, updates);
// 更新数据库
userMapper.updateById(user);
} catch (Exception e) {
log.error("更新用户失败", e);
throw new RuntimeException("更新用户失败", e);
}
}
}
六、Commons Codec - 编码解码工具类
6.1 DigestUtils - 摘要工具类
import org.apache.commons.codec.digest.DigestUtils;
public class DigestUtilsDemo {
public static void main(String[] args) {
String text = "hello world";
// MD5加密
String md5Hex = DigestUtils.md5Hex(text);
System.out.println("MD5: " + md5Hex);
// SHA-1加密
String sha1Hex = DigestUtils.sha1Hex(text);
System.out.println("SHA-1: " + sha1Hex);
// SHA-256加密
String sha256Hex = DigestUtils.sha256Hex(text);
System.out.println("SHA-256: " + sha256Hex);
// SHA-512加密
String sha512Hex = DigestUtils.sha512Hex(text);
System.out.println("SHA-512: " + sha512Hex);
}
}
// 实际应用:密码加密和文件校验
public class SecurityService {
public String encryptPassword(String password) {
// 使用SHA-256加密密码
return DigestUtils.sha256Hex(password);
}
public boolean verifyPassword(String inputPassword, String storedPassword) {
// 加密输入的密码
String encrypted = DigestUtils.sha256Hex(inputPassword);
// 比较加密后的密码
return encrypted.equals(storedPassword);
}
public String calculateFileMD5(File file) throws IOException {
// 计算文件的MD5值
try (FileInputStream fis = new FileInputStream(file)) {
return DigestUtils.md5Hex(fis);
}
}
public boolean verifyFileIntegrity(File file, String expectedMD5) throws IOException {
// 验证文件完整性
String actualMD5 = calculateFileMD5(file);
return actualMD5.equalsIgnoreCase(expectedMD5);
}
}
6.2 Base64 - Base64编码解码
import org.apache.commons.codec.binary.Base64;
public class Base64Demo {
public static void main(String[] args) {
String text = "hello world";
// Base64编码
String encoded = Base64.encodeBase64String(text.getBytes());
System.out.println("编码后: " + encoded); // "aGVsbG8gd29ybGQ="
// Base64解码
byte[] decoded = Base64.decodeBase64(encoded);
String decodedText = new String(decoded);
System.out.println("解码后: " + decodedText); // "hello world"
// URL安全的Base64编码
String urlSafeEncoded = Base64.encodeBase64URLSafeString(text.getBytes());
System.out.println("URL安全编码: " + urlSafeEncoded);
}
}
// 实际应用:图片Base64编码
public class ImageService {
public String imageToBase64(File imageFile) throws IOException {
// 读取图片文件
byte[] imageBytes = FileUtils.readFileToByteArray(imageFile);
// Base64编码
return Base64.encodeBase64String(imageBytes);
}
public void base64ToImage(String base64String, File destFile) throws IOException {
// Base64解码
byte[] imageBytes = Base64.decodeBase64(base64String);
// 写入文件
FileUtils.writeByteArrayToFile(destFile, imageBytes);
}
public String getImageDataUrl(File imageFile) throws IOException {
// 获取文件扩展名
String extension = FilenameUtils.getExtension(imageFile.getName());
// Base64编码
String base64 = imageToBase64(imageFile);
// 返回Data URL格式
return "data:image/" + extension + ";base64," + base64;
}
}
七、实战案例
7.1 用户信息处理
public class UserInfoProcessor {
/**
* 处理用户注册信息
*/
public User processRegistration(UserRegisterDTO dto) {
// 1. 验证用户名不为空
if (StringUtils.isBlank(dto.getUsername())) {
throw new IllegalArgumentException("用户名不能为空");
}
// 2. 验证密码不为空且长度符合要求
if (StringUtils.isBlank(dto.getPassword()) || dto.getPassword().length() < 6) {
throw new IllegalArgumentException("密码不能为空且长度不能少于6位");
}
// 3. 用户名转小写
String username = StringUtils.lowerCase(dto.getUsername());
// 4. 昵称默认值处理
String nickname = StringUtils.defaultIfBlank(dto.getNickname(), username);
// 5. 密码加密
String encryptedPassword = DigestUtils.sha256Hex(dto.getPassword());
// 6. 创建用户对象
User user = new User();
user.setUsername(username);
user.setPassword(encryptedPassword);
user.setNickname(nickname);
user.setCreateTime(new Date());
return user;
}
/**
* 批量导入用户
*/
public List<User> batchImport(List<UserImportDTO> dtoList) {
// 1. 验证列表不为空
if (CollectionUtils.isEmpty(dtoList)) {
throw new IllegalArgumentException("导入列表不能为空");
}
// 2. 过滤掉无效数据
List<UserImportDTO> validList = CollectionUtils.select(
dtoList,
dto -> StringUtils.isNotBlank(dto.getUsername())
&& StringUtils.isNotBlank(dto.getPassword())
).stream().collect(Collectors.toList());
// 3. 转换为User对象
List<User> users = new ArrayList<>();
for (UserImportDTO dto : validList) {
User user = new User();
try {
BeanUtils.copyProperties(user, dto);
user.setPassword(DigestUtils.sha256Hex(dto.getPassword()));
users.add(user);
} catch (Exception e) {
log.error("属性复制失败", e);
}
}
// 4. 分批插入数据库
List<List<User>> batches = ListUtils.partition(users, 100);
for (List<User> batch : batches) {
userMapper.batchInsert(batch);
}
return users;
}
}
7.2 文件处理
public class FileProcessor {
private static final String UPLOAD_DIR = "/data/uploads/";
private static final List<String> ALLOWED_EXTENSIONS =
Arrays.asList("jpg", "jpeg", "png", "gif", "pdf", "doc", "docx", "xls", "xlsx");
/**
* 处理文件上传
*/
public FileInfo uploadFile(MultipartFile file) throws IOException {
// 1. 验证文件不为空
if (file == null || file.isEmpty()) {
throw new IllegalArgumentException("文件不能为空");
}
// 2. 获取原始文件名
String originalFilename = file.getOriginalFilename();
if (StringUtils.isBlank(originalFilename)) {
throw new IllegalArgumentException("文件名不能为空");
}
// 3. 获取文件扩展名
String extension = FilenameUtils.getExtension(originalFilename);
// 4. 验证文件类型
if (!ALLOWED_EXTENSIONS.contains(extension.toLowerCase())) {
throw new IllegalArgumentException("不支持的文件类型:" + extension);
}
// 5. 生成新文件名
String newFilename = generateFilename(extension);
// 6. 创建上传目录
File uploadDir = new File(UPLOAD_DIR);
FileUtils.forceMkdir(uploadDir);
// 7. 保存文件
File destFile = new File(uploadDir, newFilename);
FileUtils.copyInputStreamToFile(file.getInputStream(), destFile);
// 8. 计算文件MD5
String md5 = DigestUtils.md5Hex(new FileInputStream(destFile));
// 9. 返回文件信息
FileInfo fileInfo = new FileInfo();
fileInfo.setOriginalFilename(originalFilename);
fileInfo.setFilename(newFilename);
fileInfo.setExtension(extension);
fileInfo.setSize(file.getSize());
fileInfo.setMd5(md5);
fileInfo.setUploadTime(new Date());
return fileInfo;
}
/**
* 生成文件名:日期 + UUID + 扩展名
*/
private String generateFilename(String extension) {
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
String uuid = UUID.randomUUID().toString().replace("-", "");
return date + "_" + uuid + "." + extension;
}
/**
* 批量删除文件
*/
public void batchDeleteFiles(List<String> filenames) {
if (CollectionUtils.isEmpty(filenames)) {
return;
}
for (String filename : filenames) {
File file = new File(UPLOAD_DIR + filename);
FileUtils.deleteQuietly(file);
}
}
/**
* 清理过期文件(7天前的文件)
*/
public void cleanExpiredFiles() {
File uploadDir = new File(UPLOAD_DIR);
if (!uploadDir.exists()) {
return;
}
// 获取7天前的时间
long expireTime = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000;
// 列出所有文件
Collection<File> files = FileUtils.listFiles(uploadDir, null, true);
// 删除过期文件
for (File file : files) {
if (file.lastModified() < expireTime) {
FileUtils.deleteQuietly(file);
log.info("删除过期文件:{}", file.getName());
}
}
}
}
7.3 数据导出
public class DataExporter {
/**
* 导出用户数据到CSV
*/
public void exportUsersToCsv(List<User> users, File destFile) throws IOException {
// 1. 验证数据不为空
if (CollectionUtils.isEmpty(users)) {
throw new IllegalArgumentException("导出数据不能为空");
}
// 2. 构建CSV内容
List<String> lines = new ArrayList<>();
// 添加表头
lines.add("ID,用户名,昵称,年龄,创建时间");
// 添加数据行
for (User user : users) {
String line = StringUtils.join(
new Object[]{
user.getId(),
user.getUsername(),
StringUtils.defaultString(user.getNickname(), ""),
ObjectUtils.defaultIfNull(user.getAge(), 0),
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(user.getCreateTime())
},
","
);
lines.add(line);
}
// 3. 写入文件
FileUtils.writeLines(destFile, "UTF-8", lines);
}
/**
* 从CSV导入用户数据
*/
public List<User> importUsersFromCsv(File csvFile) throws IOException {
// 1. 读取文件
List<String> lines = FileUtils.readLines(csvFile, "UTF-8");
// 2. 验证数据不为空
if (CollectionUtils.isEmpty(lines) || lines.size() < 2) {
throw new IllegalArgumentException("CSV文件为空或格式不正确");
}
// 3. 跳过表头,解析数据
List<User> users = new ArrayList<>();
for (int i = 1; i < lines.size(); i++) {
String line = lines.get(i);
String[] fields = StringUtils.split(line, ",");
if (ArrayUtils.isEmpty(fields) || fields.length < 5) {
log.warn("跳过无效行:{}", line);
continue;
}
User user = new User();
user.setId(NumberUtils.toLong(fields[0]));
user.setUsername(fields[1]);
user.setNickname(StringUtils.defaultIfBlank(fields[2], null));
user.setAge(NumberUtils.toInt(fields[3]));
try {
user.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(fields[4]));
} catch (ParseException e) {
log.error("日期解析失败:{}", fields[4]);
user.setCreateTime(new Date());
}
users.add(user);
}
return users;
}
}
八、最佳实践
8.1 使用建议
1. 优先使用Commons工具类
- 代码更简洁
- 处理了边界情况
- 性能经过优化
2. 注意null安全
- StringUtils.isBlank() 比 isEmpty() 更安全
- CollectionUtils.isEmpty() 处理了null情况
- ObjectUtils.defaultIfNull() 提供默认值
3. 选择合适的工具类
- 字符串操作:StringUtils
- 集合操作:CollectionUtils
- 文件操作:FileUtils
- Bean操作:BeanUtils
4. 注意性能
- 大量数据处理时使用批处理
- 文件操作注意关闭流
- 避免频繁的类型转换
5. 异常处理
- BeanUtils.copyProperties() 会抛出异常
- 文件操作需要处理IOException
- 使用try-catch或throws声明
8.2 常见陷阱
// 陷阱1:BeanUtils.copyProperties参数顺序
// ❌ 错误:参数顺序反了
BeanUtils.copyProperties(source, target); // 错误!
// ✓ 正确:目标对象在前
BeanUtils.copyProperties(target, source); // 正确
// 陷阱2:StringUtils.split vs String.split
String str = "a,,b";
String[] arr1 = str.split(","); // ["a", "", "b"]
String[] arr2 = StringUtils.split(str, ","); // ["a", "b"](忽略空字符串)
// 陷阱3:FileUtils.deleteDirectory vs File.delete
File dir = new File("testDir");
dir.delete(); // 只能删除空目录
FileUtils.deleteDirectory(dir); // 可以删除非空目录
// 陷阱4:BeanUtils.getProperty返回String
User user = new User();
user.setAge(20);
String age = BeanUtils.getProperty(user, "age"); // "20"(String类型)
Integer ageInt = (Integer) PropertyUtils.getProperty(user, "age"); // 20(Integer类型)
九、练习题
练习1:字符串处理
/**
* 实现一个方法,处理用户输入的手机号
* 要求:
* 1. 去除空格和特殊字符
* 2. 验证是否为11位数字
* 3. 格式化为:138****1234
*/
public String processPhoneNumber(String phone) {
// TODO: 实现
return null;
}
练习2:集合操作
/**
* 实现一个方法,找出两个用户列表的共同好友
* 要求:
* 1. 处理null和空列表
* 2. 返回共同好友列表
* 3. 按用户ID排序
*/
public List<User> findCommonFriends(List<User> friends1, List<User> friends2) {
// TODO: 实现
return null;
}
练习3:文件操作
/**
* 实现一个方法,批量处理图片文件
* 要求:
* 1. 验证文件类型(只允许jpg、png、gif)
* 2. 计算文件MD5
* 3. 重命名文件为:日期_MD5.扩展名
* 4. 移动到指定目录
*/
public List<FileInfo> processImages(List<File> imageFiles, String destDir) throws IOException {
// TODO: 实现
return null;
}
学习检查清单
完成本文档学习后,你应该能够:
- 理解Apache Commons的作用和价值
- 熟练使用StringUtils进行字符串操作
- 熟练使用CollectionUtils进行集合操作
- 熟练使用FileUtils进行文件操作
- 掌握BeanUtils进行对象属性复制
- 了解DigestUtils进行加密操作
- 了解Base64进行编码解码
- 能够在实际项目中应用这些工具类
- 知道常见的使用陷阱和注意事项
- 能够选择合适的工具类解决问题
推荐资源
官方文档:
学习建议:
- 先掌握最常用的StringUtils和CollectionUtils
- 在实际项目中多使用,积累经验
- 遇到问题查阅官方文档
- 对比原生API和Commons API的区别
- 注意性能和边界情况处理
记住:Apache Commons是Java开发的利器,熟练掌握可以大大提高开发效率!