From 07b7cd56511f381e6893e457013121641f4531aa Mon Sep 17 00:00:00 2001 From: haoxr <1490493387@qq.com> Date: Wed, 1 Mar 2023 23:22:01 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=94=A8=E6=88=B7=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youlai/system/common/util/ExcelUtils.java | 24 ++++++ .../framework/easyexcel/ExcelResult.java | 17 ++++ .../easyexcel/MyAnalysisEventListener.java | 13 +++ .../system/listener/UserImportListener.java | 79 ++++++++++++++++-- .../youlai/system/pojo/dto/UserImportDTO.java | 58 ------------- .../youlai/system/pojo/vo/UserImportVO.java | 30 +++++++ .../excel-templates/用户导入模板.xlsx | Bin 0 -> 12310 bytes 7 files changed, 155 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/youlai/system/common/util/ExcelUtils.java create mode 100644 src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java create mode 100644 src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java delete mode 100644 src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java create mode 100644 src/main/java/com/youlai/system/pojo/vo/UserImportVO.java create mode 100644 src/main/resources/excel-templates/用户导入模板.xlsx diff --git a/src/main/java/com/youlai/system/common/util/ExcelUtils.java b/src/main/java/com/youlai/system/common/util/ExcelUtils.java new file mode 100644 index 00000000..f107230b --- /dev/null +++ b/src/main/java/com/youlai/system/common/util/ExcelUtils.java @@ -0,0 +1,24 @@ +package com.youlai.system.common.util; + +import com.alibaba.excel.EasyExcel; +import com.youlai.system.framework.easyexcel.ExcelResult; +import com.youlai.system.framework.easyexcel.MyAnalysisEventListener; + +import java.io.InputStream; + +/** + * Excel 工具类 + * + * @author: haoxr + * @date: 2023/03/01 + */ +public class ExcelUtils { + + public static ExcelResult importExcel(InputStream is, Class clazz, MyAnalysisEventListener listener) { + EasyExcel.read(is, clazz, listener).sheet().doRead(); + ExcelResult excelResult = listener.getResult(); + return excelResult; + } + + +} diff --git a/src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java b/src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java new file mode 100644 index 00000000..d1a37136 --- /dev/null +++ b/src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java @@ -0,0 +1,17 @@ +package com.youlai.system.framework.easyexcel; + +import java.util.List; + +/** + * Excel 读取结果 + * + * @author: haoxr + * @date: 2023/03/01 + */ +public interface ExcelResult { + + List getList(); + + String getMsg(); + +} diff --git a/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java b/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java new file mode 100644 index 00000000..00259e60 --- /dev/null +++ b/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java @@ -0,0 +1,13 @@ +package com.youlai.system.framework.easyexcel; + +import com.alibaba.excel.event.AnalysisEventListener; + +/** + * 自定义解析结果监听器 + * + * @author: haoxr + * @date: 2023/03/01 + */ +public abstract class MyAnalysisEventListener extends AnalysisEventListener { + public abstract ExcelResult getResult(); +} diff --git a/src/main/java/com/youlai/system/listener/UserImportListener.java b/src/main/java/com/youlai/system/listener/UserImportListener.java index f486f36c..b8f14af3 100644 --- a/src/main/java/com/youlai/system/listener/UserImportListener.java +++ b/src/main/java/com/youlai/system/listener/UserImportListener.java @@ -1,27 +1,90 @@ package com.youlai.system.listener; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONUtil; import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.event.AnalysisEventListener; -import com.youlai.system.pojo.dto.UserImportDTO; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; +import com.alibaba.excel.util.ListUtils; +import com.youlai.system.framework.easyexcel.ExcelResult; +import com.youlai.system.framework.easyexcel.MyAnalysisEventListener; +import com.youlai.system.pojo.vo.UserImportVO; +import com.youlai.system.service.SysUserService; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; /** + * 用户导入监听器 + *

+ * https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read * * @author haoxr * @date 2022/4/10 20:49 */ -@Component -@Scope("prototype") -public class UserImportListener extends AnalysisEventListener { +@Slf4j +public class UserImportListener extends MyAnalysisEventListener { + /** + * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收 + */ + private static final int BATCH_COUNT = 100; + + /** + * 缓存的数据 + */ + private List cachedUserList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + + + /** + * 部门ID + */ + private final Long deptId; + + private final SysUserService userService; + + public UserImportListener(Long deptId) { + this.deptId = deptId; + this.userService = SpringUtil.getBean(SysUserService.class); + } + + + /** + * 每一条数据解析都会来调用 + * + * @param userImportVO 一行数据,类似于 {@link AnalysisContext#readRowHolder()} + * @param analysisContext + */ @Override - public void invoke(UserImportDTO.UserItem userItem, AnalysisContext analysisContext) { + public void invoke(UserImportVO userImportVO, AnalysisContext analysisContext) { + log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportVO)); + + + } + + /** + * 所有数据解析完成会来调用 + * + * @param analysisContext + */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } + + @Override + public ExcelResult getResult() { + return new ExcelResult() { + @Override + public List getList() { + return null; + } + + @Override + public String getMsg() { + return null; + } + }; + } } diff --git a/src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java b/src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java deleted file mode 100644 index 7f8da694..00000000 --- a/src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.youlai.system.pojo.dto; - -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; - -/** - * 用户导入对象 - * - * @author haoxr - * @date 2022/4/10 - */ -@Data -public class UserImportDTO { - - /** - * 部门ID - */ - private Long deptId; - - /** - * 角色ID - */ - private String roleIds; - - private MultipartFile file; - - /** - * 导入的用户列表 - */ - private List userList; - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class UserItem { - - @ExcelProperty(value = "用户名") - private String username; - - @ExcelProperty(value = "用户昵称") - private String nickname; - - @ExcelProperty(value = "性别") - private String gender; - - @ExcelProperty(value = "手机号码") - private String mobile; - - @ExcelProperty(value = "邮箱") - private String email; - } - -} diff --git a/src/main/java/com/youlai/system/pojo/vo/UserImportVO.java b/src/main/java/com/youlai/system/pojo/vo/UserImportVO.java new file mode 100644 index 00000000..f47a43c9 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/UserImportVO.java @@ -0,0 +1,30 @@ +package com.youlai.system.pojo.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * 用户导入对象 + * + * @author haoxr + * @date 2022/4/10 + */ +@Data +public class UserImportVO { + + @ExcelProperty(value = "用户名") + private String username; + + @ExcelProperty(value = "用户昵称") + private String nickname; + + @ExcelProperty(value = "性别") + private String gender; + + @ExcelProperty(value = "手机号码") + private String mobile; + + @ExcelProperty(value = "邮箱") + private String email; + +} diff --git a/src/main/resources/excel-templates/用户导入模板.xlsx b/src/main/resources/excel-templates/用户导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..601662142d07847810b9a04ec6c9c642a467aa70 GIT binary patch literal 12310 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 literal 0 HcmV?d00001