乐趣区

关于java:干掉复杂的工具类国产Java工具类库-Hutool-很香

Hutool 大家曾经比拟相熟了,这是一个超全的 Java 工具库,深受国内开发者的青睐。

我之前其实是不太喜爱应用这种性能太多的工具类的,也比拟放心稳定性和安全性,前面缓缓承受了就感觉其实也还好。而且,咱们还能够按需只引入本人须要的功能模块,绝对也比拟灵便。

Hutool 的官网文档介绍的曾经比拟清晰了,奈何其提供的性能切实太多,我这里列举一些我集体感觉比拟实用的性能,供大家学习参考。

Hutool 介绍

Hutool 真心是一个不错的国产 Java 工具类库,性能全面,对文件、流、加密解密、转码、正则、线程、XML 等 JDK 办法进行了封装,开箱即用!

官网是这样介绍 Hutool 的:

Hutool 蕴含的组件以及组件提供的性能如下表所示:

你能够依据我的项目需要对每个模块独自引入,也能够通过引入 hutool-all 形式引入所有模块。不过,还是不倡议引入所有模块,因为绝大部分性能我的项目可能都用不上,倡议只引入你须要的模块。

另外,Hutool 也有一个比拟显著的毛病,很多性能实现的比较简单比方图片验证码、Excel 工具类,很可能无奈满足我的项目的理论需要。像这样状况,还是倡议你抉择在某一方面更优良的工具库比方 Excel 工具库 MyExcel、EasyExcel、图片解决库 Imglib。

Hutool 实战

引入依赖

Maven 仓库地址:https://mvnrepository.com/artifact/cn.hutool

这里为了不便,咱们间接引入所有模块,理论我的项目中还是倡议只引入本人须要的模块。

Maven:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>

Gradle:

implementation 'cn.hutool:hutool-all:5.8.16'

性能演示

Hutool 提供的性能切实太多,这里只列举一些我集体感觉比拟实用的性能,供大家学习参考。

类型转换

Convert 类封装了针对 Java 常见类型的转换。

long[] b = {1,2,3,4,5};
String bStr = Convert.toStr(b);//"[1, 2, 3, 4, 5]"

double a = 67556.32;
String digitUppercase = Convert.digitToChinese(a);//"陆万柒仟伍佰伍拾陆元叁角贰分"

邮件

在 Java 中发送邮件次要品依附 javax.mail 包,然而因为应用比拟繁琐,因而 Hutool 针对其做了封装。

在 classpath(在规范 Maven 我的项目中为 src/main/resources)的 config 目录下新建mail.setting 文件,残缺配置如下(邮件服务器必须反对并关上 SMTP 协定):

# 邮件服务器的 SMTP 地址,可选,默认为 smtp.< 发件人邮箱后缀 >
host = smtp.yeah.net
# 邮件服务器的 SMTP 端口,可选,默认 25
port = 25
# 发件人(必须正确,否则发送失败)from = hutool@yeah.net
# 用户名,默认为发件人邮箱前缀
user = hutool
# 明码(留神,某些邮箱须要为 SMTP 服务独自设置受权码,详情查看相干帮忙)pass = q1w2e3

发送邮件非常简单:

MailUtil.send("hutool@foxmail.com", "测试", "邮件来自 Hutool 测试", false);

反对群发:

ArrayList<String> tos = CollUtil.newArrayList(
    "person1@bbb.com", 
    "person2@bbb.com", 
    "person3@bbb.com", 
    "person4@bbb.com");

MailUtil.send(tos, "测试", "邮件来自 Hutool 群发测试", false);

反对增加一个或者多个附件:

MailUtil.send("hutool@foxmail.com", "测试", "<h1> 邮件来自 Hutool 测试 </h1>", true, FileUtil.file("d:/aaa.xml"));

除了应用配置文件定义全局账号以外,MailUtil.send办法同时提供重载办法能够传入一个 MailAccount 对象,这个对象为一个一般 Bean,记录了邮件服务器信息。

MailAccount account = new MailAccount();
account.setHost("smtp.yeah.net");
account.setPort("25");
account.setAuth(true);
account.setFrom("hutool@yeah.net");
account.setUser("hutool");
account.setPass("q1w2e3");

MailUtil.send(account, CollUtil.newArrayList("hutool@foxmail.com"), "测试", "邮件来自 Hutool 测试", false);

惟一 ID

在分布式环境中,惟一 ID 生成利用非常宽泛,生成办法也多种多样,Hutool 针对一些罕用生成策略做了简略封装。

Hutool 提供的惟一 ID 生成器的工具类,涵盖了:

  • UUID
  • ObjectId(MongoDB)
  • Snowflake(Twitter)

拿 UUID 举例!

Hutool 重写 java.util.UUID 的逻辑,对应类为 cn.hutool.core.lang.UUID,使生成不带 - 的 UUID 字符串不再须要做字符替换, 性能晋升一倍左右

