HuTool工具的使用介绍和常用案例

HuTool工具的使用介绍和常用案例

一、 是什么

​ 一个小而全的java工具类,静态方法封装。由开源项目作者的项目中一个util包衍变而来,里面包含了各种平时我们会用到的工具类。

​ 官方文档

二、 为什么

  • 各开发人员的工具类不统一,杂而乱,容易产生重复代码。
  • 自己找的或者自己封装的有可能不够完善,而带来bug。
  • 基本上覆盖了Java底层代码的方方面面,足够全。

三、能做什么

  • 降低相关API的学习成本,提高工作效率。
  • 使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
  • 精简和优化代码,不重复造轮子,专注业务开发,减少封装和找的时间。

Hutool的目标是使用一个工具方法代替一段复杂代码,从而最大限度的避免“复制粘贴”代码的问题,彻底改变我们写代码的方式。
以计算MD5为例:

  • 【以前】打开搜索引擎 -> 搜“Java MD5加密” -> 打开某篇博客-> 复制粘贴 -> 改改好用
  • 【现在】引入Hutool -> SecureUtil.md5()
    Hutool的存在就是为了减少代码搜索成本,避免网络上参差不齐的代码出现导致的bug。

如何使用

参考API

视频教程

一、 如何引入

Maven

<dependency>
    <groupId>cn.hutoolgroupId>
    <artifactId>hutool-allartifactId>
    <version>5.5.7version>
dependency>

版本:Hutool 5.x支持JDK8+

二、常用举例(Demo)

参照我们公司的项目代码,用的最多的是,日期、非空、字符串、加密解密、tree结构,正则,UUID,io,集合,中文、常用字符串常量,分页等。

import cn.hutool.Hutool;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.FIFOCache;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.clone.CloneRuntimeException;
import cn.hutool.core.clone.CloneSupport;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.text.StrSpliter;
import cn.hutool.core.util.*;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.myutils.utils.Employee;
import io.micrometer.core.instrument.util.IOUtils;
import lombok.Data;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ResourceUtils;
import org.w3c.dom.Document;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

@SpringBootTest
public class DemoTest {
     

    /**
     * 打印所有工具类
     */
    @Test
    public void testGetAllUtils(){
     
        Hutool.printAllUtils();
    }

    /**
     * 日期工具类
     */
    @Test
    public void testDateUtil() {
     
        /**
         * yyyy-MM-dd HH:mm:ss
         * yyyy-MM-dd
         * HH:mm:ss
         * yyyy-MM-dd HH:mm
         * yyyy-MM-dd HH:mm:ss.SSS
         */
        String dateStr1 = "2017-03-01";
        Date date2 = DateUtil.parse(dateStr1);
        /**
         * 格式化日期输出
         */
        String dateStr = "2021-01-28";
        Date dateFormat = DateUtil.parse(dateStr);
        //结果 2021/01/26
        String format = DateUtil.format(dateFormat, "yyyy/MM/dd");
        //常用格式的格式化,结果:2021-01-28
        String formatDate = DateUtil.formatDate(dateFormat);
        //结果:2021-01-28 00:00:00
        String formatDateTime = DateUtil.formatDateTime(dateFormat);
        //结果:00:00:00
        String formatTime = DateUtil.formatTime(dateFormat);
        /**
         * 获取Date对象的某个部分
         */
        Date datePart = DateUtil.date();
        //获得年的部分
        System.out.println("年:"+DateUtil.year(datePart));
        //获得月份,从0开始计数
        System.out.println("月:"+DateUtil.month(datePart));
        //获得月份枚举
        System.out.println("日:"+DateUtil.dayOfMonth(datePart));
        /**
         * 日期时间偏移
         */
        //昨天
        DateTime yesterday = DateUtil.yesterday();
        System.out.println("昨天:" + yesterday);
        //明天
        System.out.println("明天:"+DateUtil.tomorrow());
        //上周
        System.out.println("上周:"+DateUtil.lastWeek());
        //下周
        System.out.println("下周:"+DateUtil.nextWeek());
        //上个月
        System.out.println("上个月:"+DateUtil.lastMonth());
        //下个月
        System.out.println("下个月:"+DateUtil.nextMonth());
        /**
         * 开始 和 结束时间
         */
        String dateStr2 = "2021-01-28 11:04:44";
        Date date = DateUtil.parse(dateStr2);
        //一天的开始,结果:2021-01-28 00:00:00
        Date beginOfDay = DateUtil.beginOfDay(date);
        System.out.println("一天的开始: "+beginOfDay);
        //一天的结束,结果:2021-01-28 23:59:59
        Date endOfDay = DateUtil.endOfDay(date);
        System.out.println("一天的结束: "+endOfDay);
        /**
         * 时间区间
         */
        String start = "2021-01-28";
        String end = "2021-02-09";
        List<DateTime> dateTimeList = DateUtil.rangeToList(DateUtil.parse(start), DateUtil.parse(end), DateField.DAY_OF_MONTH);
        dateTimeList.stream().forEach(System.out::println);
    }

