Springboot整合easyExcel导入导出Excel
背景:
最近公司有个需求要求可以导入、导出excel,因此在此记录学习一下如何使用Springboot整合easyExcel;
需求:
数据库中有张user表,有个业务要求可以导入、导出“用户名单.xls”表
一、准备:
创建项目:
关于springboot项目如何创建这里不再赘述,放一张项目结构图:
1、导入easyexcel、mybatis、mysql依赖
<!-- easyexcel相关依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>1.1.2-beta5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!-- mybatis、mysql相关依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
2、application.yml
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
3、导出excel
(1)user实体类
导出 Excel 时,若需要表头,那么相应的实体类需要继承 BaseRowModel,并加入 @ExcelProperty(value = “id”, index = 0) 注解。其中 value 代表在导出 Excel 时,该字段对应的表头名称;index 代表该字段对应的表头位置(从0开始)。如下图:
//@Data是lombok的一个注解,加上它会自动生成getter、setter方法
@Data
public class User extends BaseRowModel {
@ExcelProperty(value = "ID", index = 0)
private String id;
@ExcelProperty(value = "姓名", index = 1)
private String name;
@ExcelProperty(value = "年龄", index = 2)
private Integer age;
}
(2)Usercontroller
@GetMapping("/user/excel")
public void excelExport(HttpServletResponse response) throws IOException {
userService.excelExport(response);
}
(3)Userservice
public void excelExport(HttpServletResponse response) throws IOException {
List<User> list = userDao.queryAllUsers();
String fileName = "用户名单";
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + new String( fileName.getBytes("gb2312"), "ISO8859-1" ) + ".xls");
ServletOutputStream out = response.getOutputStream();
ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLS,true);
Sheet sheet = new Sheet(1,0,User.class);
//设置自适应宽度
sheet.setAutoWidth(Boolean.TRUE);
sheet.setSheetName("用户名单");
writer.write(list,sheet);
writer.finish();
out.flush();
response.getOutputStream().close();
out.close();
}
4、导入excel
(1)Usercontroller
@PostMapping("/user/excel")
public String excelImport(@RequestParam("file")MultipartFile file) throws IOException {
userService.excelImport(file);
return "success";
}
(2)Userservice
public void excelImport(MultipartFile file) throws IOException {
if(!file.getOriginalFilename().equals("用户名单.xls") && !file.getOriginalFilename().equals("用户名单.xlsx") ){
return;
}
InputStream inputStream = new BufferedInputStream(file.getInputStream());
//实例化实现了AnalysisEventListener接口的类
ExcelListener excelListener = new ExcelListener(userDao);
ExcelReader reader = new ExcelReader(inputStream,null,excelListener);
//读取信息
reader.read(new Sheet(1,1,User.class));
}
参考easyExcel官方GitHub demo
(3)ExcelListener
public class ExcelListener extends AnalysisEventListener<User> {
private List<User> datas = new ArrayList<>();
private static final int BATCH_COUNT = 3000;
private UserDao userDao;
public ExcelListener(UserDao userDao){
this.userDao = userDao;
}
@Override
public void invoke(User user, AnalysisContext analysisContext) {
//数据存储到datas,供批量处理,或后续自己业务逻辑处理。
datas.add(user);
//达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if(datas.size() >= BATCH_COUNT){
saveData();
// 存储完成清理datas
datas.clear();
}
}
private void saveData() {
for(User user : datas){
userDao.addUser(user);
}
}
public List<User> getDatas() {
return datas;
}
public void setDatas(List<User> datas) {
this.datas = datas;
}
/**
* 所有数据解析完成了 都会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
saveData();//确保所有数据都能入库
}
}
二、测试
刚开始的数据库表:
准备一个“用户名单.xls”表,以便待会测试导入功能:
1、 启动项目,使用postman测试“导入”功能:
点击send,然后查看数据表:
上图数据一致,说明导入成功!!!
2、再用postman测试导出功能:
没有参数,直接send,然后可以看到:
将其下载下来查看(本来这里的文件名应该是代码中命名的“用户名单.xls”,但我尝试了很久总是没有变。。。)
与数据库表数据一致,说明导出成功!
特别说明:
这里的excel名字的命名必须是这个,而且里面的主键可以不写,因为可能会遇到主键冲突的问题