Apache 工具包(commons-io commons-lang3 )保姆介绍

引言

作为 Java 后端开发者,日常开发中总会遇到大量重复工作:字符串判空、日期格式化、文件读写、参数校验...... 这些操作原生 API 要么代码繁琐,要么容易踩坑(比如空指针、流未关闭)。而 Apache Commons 工具包(尤其是commons-lang3commons-io)就像 "效率加速器",把这些常用操作封装成了简洁、安全的静态方法,一行代码就能搞定。

一、工具包整体介绍

1. 为什么要学这两个工具包?

  • commons-lang3:专注于 "业务核心处理",解决字符串、日期、对象、参数校验等高频问题,覆盖 80% 的业务代码场景。
  • commons-io:专注于 "文件 / 流处理",简化文件读写、复制、上传下载等操作,避免原生 API 的繁琐代码和资源泄露问题。
  • 适用场景:接口参数校验、日期格式化(如有效期)、自测报告生成(文件读写)、配置文件读取、文件上传下载等。

2. 依赖引入(SpringBoot 项目直接用)

无需手动下载 jar 包,在pom.xml中添加以下依赖即可(版本稳定兼容,放心使用):

复制代码
<!-- commons-lang3:字符串、日期、校验核心工具 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

<!-- commons-io:文件/流处理工具 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

添加后右键项目 → Maven → Reload Project,IDEA 会自动下载依赖。

二、核心方法速查(实战场景绑定)

(一)commons-lang3 核心方法

1. StringUtils(字符串处理:解决原生 String 的所有坑)

原生 String 的痛点:null判空会空指针、isEmpty()不识别纯空格、拼接集合繁琐。StringUtils全部搞定,业务中优先用!

