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

EasyExcel listener无法通过Autowired注入xxMapper

easyexcel listener无法通过Autowired注入xxMapper

文章目录

  • easyexcel listener无法通过Autowired注入xxMapper
    • bug记录:
    • 解决方案:
    • easyexcel 使用例子
      • controller
      • ServiceImpl
      • listener

bug记录:

productMapper注入一直为null,而procureDetailMapper却正常注入?

@Slf4j
@Component
public class ProductInfoExcelListener<T> extends AnalysisEventListener<T> {/*** 缓存的数据*/private List<ProductEntity> cachedDataList = ListUtils.newArrayList();/*** 存临时表的数据*/
//    private List<ProcureDetailEntity> tempDataList = ListUtils.newArrayList();private final StringBuilder errMsg = new StringBuilder();private boolean hasException = false;private boolean hasNext = true;private IProcureDetailMapper procureDetailMapper;@Autowiredprivate IProductMapper productMapper;public ProductInfoExcelListener(IProcureDetailMapper procureDetailMapper) {this.procureDetailMapper = procureDetailMapper;}// 每解析一行数据就会调用一次该方法 todo@Overridepublic void invoke(T t, AnalysisContext analysisContext) {// 获取行号int index = analysisContext.readRowHolder().getRowIndex() + 1;ProductExcelVo data = (ProductExcelVo) t;String productId = data.getProductId();String productNum = data.getProductNum();String categoryName = data.getCategoryName();String specName = data.getSpecName();if (!StringUtils.hasText(productId)) {hasException = true;setErrMsg(index, ":商品条码不能为空");return;}if (!StringUtils.hasText(productNum)) {hasException = true;setErrMsg(index, ":商品数量不能为空");return;}if (StringUtils.hasText(productNum)) {int productNumInteger = Integer.parseInt(productNum);if (productNumInteger <= 0) {hasException = true;setErrMsg(index, ":商品数量不能小于0");return;}}if (!StringUtils.hasText(categoryName)) {hasException = true;setErrMsg(index, ":分类名称不能为空");return;}//根据商品条码查询对应的分类信息ProductEntity productBaseDByProductId = productMapper.findProductBaseDByProductId(productId);if (productBaseDByProductId == null) {hasException = true;setErrMsg(index, ":该商品不存在");return;}if (!productBaseDByProductId.getCategoryName().equals(categoryName)) {hasException = true;setErrMsg(index, ":该商品的分类名称有误");return;}cachedDataList.add(productBaseDByProductId);log.info("invoke" + index);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// excel解析完毕以后需要执行的代码
//        saveData()log.info("doAfterAllAnalysed ");}public List getCachedDataList() {return cachedDataList;}private void setErrMsg(int index, String msg) {this.hasNext = false;this.hasException = true;errMsg.append("第").append(index).append(msg);log.error("row {} org data verify failure:{};", index, msg);}public StringBuilder getErrMsg() {return errMsg;}public boolean isHasException() {return hasException;}
}
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ProcureDetailServiceImpl implements IProcureDetailService {private final IProcureDetailMapper procureDetailMapper;@Overridepublic ProductInfo uploadAndParseExcel(MultipartFile file) throws IOException, CustomException {ProductInfoExcelListener<ProductExcelVo> listener = new ProductInfoExcelListener<>(procureDetailMapper);EasyExcel.read(file.getInputStream(),ProductExcelVo.class,listener).sheet().doRead();System.out.println("*******************");System.out.println(listener.getCachedDataList().size() == 0);System.out.println("1111111111111111111");List<ProductEntity> cachedDataList = listener.getCachedDataList();log.info("isHasException:{}", listener.getErrMsg());if(listener.isHasException()){throw new CustomException(CommonConstant.ErrorConstants.EXCEL_UNKNOWN_ERROR.getCode(), listener.getErrMsg().toString());}for (ProductEntity p: cachedDataList){System.out.println(p.toString());}return null;}
}

springboot在listener和filter中注入mapper会为null?

解决方案:

  1. https://codeleading.com/article/13375080759/
  2. 构造器注入

easyexcel 使用例子

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.0</version></dependency>

controller

 @Slf4j
@RestController
@RequestMapping("/api-procure/procureController")
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ProcureController extends BaseController {private final IProcureDetailService procureDetailService;/*** 上传excel并且校验解析 procure** @param file      excel* @param loginUser 登录用户* @return* @throws Exception*/@PostMapping("/uploadExcel/procure")public Result<ProductInfo> uploadExcelP(@RequestBody MultipartFile file, @LoginUser LoginUserBean loginUser) throws Exception {log.info("upload excel file:{}", file.getName());ProductInfo data = procureDetailService.uploadAndParseExcel(file, loginUser, CommonConstant.Type.PROCURE.getCode());return Result.succeed(data, "上传成功");}
}

