22 changed files with 805 additions and 0 deletions
			
			
		| @ -0,0 +1,3 @@ | |||
| # easyexcelTest | |||
| 根据阿里的easyexcel通过validation+正则实现excel导入校验 | |||
| 包含了简单的导入导入导出demo,所涉及到的都是web的导入导出 | |||
| @ -0,0 +1,89 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
|     <modelVersion>4.0.0</modelVersion> | |||
|     <parent> | |||
|         <groupId>org.springframework.boot</groupId> | |||
|         <artifactId>spring-boot-starter-parent</artifactId> | |||
|         <version>2.2.2.RELEASE</version> | |||
|         <relativePath/> <!-- lookup parent from repository --> | |||
|     </parent> | |||
|     <groupId>com.zhy</groupId> | |||
|     <artifactId>easyexceldemo</artifactId> | |||
|     <version>0.0.1-SNAPSHOT</version> | |||
|     <name>easyexceldemo</name> | |||
|     <description>Demo project for Spring Boot</description> | |||
| 
 | |||
|     <properties> | |||
|         <java.version>1.8</java.version> | |||
|     </properties> | |||
| 
 | |||
|     <dependencies> | |||
|         <dependency> | |||
|             <groupId>org.springframework.boot</groupId> | |||
|             <artifactId>spring-boot-starter-web</artifactId> | |||
|         </dependency> | |||
| 
 | |||
|         <dependency> | |||
|             <groupId>org.springframework.boot</groupId> | |||
|             <artifactId>spring-boot-starter-test</artifactId> | |||
|             <scope>test</scope> | |||
|             <exclusions> | |||
|                 <exclusion> | |||
|                     <groupId>org.junit.vintage</groupId> | |||
|                     <artifactId>junit-vintage-engine</artifactId> | |||
|                 </exclusion> | |||
|             </exclusions> | |||
|         </dependency> | |||
| 
 | |||
|         <!--easyExcel--> | |||
|         <dependency> | |||
|             <groupId>com.alibaba</groupId> | |||
|             <artifactId>easyexcel</artifactId> | |||
|             <version>2.1.4</version> | |||
|         </dependency> | |||
| 
 | |||
|         <dependency> | |||
|             <groupId>org.apache.poi</groupId> | |||
|             <artifactId>poi</artifactId> | |||
|             <version>3.17</version> | |||
|         </dependency> | |||
|         <dependency> | |||
|             <groupId>org.apache.poi</groupId> | |||
|             <artifactId>poi-ooxml</artifactId> | |||
|             <version>3.17</version> | |||
|         </dependency> | |||
|         <dependency> | |||
|             <groupId>cglib</groupId> | |||
|             <artifactId>cglib</artifactId> | |||
|             <version>3.1</version> | |||
|         </dependency> | |||
|         <dependency> | |||
|             <groupId>org.apache.poi</groupId> | |||
|             <artifactId>ooxml-schemas</artifactId> | |||
|             <version>1.1</version> | |||
|         </dependency> | |||
| 
 | |||
|         <dependency> | |||
|             <groupId>org.projectlombok</groupId> | |||
|             <artifactId>lombok</artifactId> | |||
|             <scope>provided</scope> | |||
|         </dependency> | |||
| 
 | |||
|         <dependency> | |||
|             <groupId>com.alibaba</groupId> | |||
|             <artifactId>fastjson</artifactId> | |||
|             <version>1.2.60</version> | |||
|         </dependency> | |||
|     </dependencies> | |||
| 
 | |||
|     <build> | |||
|         <plugins> | |||
|             <plugin> | |||
|                 <groupId>org.springframework.boot</groupId> | |||
|                 <artifactId>spring-boot-maven-plugin</artifactId> | |||
|             </plugin> | |||
|         </plugins> | |||
|     </build> | |||
| 
 | |||
| </project> | |||
| @ -0,0 +1,15 @@ | |||
| package com.zhy.easyexceldemo; | |||
| 
 | |||
