Browse Source

主子表导入数据封装。

master
刘忱 2 years ago
parent
commit
5c613b468b
  1. 15
      win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/annotations/OnlyOne.java
  2. 15
      win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/annotations/SubObject.java
  3. 177
      win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/listener/ExcelListener.java
  4. 10
      win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/util/ExcelUtils.java

15
win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/annotations/OnlyOne.java

@ -0,0 +1,15 @@
package com.win.framework.excel.core.annotations;
import java.lang.annotation.*;
/**
* 字典格式化
*
* 实现将字典数据的值格式化成字典数据的标签
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface OnlyOne {
}

15
win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/annotations/SubObject.java

@ -0,0 +1,15 @@
package com.win.framework.excel.core.annotations;
import java.lang.annotation.*;
/**
* 字典格式化
*
* 实现将字典数据的值格式化成字典数据的标签
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SubObject {
}

177
win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/listener/ExcelListener.java

@ -0,0 +1,177 @@
package com.win.framework.excel.core.listener;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.google.common.base.Objects;
import com.win.framework.common.exception.ServiceException;
import com.win.framework.excel.core.annotations.OnlyOne;
import com.win.framework.excel.core.annotations.SubObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Data
@Slf4j
public class ExcelListener<T> extends AnalysisEventListener<T> {
/**
* excel数据
*/
private List<Object> dataList;
/**
* 判断重复的属性方法
*/
private String methodName;
/**
* 子类
*/
private String subObjectMethodName;
/**
* 主表class
*/
private Class<?> mainClass;
/**
* 子表class
*/
private Class<?> subClass;
/**
* 构造函数
*/
public ExcelListener(Class<?> mainClass) {
dataList = new ArrayList<>();
this.mainClass = mainClass;
}
@Override
public void invoke(T object, AnalysisContext analysisContext) {
if(this.methodName == null) {
String methodName = this.getOnlyOneAnnotation();
if(methodName == null) {
throw new ServiceException().setMessage("未发现OnlyOne注解属性");
}
this.methodName = methodName;
}
if(this.subObjectMethodName == null) {
String subObjectMethodName = this.getSubObjectAnnotation();
if(subObjectMethodName == null) {
throw new ServiceException().setMessage("未发现SubObject注解属性");
}
this.subObjectMethodName = subObjectMethodName;
}
this.buildEntity(object);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
/**
* 判断数据是否存在
*/
private Object checkDataIsExist(T object) {
for(Object obj : dataList) {
Object methodValue1 = ReflectUtil.invoke(obj, "get" + this.methodName);
Object methodValue2 = ReflectUtil.invoke(object, "get" + this.methodName);
if(methodValue1.equals(methodValue2)) {
return obj;
}
}
return null;
}
/**
* 添加数据
* @param vo
*/
private void buildEntity(T vo) {
Object mainObject = this.checkDataIsExist(vo);
Object subObject;
try {//创建子数据对象
subObject = this.subClass.getDeclaredConstructors()[0].newInstance((Object) null);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
BeanUtil.copyProperties(vo, subObject);
if(mainObject == null) {//list中不存在主数据
try {//创建主数据对象
mainObject = this.mainClass.getDeclaredConstructors()[0].newInstance((Object) null);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
BeanUtil.copyProperties(vo, mainObject);
Method setMethod = ReflectUtil.getMethod(this.mainClass, "set" + this.subObjectMethodName);
List<Object> subClassList = new ArrayList<>();
subClassList.add(subObject);
ReflectUtil.invoke(mainObject, setMethod, subClassList);
dataList.add(mainObject);
} else {//list中存在主数据,只添加子数据
Method getMethod = ReflectUtil.getMethod(this.mainClass, "get" + this.subObjectMethodName);
List<Object> subClassList = ReflectUtil.invoke(mainObject, getMethod);
subClassList.add(subObject);
Method setMethod = ReflectUtil.getMethod(this.mainClass, "set" + this.subObjectMethodName);
ReflectUtil.invoke(mainObject, setMethod, subClassList);
}
}
private String getOnlyOneAnnotation() {
Field[] fields = mainClass.getDeclaredFields();
for (Field field : fields) {
// 只判断该字段拥有非空注解
if (AnnotationUtil.hasAnnotation(field, OnlyOne.class)){
//获取属性的名字
String attributeName = field.getName();
//将属性名字的首字母大写
return Character.toUpperCase(attributeName.charAt(0)) + attributeName.substring(1);
}
}
return null;
}
private String getSubObjectAnnotation() {
Object object;
try {
object = mainClass.getDeclaredConstructors()[0].newInstance((Object) null);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
// 只判断该字段拥有非空注解
if (AnnotationUtil.hasAnnotation(field, SubObject.class)) {
Class<?> fieldType = field.getType();
if (Collection.class.isAssignableFrom(fieldType)) {
java.lang.reflect.Type[] actualType = ((ParameterizedType) field.getGenericType()).getActualTypeArguments();
if (actualType.length != 1 || actualType[0] == null || actualType[0].toString().length() < 5 || !Objects.equal(actualType[0].toString().substring(0, 5).toLowerCase(), "class")){
// 非class类型的不处理
throw new ServiceException().setMessage("SubObject非泛型");
}
this.subClass = actualType[0].getClass();
} else {
throw new ServiceException().setMessage("SubObject注解属性必须是Collection实现类");
}
//获取属性的名字
String attributeName = field.getName();
//将属性名字的首字母大写
return Character.toUpperCase(attributeName.charAt(0)) + attributeName.substring(1);
}
}
return null;
}
}

10
win-framework/win-spring-boot-starter-excel/src/main/java/com/win/framework/excel/core/util/ExcelUtils.java

@ -1,6 +1,7 @@
package com.win.framework.excel.core.util; package com.win.framework.excel.core.util;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -27,8 +28,7 @@ public class ExcelUtils {
* @param <T> 泛型保证 head data 类型的一致性 * @param <T> 泛型保证 head data 类型的一致性
* @throws IOException 写入失败的情况 * @throws IOException 写入失败的情况
*/ */
public static <T> void write(HttpServletResponse response, String filename, String sheetName, public static <T> void write(HttpServletResponse response, String filename, String sheetName, Class<T> head, List<T> data) throws IOException {
Class<T> head, List<T> data) throws IOException {
// 输出 Excel // 输出 Excel
EasyExcel.write(response.getOutputStream(), head) EasyExcel.write(response.getOutputStream(), head)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
@ -45,4 +45,10 @@ public class ExcelUtils {
.doReadAllSync(); .doReadAllSync();
} }
public static <T> List<T> read(MultipartFile file, Class<T> head, AnalysisEventListener<T> listener) throws IOException {
return EasyExcel.read(file.getInputStream(), head, listener)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.doReadAllSync();
}
} }

Loading…
Cancel
Save