Spring Boot 集成 EasyExcel 3.x
Spring Boot 集成 EasyExcel 3.x
本章节将介绍 Spring Boot 集成 EasyExcel(优雅实现Excel导入导出)。
🤖 Spring Boot 2.x 实践案例(代码仓库)
介绍
EasyExcel 是一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具。它能让你在不用考虑性能、内存的等因素的情况下,快速完成 Excel 的读、写等功能。
EasyExcel文档地址:https://easyexcel.opensource.alibaba.com/
快速开始
引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.3</version>
</dependency>
简单导出
以导出用户信息为例,接下来手把手教大家如何使用EasyExcel实现导出功能!
定义实体类
在EasyExcel中,以面向对象思想来实现导入导出,无论是导入数据还是导出数据都可以想象成具体某个对象的集合,所以为了实现导出用户信息功能,首先创建一个用户对象User
实体类,用于封装用户信息:
package com.bailuo.entity;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.converters.Converter;
import com.bailuo.utils.GenderConverter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@ExcelIgnore
private long id;
@ExcelProperty("登录名")
@ColumnWidth(20)
private String loginName;
@ExcelProperty("用户名")
@ColumnWidth(20)
private String userName;
@ExcelProperty("密码")
@ColumnWidth(20)
private String password;
@ExcelProperty(value = "性别",converter = GenderConverter.class)
@ColumnWidth(20)
private Integer sex;
@ExcelProperty("身份证号")
@ColumnWidth(30)
private String identityCode;
@ExcelProperty("邮箱")
@ColumnWidth(30)
private String email;
@ExcelProperty("手机号")
@ColumnWidth(30)
private String mobile;
@ExcelProperty("状态")
private long type;
}
上面代码中类属性上使用了EasyExcel核心注解:
- @ExcelProperty:核心注解,
value
属性可用来设置表头名称,converter
属性可以用来设置类型转换器; - @ColumnWidth:用于设置表格列的宽度;
- @DateTimeFormat:用于设置日期转换格式;
- @NumberFormat:用于设置数字转换格式。
自定义转换器
在EasyExcel中,如果想实现枚举类型到字符串类型转换(例如gender
属性:1 -> 男
,2 -> 女
),需实现Converter
接口来自定义转换器,下面为自定义GenderConverter
性别转换器代码实现:
/**
* Excel 性别转换器
*
* @author william@StarImmortal
*/
public class GenderConverter implements Converter<Integer> {
@Override
public Class<?> supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Integer convertToJavaData(ReadConverterContext<?> context) {
return GenderEnum.convert(context.getReadCellData().getStringValue()).getValue();
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) {
return new WriteCellData<>(GenderEnum.convert(context.getValue()).getDescription());
}
}
/**
* 性别枚举
*
* @author william@StarImmortal
*/
@Getter
@AllArgsConstructor
public enum GenderEnum {
/**
* 未知
*/
UNKNOWN(0, "未知"),
/**
* 男性
*/
MALE(1, "男性"),
/**
* 女性
*/
FEMALE(2, "女性");
private final Integer value;
@JsonFormat
private final String description;
public static GenderEnum convert(Integer value) {
return Stream.of(values())
.filter(bean -> bean.value.equals(value))
.findAny()
.orElse(UNKNOWN);
}
public static GenderEnum convert(String description) {
return Stream.of(values())
.filter(bean -> bean.description.equals(description))
.findAny()
.orElse(UNKNOWN);
}
}
定义接口
package com.bailuo.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.bailuo.entity.User;
import com.bailuo.service.UserService;
import com.bailuo.vo.ResultData;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.security.ProtectionDomain;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@GetMapping("/export")
public void exportUserExcel(HttpServletResponse response) {
try {
// Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class);
// defineClassMethod.setAccessible(true);
this.setExcelResponseProp(response, "用户列表");
List<User> userList = userService.selectUserList();
for (User user : userList) {
System.out.println(user);
}
EasyExcel.write(response.getOutputStream())
.head(User.class)
.excelType(ExcelTypeEnum.XLSX)
.sheet("用户列表")
.doWrite(userList);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 设置响应结果
*
* @param response 响应结果对象
* @param rawFileName 文件名
* @throws UnsupportedEncodingException 不支持编码异常
*/
private void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("a", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
}
/**
* 读取用户列表数据
*
* @return 用户列表数据
* @throws IOException IO异常
*/
private List<User> getUserList() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
ClassPathResource classPathResource = new ClassPathResource("mock/users.json");
InputStream inputStream = classPathResource.getInputStream();
return objectMapper.readValue(inputStream, new TypeReference<List<User>>() {
});
}
}
测试接口
运行项目,通过 Postman 或者 Apifox 工具来进行接口测试
注意:在 Apifox 中访问接口后无法直接下载,需要点击返回结果中的下载图标才行,点击之后方可对Excel文件进行保存。
接口地址:http://localhost:8080/user/export
导入
以导入用户信息为例,接下来手把手教大家如何使用EasyExcel实现导入功能!
package com.bailuo.controller;
import com.alibaba.excel.EasyExcel;
import com.bailuo.entity.User;
import com.bailuo.service.UserService;
import com.bailuo.vo.ResultData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping("/excel")
public class ExcelController {
@Autowired
UserService userService;
@PostMapping("/import/user")
@ResponseBody
public ResultData importUserExcel(@RequestPart(value = "file") MultipartFile file) {
if(file==null){
System.out.println("空空空");
}else{
System.out.println("不空");
}
try {
List<User> userList = EasyExcel.read(file.getInputStream())
.head(User.class)
.sheet()
.doReadSync();
System.out.println(userList);
userService.insertUser(userList);
System.out.println("userList:"+userList);
return ResultData.success(userList);
} catch (IOException e) {
System.out.println("异常异常异常");
return null;
}
}
}