| import org.springframework.boot.SpringApplication; | |||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
| import org.springframework.context.annotation.ComponentScan; | |||
| 
 | |||
| @SpringBootApplication | |||
| @ComponentScan(value = {"com.zhy.easyexceldemo.config","com.zhy"}) | |||
| public class EasyexceldemoApplication { | |||
| 
 | |||
|     public static void main(String[] args) { | |||
|         SpringApplication.run(EasyexceldemoApplication.class, args); | |||
|     } | |||
| 
 | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| package com.zhy.easyexceldemo.common; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public class BaseRest { | |||
| 
 | |||
|     public Result addSucResult() { | |||
|         return this.addResult(true, ResultCodeEnum.SUCCESS.getValue(), ResultCodeEnum.SUCCESS.getLabel(), (Object)null); | |||
|     } | |||
| 
 | |||
|     public <T> Result addResult(boolean result, String code, String message, T data) { | |||
|         Result<T> rs = new Result(); | |||
|         rs.setResult(result); | |||
|         rs.setCode(code); | |||
|         rs.setMessage(message); | |||
|         rs.setData(data); | |||
|         return rs; | |||
|     } | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| package com.zhy.easyexceldemo.common; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| public class Result<T> { | |||
| 
 | |||
|     public static final String SUCCESS_MSG = "操作成功!"; | |||
|     private static final long serialVersionUID = -34684491868853686L; | |||
|     private boolean result; | |||
|     private String code; | |||
|     private String message; | |||
|     private String token; | |||
|     private Long count; | |||
|     private T data; | |||
| 
 | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package com.zhy.easyexceldemo.common; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public enum ResultCodeEnum { | |||
|     SUCCESS("200", "操作成功."), | |||
|     ERROR("500", "系统未知错误."), | |||
|     IMPORT_ERROR("500001", "导入错误."), | |||
|     ; | |||
| 
 | |||
| 
 | |||
|     private final String value; | |||
|     private final String label; | |||
| 
 | |||
|     private ResultCodeEnum(String value, String label) { | |||
|         this.value = value; | |||
|         this.label = label; | |||
|     } | |||
| 
 | |||
|     public String getValue() { | |||
|         return this.value; | |||
|     } | |||
| 
 | |||
|     public String getLabel() { | |||
|         return this.label; | |||
|     } | |||
| } | |||
| @ -0,0 +1,58 @@ | |||
| package com.zhy.easyexceldemo.config; | |||
| 
 | |||
| 
 | |||
| import com.alibaba.fastjson.serializer.SerializerFeature; | |||
| import com.alibaba.fastjson.support.config.FastJsonConfig; | |||
| import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.http.MediaType; | |||
| import org.springframework.http.converter.HttpMessageConverter; | |||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; | |||
| 
 | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Configuration | |||
| public class WebMvcInterceptorConfig extends WebMvcConfigurationSupport { | |||
| 
 | |||
|   /** | |||
|       * @title: | |||
|       * @projectName | |||
|       * @description: fastjson处理返回结果 | |||
|       * @author zhy | |||
|       * @date 2019/9/5 11:32 | |||
|       */ | |||
|     @SuppressWarnings("deprecation") | |||
| 	@Override | |||
|     public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | |||
|         super.configureMessageConverters(converters); | |||
|         FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); | |||
|         List<MediaType> supportedMediaTypes = new ArrayList<>(); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_JSON); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_PDF); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML); | |||
|         supportedMediaTypes.add(MediaType.APPLICATION_XML); | |||
|         supportedMediaTypes.add(MediaType.IMAGE_GIF); | |||
|         supportedMediaTypes.add(MediaType.IMAGE_JPEG); | |||
|         supportedMediaTypes.add(MediaType.IMAGE_PNG); | |||
|         supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM); | |||
|         supportedMediaTypes.add(MediaType.TEXT_HTML); | |||
|         supportedMediaTypes.add(MediaType.TEXT_MARKDOWN); | |||
|         supportedMediaTypes.add(MediaType.TEXT_PLAIN); | |||
|         supportedMediaTypes.add(MediaType.TEXT_XML); | |||
|         fastConverter.setSupportedMediaTypes(supportedMediaTypes); | |||
|         FastJsonConfig fastJsonConfig = new FastJsonConfig(); | |||
|         fastConverter.setDateFormat("yyyy-MM-dd HH:mm:ss"); | |||
|         fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNullListAsEmpty,SerializerFeature.WriteNullStringAsEmpty); | |||
|         fastConverter.setFastJsonConfig(fastJsonConfig); | |||
|         converters.add(fastConverter); | |||
|     } | |||
| } | |||
| @ -0,0 +1,45 @@ | |||
| package com.zhy.easyexceldemo.dto; | |||
| 
 | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.annotation.write.style.ColumnWidth; | |||
