当前位置: 首页 > news >正文

c 可以用来做网站吗/我赢网客服系统

c 可以用来做网站吗,我赢网客服系统,吴忠住房和城乡建设网站,电脑wordpress客服端❝最近太忙了,刚刚到家赶紧抽空赶一篇,不知道能不能帮到你。最近在做Excel导入功能,产品要求对导入数据先进行校验然后再入库。于是简单封装了一个工具,结果兄弟们用了都说好,今天就把思路分享出来。easyexcel 库我们都…

最近太忙了,刚刚到家赶紧抽空赶一篇,不知道能不能帮到你。

最近在做Excel导入功能,产品要求对导入数据先进行校验然后再入库。于是简单封装了一个工具,结果兄弟们用了都说好,今天就把思路分享出来。

easyexcel 库

我们都知道POI是Java操作Excel的基础库。为了通用性并没有做定制,而且还有一些局限性。经过一番调研决定采用二次封装库easyexcel来进行业务开发。

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>${easyexcel.version}</version>
</dependency>

easyexcel将读取Excel的生命周期抽象为了几个阶段,方便我们在各个阶段注入你想要实现的逻辑。这几个阶段包含在ReadListener接口中

public interface ReadListener<T> extends Listener {/*** 当任何一个侦听器执行错误报告时,所有侦听器都将接收此方法。 如果在此处引发异常,则整个读取将终止。* 这里是处理读取excel异常的** @param exception* @param context* @throws Exception*/void onException(Exception exception, AnalysisContext context) throws Exception;/*** 读取每行excel表头时会执行此方法** @param headMap* @param context*/void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context);/*** 读取每行数据的时候回执行此方法 ** @param data*            one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context*            analysis context*/void invoke(T data, AnalysisContext context);/*** 如果有额外的单元格信息返回就用此方法处理** @param extra*            extra information* @param context*            analysis context*/void extra(CellExtra extra, AnalysisContext context);/*** 在整个excel sheet解析完毕后执行的逻辑。** @param context*/void doAfterAllAnalysed(AnalysisContext context);/*** 用来控制是否读取下一行的策略** @param context* @return*/boolean hasNext(AnalysisContext context);
}

其抽象实现AnalysisEventListener<T>提供更加符合需要的抽象,我会进一步实现这个抽象来实现Excel的导入和校验。

在你了解一个框架的抽象接口后,尽量要去看一下它有没有能满足你需要的实现。

另外这里要多说一点,接口中的AnalysisContext包含了很多有用的上下文元信息,比如 当前行、当前的配置策略、excel整体结构等信息,你可以在需要的时候调用这些信息。

JSR303校验

最开始自己写了一个抽象的校验工具,最后发现每一个字段都要编写其具体的校验逻辑,如果一个Excel的字段量爆炸,这对开发来说就可能是噩梦。这使我想到了业界已经有的规范-JSR303校验规范,它将数据模型(Model)和校验(Validation)各自抽象,非常灵活,而且工作量明显降低。我们只需要找到和esayexcel生命周期结合的地方就行了。我们只需要引入以下依赖就能在Spring Boot项目中集成JSR303校验:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

关于JSR303相关的教程可以查看我这一篇文章。

实现过程

我们可以在解析每个字段的时候校验,这对应ReadListenerinvoke(T data, AnalysisContext context)方法,这种方式可以实现当字段校验触发约束时就停止excel解析的策略;另一种可以在Excel解析完毕后执行校验,对应doAfterAllAnalysed(AnalysisContext context)。这里以第二种为例我们来实现一下。

我们在编写代码时,尽量职责单一,一个类或者一个方法尽量只干一个事,这样让自己的代码足够清晰。

编写校验处理类

这里我把解析和校验分开实现,先编写JSR303校验工具。这里假设已经有了校验器javax.validation.Validator的实现,稍后我会讲这个实现从哪里注入