ServiceImpl

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ProcureDetailServiceImpl implements IProcureDetailService {private final IProcureDetailMapper procureDetailMapper;@Overridepublic ProductInfo uploadAndParseExcel(MultipartFile file, LoginUserBean loginUser, String type) throws IOException, CustomException {ProductInfoExcelListener<ProductExcelVo> listener = new ProductInfoExcelListener<>(procureDetailMapper, productMapper);EasyExcel.read(file.getInputStream(),ProductExcelVo.class,listener).sheet().doRead();if (listener.getCachedDataList().size() == 0) {throw new CustomException(CommonConstant.ErrorConstants.EXCEL_UNKNOWN_ERROR.getCode(), "没有有效数据");}List<ProcureDetailEntity> cachedDataList = listener.getCachedDataList();log.info("isHasException:{}", listener.getErrMsg());if (listener.isHasException()) {throw new CustomException(CommonConstant.ErrorConstants.EXCEL_UNKNOWN_ERROR.getCode(), listener.getErrMsg().toString());}
//        for (ProductEntity p : cachedDataList) {
//            System.out.println(p.toString());
//        }if (cachedDataList == null || cachedDataList.size() == 0) {throw new CustomException(CommonConstant.ErrorConstants.EXCEL_UNKNOWN_ERROR.getCode(), "未检测到有效数据");}String userId = loginUser.getUserId();Date date = new Date();//申请标号采购申请单ID 订单//“P”+YYYYMMDDHHMMSS+6位随机数  “PO”+YYYYMMDDHHMMSS+6位随机数String pattern = "YYYYMMDDHHMMSS";SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);String format = dateFormat.format(date);int i = (int) ((Math.random() * 9 + 1) * 100000);String procureId;if (type.equals(CommonConstant.Type.PROCURE.getCode())) {procureId = "P" + format + i;} else if (type.equals(CommonConstant.Type.ORDER.getCode())) {procureId = "PO" + format + i;} else {procureId = null;log.info("这一步执行到就完蛋了");}//存入t_procure_detail_tmp表procureDetailMapper.batchInsertProcureDetailTempList(procureId, userId, date, cachedDataList);//返回响应实体列表ProductInfo productInfo = new ProductInfo();List<ProcureDetailEntity> list = cachedDataList.stream().map(e -> {e.setProcureId(procureId);return e;}).collect(Collectors.toList());productInfo.setProductList(list);return productInfo;}
}

listener

/*** @description <采购申请解析返回的excel信息监听器>* <p>* <p>* 解析模板导入的数据,对商品条码、分类名称、规格名称校验其有效性是否存在,对数量校验大于0.其数据保存在采购单商品临时表.* @author: zhouchaoyu* @Date: 2023-11-14*/
@Slf4j
@Component
public class ProductInfoExcelListener<T> extends AnalysisEventListener<T> {/*** 缓存的数据*/private List<ProcureDetailEntity> cachedDataList = ListUtils.newArrayList();/*** 存临时表的数据*/
//    private List<ProcureDetailEntity> tempDataList = ListUtils.newArrayList();private final StringBuilder errMsg = new StringBuilder();private boolean hasException = false;private boolean hasNext = true;private IProcureDetailMapper procureDetailMapper;private IProductMapper productMapper;public ProductInfoExcelListener(IProcureDetailMapper procureDetailMapper, IProductMapper productMapper) {this.procureDetailMapper = procureDetailMapper;this.productMapper = productMapper;}// 每解析一行数据就会调用一次该方法 todo@Overridepublic void invoke(T t, AnalysisContext analysisContext) {// 获取行号int index = analysisContext.readRowHolder().getRowIndex() + 1;ProductExcelVo data = (ProductExcelVo) t;String productId = data.getProductId();String productNum = data.getProductNum();String categoryName = data.getCategoryName();String specName = data.getSpecName();if (!StringUtils.hasText(productId)) {hasException = true;setErrMsg(index, ":商品条码不能为空");return;}if (!StringUtils.hasText(productNum)) {hasException = true;setErrMsg(index, ":商品数量不能为空");return;}if (StringUtils.hasText(productNum)) {int productNumInteger = Integer.parseInt(productNum);if (productNumInteger <= 0) {hasException = true;setErrMsg(index, ":商品数量不能小于0");return;}}if (!StringUtils.hasText(categoryName)) {hasException = true;setErrMsg(index, ":分类名称不能为空");return;}//根据商品条码查询对应的分类信息ProductEntity productBaseDByProductId = productMapper.findProductBaseDByProductId(productId);if (productBaseDByProductId == null) {hasException = true;setErrMsg(index, ":该商品不存在");return;}if (!productBaseDByProductId.getCategoryName().equals(categoryName)) {hasException = true;setErrMsg(index, ":该商品的分类名称有误");return;}String uid = IdGenerator.getIdStr() ;ProcureDetailEntity procureDetailEntity = new ProcureDetailEntity();procureDetailEntity.setId(uid);procureDetailEntity.setProductId(productBaseDByProductId.getProductId());procureDetailEntity.setProductNum(Integer.parseInt(productNum));procureDetailEntity.setCategoryId(productBaseDByProductId.getCategoryId());procureDetailEntity.setSpecId(specName);procureDetailEntity.setRowStatus("1");procureDetailEntity.setProductName(productBaseDByProductId.getProductName());procureDetailEntity.setCategoryName(productBaseDByProductId.getCategoryName());procureDetailEntity.setInventoryCount(productBaseDByProductId.getInventoryCount());BigDecimal costPrice = productBaseDByProductId.getCostPrice();BigDecimal totalPrice = costPrice.multiply(new BigDecimal(productNum)).setScale(2, RoundingMode.HALF_UP);procureDetailEntity.setTotalPrice(totalPrice);cachedDataList.add(procureDetailEntity);log.info("invoke" + index);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// excel解析完毕以后需要执行的代码
//        saveData()log.info("doAfterAllAnalysed ");}public List<ProcureDetailEntity> getCachedDataList() {return cachedDataList;}private void setErrMsg(int index, String msg) {this.hasNext = false;this.hasException = true;errMsg.append("第").append(index).append(msg);log.error("row {} org data verify failure:{};", index, msg);}public StringBuilder getErrMsg() {return errMsg;}public boolean isHasException() {return hasException;}
}

相关文章:

EasyExcel listener无法通过Autowired注入xxMapper

easyexcel listener无法通过Autowired注入xxMapper 文章目录 easyexcel listener无法通过Autowired注入xxMapperbug记录&#xff1a;解决方案&#xff1a;easyexcel 使用例子controllerServiceImpllistener bug记录&#xff1a; productMapper注入一直为null,而procureDetailM…...

Android Spannable 使用​注意事项

1、当前示例中间的 "评论"&#xff0c;使用SpannableStringBuilder实现&#xff0c;点击评论会有高亮效果加粗&#xff0c;但再点击其它Bar时无法恢复默认样式。 2、因为SpannableString或SpannableStringBuilder中的效果是叠加的&#xff0c;恢复默认样式需要先移除…...

Apache访问控制

服务器相关的访问控制 Options指令 Options指令是Apache服务器配置文件中的一个重要指令,它可以用于控制特定目录启用哪些服务器特性。Options指令可以在Apache服务器的核心配置、虚拟主机配置、特定目录配置以及.htaccess文件中使用。 以下是一些常用的服务器特性选项: N…...

二、类与对象(二)

8 this指针 8.1 this指针的引入 我们先来定义一个日期的类Date&#xff1a; #include <iostream> using namespace std; class Date { public:void Init(int year, int month, int day){_year year;_month month;_day day;}void Print(){cout << _year <&l…...

Pytorch从零开始实战10

Pytorch从零开始实战——ResNet-50算法实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——ResNet-50算法实战环境准备数据集模型选择开始训练可视化模型预测总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c…...

设计模式-单例模式实战

目录 一、引言二、适用场景三、代码实战饿汉式单例模式懒汉式单例模式双重检查锁定单例模式静态内部类单例模式 四、实际应用举例Runtime解析 五、结论 一、引言 单例模式是一种创建型设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;且提供全局访问点以访问该实例…...

requests库出现AttributeError问题的修复与替代方法

在使用App Engine时&#xff0c;开发者们通常会面临需要发送爬虫ip请求的情况&#xff0c;而Python中的requests库是一个常用的工具&#xff0c;用于处理爬虫ip请求。然而&#xff0c;在某些情况下&#xff0c;开发者可能会遇到一个名为AttributeError的问题&#xff0c;特别是…...

opencv-2D直方图

cv2.calcHist() 是 OpenCV 中用于计算直方图的函数。它可以计算一维或多维直方图&#xff0c;用于分析图像中像素值的分布。 基本的语法如下&#xff1a; hist cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])参数说明&#xff1a; images:…...

读像火箭科学家一样思考笔记06_初学者之心

1. 专业化是目前流行的趋势 1.1. 通才&#xff08;generalist&#xff09;是指博而不精之人 1.2. 懂得的手艺越多&#xff0c;反而会家徒四壁 1.2.1. 希腊谚语 1.3. 这种态度代价很大&#xff0c;它阻断了不同学科思想的交融 2. 组合游戏 2.1. 某个行业的变革可能始于另一…...

中职组网络安全 Server-Hun-1.img Server-Hun-2.img

一串密码 smbuser用户和密码登录ssh还是失败提示需要密钥&#xff0c;尝试ftp登录成功 发现密钥存放在.ssh/下&#xff0c;在kali上生成一个密钥&#xff0c;通过上传到.ssh/下&#xff0c;将其替换掉 使用kali生成密钥 登录成功,但是无法拿到root目录下的flag 获取root用户权限…...

基于区域划分的GaN HEMT 准物理大信号模型

GaN HEMT器件的大信号等效电路模型分为经验基模型和物理基模型。经验基模型具有较高精度但参数提取困难&#xff0c;特别在GaN HEMT器件工艺不稳定的情况下不易应用。相比之下&#xff0c;物理基模型从器件工作机理出发&#xff0c;参数提取相对方便&#xff0c;且更容易更新和…...

laravel引入element-ui后,blade模板中使用elementui时,事件未生效问题(下载element-ui到本地直接引入项目)

背景 重构公司后台项目&#xff0c;使用了dcat-admin&#xff0c;但是dcat-admin有些前端功能不能满足需求。因此引入element-ui进行相关界面的优化 具体流程 1.下载element-ui到本地 2.进入如下目录 打开 node_modules\element-ui\lib 复制index.js 打开 node_modules/ele…...

【计算机网络笔记】路由算法之层次路由

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…...

【华为OD机试python】分糖果【2023 B卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。 当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够) 取出一个糖果或放回一个糖果。 小明最少需要多…...