| import com.zhy.easyexceldemo.easyexcel.ExcelPatternMsg; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import org.hibernate.validator.constraints.Length; | |||
| 
 | |||
| import javax.validation.constraints.Null; | |||
| import javax.validation.constraints.Pattern; | |||
| import java.io.Serializable; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| public class UserExcelDto implements Serializable { | |||
| 
 | |||
|     private static final long serialVersionUID = 1L; | |||
| 
 | |||
|     //名称
 | |||
|     @ExcelProperty(index = 0,value = "名称") | |||
|     @ColumnWidth(30) | |||
|     @Length(max = 10) | |||
|     private String name; | |||
| 
 | |||
|     //性别
 | |||
|     @ExcelProperty(index = 1,value = "性别") | |||
|     @ColumnWidth(30) | |||
|     @Length(max = 2) | |||
|     private String sex; | |||
| 
 | |||
|     //年龄
 | |||
|     @ExcelProperty(index = 2,value = "年龄") | |||
|     @ColumnWidth(30) | |||
|     @Pattern(regexp = ExcelPatternMsg.NUMBER,message = ExcelPatternMsg.NUMBER_MSG) | |||
|     private String age; | |||
| 
 | |||
| 
 | |||
|     //生日
 | |||
|     @ExcelProperty(index = 3,value = "生日") | |||
|     @Pattern(regexp = ExcelPatternMsg.DATE_TIME1,message = ExcelPatternMsg.DATE_TIME1_MSG) | |||
|     private String birthday; | |||
| } | |||
| @ -0,0 +1,27 @@ | |||
| package com.zhy.easyexceldemo.dto; | |||
| 
 | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.annotation.write.style.ColumnWidth; | |||
| import com.zhy.easyexceldemo.easyexcel.ExcelPatternMsg; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import org.hibernate.validator.constraints.Length; | |||
| 
 | |||
| import javax.validation.constraints.Pattern; | |||
| import java.io.Serializable; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper=false) | |||
| public class UserExcelErrDto extends UserExcelDto { | |||
| 
 | |||
| 
 | |||
|     //错误信息
 | |||
|     @ExcelProperty(index = 4,value = "错误信息") | |||
|     @ColumnWidth(50) | |||
|     private String errMsg; | |||
| 
 | |||
| 
 | |||
| } | |||
| @ -0,0 +1,130 @@ | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| import com.alibaba.excel.context.AnalysisContext; | |||
| import com.alibaba.excel.event.AnalysisEventListener; | |||
| import com.alibaba.excel.exception.ExcelAnalysisException; | |||
| import com.alibaba.excel.util.StringUtils; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| 
 | |||