    /**
     * 1.8的LocalDateTime
     */
    @Test
    public void testLocalDateTimeUtils(){
     
        System.out.println(
                "现在:" + LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss")
        );
        System.out.println(
                "每天吃饭的点:" + LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd 11:58:00")
        );
        System.out.println(
                "距离下班还有:" + LocalDateTimeUtil.between(LocalDateTime.now(),LocalDateTime.of(2021,1,28,18,30,0), ChronoUnit.SECONDS)+"s"
        );
    }

    /**
     * 原始写法(浅克隆):实现Cloneable接口
     */
    @Data
    private static class Cat implements Cloneable{
     
        private String name = "miaomiao";
        private int age = 2;
        private Map map = new HashMap();

        @Override
        public Cat clone() {
     
            try {
     
                return (Cat) super.clone();
            } catch (CloneNotSupportedException e) {
     
                throw new CloneRuntimeException(e);
            }
        }
    }
    /**
     * 克隆(深克隆):继承CloneSupport
     */
    @Data
    private static class Dog extends CloneSupport<Dog> {
     
        private String name = "wangwang";
        private int age = 3;
    }

    /**
     * 对java.util.Objects{@link Objects}的进一步封装;
     */
    @Test
    public void testObjectUtil(){
     
        //Objects的克隆
        Cat cat = new Cat();
        Cat cat1 = cat.clone();
        //ObjectUtil的深克隆
        Cat cat2 = ObjectUtil.cloneByStream(cat);

        //判断非空
        System.out.println(ObjectUtil.isNull(null));//true
        System.out.println(ObjectUtil.isNull(""));//false
        System.out.println(ObjectUtil.isNull(" "));//false
        System.out.println(ObjectUtil.isEmpty(null));//true
        System.out.println(ObjectUtil.isEmpty(""));//true
        System.out.println(ObjectUtil.isEmpty(" "));//false
        System.out.println(ObjectUtil.equals("", " "));//false
        System.out.println(ObjectUtil.isBasicType(" "));//false
    }

    /**
     * 加密解密工具:
     * 对称加密(symmetric),例如:AES、DES等
     * 非对称加密(asymmetric),例如:RSA、DSA等
     * 摘要加密(digest),例如:MD5、SHA-1、SHA-256、HMAC等
     */
    @Test
    public void testSecureUtil(){
     
        System.out.println("MD5:"+SecureUtil.md5("hzkj"));
        System.out.println("SHA256:"+SecureUtil.sha256("hzkj"));
    }

