From 85d4264415a1880f6c5c3b1788607f8b9cce2d25 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Thu, 4 May 2023 16:30:10 +0800 Subject: [PATCH] =?UTF-8?q?*=20=E9=BB=98=E8=AE=A4=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E5=8F=8D=E5=B0=84=E7=BC=93=E5=AD=98=E6=94=B9=E6=88=90`ThreadLo?= =?UTF-8?q?cal`,=E5=B9=B6=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=8F=8D?= =?UTF-8?q?=E5=B0=84=E7=BC=93=E5=AD=98=E7=B1=BB=E5=9E=8B=20[Issue=20#2792]?= =?UTF-8?q?(https://github.com/alibaba/easyexcel/issues/2792)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metadata/AbstractParameterBuilder.java | 11 + .../alibaba/excel/metadata/FieldCache.java | 10 +- .../alibaba/excel/metadata/FieldWrapper.java | 43 ++++ .../excel/metadata/GlobalConfiguration.java | 2 +- .../metadata/property/ExcelHeadProperty.java | 19 +- .../com/alibaba/excel/util/ClassUtils.java | 95 ++++---- .../AbstractExcelWriterParameterBuilder.java | 6 +- .../write/executor/ExcelWriteAddExecutor.java | 21 +- .../write/metadata/WriteBasicParameter.java | 4 +- .../metadata/holder/AbstractWriteHolder.java | 17 +- .../write/metadata/holder/WriteHolder.java | 4 +- .../easyexcel/test/core/cache/CacheData.java | 21 ++ .../test/core/cache/CacheDataTest.java | 219 ++++++++++++++++++ .../test/core/cache/CacheInvokeData.java | 21 ++ .../core/cache/CacheInvokeMemoryData.java | 21 ++ .../ExcludeOrIncludeDataTest.java | 84 +++++-- update.md | 5 +- 17 files changed, 490 insertions(+), 113 deletions(-) create mode 100644 easyexcel-core/src/main/java/com/alibaba/excel/metadata/FieldWrapper.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheData.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheDataTest.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeData.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeMemoryData.java diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java index 319c5ab6..7dc50c76 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Locale; import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CacheLocationEnum; import com.alibaba.excel.util.ListUtils; /** @@ -73,6 +74,16 @@ public abstract class AbstractParameterBuilder sortedFieldMap; + private Map sortedFieldMap; /** * Fields using the index attribute */ - private Map indexFieldMap; - - /** - * Fields to ignore - */ - private Map ignoreMap; + private Map indexFieldMap; } diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/FieldWrapper.java b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/FieldWrapper.java new file mode 100644 index 00000000..bfe9321e --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/FieldWrapper.java @@ -0,0 +1,43 @@ +package com.alibaba.excel.metadata; + +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * filed wrapper + * + * @author Jiaju Zhuang + */ +@Getter +@Setter +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor +public class FieldWrapper { + + /** + * field + */ + private Field field; + + /** + * The field name matching cglib + */ + private String fieldName; + + /** + * The name of the sheet header. + * + * @see ExcelProperty + */ + private String[] heads; +} diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java index e11f6e9d..fe823dad 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java @@ -54,6 +54,6 @@ public class GlobalConfiguration { this.use1904windowing = Boolean.FALSE; this.locale = Locale.getDefault(); this.useScientificFormat = Boolean.FALSE; - this.filedCacheLocation = CacheLocationEnum.MEMORY; + this.filedCacheLocation = CacheLocationEnum.THREAD_LOCAL; } } diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java index c8bc36d7..ce00e2eb 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java @@ -11,6 +11,7 @@ import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.enums.HeadKindEnum; import com.alibaba.excel.metadata.ConfigurationHolder; import com.alibaba.excel.metadata.FieldCache; +import com.alibaba.excel.metadata.FieldWrapper; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Holder; import com.alibaba.excel.util.ClassUtils; @@ -107,7 +108,7 @@ public class ExcelHeadProperty { } FieldCache fieldCache = ClassUtils.declaredFields(headClazz, configurationHolder); - for (Map.Entry entry : fieldCache.getSortedFieldMap().entrySet()) { + for (Map.Entry entry : fieldCache.getSortedFieldMap().entrySet()) { initOneColumnProperty(entry.getKey(), entry.getValue(), fieldCache.getIndexFieldMap().containsKey(entry.getKey())); } @@ -122,22 +123,20 @@ public class ExcelHeadProperty { * @param forceIndex * @return Ignore current field */ - private void initOneColumnProperty(int index, Field field, Boolean forceIndex) { - ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); - List tmpHeadList = new ArrayList(); - String fieldName = FieldUtils.resolveCglibFieldName(field); - boolean notForceName = excelProperty == null || excelProperty.value().length <= 0 - || (excelProperty.value().length == 1 && StringUtils.isEmpty((excelProperty.value())[0])); + private void initOneColumnProperty(int index, FieldWrapper field, Boolean forceIndex) { + List tmpHeadList = new ArrayList<>(); + boolean notForceName = field.getHeads() == null || field.getHeads().length == 0 + || (field.getHeads().length == 1 && StringUtils.isEmpty(field.getHeads()[0])); if (headMap.containsKey(index)) { tmpHeadList.addAll(headMap.get(index).getHeadNameList()); } else { if (notForceName) { - tmpHeadList.add(fieldName); + tmpHeadList.add(field.getFieldName()); } else { - Collections.addAll(tmpHeadList, excelProperty.value()); + Collections.addAll(tmpHeadList, field.getHeads()); } } - Head head = new Head(index, field, fieldName, tmpHeadList, forceIndex, !notForceName); + Head head = new Head(index, field.getField(), field.getFieldName(), tmpHeadList, forceIndex, !notForceName); headMap.put(index, head); } diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/util/ClassUtils.java b/easyexcel-core/src/main/java/com/alibaba/excel/util/ClassUtils.java index d0a99c00..c5062176 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/util/ClassUtils.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/util/ClassUtils.java @@ -1,5 +1,6 @@ package com.alibaba.excel.util; +import java.io.FileWriter; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -7,14 +8,14 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; @@ -25,17 +26,16 @@ import com.alibaba.excel.annotation.write.style.ContentFontStyle; import com.alibaba.excel.annotation.write.style.ContentStyle; import com.alibaba.excel.converters.AutoConverter; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CacheLocationEnum; import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.metadata.ConfigurationHolder; import com.alibaba.excel.metadata.FieldCache; -import com.alibaba.excel.metadata.Holder; +import com.alibaba.excel.metadata.FieldWrapper; import com.alibaba.excel.metadata.property.DateTimeFormatProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.FontProperty; import com.alibaba.excel.metadata.property.NumberFormatProperty; import com.alibaba.excel.metadata.property.StyleProperty; -import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; +import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.alibaba.excel.write.metadata.holder.WriteHolder; import lombok.AllArgsConstructor; @@ -312,16 +312,16 @@ public class ClassUtils { tempClass = tempClass.getSuperclass(); } // Screening of field - Map> orderFieldMap = new TreeMap>(); - Map indexFieldMap = new TreeMap(); - Map ignoreMap = new HashMap(16); + Map> orderFieldMap = new TreeMap<>(); + Map indexFieldMap = new TreeMap<>(); + Set ignoreSet = new HashSet<>(); ExcelIgnoreUnannotated excelIgnoreUnannotated = clazz.getAnnotation(ExcelIgnoreUnannotated.class); for (Field field : tempFieldList) { - declaredOneField(field, orderFieldMap, indexFieldMap, ignoreMap, excelIgnoreUnannotated); + declaredOneField(field, orderFieldMap, indexFieldMap, ignoreSet, excelIgnoreUnannotated); } - Map sortedFieldMap = buildSortedAllFieldMap(orderFieldMap, indexFieldMap); - FieldCache fieldCache = new FieldCache(sortedFieldMap, indexFieldMap, ignoreMap); + Map sortedFieldMap = buildSortedAllFieldMap(orderFieldMap, indexFieldMap); + FieldCache fieldCache = new FieldCache(sortedFieldMap, indexFieldMap); if (!(configurationHolder instanceof WriteHolder)) { return fieldCache; @@ -338,21 +338,21 @@ public class ClassUtils { return fieldCache; } // ignore filed - Map tempSortedFieldMapp = MapUtils.newHashMap(); + Map tempSortedFieldMapp = MapUtils.newHashMap(); int index = 0; - for (Map.Entry entry : sortedFieldMap.entrySet()) { + for (Map.Entry entry : sortedFieldMap.entrySet()) { Integer key = entry.getKey(); - Field field = entry.getValue(); + FieldWrapper field = entry.getValue(); // The current field needs to be ignored - if (writeHolder.ignore(entry.getValue().getName(), entry.getKey())) { - if (ignoreMap != null) { - ignoreMap.put(field.getName(), field); + if (writeHolder.ignore(field.getFieldName(), entry.getKey())) { + if (ignoreSet != null) { + ignoreSet.add(field.getFieldName()); } indexFieldMap.remove(index); } else { // Mandatory sorted fields - if (indexFieldMap.containsKey(key)) { + if (ignoreSet.contains(key)) { tempSortedFieldMapp.put(key, field); } else { // Need to reorder automatically @@ -374,13 +374,13 @@ public class ClassUtils { /** * it only works when {@link WriteHolder#getIncludeColumnFieldNames()} or * {@link WriteHolder#getIncludeColumnIndexes()} ()} has value - * and {@link WriteHolder#getSortByIncludeColumn()} ()} is true + * and {@link WriteHolder#getOrderByIncludeColumn()} ()} is true **/ private static void resortField(WriteHolder writeHolder, FieldCache fieldCache) { - if (!writeHolder.sortByIncludeColumn()) { + if (!writeHolder.orderByIncludeColumn()) { return; } - Map indexFieldMap = fieldCache.getIndexFieldMap(); + Map indexFieldMap = fieldCache.getIndexFieldMap(); Collection includeColumnFieldNames = writeHolder.includeColumnFieldNames(); if (!CollectionUtils.isEmpty(includeColumnFieldNames)) { @@ -392,9 +392,9 @@ public class ClassUtils { } // rebuild sortedFieldMap - Map tempSortedFieldMap = MapUtils.newHashMap(); + Map tempSortedFieldMap = MapUtils.newHashMap(); fieldCache.getSortedFieldMap().forEach((index, field) -> { - Integer tempFieldIndex = filedIndexMap.get(field.getName()); + Integer tempFieldIndex = filedIndexMap.get(field.getFieldName()); if (tempFieldIndex != null) { tempSortedFieldMap.put(tempFieldIndex, field); @@ -409,7 +409,7 @@ public class ClassUtils { } Collection includeColumnIndexes = writeHolder.includeColumnIndexes(); - if (!CollectionUtils.isEmpty(includeColumnFieldNames)) { + if (!CollectionUtils.isEmpty(includeColumnIndexes)) { // Index sorted map Map filedIndexMap = MapUtils.newHashMap(); int fieldIndex = 0; @@ -418,7 +418,7 @@ public class ClassUtils { } // rebuild sortedFieldMap - Map tempSortedFieldMap = MapUtils.newHashMap(); + Map tempSortedFieldMap = MapUtils.newHashMap(); fieldCache.getSortedFieldMap().forEach((index, field) -> { Integer tempFieldIndex = filedIndexMap.get(index); @@ -431,16 +431,16 @@ public class ClassUtils { } } - private static Map buildSortedAllFieldMap(Map> orderFieldMap, - Map indexFieldMap) { + private static Map buildSortedAllFieldMap(Map> orderFieldMap, + Map indexFieldMap) { - Map sortedAllFieldMap = new HashMap( - (orderFieldMap.size() + indexFieldMap.size()) * 4 / 3 + 1); + Map sortedAllFieldMap = MapUtils.newHashMapWithExpectedSize( + orderFieldMap.size() + indexFieldMap.size()); - Map tempIndexFieldMap = new HashMap(indexFieldMap); + Map tempIndexFieldMap = MapUtils.newLinkedHashMapWithExpectedSize(indexFieldMap.size()); int index = 0; - for (List fieldList : orderFieldMap.values()) { - for (Field field : fieldList) { + for (List fieldList : orderFieldMap.values()) { + for (FieldWrapper field : fieldList) { while (tempIndexFieldMap.containsKey(index)) { sortedAllFieldMap.put(index, tempIndexFieldMap.get(index)); tempIndexFieldMap.remove(index); @@ -454,34 +454,45 @@ public class ClassUtils { return sortedAllFieldMap; } - private static void declaredOneField(Field field, Map> orderFieldMap, - Map indexFieldMap, Map ignoreMap, + private static void declaredOneField(Field field, Map> orderFieldMap, + Map indexFieldMap, Set ignoreSet, ExcelIgnoreUnannotated excelIgnoreUnannotated) { + String fieldName = FieldUtils.resolveCglibFieldName(field); + FieldWrapper fieldWrapper = new FieldWrapper(); + fieldWrapper.setField(field); + fieldWrapper.setFieldName(fieldName); ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class); + if (excelIgnore != null) { - ignoreMap.put(field.getName(), field); + ignoreSet.add(fieldName); return; } ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); boolean noExcelProperty = excelProperty == null && excelIgnoreUnannotated != null; if (noExcelProperty) { - ignoreMap.put(field.getName(), field); + ignoreSet.add(fieldName); return; } boolean isStaticFinalOrTransient = (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) || Modifier.isTransient(field.getModifiers()); if (excelProperty == null && isStaticFinalOrTransient) { - ignoreMap.put(field.getName(), field); + ignoreSet.add(fieldName); return; } + // set heads + if (excelProperty != null) { + fieldWrapper.setHeads(excelProperty.value()); + } + if (excelProperty != null && excelProperty.index() >= 0) { if (indexFieldMap.containsKey(excelProperty.index())) { - throw new ExcelCommonException("The index of '" + indexFieldMap.get(excelProperty.index()).getName() - + "' and '" + field.getName() + "' must be inconsistent"); + throw new ExcelCommonException( + "The index of '" + indexFieldMap.get(excelProperty.index()).getFieldName() + + "' and '" + field.getName() + "' must be inconsistent"); } - indexFieldMap.put(excelProperty.index(), field); + indexFieldMap.put(excelProperty.index(), fieldWrapper); return; } @@ -489,8 +500,8 @@ public class ClassUtils { if (excelProperty != null) { order = excelProperty.order(); } - List orderFieldList = orderFieldMap.computeIfAbsent(order, key -> ListUtils.newArrayList()); - orderFieldList.add(field); + List orderFieldList = orderFieldMap.computeIfAbsent(order, key -> ListUtils.newArrayList()); + orderFieldList.add(fieldWrapper); } /** diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java b/easyexcel-core/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java index f7f9416c..7878f49e 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java @@ -122,12 +122,12 @@ public abstract class AbstractExcelWriterParameterBuilder entry : fieldCache.getSortedFieldMap().entrySet()) { - Field field = entry.getValue(); - String fieldName = FieldUtils.resolveCglibFieldName(field); + for (Map.Entry entry : fieldCache.getSortedFieldMap().entrySet()) { + FieldWrapper field = entry.getValue(); + String fieldName = field.getFieldName(); boolean uselessData = !beanKeySet.contains(fieldName) || beanMapHandledSet.contains(fieldName); if (uselessData) { continue; @@ -213,18 +214,4 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { } } - private void initSortedAllFieldMapFieldList(Class clazz, Map sortedAllFieldMap) { - if (!sortedAllFieldMap.isEmpty()) { - return; - } - - WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); - boolean needIgnore = - !CollectionUtils.isEmpty(writeSheetHolder.getExcludeColumnFieldNames()) || !CollectionUtils - .isEmpty(writeSheetHolder.getExcludeColumnIndexes()) || !CollectionUtils - .isEmpty(writeSheetHolder.getIncludeColumnFieldNames()) || !CollectionUtils - .isEmpty(writeSheetHolder.getIncludeColumnIndexes()); - ClassUtils.declaredFields(clazz, writeSheetHolder); - } - } diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java b/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java index 68cc09c9..a926209a 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java @@ -58,9 +58,9 @@ public class WriteBasicParameter extends BasicParameter { private Collection includeColumnFieldNames; /** - * Data will be sorted according to {@link #includeColumnFieldNames} or {@link #includeColumnIndexes}. + * Data will be order by {@link #includeColumnFieldNames} or {@link #includeColumnIndexes}. * * default is false. */ - private Boolean sortByIncludeColumn; + private Boolean orderByIncludeColumn; } diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java b/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java index 11566e77..d03ea3d8 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java @@ -14,7 +14,6 @@ import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; import com.alibaba.excel.converters.DefaultConverterLoader; import com.alibaba.excel.enums.HeadKindEnum; -import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.event.NotRepeatExecutor; import com.alibaba.excel.metadata.AbstractHolder; import com.alibaba.excel.metadata.Head; @@ -97,11 +96,11 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ private Collection includeColumnFieldNames; /** - * Data will be sorted according to {@link #includeColumnFieldNames} or {@link #includeColumnIndexes}. + * Data will be order by {@link #includeColumnFieldNames} or {@link #includeColumnIndexes}. * * default is false. */ - private Boolean sortByIncludeColumn; + private Boolean orderByIncludeColumn; /** * Write handler @@ -203,14 +202,14 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ this.includeColumnFieldNames = writeBasicParameter.getIncludeColumnFieldNames(); } - if (writeBasicParameter.getSortByIncludeColumn() == null) { + if (writeBasicParameter.getOrderByIncludeColumn() == null) { if (parentAbstractWriteHolder == null) { - this.sortByIncludeColumn = Boolean.FALSE; + this.orderByIncludeColumn = Boolean.FALSE; } else { - this.sortByIncludeColumn = parentAbstractWriteHolder.getSortByIncludeColumn(); + this.orderByIncludeColumn = parentAbstractWriteHolder.getOrderByIncludeColumn(); } } else { - this.sortByIncludeColumn = writeBasicParameter.getSortByIncludeColumn(); + this.orderByIncludeColumn = writeBasicParameter.getOrderByIncludeColumn(); } if (writeBasicParameter.getIncludeColumnIndexes() == null && parentAbstractWriteHolder != null) { @@ -500,8 +499,8 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ } @Override - public boolean sortByIncludeColumn() { - return getSortByIncludeColumn(); + public boolean orderByIncludeColumn() { + return getOrderByIncludeColumn(); } @Override diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java b/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java index 3f60a4d9..24ba0c6f 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java @@ -49,11 +49,11 @@ public interface WriteHolder extends ConfigurationHolder { int relativeHeadRowIndex(); /** - * Data will be sorted according to {@link #includeColumnFieldNames} or {@link #includeColumnIndexes}. + * Data will be order by {@link #includeColumnFieldNames} or {@link #includeColumnIndexes}. * * default is false. */ - boolean sortByIncludeColumn(); + boolean orderByIncludeColumn(); /** * Only output the custom columns. diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheData.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheData.java new file mode 100644 index 00000000..f6455438 --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheData.java @@ -0,0 +1,21 @@ +package com.alibaba.easyexcel.test.core.cache; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Jiaju Zhuang + */ +@Getter +@Setter +@EqualsAndHashCode +public class CacheData { + @ExcelProperty("姓名") + private String name; + + @ExcelProperty("年龄") + private Long age; +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheDataTest.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheDataTest.java new file mode 100644 index 00000000..10cb15d0 --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheDataTest.java @@ -0,0 +1,219 @@ +package com.alibaba.easyexcel.test.core.cache; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.alibaba.easyexcel.test.demo.read.DemoData; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.enums.CacheLocationEnum; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.metadata.FieldCache; +import com.alibaba.excel.read.listener.PageReadListener; +import com.alibaba.excel.util.ClassUtils; +import com.alibaba.excel.util.FieldUtils; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * @author Jiaju Zhuang + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Slf4j +public class CacheDataTest { + + private static File file07; + private static File fileCacheInvoke; + private static File fileCacheInvoke2; + private static File fileCacheInvokeMemory; + private static File fileCacheInvokeMemory2; + + @BeforeClass + public static void init() { + file07 = TestFileUtil.createNewFile("cache/cache.xlsx"); + fileCacheInvoke = TestFileUtil.createNewFile("cache/fileCacheInvoke.xlsx"); + fileCacheInvoke2 = TestFileUtil.createNewFile("cache/fileCacheInvoke2.xlsx"); + fileCacheInvokeMemory = TestFileUtil.createNewFile("cache/fileCacheInvokeMemory.xlsx"); + fileCacheInvokeMemory2 = TestFileUtil.createNewFile("cache/fileCacheInvokeMemory2.xlsx"); + } + + @Test + public void t01ReadAndWrite() throws Exception { + Field field = FieldUtils.getField(ClassUtils.class, "FIELD_THREAD_LOCAL", true); + ThreadLocal, FieldCache>> fieldThreadLocal = (ThreadLocal, FieldCache>>)field.get( + ClassUtils.class.newInstance()); + Assert.assertNull(fieldThreadLocal.get()); + EasyExcel.write(file07, CacheData.class).sheet().doWrite(data()); + EasyExcel.read(file07, CacheData.class, new PageReadListener(dataList -> { + Assert.assertNotNull(fieldThreadLocal.get()); + })) + .sheet() + .doRead(); + Assert.assertNull(fieldThreadLocal.get()); + } + + @Test + public void t02ReadAndWriteInvoke() throws Exception { + EasyExcel.write(fileCacheInvoke, CacheInvokeData.class).sheet().doWrite(dataInvoke()); + EasyExcel.read(fileCacheInvoke, CacheInvokeData.class, new AnalysisEventListener() { + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + Assert.assertEquals(2, headMap.size()); + Assert.assertEquals("姓名", headMap.get(0)); + Assert.assertEquals("年龄", headMap.get(1)); + } + + @Override + public void invoke(CacheInvokeData data, AnalysisContext context) { + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + }).sheet() + .doRead(); + + Field name = FieldUtils.getField(CacheInvokeData.class, "name", true); + ExcelProperty annotation = name.getAnnotation(ExcelProperty.class); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation); + Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues"); + memberValues.setAccessible(true); + Map map = (Map)memberValues.get(invocationHandler); + map.put("value", new String[] {"姓名2"}); + + EasyExcel.write(fileCacheInvoke2, CacheInvokeData.class).sheet().doWrite(dataInvoke()); + EasyExcel.read(fileCacheInvoke2, CacheInvokeData.class, new AnalysisEventListener() { + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + Assert.assertEquals(2, headMap.size()); + Assert.assertEquals("姓名2", headMap.get(0)); + Assert.assertEquals("年龄", headMap.get(1)); + } + + @Override + public void invoke(CacheInvokeData data, AnalysisContext context) { + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + }).sheet() + .doRead(); + + } + + @Test + public void t03ReadAndWriteInvokeMemory() throws Exception { + EasyExcel.write(fileCacheInvokeMemory, CacheInvokeMemoryData.class) + .filedCacheLocation(CacheLocationEnum.MEMORY) + .sheet() + .doWrite(dataInvokeMemory()); + EasyExcel.read(fileCacheInvokeMemory, CacheInvokeMemoryData.class, + new AnalysisEventListener() { + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + Assert.assertEquals(2, headMap.size()); + Assert.assertEquals("姓名", headMap.get(0)); + Assert.assertEquals("年龄", headMap.get(1)); + } + + @Override + public void invoke(CacheInvokeMemoryData data, AnalysisContext context) { + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + }) + .filedCacheLocation(CacheLocationEnum.MEMORY) + .sheet() + .doRead(); + + Field name = FieldUtils.getField(CacheInvokeMemoryData.class, "name", true); + ExcelProperty annotation = name.getAnnotation(ExcelProperty.class); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation); + Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues"); + memberValues.setAccessible(true); + Map map = (Map)memberValues.get(invocationHandler); + map.put("value", new String[] {"姓名2"}); + + EasyExcel.write(fileCacheInvokeMemory2, CacheInvokeMemoryData.class) + .filedCacheLocation(CacheLocationEnum.MEMORY) + .sheet() + .doWrite(dataInvokeMemory()); + EasyExcel.read(fileCacheInvokeMemory2, CacheInvokeMemoryData.class, + new AnalysisEventListener() { + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + Assert.assertEquals(2, headMap.size()); + Assert.assertEquals("姓名", headMap.get(0)); + Assert.assertEquals("年龄", headMap.get(1)); + } + + @Override + public void invoke(CacheInvokeMemoryData data, AnalysisContext context) { + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + }) + .filedCacheLocation(CacheLocationEnum.MEMORY) + .sheet() + .doRead(); + + } + + private List data() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + CacheData simpleData = new CacheData(); + simpleData.setName("姓名" + i); + simpleData.setAge((long)i); + list.add(simpleData); + } + return list; + } + + private List dataInvoke() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + CacheInvokeData simpleData = new CacheInvokeData(); + simpleData.setName("姓名" + i); + simpleData.setAge((long)i); + list.add(simpleData); + } + return list; + } + + private List dataInvokeMemory() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + CacheInvokeMemoryData simpleData = new CacheInvokeMemoryData(); + simpleData.setName("姓名" + i); + simpleData.setAge((long)i); + list.add(simpleData); + } + return list; + } +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeData.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeData.java new file mode 100644 index 00000000..6506c8af --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeData.java @@ -0,0 +1,21 @@ +package com.alibaba.easyexcel.test.core.cache; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Jiaju Zhuang + */ +@Getter +@Setter +@EqualsAndHashCode +public class CacheInvokeData { + @ExcelProperty("姓名") + private String name; + + @ExcelProperty("年龄") + private Long age; +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeMemoryData.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeMemoryData.java new file mode 100644 index 00000000..25fa25de --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/cache/CacheInvokeMemoryData.java @@ -0,0 +1,21 @@ +package com.alibaba.easyexcel.test.core.cache; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Jiaju Zhuang + */ +@Getter +@Setter +@EqualsAndHashCode +public class CacheInvokeMemoryData { + @ExcelProperty("姓名") + private String name; + + @ExcelProperty("年龄") + private Long age; +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/excludeorinclude/ExcludeOrIncludeDataTest.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/excludeorinclude/ExcludeOrIncludeDataTest.java index 578b5a63..86e32072 100644 --- a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/excludeorinclude/ExcludeOrIncludeDataTest.java +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/excludeorinclude/ExcludeOrIncludeDataTest.java @@ -34,9 +34,13 @@ public class ExcludeOrIncludeDataTest { private static File includeFieldName07; private static File includeFieldName03; private static File includeFieldNameCsv; - private static File includeFieldNameSort07; - private static File includeFieldNameSort03; - private static File includeFieldNameSortCsv; + private static File includeFieldNameOrder07; + private static File includeFieldNameOrder03; + private static File includeFieldNameOrderCsv; + + private static File includeFieldNameOrderIndex07; + private static File includeFieldNameOrderIndex03; + private static File includeFieldNameOrderIndexCsv; @BeforeClass public static void init() { @@ -52,9 +56,12 @@ public class ExcludeOrIncludeDataTest { includeFieldName07 = TestFileUtil.createNewFile("includeFieldName.xlsx"); includeFieldName03 = TestFileUtil.createNewFile("includeFieldName.xls"); includeFieldNameCsv = TestFileUtil.createNewFile("includeFieldName.csv"); - includeFieldNameSort07 = TestFileUtil.createNewFile("includeFieldNameSort.xlsx"); - includeFieldNameSort03 = TestFileUtil.createNewFile("includeFieldNameSort.xls"); - includeFieldNameSortCsv = TestFileUtil.createNewFile("includeFieldNameSort.csv"); + includeFieldNameOrder07 = TestFileUtil.createNewFile("includeFieldNameOrder.xlsx"); + includeFieldNameOrder03 = TestFileUtil.createNewFile("includeFieldNameOrder.xls"); + includeFieldNameOrderCsv = TestFileUtil.createNewFile("includeFieldNameOrder.csv"); + includeFieldNameOrderIndex07 = TestFileUtil.createNewFile("includeFieldNameOrderIndex.xlsx"); + includeFieldNameOrderIndex03 = TestFileUtil.createNewFile("includeFieldNameOrderIndex.xls"); + includeFieldNameOrderIndexCsv = TestFileUtil.createNewFile("includeFieldNameOrderIndex.csv"); } @Test @@ -119,18 +126,33 @@ public class ExcludeOrIncludeDataTest { } @Test - public void t41IncludeFieldName07() { - includeFieldNameForce(includeFieldNameForceIndex07); + public void t41IncludeFieldNameOrder07() { + includeFieldNameOrder(includeFieldNameOrder07); + } + + @Test + public void t42IncludeFieldNameOrder03() { + includeFieldNameOrder(includeFieldNameOrder03); + } + + @Test + public void t43IncludeFieldNameOrderCsv() { + includeFieldNameOrder(includeFieldNameOrderCsv); + } + + @Test + public void t41IncludeFieldNameOrderIndex07() { + includeFieldNameOrderIndex(includeFieldNameOrderIndex07); } @Test - public void t42IncludeFieldName03() { - includeFieldNameForce(includeFieldNameForceIndex03); + public void t42IncludeFieldNameOrderIndex03() { + includeFieldNameOrderIndex(includeFieldNameOrderIndex03); } @Test - public void t43IncludeFieldNameCsv() { - includeFieldNameForce(includeFieldNameForceIndexCsv); + public void t43IncludeFieldNameOrderIndexCsv() { + includeFieldNameOrderIndex(includeFieldNameOrderIndexCsv); } private void excludeIndex(File file) { @@ -192,18 +214,44 @@ public class ExcludeOrIncludeDataTest { Assert.assertEquals("column3", record.get(1)); } - private void includeFieldNameForce(File file) { + + private void includeFieldNameOrderIndex(File file) { + List includeColumnIndexes = new ArrayList<>(); + includeColumnIndexes.add(3); + includeColumnIndexes.add(1); + includeColumnIndexes.add(2); + includeColumnIndexes.add(0); + EasyExcel.write(file, ExcludeOrIncludeData.class) + .includeColumnIndexes(includeColumnIndexes) + .orderByIncludeColumn(true). + sheet() + .doWrite(data()); + List> dataMap = EasyExcel.read(file).sheet().doReadSync(); + Assert.assertEquals(1, dataMap.size()); + Map record = dataMap.get(0); + Assert.assertEquals(4, record.size()); + Assert.assertEquals("column4", record.get(0)); + Assert.assertEquals("column2", record.get(1)); + Assert.assertEquals("column3", record.get(2)); + Assert.assertEquals("column1", record.get(3)); + } + private void includeFieldNameOrder(File file) { List includeColumnFieldNames = new ArrayList<>(); - includeColumnFieldNames.add("column3"); + includeColumnFieldNames.add("column4"); includeColumnFieldNames.add("column2"); - EasyExcel.write(file, ExcludeOrIncludeData.class).includeColumnFieldNames(includeColumnFieldNames) - .sortByIncludeColumn(true).sheet().doWrite(data()); + includeColumnFieldNames.add("column3"); + EasyExcel.write(file, ExcludeOrIncludeData.class) + .includeColumnFieldNames(includeColumnFieldNames) + .orderByIncludeColumn(true). + sheet() + .doWrite(data()); List> dataMap = EasyExcel.read(file).sheet().doReadSync(); Assert.assertEquals(1, dataMap.size()); Map record = dataMap.get(0); - Assert.assertEquals(2, record.size()); - Assert.assertEquals("column3", record.get(0)); + Assert.assertEquals(3, record.size()); + Assert.assertEquals("column4", record.get(0)); Assert.assertEquals("column2", record.get(1)); + Assert.assertEquals("column3", record.get(2)); } private List data() { diff --git a/update.md b/update.md index 1c820ec8..66c04037 100644 --- a/update.md +++ b/update.md @@ -7,8 +7,9 @@ * 在`easyexcel-parent` 包中移除测试包的`dependencyManagement` * 删除`org.apache.poi.hssf.usermodel.PoiUtils.java`, 使用反射获取 [Issue #2804](https://github.com/alibaba/easyexcel/issues/2804) -* 默认对象反射缓存改成`ThreadLocal`,并支持设置 [Issue #2792](https://github.com/alibaba/easyexcel/issues/2792) -* 支持根据`includeColumnIndexes`和`includeColumnFieldNames`排序 [Issue #2697](https://github.com/alibaba/easyexcel/issues/2697) +* 默认对象反射缓存改成`ThreadLocal`,并支持设置反射缓存类型 [Issue #2792](https://github.com/alibaba/easyexcel/issues/2792) +* 支持根据`includeColumnIndexes`和`includeColumnFieldNames` + 排序 [Issue #2697](https://github.com/alibaba/easyexcel/issues/2697) # 3.2.1