需求分析
Excel导入去做一些前置检查,包括非空检查和根据前面的字段生成对应的值、唯一索引等检查。
以及导入的数据失败的原因,成功的条数日志记录。
Excel的标题名和字段名数据库映射。
思路
数据映射
之前其实是有一个版本,是按照getCell(0) 列数来获取的,并没有做数据映射。这个有一个问题,就是模板一旦出现一点改动,随之而来的就是代码的大量改动。
并且硬编码代码过多,当然他也有优点,效率高。
为了完成数据映射,那么就必须引入反射,自定义注解来帮助我们完成数据映射,自定义注解引入的话,就会出现一个bean需要单独的维护。
字典
并且之前的字典写法,static {
// 加载map
}
创建了n个map,然后put进去。
这样子,会影响性能。
下个一版本,改为enum枚举类。

有效行数
还有一个成功条数和失败条数,本人使用了Atomic原子类,总觉得i++,i—不放心,所以我就使用了原子类。 POI的API没有计算有效行数,故而需要我们写代码实现。比如:getLastRowNum()方法获取也不是正确的行数。
什么是有效行数?
每一行有真正的数据,而不是空行数据。

这个逻辑就是有三个原子类。

我认为当连续空行数大于100行,那么没必要继续遍历查询。
计算有内容行核心逻辑