方法名 作用 礼品卡业务场景 代码示例
isBlank(String str) 判断 null / 空串 / 纯空格(最常用) 卡号、手机号、用户姓名非空校验 if (StringUtils.isBlank(giftCardNo)){ throw new IllegalArgumentException("卡号不能为空")};
isNotBlank(String str) 反向判断(非空非空格) 条件查询时判断参数是否有效 if (StringUtils.isNotBlank(keyword)) { // 执行模糊查询 }
join(Collection coll, String sep) 拼接集合为字符串 标签拼接(如 ["满减","无门槛"]→"满减,无门槛") List<String> tags = Arrays.asList("满减","无门槛"); String tagStr = StringUtils.join(tags, ",");
substring(String str, int start, int end) 截取字符串 从卡号提取前缀(如 GC202405201→GC2024) String prefix = StringUtils.substring(giftCardNo, 0, 6);
trimToNull(String str) 去空格,空则返回 null 处理用户输入的模糊查询关键词 String keyword = StringUtils.trimToNull(userInput);
length(String str) 安全获取长度(null 返回 0) 校验卡号长度(如必须 11 位) Validate.isTrue(StringUtils.length(giftCardNo) == 11, "卡号必须为11位");
2. DateUtils(日期处理:线程安全 + 简洁)

原生SimpleDateFormat线程不安全,手动计算日期繁琐,DateUtils+FastDateFormat(线程安全)是最优解。

方法名 作用 礼品卡业务场景 代码示例
addDays(Date date, int days) 日期加天数 计算有效期(创建时间 + 90 天) Date expireDate = DateUtils.addDays(new Date(), 90);
addMonths(Date date, int months) 日期加月数 长期礼品卡有效期(+6 个月) Date expireDate = DateUtils.addMonths(new Date(), 6);
isAfterNow(Date date) 判断日期是否在当前时间之后 校验礼品卡是否未过期 boolean isExpired = DateUtils.isAfterNow(expireDate);
isBeforeNow(Date date) 判断日期是否在当前时间之前 校验有效期是否早于当前时间(非法参数) Validate.isTrue(!DateUtils.isBeforeNow(expireDate), "有效期不能早于当前时间");
parseDate(String str, String... formats) 字符串转 Date 前端传入有效期字符串转 Date Date inputExpire = DateUtils.parseDate("2024-12-31", "yyyy-MM-dd");

补充:FastDateFormat线程安全,全局复用:

复制代码
private static final FastDateFormat DATETIME_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
String createTime = DATETIME_FORMATTER.format(new Date()); // 格式化创建时间
3. ObjectUtils(对象处理:安全判空)

处理实体类、集合、数组的判空,比null == obj覆盖场景更全。

方法名 作用 礼品卡业务场景 代码示例
isEmpty(Object obj) 判断对象 / 集合 / 数组是否为 null / 空 校验礼品卡实体、查询列表是否为空 if (ObjectUtils.isEmpty(giftCard)) throw new RuntimeException("礼品卡不存在");
isNotEmpty(Object obj) 反向判断(非空) 处理查询结果(非空则返回数据) if (ObjectUtils.isNotEmpty(giftCardList)) { return giftCardList; }
defaultIfNull(T obj, T defaultObj) 空则返回默认值 礼品卡默认金额(null 则返回 10 元) BigDecimal amount = ObjectUtils.defaultIfNull(giftCard.getAmount(), new BigDecimal("10"));
4. Validate(参数校验:替代繁琐 if-else)

集中处理参数校验,不符合条件直接抛异常,代码更简洁,错误信息更统一。

方法名 作用 礼品卡业务场景 代码示例
notNull(Object obj, String msg) 校验对象非 null,否则抛异常 校验金额、有效期等核心参数非 null Validate.notNull(giftCard.getAmount(), "金额不能为空");
isTrue(boolean condition, String msg) 校验条件为 true,否则抛异常 校验金额 > 0、卡号长度 = 11 位 Validate.isTrue(amount.compareTo(BigDecimal.ZERO) > 0, "金额必须大于0");
notBlank(String str, String msg) 校验字符串非空非空格(3.8 + 版本) 简化卡号非空校验(无需额外调用 StringUtils) Validate.notBlank(giftCardNo, "卡号不能为空");

(二)commons-io 核心方法

1. FileUtils(文件处理:一行搞定文件读写 / 复制)

原生文件操作需要处理创建文件、目录、关流等问题,FileUtils自动处理,还能避免异常。

方法名 作用 礼品卡业务场景 代码示例
writeStringToFile(File file, String content, String encoding) 字符串写入文件(自动创建文件) 生成自测报告、导出礼品卡列表 File report = new File("gift_card_test_report.txt"); FileUtils.writeStringToFile(report, content, "UTF-8");
readFileToString(File file, String encoding) 读取文件为字符串 读取配置文件、自测报告内容 String reportContent = FileUtils.readFileToString(report, "UTF-8");
readLines(File file, String encoding) 按行读取文件 读取批量导入的礼品卡卡号文件 List<String> cardNos = FileUtils.readLines(new File("import.txt"), "UTF-8");
copyFileToDirectory(File src, File destDir) 复制文件到目录(自动创建目录) 备份自测报告、复制 Excel 导入模板 FileUtils.copyFileToDirectory(report, new File("backup"));
deleteQuietly(File file) 安静删除文件(不存在也不抛异常) 删除过期临时文件 FileUtils.deleteQuietly(new File("temp.txt"));
2. IOUtils(流处理:避免资源泄露)

处理InputStream/OutputStream时,原生 API 需要手动关流,IOUtils自动关闭,还能简化复制、流转字符串等操作。

方法名 作用 礼品卡业务场景 代码示例
copy(InputStream in, OutputStream out) 复制流(自动处理缓冲区) 上传礼品卡图片、下载模板文件 IOUtils.copy(new FileInputStream("template.xlsx"), new FileOutputStream("target.xlsx"));
closeQuietly(Closeable closeable) 安静关闭流(报错不抛异常) 关闭文件流(避免资源泄露) IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream);
toString(InputStream in, String encoding) 流转字符串 读取 HTTP 请求流中的参数 String requestBody = IOUtils.toString(request.getInputStream(), "UTF-8");
3. FilenameUtils(文件名处理:兼容不同系统)

解决 Windows/Linux 路径分隔符差异(\/)、文件名提取、后缀判断等问题。

方法名 作用 礼品卡业务场景 代码示例
getName(String path) 提取文件名(兼容所有系统路径) 获取上传图片的文件名 String fileName = FilenameUtils.getName("D:/upload/cover.png"); // 结果:cover.png
getExtension(String path) 提取文件后缀 校验上传文件格式(仅允许 png/jpg) `String ext = FilenameUtils.getExtension(filePath); Validate.isTrue("png".equals(ext) "jpg".equals (ext), "仅支持 png/jpg 格式");`
concat(String basePath, String fileName) 拼接路径(自动适配系统分隔符) 拼接图片存储路径 String fullPath = FilenameUtils.concat("static/images", fileName);
normalize(String path) 标准化路径(处理../ 等符号) 修复用户上传的不规则路径 String normalPath = FilenameUtils.normalize("static/../images/cover.png"); // 结果:images/cover.png

三、避坑指南(新手必看)

1. 版本冲突坑

  • 问题:引入commons-lang(注意没有 3)和commons-lang3会冲突,commons-lang是旧版本(已停止维护)。
  • 解决:只引入commons-lang3,避免同时引入两个版本。

2. 线程安全坑

  • 问题:用SimpleDateFormat格式化日期,多线程环境下会出现日期错乱。
  • 解决:用commons-lang3FastDateFormat,全局定义为静态变量复用(如上文示例)。

