Hutool实战指南:如何用Java工具库提升开发效率

张开发
2026/4/14 18:50:53 15 分钟阅读

分享文章

Hutool实战指南:如何用Java工具库提升开发效率
1. Hutool工具库简介Hutool是一个小而全的Java工具类库它通过静态方法封装降低了相关API的学习成本提高了工作效率。这个工具库让Java也能像脚本语言一样甜甜的。Hutool中的工具方法来自于每个用户的精雕细琢它涵盖了Java开发底层代码中的方方面面它既是大型项目开发中解决小问题的利器也是小型项目中的效率担当。Hutool是项目中util包友好的替代它节省了开发人员对项目中公用类和公用工具方法的封装时间使开发专注于业务同时可以最大程度地避免封装不完善带来的bug。Hutool Hu tool是原公司项目底层代码剥离后的开源库Hu是公司名称的表示tool表示工具。Hutool谐音糊涂一方面简单易懂一方面寓意难得糊涂。Hutool的目标是使用一个工具方法代替一段复杂代码从而最大程度地避免复制粘贴代码的问题彻底改变我们写代码的方式。以计算MD5为例以前打开搜索引擎 - 搜Java MD5加密 - 打开某篇博客 - 复制粘贴 - 改改好用现在引入Hutool - SecureUtil.md5()Hutool的存在就是为了减少代码搜索成本避免网络上参差不齐的代码出现导致的bug。2. Hutool核心组件介绍2.1 基础工具类Hutool提供了一系列基础工具类包括文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装组成各种Util工具类同时提供以下组件hutool-aopJDK动态代理封装提供类似IOC下的切面支持hutool-bloomFilter布隆过滤器提供一些Hash算法的布隆过滤hutool-cache简单缓存实现hutool-core核心包含Bean操作、日期、各种Util等hutool-cron定时任务模块提供类Crontab表达式的定时任务hutool-crypto加密解密模块提供对称、非对称和摘要算法封装hutool-db基于JDBC的数据库操作封装基于ActiveRecord思想hutool-dfa基于DFA模型的多关键字查找hutool-extra扩展模块对第三方封装模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等hutool-http基于HttpUrlConnection的Http客户端封装hutool-log自动识别日志实现的日志门面hutool-script脚本执行封装例如JavaScripthutool-setting功能更强大的Setting配置文件和Properties封装hutool-system系统参数调用封装JVM信息等hutool-jsonJSON实现hutool-captcha图片验证码实现hutool-poi针对POI中Excel和Word的封装hutool-socket基于Java的NIO和AIO的Socket封装hutool-jwtJSON Web Token (JWT)封装实现2.2 官方文档与引入方式Hutool的官方文档非常全面包括官网Hutool — A set of tools that keep Java sweet.参考文档简介 | HutoolAPI文档Document引入Hutool非常简单直接在项目中引入如下依赖即可dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.0/version /dependency3. 常用工具类实战3.1 Convert类型转换工具在Java开发中我们经常要面对各种各样的类型转换问题尤其是从命令行获取的用户参数、从HttpRequest获取的Parameter等等这些参数类型多种多样我们怎么去转换它们呢常用的做法是先整成String然后调用XXX.parseXXX方法还要承受转换失败的风险不得不加一层try catch这个小小的过程混杂在业务代码中会显得非常难看和臃肿。Convert类可以说是工具方法类里面封装了针对Java常见类型的转换用于简化类型转换。Convert类中大部分方法为toXXX参数为Object可以实现将任何可能的类型转换为指定类型。同时支持第二个参数defaultValue用于在转换失败时返回一个默认值。import cn.hutool.core.convert.Convert; import lombok.extern.slf4j.Slf4j; import java.util.Date; import java.util.List; Slf4j public class ConvertDemo { public void covert() { //转换为字符串 int a 1; String aStr Convert.toStr(a); log.info(aStr); //转换为指定类型数组 String[] b {1, 2, 3, 4}; Integer[] bArr Convert.toIntArray(b); log.info(Arrays.toString(bArr)); //转换为日期对象 String dateStr 2023-09-17; Date date Convert.toDate(dateStr); log.info(date.toString()); //转换为列表 String[] strArr {a, b, c, d}; ListString strList Convert.toList(String.class, strArr); log.info(strList.toString()); } }3.2 DateUtil日期时间工具日期时间工具类定义了一些常用的日期时间操作方法。public void dateUtil() { //Date、long、Calendar之间的相互转换 //当前时间 Date date DateUtil.date(); log.info(date.toString()); //Calendar转Date date DateUtil.date(Calendar.getInstance()); //时间戳转Date date DateUtil.date(System.currentTimeMillis()); //自动识别格式转换 String dateStr 2023-09-17; date DateUtil.parse(dateStr); //自定义格式化转换 date DateUtil.parse(dateStr, yyyy-MM-dd); //格式化输出日期 String format DateUtil.format(date, yyyy-MM-dd); log.info(format); //获取年的部分 int year DateUtil.year(date); //获取月份从0开始计数 int month DateUtil.month(date); //获取某天的开始、结束时间 Date beginOfDay DateUtil.beginOfDay(date); Date endOfDay DateUtil.endOfDay(date); //计算偏移后的日期时间 Date newDate DateUtil.offset(date, DateField.DAY_OF_MONTH, 2); //计算日期时间之间的偏移量 long betweenDay DateUtil.between(date, newDate, DateUnit.DAY); }3.3 ReflectUtil反射工具Java反射工具类可用于反射获取类的方法及创建对象。public void reflectUtil() { //获取某个类的所有方法 Method[] methods ReflectUtil.getMethods(Dog.class); //获取某个类的指定方法 Method method ReflectUtil.getMethod(Dog.class, getName); //使用反射来创建对象 Dog dog ReflectUtil.newInstance(Dog.class); //反射执行对象的方法 ReflectUtil.invoke(dog, setName,大黄); log.info(dog.getName()); } Data Builder NoArgsConstructor AllArgsConstructor public class Dog { private String name; private Float weight; }3.4 NumberUtil数字处理工具public void numberUtil() { double n1 1.234; double n2 1.234; double result; //对float、double、BigDecimal做加减乘除操作 result NumberUtil.add(n1, n2); log.info(String.valueOf(result)); result NumberUtil.sub(n1, n2); log.info(String.valueOf(result)); result NumberUtil.mul(n1, n2); log.info(String.valueOf(result)); result NumberUtil.div(n1, n2); log.info(String.valueOf(result)); //保留两位小数 BigDecimal roundNum NumberUtil.round(n1, 2); log.info(roundNum.toString()); String n3 1.234; //判断是否为数字、整数、浮点数 NumberUtil.isNumber(n3); NumberUtil.isInteger(n3); NumberUtil.isDouble(n3); }3.5 CollUtil集合操作工具集合操作的工具类定义了一些常用的集合操作。public void collUtil() { //数组转换为列表 String[] array new String[]{a, b, c, d, e}; ListString list CollUtil.newArrayList(array); //join数组转字符串时添加连接符 String joinStr CollUtil.join(list, ,); log.info(collUtil join:{}, joinStr); //将以连接符分隔的字符串再转换为列表 ListString splitList StrUtil.split(joinStr, ,); log.info(collUtil split:{}, splitList); //创建新的Map、Set、List HashMapObject, Object newMap CollUtil.newHashMap(); HashSetObject newHashSet CollUtil.newHashSet(); ArrayListObject newList CollUtil.newArrayList(); //判断列表是否为空 CollUtil.isEmpty(list); CollUtil.isNotEmpty(list); }3.6 SecureUtil加密解密工具public void secureUtil() { // 加密 String str 123456; String key secretKey; byte[] keyBytes Arrays.copyOf(key.getBytes(), 16); String encryptedStr SecureUtil.aes(keyBytes).encryptBase64(str); log.info(Encrypted string: {}, encryptedStr); // 解密 String decryptedStr SecureUtil.aes(keyBytes).decryptStr(encryptedStr); log.info(Decrypted string: {}, decryptedStr); }3.7 JSONUtil JSON处理工具JSON解析工具类针对JSONObject和JSONArray的快捷方法集合。public void jsonUtil() { Dog dog new Dog(); dog.setName(大黄); dog.setWeight(5.14f); //对象转化为JSON字符串 String jsonStr JSONUtil.parse(dog).toString(); log.info(jsonUtil parse:{}, jsonStr); //JSON字符串转化为对象 Dog dogBean JSONUtil.toBean(jsonStr, Dog.class); log.info(jsonUtil toBean:{}, dogBean); ListDog dogList new ArrayList(); dogList.add(dog); String jsonListStr JSONUtil.parse(dogList).toString(); //JSON字符串转化为列表 dogList JSONUtil.toList(new JSONArray(jsonListStr), Dog.class); log.info(jsonUtil toList:{}, dogList); }3.8 RandomUtil随机工具随机工具类RandomUtil主要针对JDK中的Random对象做封装。Test(description RandomUtil使用随机工具类) public void randomUtil() { int result; String uuid; //获得指定范围内的随机数 result RandomUtil.randomInt(1, 100); log.info(randomInt:{},StrUtil.toString(result)); //获得随机UUID uuid RandomUtil.randomUUID(); log.info(randomUUID:{}, uuid); }4. 实战Excel开发4.1 数据库表设计首先我们设计一个数据库表来存储用户信息CREATE TABLE cf_group_user ( id INT UNSIGNED AUTO_INCREMENT COMMENT id PRIMARY KEY, group_id INT UNSIGNED NOT NULL COMMENT 组织id, nickname CHAR(30) NOT NULL COMMENT 姓名, sex TINYINT UNSIGNED NOT NULL COMMENT 性别(1:男2:女), born_time DATETIME NOT NULL COMMENT 出生日期, photo VARCHAR(255) NOT NULL COMMENT 形象照片, home_address VARCHAR(255) NOT NULL COMMENT 家庭地址, mobile INT NOT NULL COMMENT 联系电话, post VARCHAR(255) NOT NULL COMMENT 职务信息 ) COMMENT 组织用户信息表 COLLATE utf8_unicode_ci; CREATE INDEX auth_id ON cf_group_user (auth_id); CREATE INDEX group_id ON cf_group_user (group_id); CREATE INDEX mobile ON cf_group_user (mobile);4.2 实体类设计对应的Java实体类如下/** * 组织用户信息表 * TableName cf_group_user */ TableName(value cf_group_user) Data public class GroupUser implements Serializable { /** * id */ TableId(type IdType.AUTO) private Integer id; /** * 组织id */ private Integer groupId; /** * 姓名 */ NotBlank(message 姓名不可为空) private String nickname; /** * 性别(0:默认1:男2:女) */ NotBlank(message 性别不可为空) private Integer sex; /** * 出生日期 */ NotBlank(message 出生日期不可为空) private Date bornTime; /** * 形象照片 */ NotBlank(message 形象照片不可为空) private String photo; /** * 家庭地址 */ NotBlank(message 家庭地址不可为空) private String homeAddress; /** * 联系电话 */ NotBlank(message 联系电话不可为空) private Integer mobile; /** * 认证信息 */ private String authId; /** * 职务信息 */ NotNull(message 职务不可为空) private String post; }4.3 Excel模板导出在工程中先确定使用的字段构建模板根据字段构建excel的模板。这里的示例如下//controller层 //返回模板 RequestMapping(/getExcelTemplate) public void getExcelTemplate(HttpServletResponse response) { groupUserService.getExcelTemplate(response); } //service层 void getExcelTemplate(HttpServletResponse response); //impl实现 Override public void getExcelTemplate(HttpServletResponse response) { try { // 1 读取对象 final ExcelReader reader ExcelUtil.getReader(ResourceUtil.getStream(templates/group.xlsx)); ListListObject lists reader.read(); ExcelWriter writer ExcelUtil.getWriter(true); writer.write(lists); response.setHeader(Content-disposition, attachment;filename URLEncoder.encode(group.xlsx, UTF-8)); response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); // 2 写出对象 ServletOutputStream outputStream response.getOutputStream(); // 通过IO写出我们的表格对象 writer.flush(outputStream, true); writer.close(); IoUtil.close(outputStream); } catch (IOException e) { log.error(EducationServiceImpl [export] 输出到响应流失败, e); throw new APIException(导出Excel异常); } }4.4 Excel数据导入导出这里我使用的是三层构建在controller 层中暴露接口进行调用所有的具体实现进行抽象。//导入信息 RequestMapping(/importStudent) public R importStudent(RequestParam MultipartFile file) { try { boolean userInfo groupUserService.getUserInfo(file); if(userInfo) return R.success(); } catch (IOException e) { log.error(EducationController [getEducation] 获取输入流失败, e); throw new APIException(获取输入流失败); } return R.error(); } //导出信息 RequestMapping(/export) public void export(RequestBody PageVo pageVo, HttpServletResponse response) { groupUserService.export(pageVo, response); } //service接口 void export(PageVo pageVo, HttpServletResponse response); boolean getUserInfo(MultipartFile file) throws IOException; //实现类 Override public void export(PageVo pageVo, HttpServletResponse response) { // 从数据库查出数据对象封装成map final ListMapString, Object educationList this.page(new Page(pageVo.getPage(), pageVo.getLimit()), Wrappers.lambdaQuery()).getRecords() .stream() // 封装成 Map 并且放入 List .map(item - { final MapString, Object map new LinkedHashMap(); // 错误这里需要根据表中字段别名进行命名 map.put(nickname, item.getNickname()); map.put(sex, item.getSex()); map.put(mobile, item.getMobile()); map.put(bornTime, item.getBornTime()); map.put(homeAddress, item.getHomeAddress()); map.put(post, item.getPost()); return map; }) .collect(Collectors.toList()); // 准备将数据集合封装成Excel对象 ExcelWriter writer ExcelUtil.getWriter(true); // 通过工具类创建writer并且进行别名 writer.addHeaderAlias(nickname, 姓名); writer.addHeaderAlias(sex, 性别( 0 表示男 1 表示 女)); writer.addHeaderAlias(mobile, 电话); writer.addHeaderAlias(bornTime, 出生日期); writer.addHeaderAlias(homeAddress, 家庭地址); writer.addHeaderAlias(post, 职位); // 准备将对象写入我们的 List writer.write(educationList, true); try { // 获取我们的输出流 final OutputStream output response.getOutputStream(); response.setHeader(Content-disposition, attachment;filename URLEncoder.encode(group.xlsx, UTF-8)); response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); writer.flush(output, true); writer.close(); // 这里可以自行关闭资源或者写一个关闭资源的工具类 IoUtil.close(output); } catch (IOException e) { log.error(EducationServiceImpl [export] 输出到响应流失败, e); throw new APIException(导出Excel异常); } } Override public boolean getUserInfo(MultipartFile file) throws IOException { ExcelReader reader ExcelUtil.getReader(file.getInputStream()); HashMapString, String head new HashMap(6); head.put(姓名,nickname); head.put(性别( 0 表示男 1 表示 女),sex); head.put(电话,mobile); head.put(出生日期, bornTime); head.put(家庭地址,homeAddress); head.put(职位,post); reader.setHeaderAlias(head); ListGroupUser read reader.read(0, 1, GroupUser.class); Group group groupService.getOne(new QueryWrapperGroup().eq(uid, UserConstant.USER_ID)); for (GroupUser user : read) { user.setGroupId(group.getId()); //TODO 默认图片 user.setPhoto(https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png); user.setStatus(1); user.setCreateTime(new DateTime()); if(!this.save(user))return false; } return true; }

更多文章