| import java.lang.reflect.Field; | |||
| import java.util.*; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = false) | |||
| public class EasyExcelListener<T> extends AnalysisEventListener<T> { | |||
| 
 | |||
|     //成功结果集
 | |||
|     private List<T> successList = new ArrayList<>(); | |||
| 
 | |||
|     //失败结果集
 | |||
|     private List<ExcelCheckErrDto<T>> errList = new ArrayList<>(); | |||
| 
 | |||
|     //处理逻辑service
 | |||
|     private ExcelCheckManager<T> excelCheckManager; | |||
| 
 | |||
|     private List<T> list = new ArrayList<>(); | |||
| 
 | |||
|     //excel对象的反射类
 | |||
|     private Class<T> clazz; | |||
| 
 | |||
|     public EasyExcelListener(ExcelCheckManager<T> excelCheckManager) { | |||
|         this.excelCheckManager = excelCheckManager; | |||
|     } | |||
| 
 | |||
|     public EasyExcelListener(ExcelCheckManager<T> excelCheckManager, Class<T> clazz) { | |||
|         this.excelCheckManager = excelCheckManager; | |||
|         this.clazz = clazz; | |||
|     } | |||
| 
 | |||
|     @Override | |||
|     public void invoke(T t, AnalysisContext analysisContext) { | |||
|         String errMsg; | |||
|         try { | |||
|             //根据excel数据实体中的javax.validation + 正则表达式来校验excel数据
 | |||
|             errMsg = EasyExcelValiHelper.validateEntity(t); | |||
|         } catch (NoSuchFieldException e) { | |||
|             errMsg = "解析数据出错"; | |||
|             e.printStackTrace(); | |||
|         } | |||
|         if (!StringUtils.isEmpty(errMsg)) { | |||
|             ExcelCheckErrDto excelCheckErrDto = new ExcelCheckErrDto(t, errMsg); | |||
|             errList.add(excelCheckErrDto); | |||
|         } else { | |||
|             list.add(t); | |||
|         } | |||
|         //每1000条处理一次
 | |||
|         if (list.size() > 1000) { | |||
|             //校验
 | |||
|             ExcelCheckResult result = excelCheckManager.checkImportExcel(list); | |||
|             successList.addAll(result.getSuccessDtos()); | |||
|             errList.addAll(result.getErrDtos()); | |||
|             list.clear(); | |||
|         } | |||
|     } | |||
| 
 | |||
|     //所有数据解析完成了 都会来调用
 | |||
|     @Override | |||
|     public void doAfterAllAnalysed(AnalysisContext analysisContext) { | |||
|         ExcelCheckResult result = excelCheckManager.checkImportExcel(list); | |||
|         successList.addAll(result.getSuccessDtos()); | |||
|         errList.addAll(result.getErrDtos()); | |||
|         list.clear(); | |||
|     } | |||
| 
 | |||
| 
 | |||
|     /** | |||
|      * @param headMap 传入excel的头部(第一行数据)数据的index,name | |||
|      * @description: 校验excel头部格式,必须完全匹配 | |||
|      */ | |||
|     @Override | |||
|     public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { | |||
|         super.invokeHeadMap(headMap, context); | |||
|         if (clazz != null) { | |||
|             try { | |||
|                 Map<Integer, String> indexNameMap = getIndexNameMap(clazz); | |||
|                 Set<Integer> keySet = indexNameMap.keySet(); | |||
|                 for (Integer key : keySet) { | |||
|                     if (StringUtils.isEmpty(headMap.get(key))) { | |||
|                         throw new ExcelAnalysisException("解析excel出错,请传入正确格式的excel"); | |||
|                     } | |||
|                     if (!headMap.get(key).equals(indexNameMap.get(key))) { | |||
|                         throw new ExcelAnalysisException("解析excel出错,请传入正确格式的excel"); | |||
|                     } | |||
|                 } | |||
| 
 | |||
|             } catch (NoSuchFieldException e) { | |||
|                 e.printStackTrace(); | |||
|             } | |||
|         } | |||
|     } | |||
| 
 | |||
| 
 | |||
|     @SuppressWarnings("rawtypes") | |||
|     public Map<Integer, String> getIndexNameMap(Class clazz) throws NoSuchFieldException { | |||
|         Map<Integer, String> result = new HashMap<>(); | |||
|         Field field; | |||
|         Field[] fields = clazz.getDeclaredFields(); | |||
|         for (int i = 0; i < fields.length; i++) { | |||
|             field = clazz.getDeclaredField(fields[i].getName()); | |||
|             field.setAccessible(true); | |||
|             ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); | |||
|             if (excelProperty != null) { | |||
|                 int index = excelProperty.index(); | |||
|                 String[] values = excelProperty.value(); | |||
|                 StringBuilder value = new StringBuilder(); | |||
|                 for (String v : values) { | |||
|                     value.append(v); | |||
|                 } | |||
|                 result.put(index, value.toString()); | |||
|             } | |||
|         } | |||
|         return result; | |||
|     } | |||
| 
 | |||
