工具篇之Hutool

一、概述

1.1介绍

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

Hutool中的工具方法来自于每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;

Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。

1.2Hutool名称的由来

Hutool = Hu + tool,是原公司项目底层代码剥离后的开源库,“Hu”是公司名称的表示,tool表示工具。Hutool谐音“糊涂”,一方面简洁易懂,一方面寓意“难得糊

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

以计算MD5为例:

- 【以前】打开搜索引擎 -> 搜“Java MD5加密” -> 打开某篇博客-> 复制粘贴 -> 改改好用

- 【现在】引入Hutool -> SecureUtil.md5()

 Hutool的存在就是为了减少代码搜索成本,避免网络上参差不齐的代码出现导致的bug。

 1.3包含组件(核心)

一个Java基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类,同时提供以下组件:

模块介绍
hutool-aopJDK动态代理封装,提供非IOC下的切面支持
hutool-bloomFilter布隆过滤,提供一些Hash算法的布隆过滤
hutool-cache简单缓存实现
hutool-core核心,包括Bean操作、日期、各种Util等
hutool-cron定时任务模块,提供类Crontab表达式的定时任务
hutool-crypto加密解密模块,提供对称、非对称和摘要算法封装
hutool-dbJDBC封装后的数据操作,基于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-jsonJSON实现
hutool-captcha图片验证码实现
hutool-poi针对POI中Excel和Word的封装
hutool-socket基于Java的NIO和AIO的Socket封装
hutool-jwtJSON Web Token (JWT)封装实现

1.4官方文档

官网:Hutool — 🍬A set of tools that keep Java sweet.

参考文档:简介 | Hutool 

API文档:Document 

1.5导入HuTool

HuTool使用非常简单直接在项目中引入如下依赖即可:

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

二、常用工具类

2.1Convert

问题

在Java开发中我们要面对各种各样的类型转换问题,尤其是从命令行获取的用户参数、从HttpRequest获取的Parameter等等,这些参数类型多种多样,我们怎么去转换他们呢?常用的办法是先整成String,然后调用XXX.parseXXX方法,还要承受转换失败的风险,不得不加一层try catch,这个小小的过程混迹在业务代码中会显得非常难看和臃肿。

 类型转换工具类,用于各种类型数据的转换。

Convert类可以说是一个工具方法类,里面封装了针对Java常见类型的转换,用于简化类型转换。**Convert**类中大部分方法为toXXX,参数为Object,可以实现将任意可能的类型转换为指定类型。同时支持第二个参数defaultValue用于在转换失败时返回一个默认值。

package com.yanyu.redisjedistest.demo;

import cn.hutool.core.convert.Convert;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;

@Slf4j
public class hutool1 {
    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(bArr.toString());

        //转换为日期对象
        String dateStr = "2020-09-17";
        Date date = Convert.toDate(dateStr);
        log.info(date.toString());

        //转换为列表
        String[] strArr = {"a", "b", "c", "d"};
        List<String> strList = Convert.toList(String.class, strArr);
        log.info(strList.toString());
    }
    public static void main(String[] args) {
        hutool1 hutool1 = new hutool1();
        hutool1.covert();
    }
}

2.2DateUtil

日期时间工具类,定义了一些常用的日期时间操作方法。

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 = "2020-09-17";
        date = DateUtil.parse(dateStr);
        //自定义格式化转换
        date = DateUtil.parse(dateStr, "yyyy-MM-dd");
        //格式化输出日期
        String format = DateUtil.format(date, "yyyy-MM-dd");
        log.info(format.toString());
        //获得年的部分
        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);
    }

2.3ReflectUtil

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());
}

Dog

Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Dog {
 private String name;
 private Float weight;
}

2.4NumberUtil

   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);
    }

2.5CollUtil

集合操作的工具类,定义了一些常用的集合操作。

 public void collUtil() {
        //数组转换为列表
        String[] array = new String[]{"a", "b", "c", "d", "e"};
        List<String> list = CollUtil.newArrayList(array);
        //join:数组转字符串时添加连接符号
        String joinStr = CollUtil.join(list, ",");
        log.info("collUtil join:{}", joinStr);
        //将以连接符号分隔的字符串再转换为列表
        List<String> splitList = StrUtil.split(joinStr, ',');
        log.info("collUtil split:{}", splitList);
        //创建新的Map、Set、List
        HashMap<Object, Object> newMap = CollUtil.newHashMap();
        HashSet<Object> newHashSet = CollUtil.newHashSet();
        ArrayList<Object> newList = CollUtil.newArrayList();
        //判断列表是否为空
        CollUtil.isEmpty(list);
        CollUtil.isNotEmpty(list);
    }

2.6SecureUtil

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);
    }

2.7JSONUtil

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);
 List<Dog> 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);
}

2.8RandomUtil

随机工具类,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);
}

三、实战exexcel开发

数据库

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);

实体类

/**
 * 组织用户信息表
 * @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;
}

在工程中先确定使用的字段构建模板,根据字段构建excel 的模板。这里的示例如下:

//controller层
//返回模板
    @RequestMapping("/getExcelTemplate")
    public void getExcelTemplate(HttpServletResponse response) {
        groupUserService.getExcelTemplate(response);
    }

//sevice层
void getExcelTemplate(HttpServletResponse response);

//impl
@Override
    public void getExcelTemplate(HttpServletResponse response) {
        try {
            // 1 读取对象
            final ExcelReader reader = ExcelUtil.getReader(ResourceUtil.getStream("templates/group.xlsx"));
            List<List<Object>> 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异常");
        }
    }

这里我使用的是三层构建,在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);
    }
void export(PageVo pageVo, HttpServletResponse response);

boolean getUserInfo(MultipartFile file) throws IOException;

@Override
    public void export(PageVo pageVo, HttpServletResponse response) {
        // 从数据库查出数据对象封装成map
        final List<Map<String, Object>> educationList = this.page(new Page<>(pageVo.getPage(), pageVo.getLimit()), Wrappers.lambdaQuery()).getRecords()
                .stream()
                // 封装成 Map 并且放入 List
                .map(item -> {
                    final Map<String, 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());
        HashMap<String, 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);
        List<GroupUser> read = reader.read(0, 1, GroupUser.class);
        Group group = groupService.getOne(new QueryWrapper<Group>().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;
    }

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烟雨平生9527

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值