在 Java 世界里,总有那样一个工具库,它既轻量又实用,把很多日常重复工作封装成"开箱即用"的 API,让你可以把精力放在业务逻辑本身。
对于中国开发者来说,Hutool 就是这样一把"瑞士军刀"------从字符串、集合、日期、IO、文件、加密,到 JDBC、JSON、HTTP、图片、并发、甚至 AI 能力(hutool-ai),它几乎覆盖了你日常开发中会用到的绝大多数工具函数。
本文说明:此文所有代码,都是有我本人在 5.8.40 版本亲测可用不报错,欢迎大家直接使用本文示例代码。
什么是 Hutool?为何它能成为开发必备
Hutool = Hu + tool,是原公司项目底层代码剥离后的开源库,"Hu"是公司名称的表示,tool 表示工具。Hutool 谐音"糊涂",一方面简洁易懂,一方面寓意"难得糊涂"。
这个始于 2014 年的开源项目,核心定位是 "减少代码搜索成本,避免复制粘贴代码导致的潜在问题"。与 Guava 等国外工具库相比,Hutool 最大的优势在于对中文场景的深度适配和开发者友好的 API 设计。
Hutool 的核心优势
- 中文友好:内置农历日期计算、中文金额转换等特色功能,完美解决本地化需求
- 零依赖:纯 Java 实现,不引入额外第三方库,避免依赖冲突
- 模块化设计:20 + 功能模块支持按需引入,最小化项目体积
- 活跃社区:Gitee 托管的国产项目,issue 响应速度远超许多国外库
- 持续进化:2025 年最新的 5.8.40 版本仍在高频更新,不断增强功能边界
版本选择指南
当前 Hutool 存在两个重要版本线:
- 5.x 系列:稳定版本,截至本文发布,最新为 5.8.40(2025 年 8 月发布),保持向下兼容
- 6.x 系列 :正在酝酿的重构版本,将包名从
cn.hutool
改为org.dromara.hutool
,并优化了大量 API 设计
⚠️ 注意:生产环境建议使用 5.8.40 稳定版,6.x 版本预计 2026 年正式发布,本文代码示例将基于 5.8.40 版本,并标注 6.x 的差异之处。
快速入门:环境配置
通过 Maven 引入 Hutool 最简单的方式是使用hutool-all
包:
xml
<dependency>
<groupId>cn.hutool </groupId>
<artifactId>hutool-all </artifactId>
<version>5.8.40</version>
</dependency>
第一个 Hutool 程序:
typescript
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
public class HutoolDemo {
public static void main(String[] args) {
// 获取当前时间并格式化
String now = DateUtil.now();
// 字符串模板替换
String welcome = StrUtil.format("欢迎使用Hutool!当前时间:{}", now);
System.out.println(welcome);
}
}
这段代码展示了 Hutool 最典型的使用方式:通过静态工具类直接调用方法,无需创建实例,极大简化了代码结构。
核心工具类详解:从字符串到加密的全场景覆盖
Hutool 的工具类遵循 "所见即所得" 的命名原则,StrUtil
处理字符串,DateUtil
处理日期,SecureUtil
处理加密,让开发者能仅凭类名就知道该用哪个工具。下面我们将逐一讲解开发中最常用的核心模块。
字符串处理:StrUtil 让字符操作如行云流水
字符串处理是 Java 开发中最频繁的操作之一,StrUtil
类封装了 200 + 常用方法,彻底告别String
类的蹩脚 API。
空判断------ 最常用也最容易出错的操作:
rust
// 原生Java写法
if (str == null || str.length() == 0 || "null".equals(str)) {
// 处理空字符串
}
// Hutool写法
if (StrUtil.isEmpty(str)) {
// 处理空字符串
}
// 更严格的空判断(纯空白字符也视为空)
if (StrUtil.isBlank(str)) {
// 处理空白字符串
}
字符串格式化------ 支持多种占位符风格:
arduino
// 标准占位符
String result1 = StrUtil.format("姓名:{},年龄:{}", "张三", 25);
// 命名占位符
Map<String, Object> map = new HashMap <>();
map.put("name", "李四");
map.put("age", 30);
String result2 = StrUtil.format("姓名:{name},年龄:{age}", map);
字符串切割与拼接------ 灵活处理各种分隔符:
ini
String str = "a,b,c,d";
// 切割字符串
List<String> list = StrUtil.split(str, ',');
// 拼接字符串
String join = StrUtil.join("|", list); // 结果:a|b|c|d
// 去除前后缀
String fileName = "report.pdf";
String name = StrUtil.removeSuffix(fileName, ".pdf"); // 结果:report
5.8.40 版本新特性:增强的脱敏功能,支持护照号码脱敏:
ini
import cn.hutool.core.util.DesensitizedUtil;
// 手机号脱敏:138****1234
String phone = DesensitizedUtil.mobilePhone("13812341234");
// 护照脱敏:E123****5678
String passport = DesensitizedUtil.passport("E12345678"); // 5.8.40新增
日期时间:DateUtil 解决所有时间难题
Java 的日期处理一直为人诟病,Date
、Calendar
、LocalDateTime
并存导致混乱,DateUtil
将这些 API 统一封装,提供直观易用的日期操作。
日期格式化------ 无需记忆繁琐的 pattern:
ini
// 获取当前时间
Date now = new Date();
// 格式化成年月日
String ymd = DateUtil.formatDate(now); // 2025-08-29
// 格式化时分秒
String hms = DateUtil.formatTime(now); // 15:30:45
// 自定义格式
String custom = DateUtil.format(now, "yyyy年MM月dd日 HH:mm:ss");
日期计算------ 链式调用轻松实现:
ini
// 昨天
Date yesterday = DateUtil.yesterday();
// 明天
Date tomorrow = DateUtil.tomorrow();
// 三天后
Date after3Days = DateUtil.offsetDay(now, 3);
// 十分钟前
Date before10Min = DateUtil.offsetMinute(now, -10);
// 计算两个日期差
Date start = DateUtil.parse("2025-01-01");
Date end = DateUtil.parse("2025-08-29");
long days = DateUtil.between(start, end, DateUnit.DAY); // 240天
中文特色功能------ 农历与节假日:
ini
// 农历转换
String lunar = DateUtil.lunar(now); // 农历七月十六
// 节假日判断
boolean isWorkday = DateUtil.isWorkday(now); // 是否工作日
boolean isHoliday = DateUtil.isHoliday(now); // 是否节假日
小贴士:Hutool 的节假日数据会通过版本更新保持同步,如需自定义节假日,可通过
HolidayUtil
进行扩展。
集合操作:CollUtil 让集合处理得心应手
Java 集合框架虽然强大,但很多常用操作仍需大量代码,CollUtil
弥补了这一不足,提供了集合创建、转换、操作的一站式解决方案。
集合创建------ 一行代码创建各种集合:
ini
// 创建列表
List<String> list = CollUtil.newArrayList("a", "b", "c");
// 创建有序映射
Map<String, Integer> map = MapUtil.newHashMap(true);
// 创建固定大小的集合
Set<Integer> set = CollUtil.newHashSet(1, 2, 3, 4);
集合判断与操作:
ini
List<Integer> numbers = CollUtil.newArrayList(1, 2, 3, 4, 5);
// 判断非空
boolean notEmpty = CollUtil.isNotEmpty(numbers);
// 取前3个元素
List<Integer> top3 = ListUtil.sub(numbers, 0, 3); // [1,2,3]
// 集合拆分
List<List<Integer>> partition = ListUtil.partition(numbers, 2); // [[1,2],[3,4],[5]]
// 集合转字符串
String str = CollUtil.join(numbers, ","); // "1,2,3,4,5"
Map 操作增强:
ini
Map<String, Object> user = new HashMap<>();
user.put("name", "张三");
user.put("age", 25);
user.put("address", null);
// 获取值,不存在时返回默认值
String name = MapUtil.getStr(user, "name", "未知");
int age = MapUtil.getInt(user, "age", 0);
// 忽略null值转换为字符串
String userStr = MapUtil.joinIgnoreNull(user, ",", "=");
// 结果:name=张三, age=25
加密工具:SecureUtil 一行代码实现加密解密
数据安全是开发必备需求,SecureUtil
封装了对称加密、非对称加密、摘要算法等多种加密方式,无需了解复杂的加密原理即可轻松使用。
MD5 加密------ 常用于密码存储:
ini
// 简单MD5加密
String md5 = SecureUtil.md5("123456");
// 带盐值的MD5加密(更安全)
String saltMd5 = SecureUtil.md5("123456" + "salt");
AES 对称加密------ 适用于敏感数据传输:
ini
String content = "需要加密的内容";
String key = "1234567890123456"; // AES密钥长度必须是16/24/32位
// 加密
String encrypt = SecureUtil.aes(key.getBytes()).encryptBase64(content);
// 解密
String decrypt = SecureUtil.aes(key.getBytes()).decryptStr(encrypt);
国密算法------ 支持 SM2/SM3/SM4 等国家标准算法:
ini
// SM3摘要算法
String sm3 = SmUtil.sm3("国密测试");
// SM4对称加密
String sm4Encrypt = SmUtil.sm4(key.getBytes()).encryptBase64(content);
注意:加密算法的密钥管理至关重要,生产环境中切勿将密钥硬编码在代码中,建议通过配置中心管理。
文件操作:FileUtil 让文件处理事半功倍
Java 的 IO 操作代码冗长且容易出错,FileUtil
和IoUtil
将这些操作简化到极致,无论是文件读写还是目录操作都能轻松完成。
文件读写------ 几行代码搞定:
arduino
// 读取文件内容
String content = FileUtil.readString("test.txt", CharsetUtil.UTF_8);
// 写入文件
FileUtil.writeString("Hello Hutool", "output.txt", CharsetUtil.UTF_8);
// 追加内容
FileUtil.appendString("\n追加一行", "output.txt", CharsetUtil.UTF_8);
// 大文件拷贝
FileUtil.copy("largeFile.zip", new File("targetDir"), true); // true表示覆盖
目录操作:
less
// 创建目录
FileUtil.mkdir("newDir");
// 创建多级目录
FileUtil.mkdir("parent/child/grandchild");
// 列出目录下所有文件
List<File> files = List.of(FileUtil.ls("parent"));
// 递归列出所有Java文件
List<File> javaFiles = FileUtil.loopFiles("com", file -> file.getName().endsWith(".class"));
文件信息获取:
ini
File file = new File("test.txt");
// 文件大小
long size = FileUtil.size(file);
// 人性化显示大小
String humanSize = FileUtil.readableFileSize(size); // 如:1.5MB
// 文件类型
String type = FileUtil.getType(file); // txt
// 最后修改时间
Date lastModified = FileUtil.lastModifiedTime(file);
HTTP 客户端:HttpUtil 轻松发送网络请求
相比HttpClient
的复杂配置,HttpUtil
让 HTTP 请求变得极其简单,无论是 GET、POST 还是文件上传下载都能轻松应对。
GET 请求:
dart
// 简单GET请求
String result = HttpUtil.get("https://api.example.com/data");
// 带参数的GET请求
Map<String, Object> paramMap = new HashMap <>();
paramMap.put("page", 1);
paramMap.put("size", 10);
String pageResult = HttpUtil.get("https://api.example.com/list", paramMap);
POST 请求:
ini
// 表单提交
Map<String, Object> formData = new HashMap <>();
formData.put("username", "test");
formData.put("password", "123456");
String loginResult = HttpUtil.post("https://api.example.com/login", formData);
// JSON提交
String json = "{"name":"hutool","version":"5.8.40"}";
HttpResponse response = HttpUtil.createPost("https://api.example.com/submit")
.body(json)
.header("Content-Type", "application/json")
.execute();
String jsonResult = response.body();
文件下载:
csharp
// 下载文件到指定路径
HttpUtil.downloadFile("https://example.com/file.zip", FileUtil.file("downloads"));
// 带进度条的下载
HttpUtil.downloadFile("https://example.com/large.zip", FileUtil.file("downloads"),
new StreamProgress() {
@Override
public void start() {
System.out.println("开始下载");
}
@Override
public void progress(long total, long progressSize) {
System.out.println("已下载:" + FileUtil.readableFileSize(progressSize));
}
@Override
public void finish() {
System.out.println("下载完成");
}
});
hutool-ai 模块:AI 能力集成新范式
随着大模型技术的普及,Hutool 在 5.8.x 版本中新增了hutool-ai
模块,为开发者提供了简单易用的 AI 能力集成方案。该模块封装了主流 AI 平台的 API,支持文本生成、图像生成等常见场景,并提供了统一的调用接口。
模块引入与初始化
使用hutool-ai
需要单独引入依赖:
xml
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-ai</artifactId>
<version>5.8.40</version>
</dependency>
初始化 AI 客户端(以豆包平台为例):
arduino
// 配置API密钥
AIConfig config = new BaseConfig();
config.setApiKey("sk-");
config.setApiUrl("https://api.deepseek.com/v1");
config.setModel("deepseek-reasoner");
// 创建deepseekAI客户端
DeepSeekServiceImpl baseAIService = new DeepSeekServiceImpl(config);
文本生成功能
DeepSeekService 是 Hutool AI 模块中专门对接 DeepSeek 大模型服务的接口,在基础 AIService 功能基础上扩展了 DeepSeek 特有的功能。
arduino
// 配置API密钥
AIConfig config = new BaseConfig();
config.setApiKey("sk-");
config.setApiUrl("https://api.deepseek.com/v1");
config.setModel("deepseek-reasoner");
// 创建deepseekAI客户端
DeepSeekServiceImpl baseAIService = new DeepSeekServiceImpl(config);
// 普通对话
String content = baseAIService.chat("写一个疯狂星期四广告词");
// 流式对话
baseAIService.chat("写一个疯狂星期四广告词", s -> {
System.out.println(s);
});
// 查询模型列表
String models = baseAIService.models();
// 查询账户余额
String balance = baseAIService.balance();
图片理解
DoubaoService 是 Hutool AI 模块中对接豆包大模型服务的扩展接口,在基础 AIService 功能基础上提供了豆包特有的多模态和高级功能支持。
arduino
// 配置API密钥
AIConfig config = new BaseConfig();
config.setApiKey("sk-");
config.setApiUrl("https://api.deepseek.com/v1");
config.setModel("deepseek-reasoner");
// 创建deepseekAI客户端
DoubaoServiceImpl baseAIService = new DoubaoServiceImpl(config);
String base64 = "xxx"; // 图片base64内容
String chatVision = baseAIService.chatVision("图片上有些什么?", Arrays.asList(base64));
视频生成
arduino
// 配置API密钥
AIConfig config = new BaseConfig();
config.setApiKey("sk-");
config.setApiUrl("https://api.deepseek.com/v1");
config.setModel("deepseek-reasoner");
// 创建deepseekAI客户端
DoubaoServiceImpl baseAIService = new DoubaoServiceImpl(config);
String videoTasks = baseAIService.videoTasks("生成一段动画视频,主角是大耳朵图图,一个活泼可爱的小男孩。视频中图图在公园里玩耍," +
"画面采用明亮温暖的卡通风格,色彩鲜艳,动作流畅。背景音乐轻快活泼,带有冒险感,音效包括鸟叫声、欢笑声和山洞回声。", "https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544");
//查询视频生成任务信息
String videoTasksInfo = baseAIService.getVideoTasksInfo("任务id");
总结:为什么 Hutool 值得你全面拥抱
经过本文的详细介绍,相信你已经对 Hutool 有了全面的认识。这款国产工具库之所以能获得广泛认可,核心在于它真正理解 Java 开发者的痛点,用最简单直接的方式解决问题。