问题背景:在做一些excel导入需求的时候,虽然会有一些导入模板,但是你永远不知道用户是怎么使用的,实际上传的是什么。可能出现的问题:1.上传文件的后缀名不是预期的2.传了一个空文件,表中的内容是空的3.header的内容或顺序不是预期的做提示拦截以便避免不规范的操作检查不严格,破坏正常的数据响应:这里我们使用easyexcel导入excel数据。具体使用配置如下:1.引入依赖com.alibabaeasyexcel2.2.62.定义实体对象@DatapublicclassRelatedPartyVO{/***Primarykeyid*/privateLongid;@ExcelProperty(value="name",index=0)//定义第一列的表头名称privateStringname;@ExcelProperty(value="formername",index=1)//第二列privateStringhisName;@ExcelProperty(value="category",index=2)privateStringrelatedType;}3.定义监听器@Slf4jpublicclassRelatedPartyListenerextendsAnalysisEventListener{/***每批读取数据量*/privatestaticfinalintBATCH_COUNT=1000;/***读取数据列表*/Listlist=newArrayList<>();/***读取数据过程中信息映射异常*/publicMapmap=newHashMap<>();/***读取文件是否为空为空,false不为空*/publicbooleanblankFlag=true;/***引入一个服务类进行具体操作*/privatefinalRelatedPartyServicerelatedPartyService;publicRelatedPartyListener(RelatedPartyServicerelatedPartyService){this.relatedPartyService=relatedPartyService;}/***每次读取一行,将数据的具体业务判断,以及异常提示放到map中*/@Overridepublicvoidinvoke(RelatedPartyVOt,AnalysisContextanalysisContext){blankFlag=false;如果(StringUtils.isBlank(t.getName())){map.put("code",String.valueOf(ApiResponseCode.ERROR_202.getCode()));map.put("msg","导入数据表中没有填写名称信息");返回;}list.add(t);如果(list.size()>=BATCH_COUNT){relatedPartyService.saveBatch(list);列表.clear();}}/***读取头部信息并验证头部信息*/@OverridepublicvoidinvokeHeadMap(MapheadMap,AnalysisContextcontext){super.invokeHeadMap(headMap,上下文);try{MapindexMap=getIndexNameMap(RelatedPartyVO.class);if(indexMap==null||indexMap.size()<1){thrownewExcelAnalysisException("解析Excel出错,请按模板输入正确的excel");}SetkeySet=indexMap.keySet();for(Integerkey:keySet){if(StringUtils.isBlank(headMap.get(key))){thrownewExcelAnalysisException("分析Excel出错,请根据模板输入正确的excel");}if(!headMap.get(key).equals(indexMap.get(key))){thrownewExcelAnalysisException("解析Excel出错,请根据模板excel输入正确的");}}}catch(NoSuchFieldExceptione){log.error("invokeHeadMaperror",e);}}/***批量解析的时候,根据业务需要的操作,最终以批量解析完成*/@OverridepublicvoiddoAfterAllAnalysed(AnalysisContextanalysisContext){relatedPartyService.saveBatch(list);日志信息("所有数据分析完成,开始去除无效数据");}/***获取excel表头内容,放入map中,方便根据实体类验证表头内容**@paramclazzheadername*@returnImportobjectremarksmap*@throwsNoSuchFieldException*/publicMapgetIndexNameMap(Classclazz)throwsNoSuchFieldException{Mapresult=newHashMap<>();}场场;Field[]fields=clazz.getDeclaredFields();对于(字段项:字段){field=clazz.getDeclaredField(item.getName());field.setAccessible(true);ExcelPropertyexcelProperty=field.getAnnotation(ExcelProperty.class);if(excelProperty!=null){intindex=excelProperty.index();String[]values=excelProperty.value();StringBuilder值=newStringBuilder();for(Stringv:values){value.append(v);}结果。put(index,value.toString());}}returnresult;}}4.读取excel,引用监听器和异常信息的反馈@OverridepublicvoiduploadRelatedParty(FiletempFile){try{log.info("uploadRelatedParty导入excel列表,更新当前库关联方状态为无效");updateAllRelatedStatusTo(StatusEnum.DISABLE.getCode());RelatedPartyListenerpartyListener=newRelatedPartyListener(this);EasyExcel.read(tempFile.getAbsolutePath(),RelatedPartyVO.class,partyListener).sheet().doRead();Mapmap=partyListener.map;if(map.size()!=0){thrownewRuntimeException(map.get("msg"));}if(partyListener.blankFlag){thrownewRuntimeException("客户端上传的空文件,回滚数据");}log.info("写入新数据完成,移除无效数据");deleteRelatedByStatus(StatusEnum.DISABLE.getCode());}catch(Exceptione){log.error("导入excel出错,数据回滚后,删除新导入的标记为有效的数据,然后更新所有历史数据为有效",e);deleteRelatedByStatus(StatusEnum.ENABLE.getCode());updateAllRelatedStatusTo(StatusEnum.ENABLE.getCode());日行新的RuntimeException(e);}最后{booleandelete=tempFile.delete();log.info("uploadRelatedParty删除文件结果为[{}]",delete);}}5。上传excel并检查文件后缀大小等内容//判断导入的是否是excel文件StringfileName=file.getOriginalFilename();if(!(fileName.endsWith(ExcelTypeEnum.XLS.getValue())||fileName.endsWith(ExcelTypeEnum.XLSX.getValue()))){returngetErrorJsonDto(ApiResponseCode.ERROR_202,"只接受Excel类型的文件!");}if(AppUtil.checkFileSize(file.getSize(),FILE_SIZE,FILE_UNIT)){returngetErrorJsonDto(ApiResponseCode.ERROR_202,"导入文件大于10M,已超出");}//写入临时文件FiletempFile=newFile("/tmp/mdm_related_pa??rty_info_"+System.currentTimeMillis()+".xlsx");file.transferTo(tempFile);//读取文件relatedPartyService.uploadRelatedParty(tempFile);注意:如果是分布式服务,需要在读取文件前加分布式锁