    /**
     * 防止 xss 注入和 SQL 注入
     */
    @Test
    public void testHtmlUtil(){
     
        //转义HTML特殊字符
        System.out.println(HtmlUtil.escape("123'123'"));
        //清除所有 HTML 标签
        System.out.println("----------");
        System.out.println(HtmlUtil.cleanHtmlTag("pre
\r\n\t\tdfdsfdsfdsf\r\n
BBBB
"
)); System.out.println("----------"); System.out.println(buildSafeStr("pre
\r\n\t\tdfdsfdsfdsf\r\n
BBBB
"
)); System.out.println("----------"); //过滤 HTML 文本,防止 XSS 攻击 System.out.println(HtmlUtil.filter("")); } public static String buildSafeStr(String in) { return in == null ? null : in.replaceAll("(\\^)|(\\&)|(\\|)|(\\$)|(\\%)|(\\@)|(\\')|(\\\")|(\\>)|(\\<)|(\\))|(\\()|(\\\\)|(\\#|$)", ""); } /** * 增强的StringUtils */ @Test public void testStrUtil(){ //字符串模板代替字符串拼接,slf4j System.out.println(StrUtil.format("this is {} for {}", "a", "b")); //截取: 从0开始,最后一个为-1, 左开右闭,不会越界报错 String str = "abcdefgh"; System.out.println(StrUtil.sub(str, 0, 3)); // abc System.out.println(StrUtil.sub(str, 1, 3)); // bc System.out.println(StrUtil.sub(str, 2, -3)); //cde System.out.println(StrUtil.sub(str, 3, 2)); //c System.out.println(StrUtil.sub(str, 3, -1)); //defg System.out.println(StrUtil.sub(str, 0, 9)); //abcdefgh //定义了很多常用字符 System.out.println(StrUtil.UNDERLINE); System.out.println(StrUtil.DOT); System.out.println(StrUtil.COMMA); System.out.println(StrUtil.DASHED); System.out.println(StrUtil.EMPTY_JSON); //判断非空 System.out.println(StrUtil.hasBlank(null));//true System.out.println(StrUtil.hasBlank(""));//true System.out.println(StrUtil.hasBlank(" "));//true System.out.println(StrUtil.hasBlank("null"));//false System.out.println(StrUtil.hasEmpty(null));//true System.out.println(StrUtil.hasEmpty(""));//true System.out.println(StrUtil.hasEmpty(" "));//false System.out.println(StrUtil.hasEmpty("null"));//false } /** * 切割字符串: * 分割限制分割数 * 分割后每个字符串是否需要去掉两端空格 * 是否忽略空白片 * 根据固定长度分割 * 通过正则分隔 */ @Test public void testStrSpliter(){ String str1 = "a, ,efedsfs, ddf"; //参数:被切分字符串,分隔符逗号,0表示无限制分片数,去除两边空格,忽略空白项 List<String> split = StrSpliter.split(str1, ',', 0, true, true); //正则切分 // StrSpliter.splitByRegex(str1,"",2,true,true); } /** * xml文件的简单操作 */ @Test public void testXmlUtil(){ File file = null; try { file = ResourceUtils.getFile("classpath:xmlFile/test.xml"); } catch (FileNotFoundException e) { e.printStackTrace(); } //读取xml Document readXML = XmlUtil.readXML(file); System.out.println(readXML.getXmlVersion()); //解析xml String str = ResourceUtil.readUtf8Str("xmlFile/test.xml"); Document parseXml = XmlUtil.parseXml(str); System.out.println(parseXml.getXmlVersion()); //创建xml Document document = XmlUtil.createXml(); //xml转成文件 XmlUtil.toFile(parseXml,"xmlFile/test2.xml"); } /** * 资源快捷读取封装 * @throws IOException */ @Test public void testResourceUtil() throws IOException { /** * 原始写法: */ //获取resource的单个文件 ClassPathResource classPathResource = new ClassPathResource("xmlFile/test.xml"); String str = IOUtils.toString(classPathResource.getInputStream(), Charset.defaultCharset()); System.out.println("原始写法:"+str); System.out.println("============="); /** * ResourceUtil写法 */ String s = ResourceUtil.readUtf8Str("xmlFile/test.xml"); System.out.println("ResourceUtil写法:"+s); /** * 获取resources下指定路径下的所有文件 */ Resource[] resources = new PathMatchingResourcePatternResolver() .getResources(ResourceUtils.CLASSPATH_URL_PREFIX + "jsonFile/*.*"); //保存文件路径 String transPath = "./jsonFile/"; for (Resource resource : resources) { //获取文件流 InputStream inputStream = resource.getInputStream(); //获取文件名 String filename = resource.getFilename(); //复制文件 File file = new File(transPath+filename); System.out.println(file.getName()); //对文件进行操作 } } /** * 树结构: TreeUtil */ @Test public void testTreeUtil(){ // 构建node列表 List<TreeNode<String>> nodeList = CollUtil.newArrayList(); nodeList.add(new TreeNode<>("1", "0", "系统管理", 5)); nodeList.add(new TreeNode<>("11", "1", "用户管理", 222222)); nodeList.add(new TreeNode<>("111", "11", "用户添加", 0)); nodeList.add(new TreeNode<>("2", "0", "店铺管理", 1)); nodeList.add(new TreeNode<>("21", "2", "商品管理", 44)); nodeList.add(new TreeNode<>("221", "2", "商品管理2", 2)); // 0表示最顶层的id是0 List<Tree<String>> treeList = TreeUtil.build(nodeList, "0"); /** * 自定义字段名 */ //配置 TreeNodeConfig treeNodeConfig = new TreeNodeConfig(); // 自定义属性名 都要默认值的 treeNodeConfig.setWeightKey("order"); treeNodeConfig.setIdKey("rid"); // 最大递归深度 treeNodeConfig.setDeep(3); //转换器 List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig, (treeNode, tree) -> { tree.setId(treeNode.getId()); tree.setParentId(treeNode.getParentId()); tree.setWeight(treeNode.getWeight()); tree.setName(treeNode.getName()); // 扩展属性 ... tree.putExtra("extraField", 666); tree.putExtra("other", new Object()); }); //获取ID对应的节点,如果有多个ID相同的节点,只返回第一个。此方法只查找此节点及子节点,采用递归深度优先遍历。 // TreeUtil.getNode(null,""); } @Test public void testIdUtil(){ //ObjectId是MongoDB数据库的一种唯一ID生成策略 IdUtil.objectId(); //uuid System.out.println("IdUtil.randomUUID() = " + IdUtil.randomUUID());//带-的 System.out.println("IdUtil.simpleUUID() = " + IdUtil.simpleUUID());//不带-的 System.out.println("IdUtil.fastUUID() = " + IdUtil.fastUUID()); System.out.println("IdUtil.fastSimpleUUID() = " + IdUtil.fastSimpleUUID()); } /** * 反射 */ @Test public void testReflectUtil(){ //获取某个类的所有方法 Method[] methods = ReflectUtil.getMethods(TestClass.class); //获取某个类的指定方法 Method method = ReflectUtil.getMethod(TestClass.class, "getA"); //构造对象 ReflectUtil.newInstance(TestClass.class); //执行方法 TestClass testClass = new TestClass(); ReflectUtil.invoke(testClass, "setA", 10); } class TestClass { private int a; public int getA() { return a; } public void setA(int a) { this.a = a; } } /** * 文件工具类(方法命名,参考linux) */ @Test public void testFileUtil(){ //ls touch mkdir del(递归删除) copy List<String> fileNames = FileUtil.listFileNames("jsonFile"); File touch = FileUtil.touch(new File("")); File mkdir = FileUtil.mkdir(""); boolean del = FileUtil.del(""); FileUtil.copy("","",true); } /** * Validator字段验证器 */ @Test public void testValidator(){ System.out.println(Validator.isEmail("[email protected]"));//true System.out.println(Validator.isCreditCode("45645654"));//false System.out.println(Validator.isChinese("我is华中科技"));//false System.out.println(Validator.hasChinese("我is华中科技"));//true System.out.println(Validator.isMobile("17158469552"));//true System.out.println(Validator.isPlateNumber("鄂"));//false //判断身份信息,大陆港澳台 Validator.isCitizenId(""); //自定义正则 Validator.isMatchRegex("",""); //验证正则 Validator.validateMatchRegex("","",""); } @Test public void testCollUtil(){ ArrayList<String> listA = CollUtil.toList("1", "3", "4", "5"); ArrayList<String> listB = CollUtil.toList("1", "2", "3"); //截取,如果越界,返回空集合 System.out.println(CollUtil.sub(listA, 0, 2)); //并集 System.out.println(CollUtil.union(listA, listB)); //交集 System.out.println(CollUtil.intersection(listA, listB)); //差集 System.out.println(CollUtil.disjunction(listA, listB)); } /** * 拼音工具-PinyinUtil */ @Test public void testPinyinUtil(){ //获取拼音: "ni hao" String pinyin = PinyinUtil.getPinyin("你好", " "); //获取首字母: "h, s, d, y, g" String result = PinyinUtil.getFirstLetter("H是第一个", ", "); } /** * HttpUtil */ @Test public void testHttpUtil(){ /** * 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> paramMap1 = new HashMap<>(); paramMap1.put("city", "北京"); String result= HttpUtil.post("https://www.baidu.com", paramMap1); } @Test public void testNumberUtil(){ BigDecimal add = NumberUtil.add(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN); BigDecimal sub = NumberUtil.sub(BigDecimal.ZERO, BigDecimal.ONE); BigDecimal mul = NumberUtil.mul(BigDecimal.ZERO, BigDecimal.ONE); BigDecimal div = NumberUtil.div(BigDecimal.ZERO, BigDecimal.ONE,2, RoundingMode.CEILING); System.out.println(add); System.out.println(sub); System.out.println(mul); System.out.println(div); BigDecimal multiply = NumberUtil.add(BigDecimal.ONE).multiply(BigDecimal.TEN); System.out.println(multiply); } @Test public void testOther(){ //json JSONUtil.isJson(""); //cache FIFOCache<Object, Object> objects = CacheUtil.newFIFOCache(3); //fast convert String numberToChinese = Convert.numberToChinese(54, true);//数字转中文 String digitToChinese = Convert.digitToChinese(32.24);//叁拾贰元贰角肆分 System.out.println(numberToChinese); System.out.println(digitToChinese); //CaptchaUtil 生成验证码 CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(50, 80); LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(80, 80); ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(50, 80); System.out.println(shearCaptcha.getCode()); BufferedImage image = lineCaptcha.getImage(); //bean Employee employee = new Employee(); employee.setId(2); employee.setEmpName("oyqj"); Map<String, Object> map = BeanUtil.beanToMap(employee); HashMap<String, Object> map1 = new HashMap<String, Object>() { { put("id", "2"); put("empName", "oyqj"); }}; System.out.println(map); Employee employee1 = BeanUtil.mapToBean(map1, Employee.class, true, CopyOptions.create().ignoreCase()); System.out.println(employee1); new Thread(()-> System.out.println("start")).start(); } public static void main(String args[]) { Thread t = new Thread() { public void run() { pong(); } }; t.start(); System.out.print("ping"); } static void pong() { System.out.print("pang"); } }

三、包含什么

对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装

模块 介绍
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-all方式引入所有模块。

结语:

  1. 时间有限,简单介绍,更多的使用经验后续一起交流。

  2. 工具包虽好,基本原理还是得要知道,实现过程要了解。

  3. 有些比较基本的且使用频率极高的工具类还是建议使用常用的,比如:

    • json的解析,FastJson
    • stream流是封装的方法,在没有对stream流比较熟悉的情况下,还是多写原生的
    • xml的使用.dom4j
    • 线程的创建和使用,有Executor和ThreadPoolExecutor
    • Bean相关的操作,apache commons的BeanUtils

你可能感兴趣的:(JAVA,开源项目,工具使用)