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封装 |
hutool-jwt | JSON Web Token (JWT)封装实现 |
pom.xml文件中引入依赖
hutool-all所有的组件都在
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.7.20version>
dependency>
Convert类可以说是一个工具方法类,里面封装了针对Java常见类型的转换,用于简化类型转换。Convert类中大部分方法为toXXX,参数为Object,可以实现将任意可能的类型转换为指定类型。同时支持第二个参数defaultValue用于在转换失败时返回一个默认值。
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);
String a = "2017-05-06";
Date value = Convert.toDate(a);
String[] a = {"a", "你", "好"};
List<String> list = Convert.toList(a);
通过Convert.convert(Class, Object)
方法可以将任意类型转换为指定类型,Hutool中预定义了许多类型转换,例如转换为URI、URL、Calendar等等,这些类型的转换都依托于ConverterRegistry
类。通过这个类和Converter
接口,我们可以自定义一些类型转换。
通过convert(TypeReference reference, Object value)
方法,自行new一个TypeReference
对象可以对嵌套泛型进行类型转换。例如,我们想转换一个对象为List
类型,此时传入的标准Class就无法满足要求,此时我们可以这样:
Object[] a = { "a", "你", "好", "", 1 };
List<String> list = Convert.convert(new TypeReference<List<String>>() {}, 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();
DateUtil.parse
方法会自动识别一些常用格式
// 自动识别的转换
String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr);
// 自定义日期格式化
String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr, "yyyy-MM-dd");
String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr);
//结果 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);
Date date = DateUtil.date();
//获得年的部分
DateUtil.year(date);
//获得月份,从0开始计数 0~11
DateUtil.month(date);
//获得月份枚举
DateUtil.monthEnum(date);
String dateStr = "2017-03-01 22:33:23";
Date date = DateUtil.parse(dateStr);
//一天的开始,结果:2017-03-01 00:00:00
Date beginOfDay = DateUtil.beginOfDay(date);
//一天的结束,结果:2017-03-01 23:59:59
Date endOfDay = DateUtil.endOfDay(date);
......
String dateStr = "2017-03-01 22:33:23";
Date date = DateUtil.parse(dateStr);
//结果:2017-03-03 22:33:23
Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);
//常用偏移,结果:2017-03-04 22:33:23
DateTime newDate2 = DateUtil.offsetDay(date, 3);
//常用偏移,结果:2017-03-01 19:33:23
DateTime newDate3 = DateUtil.offsetHour(date, -3);
简化的偏移方法(例如昨天、上周、上个月等):
//昨天
DateUtil.yesterday()
//明天
DateUtil.tomorrow()
//上周
DateUtil.lastWeek()
//下周
DateUtil.nextWeek()
//上个月
DateUtil.lastMonth()
//下个月
DateUtil.nextMonth()
//年龄
DateUtil.ageOfNow("1990-01-30");
//是否闰年
DateUtil.isLeapYear(2017);
BufferedInputStream in = FileUtil.getInputStream("d:/test.txt");
BufferedOutputStream out = FileUtil.getOutputStream("d:/test2.txt");
long copySize = IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE);
// IoUtil.getReader:将InputStream转为BufferedReader用于读取字符流,它是部分readXXX方法的基础。
BufferedInputStream in = FileUtil.getInputStream("d:/test.txt");
BufferedReader reader = IoUtil.getReader(in, Charsets.UTF_8);
// IoUtil.getWriter:将OutputStream转为OutputStreamWriter用于写入字符流,它是部分writeXXX的基础
BufferedOutputStream out = FileUtil.getOutputStream("d:/test2.txt");
OutputStreamWriter writer = IoUtil.getWriter(out, Charsets.UTF_8);
读取流中的内容总结下来,可以分为read方法和readXXX方法。
read
方法有诸多的重载方法,根据参数不同,可以读取不同对象中的内容,这包括:
InputStream
Reader
这三个重载大部分返回String字符串,为字符流读取提供极大便利。
BufferedInputStream in = FileUtil.getInputStream("d:/test.txt");
String read = IoUtil.read(in, Charsets.UTF_8);
System.out.println(read);
以下写法过于复杂,只是为了演示效果
BufferedInputStream in = FileUtil.getInputStream("d:/test.txt");
BufferedReader reader = IoUtil.getReader(in, Charsets.UTF_8);
String read = IoUtil.read(reader, true);
System.out.println(read);
控制台输出
this is a file !
世界
hello world
readXXX
方法主要针对返回值做一些处理,例如:
readBytes
返回byte数组(读取图片等)readHex
读取16进制字符串readObj
读取序列化对象(反序列化)readLines
按行读取返回byte数组
// 功能示例,拷贝文件(只为演示效果)
BufferedInputStream inputStream = FileUtil.getInputStream("E:/下载/a.jpg");
byte[] bytes = IoUtil.readBytes(inputStream);
BufferedOutputStream stream = FileUtil.getOutputStream("D:/a.jpg");
IoUtil.write(stream, true, bytes);
readLines后返回一个集合,每一行数据是集合中一个元素
BufferedInputStream inputStream = FileUtil.getInputStream("d:/test.txt");
ArrayList<String> strings = IoUtil.readLines(inputStream, Charsets.UTF_8, new ArrayList<>());
System.out.println(strings);
toStream
方法则是将某些对象转换为流对象
String
转换为ByteArrayInputStream
File
转换为FileInputStream
ls
列出目录和文件touch
创建文件,如果父目录不存在也自动创建mkdir
创建目录,会递归创建每层目录del
删除文件或目录(递归删除,不判断是否为空),这个方法相当于Linux的delete命令copy
拷贝文件或目录// 创建文件,如果父目录不存在也自动创建
File touch = FileUtil.touch("D:/file2/a.txt");
System.out.println(touch.getAbsolutePath());
File mkdir = FileUtil.mkdir("D:/file2");
System.out.println(mkdir.getAbsolutePath());
copy文件,源文件或目标文件不存在时,会自动创建文件
// param1: 源文件 param2: 目标文件 param3: 是否复写
File copy = FileUtil.copy("D:/test.txt", "D:/file2/test2.txt", true);
System.out.println(copy.getAbsolutePath());
在JDK中,同样有一个FileReader类,但是并不如想象中的那样好用,于是Hutool便提供了更加便捷FileReader类。
FileReader提供了以下方法来快速读取文件内容:
readBytes
返回字节数组readString
返回字符串//默认UTF-8编码,可以在构造中传入第二个参数做为编码
FileReader reader = new FileReader("D:/test.txt", Charsets.UTF_8);
String result = fileReader.readString();
readLines
返回字符串集合FileReader reader = new FileReader("D:/test.txt", Charsets.UTF_8);
List<String> s = reader.readLines();
同时,此类还提供了以下方法用于转换为流或者BufferedReader:
getReader
FileReader reader = new FileReader("D:/test.txt", Charsets.UTF_8);
BufferedReader bfReader = reader.getReader();
FileReader reader = new FileReader("D:/test.txt", Charsets.UTF_8);
BufferedInputStream stream = reader.getInputStream();
FileWriter writer = new FileWriter("D:/test.txt");
writer.write("test");
写入文件分为追加模式和覆盖模式两类,追加模式可以用append
方法,覆盖模式可以用write
方法,同时也提供了一个write方法,第二个参数是可选覆盖模式。
追加模式
FileWriter writer = new FileWriter("D:/test.txt", Charsets.UTF_8);
writer.write("test", true);
// 或者
writer.append("aaabbb");
同样,此类提供了:
getOutputStream
getWriter
getPrintWriter
就是给定一些字符串,如果一旦有空的就返回true,常用于判断好多字段是否有空的(例如web表单数据)。
这两个方法的区别是hasEmpty
只判断是否为null或者空字符串(""),hasBlank
则会把不可见字符也算做空,isEmpty
和isBlank
同理。
boolean aa = StrUtil.hasEmpty("", "aa");
System.out.println(aa); // true
这两个是去掉字符串的前缀后缀的,例如去个文件名的扩展名啥。
去掉前缀就是把最前面符合的字符去掉
String abc = StrUtil.removePrefix("abc.abc.jpg", "abc.");
System.out.println(abc); // abc.jpg
去掉后缀同理就是把最后面符合的字符去掉
String abc = StrUtil.removeSuffix("afdsfs.jpg.jpg", ".jpg");
System.out.println(abc); // afdsfs.jpg
还有忽略大小写的removePrefixIgnoreCase
和removeSuffixIgnoreCase
都比较实用
对用过slf4j的应该很友好0.0
String template = "hell{} worl{}";
String str = StrUtil.format(template, "o", "d"); //str -> hello world
// 判断空
int[] a = {};
int[] b = null;
ArrayUtil.isEmpty(a);
ArrayUtil.isEmpty(b);
// 判断非空
int[] a = {1,2};
ArrayUtil.isNotEmpty(a);
UUID全称通用唯一识别码(universally unique identifier),JDK通过java.util.UUID
提供了 Leach-Salz 变体的封装。在Hutool中,生成一个UUID字符串方法如下:
//生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
String uuid = IdUtil.randomUUID();
//生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42
String simpleUUID = IdUtil.simpleUUID();
ZipUtil就是针对java.util.zip
做工具化封装,使压缩解压操作可以一个方法搞定,并且自动处理文件和目录的问题,不再需要用户判断,压缩后的文件也会自动创建文件,自动创建父目录,大大简化的压缩解压的复杂度。
ZipUtil.zip
方法提供一系列的重载方法
文件或目录必须存在,否则异常
//将test目录下的所有文件目录打包到d:/test.zip
ZipUtil.zip("d:/test");
源文件或目录必须 存在,否则异常
//将aaa目录下的所有文件目录打包到d:/bbb/目录下的aaa.zip文件中
// 此处第二个参数必须为文件,不能为目录
ZipUtil.zip("d:/aaa", "d:/bbb/aaa.zip");
源文件或目录必须存在
//将aaa目录以及其目录下的所有文件目录打包到d:/bbb/目录下的ccc.zip文件中
// true: 带目录
// false: 不带目录 (默认值)
ZipUtil.zip("d:/aaa", "d:/bbb/ccc.zip", true);
ZipUtil.zip(FileUtil.file("d:/ccc/ccc.zip"), false,
FileUtil.file("d:/aaa"),
FileUtil.file("d:/bbb")
);
注意点:
假如上面代码块中,aaa和bbb目录下的文件重名了,并且压缩时选择了false(不带目录),由于文件重名会导致报错,同样的会抛出异常;但是压缩文件还是会生成,只是压缩包中只存在一个文件
ZipUtil.unzip
解压。同样有几个重载,满足不同需求。
源文件或目录必须存在,否则异常
//将test.zip解压到e:\\aaa目录下,返回解压到的目录
File unzip = ZipUtil.unzip("E:/aaa/test.zip", "e:/aaa");
java.lang.IllegalArgumentException:MALFORMED
错误基本是因为编码问题,Hutool默认使用UTF-8编码,自定义为其他编码即可(一般为GBK)。
File unzip = ZipUtil.unzip("E:/aaa/test.zip", "e:/aaa", CharsetUtil.CHARSET_GBK);
Hutool-http的核心集中在两个类:
multipart/form-data
表单,不必单做做操作。针对最为常用的GET和POST请求,HttpUtil封装了两个方法,
HttpUtil.get
HttpUtil.post
这两个方法用于请求普通页面,然后返回页面内容的字符串,同时提供一些重载方法用于指定请求参数(指定参数支持File对象,可实现文件上传,当然仅仅针对POST请求)。
// 最简单的HTTP请求,可以自动通过header等信息判断编码,不区分HTTP和HTTPS
String result1 = HttpUtil.get("https://www.baidu.com");
// 当无法识别页面编码的时候,可以自定义请求页面的编码
String result2 = HttpUtil.get("https://www.baidu.com", CharsetUtil.CHARSET_UTF_8);
//可以单独传入http参数,这样参数会自动做URL编码,拼接在URL中
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result3 = HttpUtil.get("https://www.baidu.com", paramMap);
//POST请求
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result = HttpUtil.post(url, paramMap);
HashMap<String, Object> paramMap = new HashMap<>();
//文件上传只需将参数中的键指定(默认file),值设为文件对象即可,对于使用者来说,文件上传与普通表单提交并无区别
paramMap.put("file", FileUtil.file("D:/face.jpg"));
String result= HttpUtil.post("https://www.baidu.com", paramMap);
HttpUtil.downloadFile方法
String fileUrl = "http://xxxisos/x86_64/CentOS-8.4.2105-x86_64-dvd1.iso";
//将文件下载后保存在E盘,返回结果为下载文件大小
long size = HttpUtil.downloadFile(fileUrl, FileUtil.file("e:/"));
System.out.println("Download size: " + size);
HttpUtil.download方法
String fileUrl = "http://xxx/isos/x86_64/CentOS-8.4.2105-x86_64-dvd1.iso";
long size = HttpUtil.download(fileUrl, response.getOutputStream(), true);
System.out.println("Download size: " + size);
//链式构建请求
String result2 = HttpRequest.post(url)
.header(Header.USER_AGENT, "Hutool http")//头信息,多个头信息多次调用此方法即可
.form(paramMap)//表单内容
.timeout(20000)//超时,毫秒
.execute().body();
通过链式构建请求,我们可以很方便的指定Http头信息和表单信息,最后调用execute方法即可执行请求,返回HttpResponse对象。HttpResponse包含了服务器响应的一些信息,包括响应的内容和响应的头信息。通过调用body方法即可获取响应内容
String json = "......";
// 将json参数放入请求体中
String result2 = HttpRequest.post(url)
.body(json)
.execute().body();
HttpRequest request = HttpUtil.createRequest(Method.GET, "http://xxx/xxxxxx");
HttpRequest request = HttpUtil.createRequest(Method.DELETE, "http://xxx/xxxxxx");
HttpRequest request = HttpUtil.createRequest(Method.POST, "http://xxx/xxxxxx");
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
// 生成指定url对应的二维码到文件,宽和高都是300像素
QrCodeUtil.generate("https://hutool.cn/", 300, 300, FileUtil.file("d:/qrcode.jpg"));
通过QrConfig
可以自定义二维码的生成参数,例如长、宽、二维码的颜色、背景颜色、边距等参数,使用方法如下:
QrConfig config = new QrConfig(300, 300);
// 设置边距,既二维码和背景之间的边距
config.setMargin(2);
// 设置前景色,既二维码颜色(青色)
config.setForeColor(Color.blue);
// 设置背景色(灰色)
config.setBackColor(Color.lightGray);
// 生成二维码到文件,也可以到流
QrCodeUtil.generate("http://hutool.cn/", config, FileUtil.file("d:/qrcode.jpg"));
QrConfig config = new QrConfig(300, 300);
// 设置边距,既二维码和背景之间的边距
config.setMargin(2);
// 设置前景色,既二维码颜色(青色)
config.setForeColor(Color.blue);
// 设置背景色(灰色)
config.setBackColor(Color.lightGray);
// 设置logo
config.setImg("E:/下载/java.jpg");
QrCodeUtil.generate(
"http://hutool.cn/", //二维码内容
config,
FileUtil.file("D:/qrcodeWithLogo.jpg")//写出到的文件,或者写入流
);
很多时候,二维码无法识别,这时就要调整纠错级别。纠错级别使用zxing的ErrorCorrectionLevel
枚举封装,包括:L、M、Q、H几个参数,由低到高。低级别的像素块更大,可以远距离识别,但是遮挡就会造成无法识别。高级别则相反,像素块小,允许遮挡一定范围,但是像素块更密集。
QrConfig config = new QrConfig();
// 高纠错级别
config.setErrorCorrection(ErrorCorrectionLevel.H);
QrCodeUtil.generate("https://hutool.cn/", config, FileUtil.file("e:/qrcodeCustom.jpg"));
// decode -> "http://hutool.cn/" 获取到url
String decode = QrCodeUtil.decode(FileUtil.file("d:/qrcode.jpg"));