点击上方“Java基基”,选择“设为星标”
做积极的人,而不是积极废人!
每天 14:00 更新文章,每天掉亿点点头发...
源码精品专栏
原来
Excel 与导出是项目中的一个功能很容易导入中的 Excel,由于 Java 导出。poi,在高处常用导入与运行 OOM 或完全使用 Excel,基于 Easy项目。
简化计算功能,轻松将Excel与解决对象简化了一个API映射Excel之间的简单关系,几行代码除了实现复杂的导入功能,通过导入了。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
EasyExcel 问题
一切都是美好的,不过经常把Excel导入与发布的发现,一样的Excel还是没有完美的。
首先,导入与导出的 Excel 本质是将 Excel 文件内容与 Java 对象之间做一个功能映射,轻松将 Excel 的只是在这之间多转换。如果项目中的 Excel 导入与导出比较,会大量的样板式代码,使用体验类似于 JDBC。
另外,还会附带另外一种校验功能,这是 Easy Excel 不支持的功能。
而目前的 spring boot 已经成为必备的 Java 开发框架,excel 也没有进行整合。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://gitee.com/zhijiantianya/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
分析与解决
导入内容和导出方法通常会发生在 Web 环境中,对于 Spring MVC 来说,可以将请求信息转换为各种类型的控制器方法参数,将控制器返回值作为客户端支持的。
如果使用自定义板的控制器参数接收 Excel 文件内容,将方法控制器的方法返回值转换为 Excel 文件,可以直接从 Excel 导入与导出时的样式代码。
另外在将转换为控制器方法参数时还可以加入自定义请求的逻辑。
Excel 与外接样板代码、看问题的业务逻辑,这里可以单独拿出来,我在 EasyExcel 的基础上板式项目中封装了一个 easyexcel-spring-booter 的项目,导入了 EasyExcel 上手的尺寸窗帘,对用户而言只需要使用 EasyExcel 定义的注解提供映射关系就可以了,适用于场景的简单导入关系。
项目代码已上传:
https://github.com/zzuhkp/easyexcel-spring-boot-starter
下面就来看看如何使用吧。
Spring Boot Excel 导入与导出
引入依
首先需要依赖,坐标如下。
<dependency>
<groupId>com.zzuhkp</groupId>
<artifactId>easyexcel-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
很可能是当前项目的物品传输中央,需要的小伙伴可以自行上传到仓库或直接把代码嵌入自己的仓库。
Excel导入
首先看下要导入的Excel内容吧。
![df608d7ef6cd006c71890b08526a2f2f.png](https://img-blog.csdnimg.cn/img_convert/df608d7ef6cd006c71890b08526a2f2f.png)
为了接收 Excel 文件内容,我们需要定义一个 Model 类。
@Data
public class DemoData {
@ExcelProperty(index = 0)
private Integer integer;
@ExcelProperty(index = 1)
private String string;
@ExcelProperty(index = 2)
private Date date;
}
导入基本功能
然后使用List<T>
参数接收。
@PostMapping("/list/obj")
public List<DemoData> listObj(@ExcelParam List<DemoData> list) {
return list;
}
注意参数前添加了@ExcelParam
注解,使用标识Excel文件参数。这样,一个导入实现功能了,是不是很简单呢?
下接收名称为文件的格式不作为 Excel 文件修改,如果满足还可以默认。
@ExcelParam(value = "file", required = true)
进阶导入功能
例如,Excel 这个对象可能是我们比较有趣的对象的元数据,Excel 是第几行记录产生的,这个对象的字段几列,这时我们可以使用ReadRows<T>
接收。
@PostMapping("/list/rows")
public ReadRows<DemoData> readRows(@ExcelParam ReadRows<DemoData> readRows) {
return readRows;
}
ReadRows 使用两个字段记录行映射关系与列映射关系。
public class ReadRows<T> {
private ExcelReadHeadProperty excelReadHeadProperty;
private List<ReadRow<T>> rows;
}
ExcelReadHeadProperty
是Excel自带的类,列映射关系的元数据。ReadRow是自定义的类,表示Easy行映射关系的元数据。
看下ReadRow定义吧。
public class ReadRow<T> {
// 行索引,从 0 开始
private final Integer rowIndex;
// 行记录对应对象
private final T data;
}
使用ExcelReadHeadProperty
获取字段的索引列的示例。
// 对象字段名称 -> 从 0 开始的列索引
Map<String, Integer> fieldColumnIndexMap = readRows.getExcelReadHeadProperty().getHeadMap().values()
.stream().collect(Collectors.toMap(Head::getFieldName, Head::getColumnIndex));
Excel 导出
这里对Excel的导出进行了简单的支持。将List<T>
定义为controller
方法返回值认知。
@ExcelResponse
@GetMapping("/list/download")
public List<DemoData> downloadList() {
return Arrays.asList(new DemoData(1, "hello", new Date()), new DemoData(2, "excel", new Date()));
}
需要注意的是使用@ExcelResponse
注解表示响应内容为 Excel 文件。默认情况下,下载的文件名称为default.xlxs
,写入名称为 Sheet1 的工作表中。如果不满足需求可以修改。
@ExcelResponse(fileName = "测试文件", sheetName = "工作表1")
Excel导入参数校验
的参数是滑Excel的导入功能,在这里进行了常用的支持,使用如荔枝般顺顺的弹簧靴。
恰巧
与spring boot解使用方式一样,将@Validated
或 @Valid
注添加到@ExcelParam
参数上即可。
@PostMapping("/list/obj")
public List<DemoData> listObj(@ExcelParam @Validated List<DemoData> list) {
return list;
}
智能规则定义
Bean Validation 定义验证规则
下框架使用JSR-303 Bean Validation
规范定义的校验可解校验,需要手动情况spring-boot-starter-validation
,通过设置环境变量默认值easyexcel.validator.default.enable=false
。
@Data
public class DemoData {
@NotNull(message = "参数不能为空")
private Integer integer;
private String string;
private Date date;
}
还可以自定义另外对对象表示感谢。
... 省略其他元注解
@Constraint(validatedBy = {DemoDataValid.DemoDataValidator.class})
public @interface DemoDataValid {
... 省略注解属性
class DemoDataValidator implements ConstraintValidator<DemoDataValid, DemoData> {
@Override
public boolean isValid(DemoData value, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("测试对象校验").addConstraintViolation();
return false;
}
}
}
@DemoDataValid
public class DemoData {
... 省略属性
}
ExcelValidator 接口定义校验规则
Bean Validation
注解只能定义为对某个对象或对象,如果需要所有的对象进行验证,然后可以实现框架定义的ExcelValidator
接口,将实现 Bean。
这个接口定义如下。
public interface ExcelValidator<T> {
ExcelValidErrors validate(ReadRows<T> readRows);
}
ExcelValidErrors
接收确认的错误信息,分别用于使用接口ExcelValidObjectError
和ExcelValidFieldError
接口定义行错误信息和单元格错误信息。
public class ExcelValidErrors {
// 行错误信息或单元格错误信息列表
private final List<ExcelValidObjectError> errors;
}
public interface ExcelValidObjectError {
// 获取行号,从 1 开始
Integer getRow();
// 获取错误消息
String getMessage();
}
public interface ExcelValidFieldError extends ExcelValidObjectError {
// 获取列,从 1 开始
Integer getColumn();
}
例如,如果需要对所有的 DemoData 替换整数字段的值不能重复,可以使用替换的代码。
@Component
public class CustomExcelValidator implements ExcelValidator<DemoData> {
@Override
public ExcelValidErrors validate(ReadRows<DemoData> readRows) {
ExcelValidErrors errors = new ExcelValidErrors();
Map<Integer, List<ReadRow<DemoData>>> group = readRows.getRows().stream()
.collect(Collectors.groupingBy(item -> item.getData().getInteger()));
for (Map.Entry<Integer, List<ReadRow<DemoData>>> entry : group.entrySet()) {
if (entry.getValue().size() > 1) {
for (ReadRow<DemoData> readRow : entry.getValue()) {
errors.addError(new DefaultExcelObjectError(readRow.getRowIndex() + 1, "参数重复"));
}
}
}
return errors;
}
}
校验结果接收
与 Spring MVC 类似设计,这里也提供了接收会话结果的方式。
异常智能手机结果
开启异常方式后,如果信息通知结果中包含错误,错误信息封装ExcelValidException
,可以通过异常异常和异常收集。
@RestControllerAdvice
public class GlobalExceptionControllerAdvice {
@ExceptionHandler(ExcelValidException.class)
public String handleException(ExcelValidException e) {
ExcelValidErrors errors = e.getErrors();
return JSON.toJSONString(errors);
}
}
控制器方法参数验证结果
如果不想通过异常信息的方式接收到错误的信息,还可以将其添加到@ExcelParam
参数的背面,示例代码如下。
@PostMapping("/list/obj")
public List<DemoData> listObj(@ExcelParam @Validated List<DemoData> list, ExcelValidErrors errors) {
if (errors.hasErrors()) {
String messages = errors.getAllErrors().stream().map(ExcelValidObjectError::getMessage).collect(Collectors.joining(" | "));
throw new RuntimeException("发现异常:" + messages);
}
return list;
}
总结
easyexcel-spring-boot-starter
应用了前面文章的各种 Spring 知识量并不大,对具体的小伙伴可以自行统一代码。由于这个框架把 Excel 中的所有数据收集到内存中,因此比较适合一些比较简单的场景。
欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:
已在知识星球更新源码解析如下:
最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。
提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)