| 
 | |||
| } | |||
| @ -0,0 +1,53 @@ | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| import com.alibaba.excel.EasyExcelFactory; | |||
| import com.alibaba.excel.write.metadata.style.WriteCellStyle; | |||
| import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; | |||
| import org.apache.poi.ss.usermodel.IndexedColors; | |||
| 
 | |||
| import javax.servlet.ServletOutputStream; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public class EasyExcelUtils { | |||
| 
 | |||
|     private EasyExcelUtils(){} | |||
| 
 | |||
| 
 | |||
|     @SuppressWarnings("rawtypes") | |||
| 	public static void webWriteExcel(HttpServletResponse response, List objects, Class clazz, String fileName) throws IOException { | |||
|         String sheetName = fileName; | |||
|         webWriteExcel(response,objects,clazz,fileName,sheetName); | |||
|     } | |||
| 
 | |||
|      | |||
|     @SuppressWarnings("rawtypes") | |||
| 	public static void webWriteExcel(HttpServletResponse response, List objects, Class clazz, String fileName, String sheetName) throws IOException { | |||
|         response.setContentType("application/vnd.ms-excel"); | |||
|         response.setCharacterEncoding("utf-8"); | |||
|         response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); | |||
|         // 头的策略
 | |||
|         WriteCellStyle headWriteCellStyle = new WriteCellStyle(); | |||
|         // 背景设置为白
 | |||
|         headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); | |||
|         // 内容的策略
 | |||
|         WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); | |||
|         HorizontalCellStyleStrategy horizontalCellStyleStrategy = | |||
|                 new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); | |||
|         ServletOutputStream outputStream = response.getOutputStream(); | |||
|         try { | |||
|             EasyExcelFactory.write(outputStream, clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName).doWrite(objects); | |||
|         }catch (Exception e){ | |||
|             e.printStackTrace(); | |||
|         }finally { | |||
|             outputStream.close(); | |||
|         } | |||
|     } | |||
| 
 | |||
| 
 | |||
| 
 | |||
| } | |||
| @ -0,0 +1,37 @@ | |||
|   | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| import com.alibaba.excel.annotation.ExcelProperty; | |||
| 
 | |||
| import javax.validation.ConstraintViolation; | |||
| import javax.validation.Validation; | |||
| import javax.validation.Validator; | |||
| import javax.validation.groups.Default; | |||
| import java.lang.reflect.Field; | |||
| import java.util.Set; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public class EasyExcelValiHelper { | |||
| 
 | |||
|     private EasyExcelValiHelper(){} | |||
|   | |||
|     private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); | |||
|   | |||
|     public static <T> String validateEntity(T obj) throws NoSuchFieldException { | |||
|         StringBuilder result = new StringBuilder(); | |||
|         Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class); | |||
|         if (set != null && !set.isEmpty()) { | |||
|             for (ConstraintViolation<T> cv : set) { | |||
|             	Field declaredField = obj.getClass().getDeclaredField(cv.getPropertyPath().toString()); | |||
|             	ExcelProperty annotation = declaredField.getAnnotation(ExcelProperty.class); | |||
|                 result.append(annotation.value()[0]+cv.getMessage()).append(";"); | |||
|             } | |||
|         } | |||
|         return result.toString(); | |||
|     } | |||
|   | |||
| 
 | |||
| 
 | |||