import cn.felord.validate.Excel;
import lombok.AllArgsConstructor;
import org.springframework.util.StringUtils;import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.*;
import java.util.stream.Collectors;/***  excel 校验工具** @param <T> the type parameter* @author felord.cn* @since 2021 /4/14 14:14*/
@AllArgsConstructor
public class ExcelValidator<T> {private final Validator validator;private final Integer beginIndex;/***  集合校验** @param data 待校验的集合* @return list*/public List<String> validate(Collection<T> data) {int index = beginIndex + 1;List<String> messages = new ArrayList<>();for (T datum : data) {String validated = this.doValidate(index, datum);if (StringUtils.hasText(validated)) {messages.add(validated);}index++;}return messages;}/*** 这里是校验的根本方法** @param index 本条数据所在的行号* @param data 待校验的某条数据* @return 对数据的校验异常进行提示,如果有触发校验规则的会封装提示信息。*/private String doValidate(int index, T data) {// 这里使用了JSR303的的校验器,同时使用了分组校验,Excel为分组标识Set<ConstraintViolation<T>> validate = validator.validate(data, Excel.class);return validate.size()>0 ? "第" + index +"行,触发约束:" + validate.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(",")): "";}
}

上面就是整个校验的逻辑,如果校验通过不提示任何信息,如果校验不通过把校验的约束信息封装返回。这里的Validator是从哪里来的呢?当Spring Boot集成了JSR303会有一个Validator实现被自动注入Spring IoC,我们可以利用它。

实现AnalysisEventListener

这个完全是easyexcel的功能了,我们只需要实现最开始提到的Excel抽象解析监听器接口AnalysisEventListener,并将解析字段加入集合,等完全解析完毕后再进行校验。这里如果校验不通过就会抛出携带校验信息的异常,异常经过处理返回前端提示。

切记AnalysisEventListener的实现不能注入Spring IoC

import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import cn.felord.exception.ServiceException;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;/*** 该类不可被Spring托管** @param <T> the type parameter* @author felord.cn* @since 2021 /4/14 14:19*/
public class JdbcEventListener<T> extends AnalysisEventListener<T> {/*** Excel总条数阈值*/private static final Integer MAX_SIZE = 10000;/*** 校验工具*/private final ExcelValidator<T> excelValidator;/*** 如果校验通过消费解析得到的excel数据*/private final Consumer<Collection<T>> batchConsumer;/*** 解析数据的临时存储容器*/private final List<T> list = new ArrayList<>();/*** Instantiates a new Jdbc event listener.** @param excelValidator Excel校验工具* @param batchConsumer  Excel解析结果批量消费工具,可实现为写入数据库等消费操作*/public JdbcEventListener(ExcelValidator<T> excelValidator, Consumer<Collection<T>> batchConsumer) {this.excelValidator = excelValidator;this.batchConsumer = batchConsumer;}@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {list.clear();throw exception;}@Overridepublic void invoke(T data, AnalysisContext context) {// 如果没有超过阈值就把解析的excel字段加入集合if (list.size() >= MAX_SIZE) {throw new ServiceException("单次上传条数不得超过:" + MAX_SIZE);}list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {//全部解析完毕后 对集合进行校验并消费if (!CollectionUtils.isEmpty(this.list)) {List<String> validated = this.excelValidator.validate(this.list);if (CollectionUtils.isEmpty(validated)) {this.batchConsumer.accept(this.list);} else {throw new ServiceException(JSONUtil.toJsonStr(validated));}}}
}

封装最终的工具

这里参考esayexcel的文档封装成一个通用的Excel读取工具

import com.alibaba.excel.EasyExcel;
import lombok.AllArgsConstructor;
import lombok.Data;import javax.validation.Validator;
import java.io.InputStream;
import java.util.Collection;
import java.util.function.Consumer;/*** excel读取工具** @author felord.cn* @since 2021 /4/14 15:10*/
@AllArgsConstructor
public class ExcelReader {private final Validator validator;/*** Read Excel.** @param <T>  the type parameter* @param meta the meta*/public <T> void read(Meta<T> meta) {ExcelValidator<T> excelValidator = new ExcelValidator<>(validator, meta.headRowNumber);JdbcEventListener<T> readListener = new JdbcEventListener<>(excelValidator, meta.consumer);EasyExcel.read(meta.excelStream, meta.domain, readListener).headRowNumber(meta.headRowNumber).sheet().doRead();}/*** 解析需要的元数据** @param <T> the type parameter*/@Datapublic static class Meta<T> {/*** excel 文件流*/private InputStream excelStream;/*** excel头的行号,参考easyexcel的api和你的实际情况*/private Integer headRowNumber;/*** 对应excel封装的数据类,需要参考easyexcel教程*/private Class<T> domain;/*** 解析结果的消费函数*/private Consumer<Collection<T>> consumer;}}

我们把这个工具注入Spring IoC,方便我们使用。

/*** Excel 读取工具** @param validator the validator* @return the excel reader*/
@Bean
public ExcelReader excelReader(Validator validator) {return new ExcelReader(validator);
}

编写接口

这里Excel的数据类ExcelData就不赘述了,过于简单!去看esayexcel的文档即可。编写一个Spring MVC接口示例,没错就是这么简单。

@Autowired
private  ExcelReader excelReader;
@Autowired
private  DataService dataService;@PostMapping("/excel/import")
public Rest<?> importManufacturerInfo(@RequestPart MultipartFile file) throws IOException {InputStream inputStream = file.getInputStream();ExcelReader.Meta<ExcelData> excelDataMeta = new ExcelReader.Meta<>();excelDataMeta.setExcelStream(inputStream);excelDataMeta.setDomain(ExcelData.class);excelDataMeta.setHeadRowNumber(2);// 批量写入数据库的逻辑excelDataMeta.setConsumer(dataService::saveBatch);this.excelReader.read(excelDataMeta);return RestBody.ok();
}

总结

今天演示了如何将easyexcelJSR303结合起来,其实原理很简单,你只需要找到两个技术的结合点,并把它们组合起来即可,你学到了吗?请多多点赞、关注、转发、再看,多多支持:码农小胖哥 学习更多有用的技巧。

Spring Security 实战干货:WebSecurity和HttpSecurity的关系

2021-04-19

爆料:Spring 2021年的一些发展方向

2021-04-17


http://www.jmfq.cn/news/4972951.html

相关文章:

  • 专做批发网站/网站百度权重
  • 受欢迎的天津网站建设/电商的推广方式有哪些
  • 建设小说网站风险分析/seo海外
  • 石家庄英文网站建设/网店培训
  • python培训价格/宁波seo企业推广
  • 好的网站具备条件/亚马逊市场营销案例分析
  • 南皮县网站建设价格/中国新闻网发稿
  • 网站建设 广西/百度seo效果
  • 公司营销型网站建设/北京网站设计公司
  • 网站备案 公司/seo咨询岳阳
  • 政府网站建设管理工作汇报/seo技术顾问阿亮
  • 青岛高端网站建设/搜索引擎推广的方法有哪些
  • 国内优秀网站赏析/百度风云榜
  • 网站建设设计费用摊销年限/2345浏览器网页版
  • 万邦工程管理咨询有限公司/台州做优化
  • 东莞做工业产品网站建设/网站查询
  • 自适应网站好建们/关键词收录
  • 谁有专门做外挂的网站/安卓优化大师破解版
  • 找人做网站防止别人用/开电商需要多少钱
  • 高品质的网站开发公司/b站黄页推广
  • 网站制作 太原/东莞网络营销推广专业
  • 微信的微网站是什么/自动点击器app
  • phpcms网站模板下载/找片子有什么好的关键词
  • 江西南昌小程序开发/五种关键词优化工具
  • 做动漫网站的心得体会/如何百度推广
  • 哪个网站是做红酒酒的/seo免费优化网址软件
  • wordpress站内搜索次数限制/网络营销核心要素
  • 东莞专业网站设计平台/什么是网络营销平台
  • 建设网站费用如何入账/石家庄网站优化
  • 深圳专业商城网站设计/北京网站建设公司优势