Java工具类Hutool使用
Java工具类Hutool使用
前言
- 在开发的过程中,我们需要一些工具类实现某些特殊处理,例如字符串格式处理,日期处理,文件处理等操作。如果在传统的开发过程中,我们将自己开发一些工具类用于实现这些功能。但自己开发可能就会在不经意间由于代码的不严谨,引发某些bug。而当我们使用hutool 提供和工具库,就能有效提高开发效率。
- 应用官方的介绍:
- Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类
- 官网:hutool.cn/
- 源码:https://gitee.com/dromara/hutool
基础功能使用
引入依赖
-
添加hutool 的依赖,该依赖需要指定版本,该是一个Hutool的集成打包产品,由于考虑到“懒人”用户及分不清各个模块作用的用户,“无脑”引入hutool-all模块是快速开始和深入应用的最佳方式。
-
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.5</version> </dependency>
使用
-
当引入hutool依赖后,即可想使用我们在工程中新建的工具类一般使用由hutool 提供的工具类,无需再进行其余配置,真正做到引入可用。
-
//当前时间 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();
-
hutool 对日期进行了非常详细的封装,可以有效避免我们自己的日期格式出现混乱的情况。而且hutool 为我们提供了多个日期格式解析,转换成yyyy-MM-dd HH:mm:ss 格式,同时我们可以引用这些日期格式:
-
yyyy/MM/dd HH:mm:ss yyyy.MM.dd HH:mm:ss yyyy年MM月dd日 HH时mm分ss秒 yyyy-MM-dd yyyy/MM/dd yyyy.MM.dd HH:mm:ss HH时mm分ss秒 yyyy-MM-dd HH:mm yyyy-MM-dd HH:mm:ss.SSS yyyyMMddHHmmss yyyyMMddHHmmssSSS yyyyMMdd EEE, dd MMM yyyy HH:mm:ss z EEE MMM dd HH:mm:ss zzz yyyy yyyy-MM-dd'T'HH:mm:ss'Z' yyyy-MM-dd'T'HH:mm:ss.SSS'Z' yyyy-MM-dd'T'HH:mm:ssZ yyyy-MM-dd'T'HH:mm:ss.SSSZ
-
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);
-
字符串工具,随机uuid 工具也是日常使用频繁的工具类:
-
//subString方法越界啥的都会报异常,还得自己判断,hutool把各种情况判断都加进来了,而且index的位置还支持负数,-1表示最后一个字符(这个思想来自于Python,如果学过Python的应该会很喜欢的),还有就是如果不小心把第一个位置和第二个位置搞反了,也会自动修正(例如想截取第4个和第2个字符之间的部分也是可以的哦~) 举个栗子 String str = "abcdefgh"; String strSub1 = StrUtil.sub(str, 2, 3); //strSub1 -> c String strSub2 = StrUtil.sub(str, 2, -3); //strSub2 -> cde String strSub3 = StrUtil.sub(str, 3, 2); //strSub2 -> c
-
//唯一字符串 //生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3 String uuid = IdUtil.randomUUID(); //生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42 String simpleUUID = IdUtil.simpleUUID();
基于Hutool的excel开发
引入依赖
-
excel 包完全依赖于hutool 工具包,不需要额外的引入,hutool all中已经包含了hutool 的全部工具包
-
<!-- hutool工具类 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.22</version> </dependency>
开发
-
首先确定我们要对那些表进行数据的导入导出,这里的建议是对数据更改不频繁的表进行数据的导入导出,而且对于数据的唯一性要求不高,否则在进行数据导入的过程中,需要进行复杂的逻辑处理。这里我使用的是组织的用户信息表,该表的数据只有组织自己进行维护,就可以使用标准导入。
-
/** * 组织用户信息表 * @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; }
-
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);
-
在确定表后,我们需要选取那些字段是我们需要使用的,在excel 表中进行展示,需要用户填入,根据字段构建反射。
实现
-
在工程中先确定使用的字段构建模板,根据字段构建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; }
-
使用hutool 进行excel 处理的时候,需要自己定义字段与excel 表头见的映射关系,这一点是比较麻烦的。但相比于其他excel的使用方式,这是一种非常简单的实现。