| } | |||
| @ -0,0 +1,18 @@ | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| public class ExcelCheckErrDto<T> { | |||
|     private T t; | |||
| 
 | |||
|     private String errMsg; | |||
| 
 | |||
|     public ExcelCheckErrDto(T t, String errMsg){ | |||
|         this.t = t; | |||
|         this.errMsg = errMsg; | |||
|     } | |||
| } | |||
| @ -0,0 +1,19 @@ | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| import java.util.List; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public interface ExcelCheckManager<T> { | |||
| 
 | |||
|     /** | |||
|      * @description: 校验方法 | |||
|      * @param objects | |||
|      * @throws | |||
|      * @return com.cec.moutai.common.easyexcel.ExcelCheckResult | |||
|      * @author zhy | |||
|      * @date 2019/12/24 14:57 | |||
|      */ | |||
|     ExcelCheckResult checkImportExcel(List<T> objects); | |||
| } | |||
| @ -0,0 +1,26 @@ | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| import lombok.Data; | |||
| 
 | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| public class ExcelCheckResult<T> { | |||
|     private List<T> successDtos; | |||
| 
 | |||
|     private List<ExcelCheckErrDto<T>> errDtos; | |||
| 
 | |||
|     public ExcelCheckResult(List<T> successDtos, List<ExcelCheckErrDto<T>> errDtos){ | |||
|         this.successDtos =successDtos; | |||
|         this.errDtos = errDtos; | |||
|     } | |||
| 
 | |||
|     public ExcelCheckResult(List<ExcelCheckErrDto<T>> errDtos){ | |||
|         this.successDtos =new ArrayList<>(); | |||
|         this.errDtos = errDtos; | |||
|     } | |||
| } | |||
| @ -0,0 +1,58 @@ | |||
| package com.zhy.easyexceldemo.easyexcel; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public class ExcelPatternMsg { | |||
| 
 | |||
|     private ExcelPatternMsg(){} | |||
| 
 | |||
|     //只能输入整数或者小数
 | |||
|     public static final String DECIMAL = "^[0-9]+\\.{0,1}[0-9]{0,2}$"; | |||
|     public static final String DECIMAL_MSG = "只能输入整数或者小数"; | |||
| 
 | |||
|     //日期格式 yyyy/MM/dd
 | |||
|     public static final String DATE1 = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\\/(((0[13578]|1[02])\\/(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)\\/(0[1-9]|[12][0-9]|30))|(02\\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))\\/02\\/29)$"; | |||
|     public static final String DATE1_MSG = "输入正确的日期格式:yyyy/MM/dd"; | |||
| 
 | |||
|     //日期格式 yyyy-MM-dd
 | |||
|     public static final String DATE2 = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)$"; | |||
|     public static final String DATE2_MSG = "输入正确的日期格式:yyyy-MM-dd"; | |||
| 
 | |||
| 
 | |||
|     //日期格式 yyyyMMdd
 | |||
|     public static final String DATE3 = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229)$"; | |||
|     public static final String DATE3_MSG = "输入正确的日期格式:yyyyMMdd"; | |||
| 
 | |||
|     //日期格式 yyyy-MM-dd HH:mm:ss
 | |||
|     public static final String DATE_TIME1 = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"; | |||
|     public static final String DATE_TIME1_MSG = "输入正确的日期格式:yyyy-MM-dd HH:mm:ss"; | |||
| 
 | |||
| 
 | |||
|     //日期格式 yyyy/MM/dd HH:mm:ss
 | |||
|     public static final String DATE_TIME2 = "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\\/(((0[13578]|1[02])\\/(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)\\/(0[1-9]|[12][0-9]|30))|(02\\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))\\/02\\/29))\\s([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"; | |||
|     public static final String DATE_TIME2_MSG = "输入正确的日期格式:yyyy/MM/dd HH:mm:ss"; | |||
| 
 | |||
|     //日期格式 yyyyMMddHHmmss
 | |||
|     public static final String DATE_TIME3 = "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])$"; | |||
|     public static final String DATE_TIME3_MSG = "输入正确的日期格式:yyyyMMddHHmmss"; | |||
| 
 | |||
| 
 | |||
|     //日期格式 yyyyMMddHHmmssSSS
 | |||