ARM 汇编基础

我们在学习 STM32 的时候几乎没有用到过汇编&#xff0c;可能在学习 UCOS 、 FreeRTOS 等 RTOS 类操作系统移植的时候可能会接触到一点汇编。但是我们在进行嵌入式 Linux 开发的时候是绝 对要掌握基本的 ARM 汇编&#xff0c;因为 Cortex-A 芯片一上电 SP 指针还…...

虹科Pico汽车示波器 | 汽车免拆检修 | 2017款东风本田XR-V车转向助力左右不一致

一、故障现象 一辆2017款东风本田XR-V车&#xff0c;搭载R18ZA发动机&#xff0c;累计行驶里程约为4万km。车主反映&#xff0c;车辆行驶或静止时&#xff0c;向右侧转向比向左侧转向沉重。 二、故障诊断 接车后试车&#xff0c;起动发动机&#xff0c;组合仪表上无故障灯点亮&…...

阿里云服务器ECS经济型e实例优惠99元性能怎么样?

阿里云服务器ECS经济型e实例优惠99元性能怎么样&#xff1f;阿里云服务器优惠99元一年&#xff0c;配置为云服务器ECS经济型e实例&#xff0c;2核2G配置、3M固定带宽和40G ESSD Entry系统盘&#xff0c;CPU采用Intel Xeon Platinum架构处理器&#xff0c;2.5 GHz主频&#xff0…...

vue3引入vuex基础

一&#xff1a;前言 使用 vuex 可以方便我们对数据的统一化管理&#xff0c;便于各组件间数据的传递&#xff0c;定义一个全局对象&#xff0c;在多组件之间进行维护更新。因此&#xff0c;vuex 是在项目开发中很重要的一个部分。接下来让我们一起来看看如何使用 vuex 吧&#…...

C++二维数组中的查找

4. 二维数组中的查找 题目链接 牛客网 题目描述 给定一个二维数组,其每一行从左到右递增排序,从上到下也是递增排序。给定一个数,判断这个数是否在该二维数组中。 Consider the following matrix: [[1, 4, 7, 11, 15],[2, 5, 8, 12, 19],[3, 6, 9, 16, 22],[1…...

【计算思维】蓝桥杯STEMA 科技素养考试真题及解析 2

1、兰兰有一些数字卡片&#xff0c;从 1 到 100 的数字都有&#xff0c;她拿出几张数字卡片按照一定顺序摆放。想一想&#xff0c;第 5 张卡片应该是 A、11 B、12 C、13 D、14 答案&#xff1a;C 2、按照下图的规律&#xff0c;阴影部分应该填 A、 B、 C、 D、 答案&am…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...