难点与问题
第一个难点
list.add()内容覆盖问题
参照我的博客解决方案。
https://blog.csdn.net/qq_41520636/article/details/124493078
第二个难点
比如:
class A {
private B b;
}
class B {
}
此时应该怎么处理这个B,相当于标题栏里面正好有两个Bean,还好这个情况只有一个,不然我心态崩了。
这个解决方案只有看代码了。
第三个难点
比如:
class A{
private String name;
}
class B {
private String name;
}
这两个其实一对一关系,并且在标题映射时,我用怎么让B获取到A的值。
实现
因为是公司代码就不贴全部代码,只贴核心代码。
/*** <p>* excel导入注解* </p>** @author lisonglin* @version 1.0* @since 2022/4/25 16:19*/@Documented@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ExcelImport {/*** 与excel标题头对应*/String exportName();/*** 转换格式, 如时间类型 yyyy-MM-dd HH:mm:ss*/String pattern() default "";/*** 在excel中位置*/int order() default 0;/*** 长度**/int width() default 0;/*** 检查非空**/boolean checkNotNull() default false;/*** 唯一性*/boolean uniqueness() default false;/*** 可根据其他属性生成的Code(如果没有设置,则根据其他属性生成)*/String rule() default "";}
/*** <p>* 字典* </p>** @author lisonglin* @version 1.0* @since 2022/4/25 19:42*/@Documented@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface Dict {/*** 对应字典名称**/Class dictClass();}
/*** <p>* 字段映射* </p>** @author lisonglin* @version 1.0* @since 2022/5/6 19:27*/@Documented@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ExcelMapping {/*** 映射名*/String mappingName() default "";/*** 是否必填*/boolean isRequired() default false;}
/*** <p>* 默认值注解* </p>** @author lisonglin* @version 1.0* @since 2022/4/25 18:28*/@Documented@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ExcelToValue {String value() default "";}
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface TableName {String value() default "";}
@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Column {String value() default "";}
@TableName("ZJDSP_ZJDZD")public class ZjdspZjdzd implements Serializable {/****/@JSONField(name = "iid")@Column("IID")private String iid;/****/@ExcelToValue(value = Constants.INPUT_INDEX)@JSONField(name = "input_index")@Column("INPUT_INDEX")private String inputIndex;/*** 要素代码*/@ExcelToValue(value = YsdmConstans.YSDM_ZRZ)@JSONField(name = "ysdm")@Column("YSDM")private String ysdm;/*** 所有权人代码*/@ExcelImport(exportName = "所有权人代码", checkNotNull = true, uniqueness = true)@JSONField(name = "suyqrdm")@Column("SUYQRDM")private String suyqrdm;/*** 宅基地代码(所有权人代码+6位顺序号)*/@ExcelMapping(mappingName = "ZjdspZjdzd")@ExcelImport(exportName = "宅基地代码", checkNotNull = true, uniqueness = true, rule = "SUYQRDM")@JSONField(name = "zjddm")@Column("ZJDDM")private String zjddm;@ExcelToValueprivate ZjdspZjdzdxx zjdspZjdzdxx;}
@TableName("ZJDSP_ZJDZDXX")public class ZjdspZjdzdxx implements Serializable {/****/@JSONField(name = "iid")@Column("IID")private String iid;/****/@ExcelToValue(value = Constants.INPUT_INDEX)@JSONField(name = "input_index")@Column("INPUT_INDEX")private String inputIndex;/*** 要素代码*/@ExcelToValue(value = YsdmConstans.YSDM_ZJDZDXX)@JSONField(name = "ysdm")@Column("YSDM")private String ysdm;/*** 宅基地代码*/@ExcelMapping(mappingName = "ZjdspZjdzdxx", isRequired = true)@JSONField(name = "zjddm")@Column("ZJDDM")private String zjddm;}
package antu.zjdsjjg.tool;import antu.com.Database;import antu.com.annotations.Column;import antu.com.annotations.TableName;import antu.com.tools.LogUtils;import antu.zjdsjjg.action.AppConfig;import antu.zjdsjjg.domian.*;import antu.zjdsjjg.domian.constants.Constants;import antu.zjdsjjg.domian.constants.ExcelConstants;import antu.zjdsjjg.model.ZjdspDrlsLog;import antu.zjdsjjg.model.port.ObjectLocal;import antu.zjdsjjg.model.vo.ContentVo;import antu.zjdsjjg.provider.wh.GetWhAdapterProvider;import antu.zjdsjjg.provider.wh.GetWhAdapterProviderImpl;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.apache.commons.lang.StringUtils;import org.apache.commons.lang3.SerializationUtils;import org.apache.poi.hssf.usermodel.HSSFDataFormat;import org.apache.poi.hssf.usermodel.HSSFDateUtil;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.ss.usermodel.*;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.springframework.util.StopWatch;import org.springframework.web.multipart.MultipartFile;import java.beans.PropertyDescriptor;import java.io.IOException;import java.io.InputStream;import java.io.Serializable;import java.lang.reflect.*;import java.text.DecimalFormat;import java.text.SimpleDateFormat;import java.util.*;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.atomic.AtomicInteger;/*** <p>* excel工具类* </p>** @author lisonglin* @version 1.0* @since 2022/3/9 14:10*/public class ExcelTool {/*** 导入excel** @param multipartFile 文件* @param sheet 工作表* @param jsonData json* @return 导入的数据*/public static List<Object> importExcel(MultipartFile multipartFile, String jsonData, String token,String... sheet) {JSONObject jsonObject = JSONObject.parseObject(jsonData);String xzqdm = jsonObject.getString("xzqdm");String userid = jsonObject.getString("userid");String cjzzdm = jsonObject.getString("cjzzdm");String zjzzdm = jsonObject.getString("zjzzdm");StopWatch watch = new StopWatch();watch.start();// 获取用户名String userSql = "select name from st_employee where employee_id = ?";Database atpDb = new Database(AppConfig.atp_db);String userName = atpDb.firstOrDefault(String.class, userSql, userid);// 日志记录初始值ZjdspDrlsLog zjdspDrlsLog = new ZjdspDrlsLog();// 设置行政区代码zjdspDrlsLog.setXzqdm(xzqdm);// 设置操作系统名zjdspDrlsLog.setMis(AppConfig.zjdsjjg_db);// 设置导入时间为系统时间zjdspDrlsLog.setImportDate(new java.sql.Timestamp(System.currentTimeMillis()));// 设置导入人zjdspDrlsLog.setCreateUser(userName);zjdspDrlsLog.setCjzzdm(cjzzdm);zjdspDrlsLog.setZjzzdm(zjzzdm);if (!checkFile(multipartFile)) {LogUtils.warn("上传的文件类型出错!");// 设置导入状态为失败zjdspDrlsLog.setHandleType(ExcelConstants.EXCEL_TYPE_ERROR);// 设置导入类型zjdspDrlsLog.setGrade(ExcelConstants.EXCEL_GRADE_ERROR);// 设置失败原因zjdspDrlsLog.setContent("上传的文件类型出错!");return null;}Workbook workBook = getWorkBook(multipartFile);return parseExcel(workBook, zjdspDrlsLog, xzqdm, token, watch, sheet);}/*** 日期类型转换** @param cell 单元格* @return 字符串的时间*/public static String stringDateProcess(Cell cell) {String result;// 处理日期格式、时间格式short dataFormat = cell.getCellStyle().getDataFormat();if (HSSFDateUtil.isCellDateFormatted(cell)) {SimpleDateFormat sdf = null;if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {sdf = new SimpleDateFormat("HH:mm");} else {// 日期sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");}Date date = cell.getDateCellValue();result = sdf.format(date);} else if (dataFormat == ExcelConstants.EXCEL_DATE_MD) {// 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");double value = cell.getNumericCellValue();Date date = DateUtil.getJavaDate(value);result = sdf.format(date);} else {double value = cell.getNumericCellValue();// int类型if (String.valueOf(value).indexOf(".0") > 0) {result = String.valueOf(value).substring(0, String.valueOf(value).indexOf(".0"));} else {// double类型DecimalFormat format = new DecimalFormat();int len = (value + "").length() - (value + "").indexOf(".") - 1;if (len > 0) {format.applyPattern("#." + StringUtils.repeat("0", len));} else {format.applyPattern("#");}result = format.format(value);}}return result;}/*** 转换excel数据类型** @param cell 单元格* @return 转换后的数据*/private static String convertCellValueToString(Cell cell) {if (cell == null || cell.toString().trim().equals(Constants.EMPTY)) {return null;}String cellValue;switch (cell.getCellTypeEnum()) {case BOOLEAN:// 读取布尔cellValue = String.valueOf(cell.getBooleanCellValue());break;case NUMERIC:// 读取日期格式cellValue = stringDateProcess(cell);break;case FORMULA:// 读取公式cellValue = String.valueOf(cell.getCellFormula());break;case STRING:// 读取StringcellValue = String.valueOf(cell.getStringCellValue());break;case ERROR:// 读取故障cellValue = "非法字符";break;case _NONE:case BLANK:cellValue = "";break;default:cellValue = "未知类型";}return cellValue;}/*** 获取字段键值对 如:{所有权人代码=["setSuyqrdm", "yyyy-MM-dd", “”, “91360421MA35XB656Y”]}* 键值对关系:* Excel表头的字段名称 = [字段set方法名, 时间格式, 需要匹配的字典, 默认值]** @param clazz 实体类* @return 字段键值对*/public static List<Object> getFieldMap(Class<?> clazz, Object catObj) {Field[] fields = clazz.getDeclaredFields();List<Object> objectList = new ArrayList<>();// 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中Map<String, ObjectLocal> fieldMap = new HashMap<>(10);Map<String, Object[]> childrenSetMap = new HashMap<>(2);try {// 循环读取所有字段for (Field field : fields) {putMap(clazz, fieldMap, field, catObj, childrenSetMap);}} catch (Exception e) {throw new RuntimeException(e);}objectList.add(fieldMap);objectList.add(childrenSetMap);return objectList;}/*** 将对象实例添加进Map中(处理一些默认值)** @param clazz bean* @param fieldMap 字段Map* @param field 字段属性* @param newInstance 实例化对象* @throws Exception 异常*/private static void putMap(Class<?> clazz, Map<String, ObjectLocal> fieldMap, Field field, Object newInstance,Map<String, Object[]> childrenSetMap) throws Exception {ExcelImport exa = field.getAnnotation(ExcelImport.class);ExcelToValue eValue = field.getAnnotation(ExcelToValue.class);boolean isExist = field.isAnnotationPresent(ExcelToValue.class);Dict dict = field.getAnnotation(Dict.class);Column column = field.getAnnotation(Column.class);ExcelMapping excelMapping = field.getAnnotation(ExcelMapping.class);Enum[] enumConstants = null;if (null != excelMapping){String fieldName = field.getName();PropertyDescriptor propertyDescriptor = new PropertyDescriptor(fieldName, clazz);Method writeMethod = propertyDescriptor.getWriteMethod();Method readMethod = propertyDescriptor.getReadMethod();boolean required = excelMapping.isRequired();String mappingName = excelMapping.mappingName();if (required) {// zjdxxchildrenSetMap.put(mappingName, new Object[]{writeMethod});} else {// zjdzdchildrenSetMap.put(mappingName, new Object[]{readMethod});}}if (exa != null) {String fieldName = field.getName();// 数据库映射值String value = column.value();PropertyDescriptor propertyDescriptor = new PropertyDescriptor(fieldName, clazz);Method writeMethod = propertyDescriptor.getWriteMethod();Method readMethod = propertyDescriptor.getReadMethod();// 非空检查boolean checkNotNull = exa.checkNotNull();// 唯一性检查boolean uniqueness = exa.uniqueness();// 可生成性检查String generativeCode = exa.rule();Method dictMethod = null;if (dict != null) {Class<Enum> aClass = dict.dictClass();// 获取所有枚举实例enumConstants = aClass.getEnumConstants();dictMethod = aClass.getDeclaredMethod("getNameByRole", String.class);}ObjectLocal objectLocal = new ObjectLocal();objectLocal.setWriteMethod(writeMethod);objectLocal.setReadMethod(readMethod);objectLocal.setCheckNotNull(checkNotNull);objectLocal.setUniqueness(uniqueness);objectLocal.setGenerativeCode(generativeCode);objectLocal.setDictMethod(dictMethod);objectLocal.setEnumConstants(enumConstants);objectLocal.setValue(value);objectLocal.setNewInstance(newInstance);fieldMap.put(exa.exportName(), objectLocal);}if (isExist) {// 默认值String value = eValue.value();String fieldName2 = field.getName();PropertyDescriptor propertyDescriptor2 = new PropertyDescriptor(fieldName2, clazz);Method writeMethod2 = propertyDescriptor2.getWriteMethod();if (!StringUtil.isNullOrEmpty(value)) {writeMethod2.invoke(newInstance, value);} else {// 内部对象Class<?> type = field.getType();// 内部对象Object instance = type.newInstance();for (Field declaredField : type.getDeclaredFields()) {putMap(type, fieldMap, declaredField, instance, childrenSetMap);}// 内部对象set进包裹对象childrenSetMap.put("children", new Object[]{writeMethod2, newInstance, instance});}}}/*** 解析excel** @param workbook 工作簿* @param zjdspDrlsLog 日志* @param sheets 工作表* @return 解析的数据*/public static List<Object> parseExcel(Workbook workbook, ZjdspDrlsLog zjdspDrlsLog, String xzqdm, String token,StopWatch watch, String... sheets) {List<Object> resultList = new CopyOnWriteArrayList<>();List<Object> resultList2 = new CopyOnWriteArrayList<>();// 返回的真实行数AtomicInteger realRow = new AtomicInteger(0);// 连续空行数AtomicInteger emptyRow = new AtomicInteger(0);// 失败行数AtomicInteger failureRow = new AtomicInteger(0);// 主体内容,包括成功条数和失败条数,失败原因,以及失败的数据List<ContentVo> contentVoList = new ArrayList<>();Database zjdsjjgDb = new Database(AppConfig.zjdsjjg_db);// 解析sheetfor (String sheet : sheets) {try {String clazzName = ExcelEnum.getNameByRole(sheet);Class<?> classType = Class.forName(clazzName);Object catObj = classType.newInstance();TableName tableName = catObj.getClass().getAnnotation(TableName.class);String table = tableName.value();// 获取自定义注解的信息List<Object> list = getFieldMap(classType, catObj);Map<String, ObjectLocal> fieldMap = (Map<String, ObjectLocal>) list.get(0);SimpleObject simpleObject = new SimpleObject();Map<String, String> ruleMap = new HashMap<>(10);Sheet wbSheet = workbook.getSheet(sheet);// 校验sheet是否合法if (sheet == null) {// 设置导入状态为失败zjdspDrlsLog.setHandleType(ExcelConstants.EXCEL_TYPE_ERROR);// 设置导入类型zjdspDrlsLog.setGrade(ExcelConstants.EXCEL_GRADE_ERROR);// 设置失败原因zjdspDrlsLog.setContent("解析Excel失败,该sheet不存在!");continue;}// 获取第一行数据int firstRowNum = wbSheet.getFirstRowNum();Row firstRow = wbSheet.getRow(firstRowNum);if (null == firstRow) {LogUtils.warn("解析Excel失败,在第一行没有读取到任何数据!");// 设置导入状态为失败zjdspDrlsLog.setHandleType(ExcelConstants.EXCEL_TYPE_ERROR);// 设置导入类型zjdspDrlsLog.setGrade(ExcelConstants.EXCEL_GRADE_ERROR);// 设置失败原因zjdspDrlsLog.setContent("解析Excel失败,在第一行没有读取到任何数据!");continue;}// 第二行数据int startRow = firstRowNum + 2;// 获取物理行数,不包括空行或隔行int lastRowNum = wbSheet.getLastRowNum();if (lastRowNum > 1000) {lastRowNum = 1000;}// 取得标题头行Row titleRow = wbSheet.getRow(1);// 得到第一行的所有列Iterator<Cell> cellTitle = titleRow.cellIterator();// 将标题的文字内容放入到一个map中。Map<Integer, String> titleMap = new HashMap<>(16);// 循环标题所有的列for (int i = 0; cellTitle.hasNext(); i++) {Cell cell = cellTitle.next();if (cell == null) {continue;}String value = cell.getStringCellValue().trim();titleMap.put(i, value);}int titleSize = titleMap.size();// 计算有内容行for (int i = startRow; i <= lastRowNum; i++) {Row row = wbSheet.getRow(i);// 连续空行数超过一百行,跳过后续内容int emptyRowToInt = emptyRow.get();if (emptyRowToInt >= 100) {break;}if (null == row) {emptyRow.getAndIncrement();continue;}// 连续空行列数AtomicInteger emptyColumn = new AtomicInteger(0);// 遍历一行的列for (int rowNum = 0; rowNum < titleSize; rowNum++) {Cell cell = row.getCell(rowNum);if (cell == null || CellType.BLANK == cell.getCellTypeEnum()) {emptyColumn.incrementAndGet();int i2 = emptyColumn.get();// 连续空行列数大于标题数,空行数加一if (i2 >= titleSize) {emptyRow.getAndIncrement();}}}if (emptyRow.get() <= 0) {realRow.getAndIncrement();}}// 解析内容行for (int i = 0; i < realRow.get(); i++) {int traverse = startRow + i;Row row = wbSheet.getRow(traverse);boolean checkAndConvert = true;// 解析内容列for (int rowNum = 0; rowNum < titleSize; rowNum++) {Cell cell = row.getCell(rowNum);// 对应的标题String title = titleMap.get(rowNum);// 拥有的字段mao和Excel的标题匹配if (fieldMap.containsKey(title)) {ObjectLocal obj = fieldMap.get(title);ObjectLocal objectLocal = obj;// 不为空检查boolean checkNotNull = obj.isCheckNotNull();if (cell == null || CellType.BLANK == cell.getCellTypeEnum()) {// 检验数据是否合法if (checkNotNull) {// 日志记录(失败的导入)checkContent(failureRow, contentVoList, title, "", ExcelConstants.CHECK_NOT_NULL);realRow.incrementAndGet();continue;}}// 父类实例化对象checkAndConvert = checkAndConvert(cell, objectLocal, zjdsjjgDb, failureRow, contentVoList, title, ruleMap, xzqdm, token, table);}}if (checkAndConvert){// 子类set进父类Map<String, Object[]> childrenSetMap = (Map<String, Object[]>) list.get(1);Object[] children = childrenSetMap.get("children");//Method writeMethod = (Method) children[0];Object newInstance = children[1];Object instance = children[2];Object[] newInstanceObjects = childrenSetMap.get(newInstance.getClass().getSimpleName());Object[] instanceObjects = childrenSetMap.get(instance.getClass().getSimpleName());Method instanceReadMethod = (Method) newInstanceObjects[0];Method newInstanceWriteMethod = (Method) instanceObjects[0];// zjdxx.setZjddm(zjdzd.getZjddm)newInstanceWriteMethod.invoke(instance, instanceReadMethod.invoke(newInstance));//writeMethod.invoke(newInstance, instance);simpleObject.setInstance(instance);simpleObject.setNewInstance(newInstance);SimpleObject simpleObject2 = SerializationUtils.clone(simpleObject);if (simpleObject2.getInstance() != null) {resultList2.add(simpleObject2.getInstance());}resultList.add(simpleObject2.getNewInstance());}}try {zjdsjjgDb.BeginTransaction();String newInstanceSql = SqlTool.genSqlInsert(simpleObject.getNewInstance(),resultList.size());if (resultList2.size() > 0) {String instanceSql = SqlTool.genSqlInsert(simpleObject.getInstance(), resultList2.size());Object[] resultColumn = SqlTool.genColumn(resultList2);zjdsjjgDb.executeUpdate(instanceSql, resultColumn);}zjdsjjgDb.executeUpdate(newInstanceSql, SqlTool.genColumn(resultList));zjdsjjgDb.CompleteTransaction();} catch (Exception e) {zjdsjjgDb.AbortTransaction();e.printStackTrace();}// 日志记录 (导入总数)LogUtils.info("》》》》" + sheet + ",共有:" + realRow + "行");zjdspDrlsLog.setGrade(ExcelConstants.EXCEL_GRADE_INFO);zjdspDrlsLog.setHandleType(ExcelConstants.EXCEL_TYPE_INFO);String dataCount = String.format("》》》》 %s工作簿,总共有{ %s }条数据", sheet, realRow);zjdspDrlsLog.setDataCount(dataCount);int failureRowToInt = failureRow.get();int realRowToInt = realRow.get();int result = realRowToInt - failureRowToInt;String contentStr = JSON.toJSON(contentVoList).toString();String content = String.format("入库成功{ %s }条,导入失败{ %s }条。导入失败原因:%s", result, failureRowToInt,contentStr);zjdspDrlsLog.setContent(content);} catch (Exception e) {// 设置导入状态为失败zjdspDrlsLog.setHandleType(ExcelConstants.EXCEL_TYPE_ERROR);// 设置导入类型zjdspDrlsLog.setGrade(ExcelConstants.EXCEL_GRADE_ERROR);// 设置失败原因zjdspDrlsLog.setContent(e.getMessage());throw new RuntimeException(e);} finally {try {watch.stop();zjdspDrlsLog.setTotalTime("总共耗时:" + watch.getTotalTimeSeconds() + "秒");zjdsjjgDb.BeginTransaction();zjdsjjgDb.insert(zjdspDrlsLog);zjdsjjgDb.CompleteTransaction();} catch (Exception e) {zjdsjjgDb.AbortTransaction();e.printStackTrace();}try {workbook.close();} catch (IOException e) {throw new RuntimeException(e);}}}return resultList;}private static void checkContent(AtomicInteger failureRow, List<ContentVo> contentVoList, String titleString,String cellValue, String reason) {ContentVo contentVo = new ContentVo();failureRow.getAndIncrement();// 失败的数据关键字contentVo.setKey(titleString + ":" + cellValue);// 失败原因contentVo.setReason(reason);contentVoList.add(contentVo);}private static boolean checkAndConvert(Cell cell, ObjectLocal obj, Database zjdsjjgDb, AtomicInteger failureRow,List<ContentVo> contentVoList, String titleString,Map<String, String> ruleMap, String xzqdm, String token, String table) throws IllegalAccessException, InvocationTargetException {// set方法Method setMethod = obj.getWriteMethod();// 字典Method dictMethod = obj.getDictMethod();// 父类实例化对象Object clazz = obj.getNewInstance();// 枚举类实例化对象Enum[] anEnum = obj.getEnumConstants();// 唯一性检查boolean uniqueness = obj.isUniqueness();// 可生成性检查String rule = obj.getGenerativeCode();// 数据库映射值String column = obj.getValue();// 检验数据是否合法if (uniqueness) {// 检查唯一性String cellValue = cell.getStringCellValue();String sqlFormat = "select %s from %s where %s = ?";String sql = String.format(sqlFormat, column.toLowerCase(), table, column.toLowerCase());// 查询数据库String index = zjdsjjgDb.firstOrDefault(String.class, sql, cellValue);if (!StringUtil.isNullOrEmpty(index)) {// 唯一性检查失败// 日志记录LogUtils.info("》》》》" + cellValue + "已存在,请检查");// 失败内容checkContent(failureRow, contentVoList, titleString, cellValue, ExcelConstants.CHECK_NOT_UNIQUENESS);return false;} else {// 唯一性检查成功// 将有唯一性的数据放入Map集合// map存放 <数据库映射值, 单元格值>ruleMap.put(column, cellValue);if (StringUtil.isNullOrEmpty(cellValue)) {if (!StringUtil.isNullOrEmpty(rule)) {// 检查可生成性if (ruleMap.containsKey(rule)) {// 根据集合中的唯一性数据生成对应的数据// 那么生成规则是什么呢?String genRule = ruleMap.get(rule);GetWhAdapterProvider whAdapterProvider = new GetWhAdapterProviderImpl();String wh = whAdapterProvider.getWh(column, xzqdm, genRule, token);setMethod.invoke(clazz, wh);}} else {// 不检查可生成性convert(cell, setMethod, dictMethod, clazz, anEnum);}} else {// 不检查可生成性convert(cell, setMethod, dictMethod, clazz, anEnum);}}} else {convert(cell, setMethod, dictMethod, clazz, anEnum);}return true;}private static void convert(Cell cell, Method setMethod, Method dictMethod, Object clazz, Enum[] anEnum) throws IllegalAccessException, InvocationTargetException {// 得到setter方法的参数Type[] ts = setMethod.getGenericParameterTypes();String xclass = ts[0].toString();// 判断参数类型if ("class java.lang.String".equals(xclass)) {// 拥有字典的场合if (null != dictMethod) {// 字典映射后的value enum实例化对象Object dictValue = dictMethod.invoke(anEnum, convertCellValueToString(cell));setMethod.invoke(clazz, dictValue);} else {setMethod.invoke(clazz, convertCellValueToString(cell));}} else if ("class java.util.Date".equals(xclass)) {setMethod.invoke(clazz, !StringUtil.isNullOrEmpty(convertCellValueToString(cell)) ?DataTimeTool.StrToDate(convertCellValueToString(cell)) : null);} else if ("class java.lang.Boolean".equals(xclass)) {setMethod.invoke(clazz, convertCellValueToString(cell));} else if ("class java.lang.Integer".equals(xclass)) {setMethod.invoke(clazz, !StringUtils.isBlank(convertCellValueToString(cell)) ?Integer.parseInt(convertCellValueToString(cell)) : 0);} else if ("class java.lang.Long".equals(xclass)) {setMethod.invoke(clazz, convertCellValueToString(cell));} else if ("class java.lang.Double".equals(xclass)) {setMethod.invoke(clazz, !StringUtils.isBlank(convertCellValueToString(cell)) ?Double.parseDouble(convertCellValueToString(cell)) : 0D);} else if ("class java.lang.Object".equals(xclass)) {setMethod.invoke(clazz, convertCellValueToString(cell));}}/*** 根据文件后缀名类型获取对应的工作簿对象** @param multipartFile 导入的文件* @return 包含文件数据的工作簿对象*/public static Workbook getWorkBook(MultipartFile multipartFile) {//获得文件名String fileName = multipartFile.getOriginalFilename();Workbook workbook = null;try {InputStream ips = multipartFile.getInputStream();if (Objects.requireNonNull(fileName).endsWith(ExcelConstants.EXCEL_XLSX_TYPE)) {//2007 及2007以上workbook = new XSSFWorkbook(ips);} else if (fileName.endsWith(ExcelConstants.EXCEL_XLS_TYPE)) {//2003workbook = new HSSFWorkbook(ips);} else {throw new NoSuchMethodError("没有能够处理此文件的方法");}} catch (IOException e) {e.getMessage();}return workbook;}/*** 检查文件类型** @param file 导入的文件* @return 是否是XLS或XLSX文件*/public static boolean checkFile(MultipartFile file) {//判断文件是否存在if (null == file) {return false;}//获得文件名String fileName = file.getOriginalFilename();//判断文件是否是excel文件return Objects.requireNonNull(fileName).endsWith(ExcelConstants.EXCEL_XLSX_TYPE) || fileName.endsWith(ExcelConstants.EXCEL_XLS_TYPE);}}class SimpleObject implements Serializable {private Object newInstance;private Object instance;public Object getInstance() {return instance;}public void setInstance(Object instance) {this.instance = instance;}public Object getNewInstance() {return newInstance;}public void setNewInstance(Object newInstance) {this.newInstance = newInstance;}}
public class ObjectLocal implements Serializable {
private Method writeMethod;
private Method readMethod;
private boolean checkNotNull;
private boolean uniqueness;
private String generativeCode;
private Method dictMethod;
private Enum[] enumConstants;
private String value;
private Object newInstance;
public Method getWriteMethod() {
return writeMethod;
}
public void setWriteMethod(Method writeMethod) {
this.writeMethod = writeMethod;
}
public Method getReadMethod() {
return readMethod;
}
public void setReadMethod(Method readMethod) {
this.readMethod = readMethod;
}
public boolean isCheckNotNull() {
return checkNotNull;
}
public void setCheckNotNull(boolean checkNotNull) {
this.checkNotNull = checkNotNull;
}
public boolean isUniqueness() {
return uniqueness;
}
public void setUniqueness(boolean uniqueness) {
this.uniqueness = uniqueness;
}
public String getGenerativeCode() {
return generativeCode;
}
public void setGenerativeCode(String generativeCode) {
this.generativeCode = generativeCode;
}
public Method getDictMethod() {
return dictMethod;
}
public void setDictMethod(Method dictMethod) {
this.dictMethod = dictMethod;
}
public Enum[] getEnumConstants() {
return enumConstants;
}
public void setEnumConstants(Enum[] enumConstants) {
this.enumConstants = enumConstants;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Object getNewInstance() {
return newInstance;
}
public void setNewInstance(Object newInstance) {
this.newInstance = newInstance;
}
}
参照连接:https://blog.csdn.net/fangchao2011/article/details/105534252
https://blog.csdn.net/lbq15735104044/article/details/108980532
