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 {@ExcelIgnoreprivate 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> {@Overridepublic Class<?> supportJavaTypeKey() {return Integer.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}@Overridepublic Integer convertToJavaData(ReadConverterContext<?> context) {return GenderEnum.convert(context.getReadCellData().getStringValue()).getValue();}@Overridepublic 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;@JsonFormatprivate 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 {@AutowiredUserService 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 {@AutowiredUserService userService;@PostMapping("/import/user")@ResponseBodypublic 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;}}
}