这几天在微信公众号看到有号主推荐一个Java工具类库,当时没有在意,觉得已经有Java的common
包了,还有Guava
类库,已经够用了。但是今天又来看了一遍,觉得这个类库别有一番风味。
Github上关于Hutool介绍:
“Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以"甜甜的"。
Hutool中的工具方法来自于每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
Hutool是项目中"util"包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
”
为什么Hutool会诞生,Hutool的优势在哪,我们来看看官方介绍。
“Hutool的目标是使用一个工具方法代替一段复杂代码,从而最大限度的避免“复制粘贴”代码的问题,彻底改变我们写代码的方式。
以计算MD5为例:
【以前】打开搜索引擎 -> 搜“Java MD5加密” -> 打开某篇博客-> 复制粘贴 -> 改改好用
【现在】引入Hutool ->
SecureUtil.md5()
Hutool的存在就是为了减少代码搜索成本,避免网络上参差不齐的代码出现导致的bug。
”
官方文档网址:
“https://www.hutool.cn/docs/#/
”
Hutool主要组件:
模块 | 介绍 |
---|---|
hutool-aop | JDK动态代理封装,提供非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 | 脚本执行封装,例如Javascript |
hutool-setting | 功能更强大的Setting配置文件和Properties封装 |
hutool-system | 系统参数调用封装(JVM信息等) |
hutool-json | JSON实现 |
hutool-captcha | 图片验证码实现 |
hutool-poi | 针对POI中Excel和Word的封装 |
hutool-socket | 基于Java的NIO和AIO的Socket封装 |
Maven导入
cn.hutool
hutool-all
5.4.2
来介绍几个我用过的方法。
在Java开发中我们要面对各种各样的类型转换问题,尤其是从命令行获取的用户参数、从HttpRequest获取的Parameter等等,这些参数类型多种多样,我们怎么去转换他们呢?常用的办法是先整成String,然后调用XXX.parseXXX
方法,还要承受转换失败的风险,不得不加一层try...catch
,这个小小的过程混迹在业务代码中会显得非常难看和臃肿。
int a = 1;
//aStr为"1"
String aStr = Convert.toStr(a);
long[] b = {1,2,3,4,5};
//bStr为:"[1, 2, 3, 4, 5]"
String bStr = Convert.toStr(b);
将int
转换String
,只要Convert.toStr(a)
。不用去try catch了。
String[] b = { "1", "2", "3", "4" };
//结果为Integer数组
Integer[] intArray = Convert.toIntArray(b);
long[] c = {1,2,3,4,5};
//结果为Integer数组
Integer[] intArray2 = Convert.toIntArray(c);
String a = "2017-05-06";
Date value = Convert.toDate(a);
将String
转换成Date
。跟以前的DateUtils
工具类比,这个比较简单吧。
String转换成16进制
String a = "我是一个小小的可爱的字符串";
//结果:"e68891e698afe4b880e4b8aae5b08fe5b08fe79a84e58fafe788b1e79a84e5ad97e7aca6e4b8b2"
String hex = Convert.toHex(a, CharsetUtil.CHARSET_UTF_8);
16进制转换成String
String hex = "e68891e698afe4b880e4b8aae5b08fe5b08fe79a84e58fafe788b1e79a84e5ad97e7aca6e4b8b2";
//结果为:"我是一个小小的可爱的字符串"
String raw = Convert.hexStrToStr(hex, CharsetUtil.CHARSET_UTF_8);
//注意:在4.1.11之后hexStrToStr将改名为hexToStr
String raw = Convert.hexToStr(hex, CharsetUtil.CHARSET_UTF_8);
在接收表单的时候,我们常常被中文乱码所困扰,其实大多数原因是使用了不正确的编码方式解码了数据。于是Convert.convertCharset
方法便派上用场了,它可以把乱码转为正确的编码方式:
String a = "我不是乱码";
//转换后result为乱码
String result = Convert.convertCharset(a, CharsetUtil.UTF_8, CharsetUtil.ISO_8859_1);
String raw = Convert.convertCharset(result, CharsetUtil.ISO_8859_1, "UTF-8");
Assert.assertEquals(raw, a);
double a = 67556.32;
//结果为:"陆万柒仟伍佰伍拾陆元叁角贰分"
String digitUppercase = Convert.digitToChinese(a);
这个功能不错。
//当前时间
Date date = DateUtil.date();
//当前时间
Date date2 = DateUtil.date(Calendar.getInstance());
//当前时间,可以用于将时间戳转换成日期
Date date3 = DateUtil.date(System.currentTimeMillis());
//当前时间字符串,格式:yyyy-MM-dd HH:mm:ss
String now = DateUtil.now();
//当前日期字符串,格式:yyyy-MM-dd
String today= DateUtil.today();
当然也可以自定义格式转换
String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr, "yyyy-MM-dd");
//结果 2017/03/01
String format = DateUtil.format(date, "yyyy/MM/dd");
//常用格式的格式化,结果:2017-03-01
String formatDate = DateUtil.formatDate(date);
//结果:2017-03-01 00:00:00
String formatDateTime = DateUtil.formatDateTime(date);
//结果:00:00:00
String formatTime = DateUtil.formatTime(date);
有时候需要易读的时间差,比如XX天XX小时XX分XX秒
//Level.MINUTE表示精确到分
String formatBetween = DateUtil.formatBetween(between, Level.MINUTE);
//输出:31天1小时
Console.log(formatBetween);
用于计算某段代码运行时间
TimeInterval timer = DateUtil.timer();
//---------------------------------
//-------这是执行过程
//---------------------------------
timer.interval();//花费毫秒数
timer.intervalRestart();//返回花费时间,并重置开始时间
timer.intervalMinute();//花费分钟数
这个功能有趣
// "摩羯座"
String zodiac = DateUtil.getZodiac(Month.JANUARY.getValue(), 19);
// "狗"
String chineseZodiac = DateUtil.getChineseZodiac(1994);
还可以计算年龄,是否闰年等功能
//年龄
DateUtil.ageOfNow("1990-01-30");
//是否闰年
DateUtil.isLeapYear(2017);
还可以获取农历日期哦
//通过农历构建
ChineseDate chineseDate = new ChineseDate(1992,12,14);
//通过公历构建
ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate("1993-01-06"));
具体方法如下
// 一月
date.getChineseMonth();
// 正月
date.getChineseMonthName();
// 初一
date.getChineseDay();
// 庚子
date.getCyclical();
// 生肖:鼠
date.getChineseZodiac();
// 传统节日(部分支持,逗号分隔):春节
date.getFestivals();
// 庚子鼠年 正月初一
date.toString();
针对JDK8+日期API的封装,此工具类的功能包括LocalDateTime
和LocalDate
的解析、格式化、转换等操作。
将A文件拷贝到B文件
BufferedInputStream in = FileUtil.getInputStream("d:/test.txt");
BufferedOutputStream out = FileUtil.getOutputStream("d:/test2.txt");
long copySize = IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE);
很多时候我们需要监听一个文件的变化或者目录的变动,包括文件的创建、修改、删除,以及目录下文件的创建、修改和删除,在JDK7前我们只能靠轮询方式遍历目录或者定时检查文件的修改事件,这样效率非常低,性能也很差。因此在JDK7中引入了WatchService
。不过考虑到其API并不友好,于是Hutool便针对其做了简化封装,使监听更简单,也提供了更好的功能。
WatchMonitor
提供的事件有:
ENTRY_MODIFY
文件修改的事件
ENTRY_CREATE
文件或目录创建的事件
ENTRY_DELETE
文件或目录删除的事件
OVERFLOW
丢失的事件
具体使用可以看看官方使用文档。
还有更多的文件读取功能。
我来列举几个工具的使用
主要用来:
获取方法的参数和返回值类型(包括Type和Class)
获取泛型参数类型(包括对象的泛型参数或集合元素的泛型类型)
获取方法参数类型
Method method = ReflectUtil.getMethod(TestClass.class, "intTest", Integer.class);
Type type = TypeUtil.getParamType(method, 0);
// 结果:Integer.class
获取方法返回值的类型
Method method = ReflectUtil.getMethod(TestClass.class, "getList");
Type type = TypeUtil.getReturnType(method);
// 结果:java.util.List
IdcardUtil
现在支持大陆15位、18位身份证,港澳台10位身份证。
工具中主要的方法包括:
isValidCard
验证身份证是否合法
convert15To18
身份证15位转18位
getBirthByIdCard
获取生日
getAgeByIdCard
获取年龄
getYearByIdCard
获取生日年
getMonthByIdCard
获取生日月
getDayByIdCard
获取生日天
getGenderByIdCard
获取性别
getProvinceByIdCard
获取省份
代码举例
String ID_18 = "321083197812162119";
String ID_15 = "150102880730303";
//是否有效
boolean valid = IdcardUtil.isValidCard(ID_18);
boolean valid15 = IdcardUtil.isValidCard(ID_15);
//转换
String convert15To18 = IdcardUtil.convert15To18(ID_15);
Assert.assertEquals(convert15To18, "150102198807303035");
//年龄
DateTime date = DateUtil.parse("2017-04-10");
int age = IdcardUtil.getAgeByIdCard(ID_18, date);
Assert.assertEquals(age, 38);
int age2 = IdcardUtil.getAgeByIdCard(ID_15, date);
Assert.assertEquals(age2, 28);
//生日
String birth = IdcardUtil.getBirthByIdCard(ID_18);
Assert.assertEquals(birth, "19781216");
String birth2 = IdcardUtil.getBirthByIdCard(ID_15);
Assert.assertEquals(birth2, "19880730");
//省份
String province = IdcardUtil.getProvinceByIdCard(ID_18);
Assert.assertEquals(province, "江苏");
String province2 = IdcardUtil.getProvinceByIdCard(ID_15);
Assert.assertEquals(province2, "内蒙古");
可以将Map填充到Bean里面
@Data
public class Person{
private String name;
private int age;
}
HashMap map = CollUtil.newHashMap();
map.put("name", "Joe");
map.put("age", 12);
SubPerson person = BeanUtil.fillBeanWithMap(map, new Person(), false);
还可以将Bean转换成Map
// Bean转换为Map
Map map = BeanUtil.beanToMap(person);
// 返回"sub名字"
map.get("SubName")
BeanUtil.copyProperties(studentVo,studentDto,true, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
还可以自定义属性的拷贝。
关于Bean与Bean之间的拷贝。还可以看看我的这篇文章:
“都2020年了还在用BeanUtils.copyProperties进行属性拷贝?MapStruct了解下
”
举个例子。我有一个用户表,这个表根据用户名被Hash到不同的数据库实例上,我要找出这些用户中最热门的5个,怎么做?我是这么做的:
在每个数据库实例上找出最热门的5个
将每个数据库实例上的这5条数据按照热门程度排序,最后取出前5条
这个过程看似简单,但是你应用服务器上的代码要写不少。首先需要Query N个列表,加入到一个新列表中,排序,再取前5。这个过程不但代码繁琐,而且牵涉到多个列表,非常浪费空间。
于是,BoundedPriorityQueue
应运而生。
示例代码如下:
这个有关于排列、组合的计算
排列
arrangementCount
计算排列数
arrangementSelect
排列选择(从列表中选择n个排列)
组合
combinationCount
计算组合数,即C(n, m) = n!/((n-m)! * m!)
combinationSelect
组合选择(从列表中选择n个组合)
这个功能不错,可以用于并发测试。
ConcurrencyTester tester = ThreadUtil.concurrencyTest(100, () -> {
// 测试的逻辑内容
long delay = RandomUtil.randomLong(100, 1000);
ThreadUtil.sleep(delay);
Console.log("{} test finished, delay: {}", Thread.currentThread().getName(), delay);
});
// 获取总的执行时间,单位毫秒
Console.log(tester.getInterval());
还有一些缓存工具类。相比传统的集合,Hutool缓存类更丰富,可以设置存活时间,还有不同的存活方式。
加密工具也可以了解下。
这个功能非常不错,Java中定时任务使用的最多的就是quartz了,但是这个框架太过庞大,而且我也不需要用到这么多东西,使用方法也是比较复杂(当然可以使用Spring的注解完成)。
用过Linux的crontab的人都知道,使用其定时的表达式可以非常灵活的定义定时任务的时间以及频率(Linux的crontab精确到分,而Quartz的精确到秒,不过对我来说精确到分已经够用了,精确到秒的可以使用Timer可以搞定),然后就是crontab的那个迷人的配置文件,可以把定时任务很清晰的罗列出来,这个我也是比较喜欢的。于是Hutool-cron诞生。
来看看如何使用
对于Maven项目,首先在src/main/resources/config
下放入cron.setting文件(默认是这个路径的这个文件),然后在文件中放入定时规则,规则如下:
# 我是注释
[com.company.aaa.job]
TestJob.run = */10 * * * *
TestJob2.run = */10 * * * *Copy to clipboardErrorCopied
中括号表示分组,也表示需要执行的类或对象方法所在包的名字,这种写法有利于区分不同业务的定时任务。
TestJob.run
表示需要执行的类名和方法名(通过反射调用,不支持Spring和任何框架的依赖注入),*/10 * * * *
表示定时任务表达式,此处表示每10分钟执行一次,以上配置等同于:
com.company.aaa.job.TestJob.run = */10 * * * *
com.company.aaa.job.TestJob2.run = */10 * * * *
然后启动;
CronUtil.start();
这个启动方法加在需要触发的地方,比如随系统启动,可以加在main方法中。
当然也可以自定义定时任务
CronUtil.schedule("*/2 * * * * *", new Task() {
@Override
public void execute() {
Console.log("Task excuted.");
}
});
// 支持秒级别定时任务
CronUtil.setMatchSecond(true);
CronUtil.start();
怎么样,这款工具对你有没有帮助呢。
我写出这样干净的代码,老板直夸我
云南丽江旅游攻略
使用ThreadLocal怕内存泄漏?
Java进阶之路思维导图
程序员必看书籍推荐
3万字的Java后端面试总结(附PDF)
扫码二维码,获取更多精彩。或微信搜Lvshen_9,可后台回复获取资料
1.回复"java" 获取java电子书;
2.回复"python"获取python电子书;
3.回复"算法"获取算法电子书;
4.回复"大数据"获取大数据电子书;
5.回复"spring"获取SpringBoot的学习视频。
6.回复"面试"获取一线大厂面试资料
7.回复"进阶之路"获取Java进阶之路的思维导图
8.回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)
9.回复"总结"获取Java后端面试经验总结PDF版
10.回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)
11.回复"并发导图"获取Java并发编程思维导图(xmind终极版)
另:点击【我的福利】有更多惊喜哦。