本文SpringBoot学习小营地是SpringBoot与EasyPoi的整合,通过此文章你可以做到基本数据的导入与导出以及导入数据校验
参考官网: easypoi
cn.afterturn
easypoi-spring-boot-starter
4.1.2
也可以替换为:
cn.afterturn
easypoi-base
3.0.3
cn.afterturn
easypoi-web
3.0.3
cn.afterturn
easypoi-annotation
3.0.3
excel操作
由于我使用Google浏览器开始未配置时,导入文件报错:上传文件大小超出
所以本项目中目前定义了上传以及请求文件大小限制(具体可根据业务需求自行修改)
#HTML页面配置
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
#设置文件单次上传与请求无大小限制
servlet:
multipart:
max-file-size: -1
max-request-size: -1
本项目导入导出均可在PostMan软件中测试 当然 本文也编写了导入的HTML页面。
项目结构如下
本文中做了深入导出(关联对象属性导出)具体实体类类注解用法请还是参考官网 easypoi
/**
* @author : leilei
* @date : 11:29 2020/2/22
* @desc : name为在excel 名字 width:表格宽度 orderNum:处于excel第几行 默认为0 replace:替换 例如我的 true 替换为男 suffix:后缀 男生 女生
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
@Excel(name = "用户名", width = 15)
private String username;
@Excel(name = "密码", width = 15, orderNum = "4")
private String password;
@Excel(name = "性别", replace = {"男_true", "女_false"}, suffix = "生", width = 15, orderNum = "1")
private Boolean sex;
@Excel(name = "年龄")
private Integer age;
@Excel(name = "头像", width = 15, height = 15, type = 2, orderNum = "2")
private String headimg;
@Excel(name = "创建时间", exportFormat = "yyyy-MM-dd HH:mm:ss", importFormat ="yyyy-MM-dd HH:mm:ss",width = 25, orderNum = "3")
private LocalDateTime createTime;
/**连表查询时 需要深入导出关联对象属相*/
@ExcelEntity
private DepartMent departMent;
}
须深入导出 关联的对象
/**
* @author : leilei
* @date : 14:36 2020/2/22
* @desc :
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DepartMent {
@Excel(name = "部门")
private String name;
}
由于本文并未连接数据库,所以 导入导出只能通过new 对象存集合的方式进行展示
public interface IEasyPoiService {
/**
* 查询用户列表
* @return
*/
List findUserList();
}
public static String HeadImgUrl = "/static/head.jpg";
@Override
public List findUserList() {
List users = new ArrayList<>();
for (int i = 0; i < 15; i++) {
User user = new User();
user.setUsername("leilei" + i);
if (i % 2 == 0) {
user.setSex(true);
user.setDepartMent(new DepartMent("电商部门"));
} else {
user.setSex(false);
user.setDepartMent(new DepartMent("传统部门"));
}
user.setPassword("leilei" + i);
int age = new Random().nextInt(70 - 35) + 35;
user.setAge(age);
user.setHeadimg(HeadImgUrl);
user.setCreateTime(LocalDateTime.now());
users.add(user);
}
return users;
}
因为本文是SpringBoot 项目,所有的静态资源都是放在src/main/java/resources/static下 直接导入时读取不到文件的(本文中,用户头像存放于本地static下),所以需要自定义一个文件读取类
**
* @author leilei
* @date 2020/02/22
* @desc 文件加载读取类, 根据路径加载指定文件 参照官网修改
*/
@Slf4j
public class FileLoaderImpl implements IFileLoader {
@Override
public byte[] getFile(String url) {
InputStream fileis = null;
ByteArrayOutputStream baos = null;
try {
//判断是否是网络地址
if (url.startsWith("http")) {
URL urlObj = new URL(url);
URLConnection urlConnection = urlObj.openConnection();
urlConnection.setConnectTimeout(30);
urlConnection.setReadTimeout(60);
urlConnection.setDoInput(true);
fileis = urlConnection.getInputStream();
} else {
//先用绝对路径查询,再查询相对路径
try {
fileis = new FileInputStream(url);
} catch (FileNotFoundException e) {
//获取项目文件
fileis = FileLoaderImpl.class.getClassLoader().getResourceAsStream(url);
if (fileis == null) {
fileis = FileLoaderImpl.class.getResourceAsStream(url);
}
}
}
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = fileis.read(buffer)) > -1) {
baos.write(buffer, 0, len);
}
baos.flush();
return baos.toByteArray();
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
IOUtils.closeQuietly(fileis);
IOUtils.closeQuietly(baos);
}
log.error(fileis + "这个路径文件没有找到,请查询");
return null;
}
}
/**
* @author leilei
* @date 2020/02/22
* @desc 使自定义的文件加载类生效 (本地图片)
*/
@Component
public class ExcelListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
POICacheManager.setFileLoader(new FileLoaderImpl());
}
}
@Autowired
private IEasyPoiService easyPoiService;
/**
* 导出1 使用本身代码 导出须校验的数据集
*/
@RequestMapping("/outexcel")
public String download(ModelMap map) {
List list = easyPoiService.findUserVoList();
//导出基本信息的配置
ExportParams params = new ExportParams("用户列表", "用户", ExcelType.XSSF);
// params.setFreezeCol(2);//冻结的列
/**excel文件要导出的数据*/
map.put(NormalExcelConstants.DATA_LIST, list);
/**excel文件导出的实体*/
map.put(NormalExcelConstants.CLASS, UserVo.class);
/**excel文件参数*/
map.put(NormalExcelConstants.PARAMS, params);
/**excel文件名称*/
map.put(NormalExcelConstants.FILE_NAME, "用户列表");
return NormalExcelConstants.EASYPOI_EXCEL_VIEW;
}
/**
* 导出2 使用网上excel导出导入工具类 无需校验的导入导出
*
* @param response
*/
@RequestMapping(value = "/export")
public void exportExcel(HttpServletResponse response) throws IOException {
List users = easyPoiService.findUserList();
ExcelUtils.exportExcel(users, "用户信息表", "用户信息", User.class, "用户信息", response);
}
package com.leilei.util;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
/**
* excel 工具类
*
* @author easypoi
* @date 2020/02/22
*/
public class ExcelUtils {
/**
* 导出excel到
*
* @param list 数据
* @param title 表头
* @param sheetName sheetName
* @param pojoClass 解析的对象类型
* @param fileName 文件名称
* @param isCreateHeader 是否创建表头
* @return 文件路径
*/
public static String exportExcelToFile(List> list, String title, String sheetName, Class> pojoClass, String fileName, boolean isCreateHeader) {
OutputStream out = null;
Workbook workbook = null;
try {
ExportParams exportParams = new ExportParams(title, sheetName, ExcelType.XSSF);
exportParams.setCreateHeadRows(isCreateHeader);
fileName = encodingFilename(fileName);
out = new FileOutputStream(getAbsoluteFile(fileName));
workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
workbook.write(out);
return fileName;
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
} finally {
if (workbook != null) {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* excel 导出到文件
*
* @param list 数据
* @param title 表头
* @param sheetName sheet名称
* @param pojoClass pojo类型
* @param fileName 文件名
* @return 文件路径
*/
public static String exportExcelToFile(List> list, String title, String sheetName, Class> pojoClass, String fileName) {
return exportExcelToFile(list, title, sheetName, pojoClass, fileName, true);
}
/**
* excel 导出到文件
*
* @param list 数据
* @param title 表头
* @param sheetName sheet名称
* @param pojoClass pojo类型
* @return 文件路径
*/
public static String exportExcelToFile(List> list, String title, String sheetName, Class> pojoClass) {
return exportExcelToFile(list, title, sheetName, pojoClass, title, true);
}
/**
* excel 导出到文件
*
* @param list 数据
* @param fileName 文件名
* @param pojoClass pojo类型
* @return 文件路径
*/
public static String exportExcelToFile(List> list, String fileName, Class> pojoClass) {
return exportExcelToFile(list, fileName, fileName, pojoClass, fileName, true);
}
/**
* excel 导出
*
* @param list 数据
* @param title 标题
* @param sheetName sheet名称
* @param pojoClass pojo类型
* @param fileName 文件名称
* @param isCreateHeader 是否创建表头
* @param response
*/
public static void exportExcel(List> list, String title, String sheetName, Class> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) throws IOException {
ExportParams exportParams = new ExportParams(title, sheetName, ExcelType.XSSF);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* excel 导出
*
* @param list 数据
* @param title 标题
* @param sheetName sheet名称
* @param pojoClass pojo类型
* @param fileName 文件名称
* @param response
*/
public static void exportExcel(List> list, String title, String sheetName, Class> pojoClass, String fileName, HttpServletResponse response) throws IOException {
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName, ExcelType.XSSF));
}
/**
* excel 导出
*
* @param list 数据
* @param pojoClass pojo类型
* @param fileName 文件名称
* @param response
* @param exportParams 导出参数
*/
public static void exportExcel(List> list, Class> pojoClass, String fileName, ExportParams exportParams, HttpServletResponse response) throws IOException {
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* excel 导出
*
* @param list 数据
* @param fileName 文件名称
* @param response
*/
public static void exportExcel(List
在浏览器中访问localhost:8080/export 或者 localhost:8080/outexcel 即可将自定义的十多条用户数据导出到Excel表格中 打开即可查看
poi导入测试页面
poi导入测试页面
使用本文提供的Excel工具类进行导入
/**
* 普通导入
*
* @param file
*/
@PostMapping("/import1")
public Object importExcel(MultipartFile file) throws IOException {
List users = ExcelUtils.importExcel(file, User.class);
users.forEach(e -> System.out.println(e));
return users;
}
新建导入导出实体类
Easypoi 中的一些注解 校验
@NotNull 表示导入的此字段值不能为空
@Max 表示此字段值 最大值
@Min 表示此字段值 最小值
还可以正则校验等
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserVo {
@Excel(name = "用户名", width = 15)
@NotNull(message = "用户名不能为空哦!!")
private String username;
@Excel(name = "密码", width = 15, orderNum = "4")
@NotNull(message = "密码不能为空!!")
private String password;
@Excel(name = "性别", replace = {"男_true", "女_false"}, suffix = "生", width = 15, orderNum = "1")
private Boolean sex;
@Excel(name = "年龄")
@Max(value = 65,message = "年龄太大了,不适合工作哦")
private Integer age;
@Excel(name = "头像", width = 15, height = 15, type = 2, orderNum = "2")
private String headimg;
@Excel(name = "创建时间", exportFormat = "yyyy-MM-dd HH:mm:ss", importFormat ="yyyy-MM-dd HH:mm:ss",width = 25, orderNum = "3")
private LocalDateTime createTime;
/**连表查询时 需要深入导出关联对象属相*/
@ExcelEntity
private DepartMent departMent;
自定义校验规则
本文自定义的校验规则 是校验用户名不可重复(其他校验规则可根据自己的业务场景来定) 须编写一个类 实现IExcelVerifyHandler 并覆写其中的方法
/**
* @author : leilei
* @date : 15:36 2020/2/22
* @desc :自定义excel校验名字是否重复 实现IExcelVerifyHandler接口
*/
@Component
public class MyExcelverifiyName implements IExcelVerifyHandler {
@Autowired
private ICheckUserVoService checkUserVoService;
@Override
public ExcelVerifyHandlerResult verifyHandler(UserVo userVo) {
//设置默认验证为true
ExcelVerifyHandlerResult excelVerifyHandlerResult = new ExcelVerifyHandlerResult(true);
if (StringUtils.isNotBlank(userVo.getUsername())) {
UserVo one = checkUserVoService.findOneByname(userVo.getUsername());
//查询不为空则说明数据库中用户已存在,此次录入为重复录入
if (one != null) {
excelVerifyHandlerResult.setSuccess(false);
excelVerifyHandlerResult.setMsg("对不起,此用户已存在,请不要重复提交");
}
}
return excelVerifyHandlerResult;
}
}
校验规则实现类与接口编写
/**
* @author : leilei
* @date : 15:51 2020/2/22
* @desc : 自定义校验规则接口
*/
public interface ICheckUserVoService {
UserVo findOneByname(String username);
}
/**
* @author : leilei
* @date : 15:51 2020/2/22
* @desc : 校验用户是否重复
*/
@Service
public class CheckUserVoServiceImpl implements ICheckUserVoService {
@Override
public UserVo findOneByname(String username) {
/**
* 虚假数据 由于我这里是根据名字查 那么我模拟一个对象返回即可 (实际开发可根据身份证去数据库查询)
*/
if (username .equals("leilei0") ) {
return new UserVo("leilei0", "1", true, 22, "aaa", LocalDateTime.now(), new DepartMent("dianshan"));
}
return null;
}
}
控制层
/**
* 文件校验导入
*
* @return
*/
@RequestMapping("/import2")
public Object upload(MultipartFile file,HttpServletResponse resp) throws Exception {
//导入的基本配置
ImportParams params = new ImportParams();
//表头一行
params.setHeadRows(1);
//标题一行
params.setTitleRows(1);
//代表导入这里是需要验证的(根据字段上的注解校验)
params.setNeedVerify(true);
//设及一个自定义校验 (自定义校验名字不可重复)
params.setVerifyHandler(excelVerifyHandler);
//使用框架自身导入工具
ExcelImportResult result = ExcelImportUtil.importExcelMore(file.getInputStream(), UserVo.class, params);
//导入成功的数据
List list = result.getList();
//失败结果集
List failList = result.getFailList();
//拿到导出失败的工作簿
Workbook failWorkbook = result.getFailWorkbook();
//验证是否有失败的数据
if (result.isVerifyFail()) {
ServletOutputStream fos = resp.getOutputStream();
//mime类型
resp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
resp.setHeader("Content-disposition", "attachment;filename=error.xlsx");
result.getFailWorkbook().write(fos);
fos.close();
}
return failList;
}
导入后 会下载一个Excel 文件 文件中会包含导入失败的数据以及失败原由
SpringBoot 与EasyPoi 导入导出Excel 就到这里了 附上我的源码地址: springboot-easypoi