前言
在开发应用系统的时候,导出文件是必不可放的功能。
以前用过POI、easyexcel等工具的导入导出功能,但总感觉太麻烦了,代码特别多,感觉并不是很好用。
今天给大家介绍一款新工具,java工具类库Hutool。
Hutool简介
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让使用者更轻松。
Hutool中的工具方法来自于每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
使用
首先在POM.xml中加入GAV
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.7</version>
</dependency>
<!--解析excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.1</version>
</dependency>
<!--处理2007 excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
导出
@RequestMapping("/export")
@ResponseBody
public void export(HttpServletResponse response){
List<User> list = new ArrayList<>();
list.add(new User("zhangsan","1231",new Date()));
list.add(new User("zhangsan1","1232",new Date()));
list.add(new User("zhangsan2","1233",new Date()));
list.add(new User("zhangsan3","1234",new Date()));
list.add(new User("zhangsan4","1235",new Date()));
list.add(new User("zhangsan5","1236", DateUtil.date(new Date())));
// 通过工具类创建writer,默认创建xls格式
ExcelWriter writer = ExcelUtil.getWriter();
//自定义标题别名
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("birthDay", "生日");
// 合并单元格后的标题行,使用默认标题样式
writer.merge(2, "申请人员信息");
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(list, true);
//out为OutputStream,需要写出到的目标流
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
String name = StringUtils.toUtf8String("申请学院");
response.setHeader("Content-Disposition","attachment;filename="+name+".xls");
ServletOutputStream out= null;
try {
out = response.getOutputStream();
writer.flush(out, true);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
// 关闭writer,释放内存
writer.close();
}
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
效果
导入
数据库
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50724
Source Host : localhost:3306
Source Database : ssm
Target Server Type : MYSQL
Target Server Version : 50724
File Encoding : 65001
Date: 2020-04-27 16:37:43
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `excel`
-- ----------------------------
DROP TABLE IF EXISTS `excel`;
CREATE TABLE `excel` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(20) DEFAULT NULL,
`height` double(16,2) DEFAULT NULL,
`weight` double(16,2) DEFAULT NULL,
`edu` varchar(255) DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`status` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of excel
-- ----------------------------
INSERT INTO `excel` VALUES ('7', '万超2', '20', '187.90', '65.90', '本科', '2020-04-27 16:08:53', '2020-04-27 16:08:53', '1');
INSERT INTO `excel` VALUES ('8', '马汉2', '14', '138.80', '78.24', '硕士', '2020-04-27 16:08:53', '2020-04-27 16:08:53', '2');
INSERT INTO `excel` VALUES ('9', '万超2', '20', '187.90', '65.90', '本科', '2020-04-27 16:12:23', '2020-04-27 16:12:23', '1');
INSERT INTO `excel` VALUES ('10', '马汉2', '14', '138.80', '78.24', '硕士', '2020-04-27 16:12:23', '2020-04-27 16:12:23', '2');
INSERT INTO `excel` VALUES ('11', '万超0', '20', '187.90', '65.90', '本科', '2020-04-27 16:12:37', '2020-04-27 16:12:37', '1');
INSERT INTO `excel` VALUES ('12', '马汉0', '14', '138.80', '78.24', '硕士', '2020-04-27 16:12:37', '2020-04-27 16:12:37', '2');
mysql中默认当前时间为CURRENT_TIMESTAMP
application.properties
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
# com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
#开启驼峰命名转换
mybatis.configuration.map-underscore-to-camel-case=true
#实体类的别名
#mybatis.type-aliases-package=com.example.springboot.model
#前缀的默认值,是让controller层到templates文件夹寻找xx.html(src/main/resources/templates)
#spring.thymeleaf.prefix=classpath:/templates/
#logging.level.com,后面的路径指的是mybatis对应的方法接口所在的包。并不是mapper.xml所在的包
logging.level.com.example.springbootexcel.mapper=debug
excelImport.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Excel导入</title></head>
<body>
<form enctype="multipart/form-data" method="post" action="/excelImport">
选择Excel表格:<input type="file" name="file"/><br/>
<input type="submit" value="上传"/></form>
</body>
</html>
model
@Getter
@Setter
public class Excel {
private Long id;
private String name;
private Integer age;
private Double height;
private Double weight;
private String edu;
private Date createTime;
private Date updateTime;
private Integer status;
}
mapper
接口
package com.example.springbootexcel.mapper;
import com.example.springbootexcel.model.Excel;
import java.util.List;
public interface ExcelMapper {
/**
* 批量插入
* @param recordList
* @return
*/
int insertList(List<Excel> recordList);
}
ExcelMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootexcel.mapper.ExcelMapper">
<insert id="insertList" parameterType="com.example.springbootexcel.model.Excel">
insert into excel (
name,
age,
height,
weight,
edu,
update_time,
status
)
values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.name,jdbcType=VARCHAR},
#{item.age,jdbcType=INTEGER},
#{item.height,jdbcType=DOUBLE},
#{item.weight,jdbcType=DOUBLE},
#{item.edu,jdbcType=VARCHAR},
NOW(),
#{item.status,jdbcType=INTEGER}
)
</foreach>
</insert>
</mapper>
service
import com.example.springbootexcel.mapper.ExcelMapper;
import com.example.springbootexcel.model.Excel;
import com.example.springbootexcel.utils.ExcelUtil;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Service
public class ExcelService {
@Autowired
private ExcelMapper excelMapper;
public int addList(List<Excel> list){
return excelMapper.insertList(list);
}
}
controller
package com.example.springbootexcel.controller;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.example.springbootexcel.model.Excel;
import com.example.springbootexcel.service.ExcelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @author guoqiang
* @date 2020-04-27 10:08
*/
@Controller
public class ExcelController2 {
@Autowired
private ExcelService service;
@GetMapping("/toHtml")
public String test(HttpServletRequest request) {
return "excelImport";
}
//处理文件上传
@ResponseBody//返回json数据
@RequestMapping(value = "/excelImport", method = RequestMethod.POST)
public String uploadImg(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
System.out.println(file);
if (file.isEmpty()) {
System.out.println( "文件为空!");
return "excelImport";
}
// 1.获取上传文件输入流
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (Exception e) {
//return ResponseData.fail(ResponseCodeEnum.ERROR_PARAM_INVALID);
e.printStackTrace();
}
// // 2.应用HUtool ExcelUtil获取ExcelReader指定输入流和sheet
// ExcelReader excelReader = ExcelUtil.getReader(inputStream, "导入材料清单");
// // 可以加上表头验证
// // 3.读取第二行到最后一行数据
// List<List<Object>> read = excelReader.read(2, excelReader.getRowCount());
// for (List<Object> objects : read) {
// // objects.get(0),读取某行第一列数据
// // objects.get(1),读取某行第二列数据
// System.out.println(objects.get(0));
// }
//调用用 hutool 方法读取数据 默认调用第一个sheet
ExcelReader excelReader = ExcelUtil.getReader(inputStream);
//从第二行开始获取数据 excelReader.read的结果是一个2纬的list,外层是行,内层是行对应的所有列
//读取方式1
// List<List<Object>> read = excelReader.read(1, excelReader.getRowCount());
// //System.out.println("数据:"+read);
// List<Excel> excels = new ArrayList<>();
// //循环获取的数据
// for (int i = 0; i < read.size(); i++) {
// List list = read.get(i);
// Excel excel = new Excel();
// excel.setName(list.get(0).toString());
// excel.setAge(Integer.parseInt(list.get(1).toString()));
// excel.setHeight(Double.parseDouble(list.get(2).toString()));
// excel.setWeight(Double.parseDouble(list.get(3).toString()));
// excel.setEdu(list.get(4).toString());
// excel.setStatus(Integer.parseInt(list.get(5).toString()));
// excels.add(excel);
// }
//读取方式2
//读取为Bean列表,Bean中的字段名为标题,字段值为标题对应的单元格值。
List<Excel> excels = excelReader.readAll(Excel.class);
service.addList(excels);
System.out.println("导入成功");
return "excelImport";
}
}
采用读取方式1,需要将各列的值赋给model对应的属性
//读取方式1
List<List<Object>> read = excelReader.read(1, excelReader.getRowCount());
//System.out.println("数据:"+read);
List<Excel> excels = new ArrayList<>();
//循环获取的数据
for (int i = 0; i < read.size(); i++) {
List list = read.get(i);
Excel excel = new Excel();
excel.setName(list.get(0).toString());
excel.setAge(Integer.parseInt(list.get(1).toString()));
excel.setHeight(Double.parseDouble(list.get(2).toString()));
excel.setWeight(Double.parseDouble(list.get(3).toString()));
excel.setEdu(list.get(4).toString());
excel.setStatus(Integer.parseInt(list.get(5).toString()));
excels.add(excel);
}
方式2省事些,可以直接赋值给对象
//读取方式2
//读取为Bean列表,Bean中的字段名为标题,字段值为标题对应的单元格值。
List<Excel> excels = excelReader.readAll(Excel.class);
运行结果
excel03和07都能导入
补充知识:ExcelReader
来自:https://www.hutool.cn/docs/#/poi/Excel%E8%AF%BB%E5%8F%96-ExcelReader
介绍
读取Excel内容的封装,通过构造ExcelReader对象,指定被读取的Excel文件、流或工作簿,然后调用readXXX方法读取内容为指定格式。
使用
- 读取Excel中所有行和列,都用列表表示
ExcelReader reader = ExcelUtil.getReader("d:/aaa.xlsx");
List<List<Object>> readAll = reader.read();
- 读取为Map列表,默认第一行为标题行,Map中的key为标题,value为标题对应的单元格值。
ExcelReader reader = ExcelUtil.getReader("d:/aaa.xlsx");
List<Map<String,Object>> readAll = reader.readAll();
- 读取为Bean列表,Bean中的字段名为标题,字段值为标题对应的单元格值。
ExcelReader reader = ExcelUtil.getReader("d:/aaa.xlsx");
List<Person> all = reader.readAll(Person.class);