|     public static final String DATE_TIME4 = "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])([0-9]{3})$"; | |||
|     public static final String DATE_TIME4_MSG = "输入正确的日期格式:yyyyMMddHHmmssSSS"; | |||
| 
 | |||
| 
 | |||
|     //日期格式 yyyyMMdd HH:mm:ss
 | |||
|     public static final String DATE_TIME5 = "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))\\s([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"; | |||
|     public static final String DATE_TIME5_MSG = "输入正确的日期格式:yyyyMMdd HH:mm:ss"; | |||
| 
 | |||
| 
 | |||
|     //数字和字母
 | |||
|     public static final String NUMBER_LETTER = "^[a-z0-9A-Z]+$"; | |||
|     public static final String NUMBER_LETTER_MSG = "只能输入数字和字母"; | |||
| 
 | |||
|     //数字
 | |||
|     public static final String NUMBER = "^[0-9]*$"; | |||
|     public static final String NUMBER_MSG = "只能输入数字"; | |||
| } | |||
| @ -0,0 +1,31 @@ | |||
| package com.zhy.easyexceldemo.pojo; | |||
| 
 | |||
| import com.alibaba.fastjson.annotation.JSONField; | |||
| import com.fasterxml.jackson.annotation.JsonFormat; | |||
| import lombok.Data; | |||
| 
 | |||