3. 判空方法选择坑

  • 问题:混淆isEmpty()isBlank(),导致纯空格参数校验失败。
  • 解决:业务中优先用StringUtils.isBlank()(识别 null / 空串 / 纯空格),isEmpty()仅识别 null / 空串,几乎不用。
方法 null ""(空串) " "(纯空格) 适用场景
isEmpty() true true false 极少场景(需精确判断空串)
isBlank() true true true 绝大多数业务判空

4. 异常处理坑

  • 问题:FileUtilsIOUtils的方法会抛IOException,直接忽略会导致编译报错。
  • 解决:两种方式:
    1. try-catch捕获异常,打印日志:

      复制代码
      try {
          FileUtils.writeStringToFile(report, content, "UTF-8");
      } catch (IOException e) {
          log.error("生成报告失败", e); // 用日志框架打印异常
          throw new RuntimeException("生成报告失败");
      }
    2. 在方法上声明throws IOException(适合工具类方法)。

5. 路径兼容坑

  • 问题:Windows 系统用\作为路径分隔符,Linux 用/,直接写死路径会导致跨系统部署失败。
  • 解决:用FilenameUtils.concat()拼接路径,自动适配系统分隔符,不要手动写\/

四、实战示例(直接复制到项目用)

以下是结合礼品卡系统的完整示例,包含参数校验、日期处理、报告生成:

复制代码
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.math.BigDecimal;
import java.util.Date;

public class GiftCardCommonsDemo {
    private static final FastDateFormat DATETIME_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");

    // 礼品卡参数校验+创建
    public static void createGiftCard(String giftCardNo, BigDecimal amount, String expireDateStr) throws Exception {
        // 1. 参数校验(StringUtils+Validate)
        Validate.notBlank(giftCardNo, "卡号不能为空");
        Validate.isTrue(StringUtils.length(giftCardNo) == 11, "卡号必须为11位");
        Validate.notNull(amount, "金额不能为空");
        Validate.isTrue(amount.compareTo(BigDecimal.ZERO) > 0, "金额必须大于0");
        Validate.notBlank(expireDateStr, "有效期不能为空");

        // 2. 日期处理(DateUtils)
        Date expireDate = DateUtils.parseDate(expireDateStr, "yyyy-MM-dd");
        Validate.isTrue(!DateUtils.isBeforeNow(expireDate), "有效期不能早于当前时间");
        String createTime = DATETIME_FORMATTER.format(new Date());

        // 3. 生成创建日志(FileUtils)
        String logContent = String.format("礼品卡创建成功:卡号=%s,金额=%.2f元,有效期=%s,创建时间=%s",
                giftCardNo, amount, expireDateStr, createTime);
        File logFile = new File("gift_card_create_log.txt");
        FileUtils.writeStringToFile(logFile, logContent + "\n", "UTF-8", true); // 追加写入

        System.out.println(logContent);
    }

    public static void main(String[] args) throws Exception {
        // 测试创建礼品卡
        createGiftCard("GC202405201", new BigDecimal("100"), "2024-12-31");
    }
}

运行后会生成日志文件,输出结果:礼品卡创建成功:卡号=GC202405201,金额=100.00元,有效期=2024-12-31,创建时间=2024-05-20 16:30:00

五、总结

Apache Commons 工具包是 Java 后端的 "必备工具",commons-lang3commons-io更是覆盖了大部分高频场景。本文整理的速查表和实战示例,新手可以直接复制使用,老手可以快速查阅,建议收藏备用~

如果在使用过程中遇到问题,或者有其他好用的方法,欢迎在评论区交流补充!

相关推荐
毕设源码-邱学长2 小时前
【开题答辩全过程】以 服装购物平台为例,包含答辩的问题和答案
java·eclipse
多喝开水少熬夜2 小时前
堆相关算法题基础-java实现
java·开发语言·算法
richxu202510012 小时前
Java开发环境搭建之 10.使用IDEA创建和管理Mysql数据库
java·ide·intellij-idea
7澄12 小时前
Java 集合框架:List 体系与实现类深度解析
java·开发语言·vector·intellij-idea·集合·arraylist·linkedlist
行思理2 小时前
IntelliJIdea 工具新手操作技巧
java·spring·intellijidea
xfmtznfl2165pv2 小时前
如何在VSCode中设置工作区特定的选项?
ide·vscode·编辑器
Adellle2 小时前
Java中同步和异步的区别,以及阻塞和非阻塞的区别
java·开发语言
qq_12498707533 小时前
基于springboot+vue的物流管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·毕业设计
学习编程的Kitty4 小时前
JavaEE初阶——多线程(5)单例模式和阻塞队列
java·开发语言·单例模式