// 生成的 UUID 是带 - 的字符串,相似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
String uuid = IdUtil.randomUUID();

// 生成的是不带 - 的字符串,相似于:b17f24ff026d40949c85a24f4f375d42
String simpleUUID = IdUtil.simpleUUID();

HTTP 申请工具类

针对最为罕用的 GET 和 POST 申请,HttpUtil 封装了两个办法,

  • HttpUtil.get
  • HttpUtil.post

GET 申请:

// 最简略的 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("https://www.baidu.com", 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);

缓存

Hutool 提供了常见的几种缓存策略的实现:

  1. FIFO(first in first out):先进先出策略。
  2. LFU(least frequently used):起码使用率策略。
  3. LRU(least recently used):最近最久未应用策略。
  4. Timed:定时策略。
  5. Weak:弱援用策略。

并且,Hutool 还反对将小文件以 byte[] 的模式缓存到内容中,缩小文件的拜访,以解决频繁读取文件引起的性能问题。

FIFO(first in first out) 策略缓存应用:

Cache<String,String> fifoCache = CacheUtil.newFIFOCache(3);

// 退出元素,每个元素能够设置其过期时长,DateUnit.SECOND.getMillis()代表每秒对应的毫秒数,在此为 3 秒
fifoCache.put("key1", "value1", DateUnit.SECOND.getMillis() * 3);
fifoCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
fifoCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);

// 因为缓存容量只有 3,当退出第四个元素的时候,依据 FIFO 规定,最先放入的对象将被移除
fifoCache.put("key4", "value4", DateUnit.SECOND.getMillis() * 3);

//value1 为 null
String value1 = fifoCache.get("key1");

控制台打印封装

个别状况下,咱们打印信息到控制台小伙伴们应该再相熟不过了!

System.out.println("Hello World");

然而,这种形式不满足很多场景的须要:

  1. 不反对参数,对象打印须要拼接字符串
  2. 不能间接打印数组,须要手动调用Arrays.toString

为此,Hutool 封装了 Console 对象。

Console对象的应用更加相似于 Javascript 的 console.log() 办法,这也是借鉴了 JS 的一个语法糖。

String[] a = {"java", "c++", "c"};
Console.log(a);// 控制台输入:[java, c++, c]

Console.log("This is Console log for {}.", "test");// 控制台输入:This is Console log for test.

加密解密

Hutool 反对对称加密、非对称加密、摘要加密、音讯认证码算法、国密。

这里以国密为例,Hutool 针对 Bouncy Castle 做了简化包装,用于实现国密算法中的 SM2、SM3、SM4。

国密算法须要引入 Bouncy Castle 库的依赖:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15to18</artifactId>
    <version>1.69</version>
</dependency>

SM2 应用自定义密钥对加密或解密

String text = "JavaGuide: 一份涵盖大部分 Java 程序员所须要把握的外围常识。筹备 Java 面试,首选 JavaGuide!";
System.out.println("原文:" + text);

KeyPair pair = SecureUtil.generateKeyPair("SM2");
// 公钥
byte[] privateKey = pair.getPrivate().getEncoded();
// 私钥
byte[] publicKey = pair.getPublic().getEncoded();

SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
// 公钥加密,私钥解密
String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
System.out.println("加密后:" + encryptStr);

String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
System.out.println("解密后:" + decryptStr);

SM2 签名和验签

// 加签
String sign = sm2.signHex(HexUtil.encodeHexStr(text));
System.out.println("签名:" + sign);
// 验签
boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(text), sign);
System.out.println("验签:" + verify);

输入后果:

线程池

Hutool 反对应用建造者的模式创立自定义线程池,这样看着更加清晰。

private static ExecutorService pool = ExecutorBuilder.create()
              .setCorePoolSize(10)// 初始池大小
              .setMaxPoolSize(20) // 最大池大小
              .setWorkQueue(new LinkedBlockingQueue<>(100))// 最大期待数为 100
              .setThreadFactory(ThreadFactoryBuilder.create().setNamePrefix("IM-Pool-").build())// 线程池命名
              .build();

理论我的项目中,如果一个对象的属性比拟多,无限思考应用建造者模式创建对象。

并且,Hutool 还提供一个全局的线程池,默认所有异步办法在这个线程池中执行。

  • ThreadUtil.execute : 间接在公共线程池中执行线程
  • ThreadUtil.execAsync: 执行异步办法
  • ……

Hutool 本身就大量用到了 ThreadUtil,比方敏感词工具类 SensitiveUtil

public static void init(final Collection<String> sensitiveWords, boolean isAsync){if(isAsync){
    // 异步初始化敏感词树
    ThreadUtil.execAsync(new Callable<Boolean>(){
      @Override
      public Boolean call() throws Exception {init(sensitiveWords);
        return true;
      }
      
    });
  }else{
    // 同步初始化敏感词树
    init(sensitiveWords);
  }
}

相干地址

  • 我的项目地址:https://github.com/dromara/hutool
  • 官网:https://hutool.cn/
退出移动版