| import java.io.Serializable; | |||
| import java.util.Date; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Data | |||
| public class User implements Serializable { | |||
| 
 | |||
|     private static final long serialVersionUID = 1L; | |||
| 
 | |||
|     //名称
 | |||
|     private String name; | |||
| 
 | |||
|     //性别
 | |||
|     private String sex; | |||
| 
 | |||
|     //年龄
 | |||
|     private Integer age; | |||
| 
 | |||
|     //生日
 | |||
|     @JSONField(format="yyyy-MM-dd HH:mm:ss") | |||
|     @JsonFormat( pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") | |||
|     private Date birthday; | |||
| } | |||
| @ -0,0 +1,61 @@ | |||
| package com.zhy.easyexceldemo.rest; | |||
| 
 | |||
| import com.alibaba.excel.EasyExcelFactory; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.zhy.easyexceldemo.common.BaseRest; | |||
| import com.zhy.easyexceldemo.common.Result; | |||
| import com.zhy.easyexceldemo.dto.UserExcelDto; | |||
| import com.zhy.easyexceldemo.dto.UserExcelErrDto; | |||
| import com.zhy.easyexceldemo.easyexcel.EasyExcelListener; | |||
| import com.zhy.easyexceldemo.easyexcel.EasyExcelUtils; | |||
| import com.zhy.easyexceldemo.easyexcel.ExcelCheckErrDto; | |||
| import com.zhy.easyexceldemo.pojo.User; | |||
| import com.zhy.easyexceldemo.service.UserService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| 
 | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.stream.Collectors; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @RestController | |||
| @RequestMapping("/user") | |||
| public class UserRest extends BaseRest { | |||
| 
 | |||
|     @Autowired | |||
|     private UserService userService; | |||
| 
 | |||
|     /** | |||
|      * easyexcel通过validation和正则实现excel导入校验 | |||
|      * 导入表头校验 | |||
|      * 导入数据校验 | |||
|      * 导入业务逻辑校验 | |||
|      */ | |||
|     @PostMapping("/importExcel") | |||
|     public Result importExcel(HttpServletResponse response, @RequestParam MultipartFile file) throws IOException { | |||
|         EasyExcelListener easyExcelListener = new EasyExcelListener(userService, UserExcelDto.class); | |||
|         EasyExcelFactory.read(file.getInputStream(), UserExcelDto.class, easyExcelListener).sheet().doRead(); | |||
|         List<ExcelCheckErrDto<UserExcelDto>> errList = easyExcelListener.getErrList(); | |||
|         if (!errList.isEmpty()) { | |||
|             //如果包含错误信息就导出错误信息
 | |||
|             exportErrorMsg(response, errList); | |||
|         } | |||
|         return addSucResult(); | |||
|     } | |||
| 
 | |||
|     private static void exportErrorMsg(HttpServletResponse response, List<ExcelCheckErrDto<UserExcelDto>> errList) throws IOException { | |||
|         List<UserExcelErrDto> excelErrDtos = errList.stream().map(excelCheckErrDto -> { | |||
|             UserExcelErrDto userExcelErrDto = JSON.parseObject(JSON.toJSONString(excelCheckErrDto.getT()), UserExcelErrDto.class); | |||
|             userExcelErrDto.setErrMsg(excelCheckErrDto.getErrMsg()); | |||
|             return userExcelErrDto; | |||
|         }).collect(Collectors.toList()); | |||
|         EasyExcelUtils.webWriteExcel(response, excelErrDtos, UserExcelErrDto.class, "用户导入错误信息"); | |||
|     } | |||
| } | |||
| @ -0,0 +1,10 @@ | |||
| package com.zhy.easyexceldemo.service; | |||
| 
 | |||
| import com.zhy.easyexceldemo.dto.UserExcelDto; | |||
| import com.zhy.easyexceldemo.easyexcel.ExcelCheckManager; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| public interface UserService extends ExcelCheckManager<UserExcelDto> { | |||
| } | |||
| @ -0,0 +1,42 @@ | |||
| package com.zhy.easyexceldemo.service.impl; | |||
| 
 | |||
| import com.alibaba.excel.util.StringUtils; | |||
| import com.zhy.easyexceldemo.dto.UserExcelDto; | |||
| import com.zhy.easyexceldemo.easyexcel.ExcelCheckErrDto; | |||
| import com.zhy.easyexceldemo.easyexcel.ExcelCheckResult; | |||
| import com.zhy.easyexceldemo.service.UserService; | |||
| import org.springframework.stereotype.Service; | |||
| 
 | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| 
 | |||
| /** | |||
|  * @author woniu | |||
|  */ | |||
| @Service | |||
| public class UserServiceImpl implements UserService { | |||
| 
 | |||
|     public static final String ERR_NAME = "蜗牛哥"; | |||
| 
 | |||
|     @Override | |||
|     public ExcelCheckResult checkImportExcel(List<UserExcelDto> userExcelDtos) { | |||
|         //成功结果集
 | |||
|         List<UserExcelDto> successList = new ArrayList<>(); | |||
|         //错误数组
 | |||
|         List<ExcelCheckErrDto<UserExcelDto>> errList = new ArrayList<>(); | |||
|         for (UserExcelDto userExcelDto : userExcelDtos) { | |||
|             //错误信息
 | |||
|             StringBuilder errMsg = new StringBuilder(); | |||
|             //根据自己的业务去做判断
 | |||
|             if (ERR_NAME.equals(userExcelDto.getName()))  | |||
|                 errMsg.append("请输入正确的名字").append(";"); | |||
|             if (StringUtils.isEmpty(errMsg.toString())){ | |||
|                 //这里有两个选择,1、一个返回成功的对象信息,2、进行持久化操作
 | |||
|                 successList.add(userExcelDto); | |||
|             }else{//添加错误信息
 | |||
|                 errList.add(new ExcelCheckErrDto(userExcelDto,errMsg.toString())); | |||
|             } | |||
|         } | |||
|         return new ExcelCheckResult(successList,errList); | |||
|     } | |||
| } | |||
| @ -0,0 +1,2 @@ | |||
| server: | |||
|   port: 8888 | |||
| @ -0,0 +1,13 @@ | |||
| package com.zhy.easyexceldemo; | |||
| 
 | |||
| import org.junit.jupiter.api.Test; | |||
| import org.springframework.boot.test.context.SpringBootTest; | |||
| 
 | |||
| @SpringBootTest | |||
| class EasyexceldemoApplicationTests { | |||
| 
 | |||
|     @Test | |||
|     void contextLoads() { | |||
|     } | |||
| 
 | |||
| } | |||
					Loading…
					
					
				
		Reference in new issue