程序员蜗牛
1 year ago
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