Prechádzať zdrojové kódy

优化文件导出逻辑

woody 11 mesiacov pred
rodič
commit
fa5a9d3271

+ 83 - 48
framework-common/src/main/java/com/chelvc/framework/common/util/ExcelUtils.java

@@ -18,8 +18,11 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeSet;
+import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 
+import com.chelvc.framework.common.function.MultipleConsumer;
+import com.chelvc.framework.common.function.MultipleFunction;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import lombok.NonNull;
@@ -182,7 +185,7 @@ public final class ExcelUtils {
      * @return 读取数量
      * @throws IOException I/O操作异常
      */
-    public static int read(@NonNull File file, @NonNull Reader reader) throws IOException {
+    public static int read(@NonNull File file, @NonNull BiConsumer<Row, Integer> reader) throws IOException {
         return read(file, 0, reader);
     }
 
@@ -195,7 +198,7 @@ public final class ExcelUtils {
      * @return 读取数量
      * @throws IOException I/O操作异常
      */
-    public static int read(@NonNull File file, int index, @NonNull Reader reader) throws IOException {
+    public static int read(@NonNull File file, int index, @NonNull BiConsumer<Row, Integer> reader) throws IOException {
         // 尝试以xml方式解析Excel文件
         OPCPackage pkg;
         try {
@@ -219,7 +222,7 @@ public final class ExcelUtils {
      * @return 读取数量
      * @throws IOException I/O操作异常
      */
-    public static int read(@NonNull String file, @NonNull Reader reader) throws IOException {
+    public static int read(@NonNull String file, @NonNull BiConsumer<Row, Integer> reader) throws IOException {
         return read(file, 0, reader);
     }
 
@@ -232,7 +235,8 @@ public final class ExcelUtils {
      * @return 读取数量
      * @throws IOException I/O操作异常
      */
-    public static int read(@NonNull String file, int index, @NonNull Reader reader) throws IOException {
+    public static int read(@NonNull String file, int index, @NonNull BiConsumer<Row, Integer> reader)
+            throws IOException {
         // 尝试以xml方式解析Excel文件
         OPCPackage pkg;
         try {
@@ -256,7 +260,7 @@ public final class ExcelUtils {
      * @return 读取数量
      * @throws IOException I/O操作异常
      */
-    public static int read(@NonNull InputStream input, @NonNull Reader reader) throws IOException {
+    public static int read(@NonNull InputStream input, @NonNull BiConsumer<Row, Integer> reader) throws IOException {
         return read(input, 0, reader);
     }
 
@@ -269,7 +273,8 @@ public final class ExcelUtils {
      * @return 读取数量
      * @throws IOException I/O操作异常
      */
-    public static int read(@NonNull InputStream input, int index, @NonNull Reader reader) throws IOException {
+    public static int read(@NonNull InputStream input, int index, @NonNull BiConsumer<Row, Integer> reader)
+            throws IOException {
         // 标记输入流开始位置
         if (!(input instanceof BufferedInputStream || input instanceof ByteArrayInputStream)) {
             input = new BufferedInputStream(input);
@@ -301,7 +306,7 @@ public final class ExcelUtils {
      * @param reader Excel读接口
      * @return 读取数量
      */
-    public static int read(@NonNull OPCPackage pkg, @NonNull Reader reader) {
+    public static int read(@NonNull OPCPackage pkg, @NonNull BiConsumer<Row, Integer> reader) {
         return read(pkg, 0, reader);
     }
 
@@ -313,11 +318,11 @@ public final class ExcelUtils {
      * @param reader Excel读接口
      * @return 读取数量
      */
-    public static int read(@NonNull OPCPackage pkg, int index, @NonNull Reader reader) {
+    public static int read(@NonNull OPCPackage pkg, int index, @NonNull BiConsumer<Row, Integer> reader) {
         return new AbstractExcelReader(pkg, index) {
             @Override
             public void read(Row row, int count) {
-                reader.read(row, count);
+                reader.accept(row, count);
             }
         }.process();
     }
@@ -329,7 +334,7 @@ public final class ExcelUtils {
      * @param reader   Excel读接口
      * @return 读取数量
      */
-    public static int read(@NonNull Workbook workbook, @NonNull Reader reader) {
+    public static int read(@NonNull Workbook workbook, @NonNull BiConsumer<Row, Integer> reader) {
         return read(workbook, 0, reader);
     }
 
@@ -341,13 +346,13 @@ public final class ExcelUtils {
      * @param reader   Excel读接口
      * @return 读取数量
      */
-    public static int read(@NonNull Workbook workbook, int index, @NonNull Reader reader) {
+    public static int read(@NonNull Workbook workbook, int index, @NonNull BiConsumer<Row, Integer> reader) {
         AssertUtils.check(index > -1, () -> "index must be greater than -1");
         int count = 0;
         for (int i = 0, n = workbook.getNumberOfSheets(); i < n; i++) {
             Sheet sheet = workbook.getSheetAt(i);
             for (int j = index, k = sheet.getLastRowNum(); j <= k; j++) {
-                reader.read(sheet.getRow(j), ++count);
+                reader.accept(sheet.getRow(j), ++count);
             }
         }
         return count;
@@ -427,7 +432,21 @@ public final class ExcelUtils {
      * @return 写入数量
      */
     public static <T> int write(@NonNull Sheet sheet, @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
-                                @NonNull Writer<T> writer) {
+                                @NonNull MultipleConsumer<Row, T, Integer> writer) {
+        return write(sheet, 0, provider, writer);
+    }
+
+    /**
+     * 将对象实例写入到Excel中
+     *
+     * @param sheet    Excel工作表
+     * @param provider 对象实例列表分页提供方法
+     * @param writer   Excel对象实例写入接口
+     * @param <T>      数据类型
+     * @return 写入数量
+     */
+    public static <T> int write(@NonNull Sheet sheet, @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
+                                @NonNull MultipleFunction<Row, T, Integer, Integer> writer) {
         return write(sheet, 0, provider, writer);
     }
 
@@ -443,7 +462,26 @@ public final class ExcelUtils {
      */
     public static <T> int write(@NonNull Sheet sheet, int index,
                                 @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
-                                @NonNull Writer<T> writer) {
+                                @NonNull MultipleConsumer<Row, T, Integer> writer) {
+        return write(sheet, index, provider, (row, object, count) -> {
+            writer.accept(row, object, count);
+            return row.getRowNum();
+        });
+    }
+
+    /**
+     * 将对象实例写入到Excel中
+     *
+     * @param sheet    Excel工作表
+     * @param index    开始行下标
+     * @param provider 对象实例列表分页提供方法
+     * @param writer   Excel对象实例写入接口
+     * @param <T>      数据类型
+     * @return 写入数量
+     */
+    public static <T> int write(@NonNull Sheet sheet, int index,
+                                @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
+                                @NonNull MultipleFunction<Row, T, Integer, Integer> writer) {
         int page = 1, size = BATCH_FETCH_SIZE, count = 0;
         while (true) {
             Collection<T> objects = provider.apply(page++, size);
@@ -451,7 +489,7 @@ public final class ExcelUtils {
                 break;
             }
             for (T object : objects) {
-                index = writer.write(sheet.createRow(index), object, ++count) + 1;
+                index = writer.apply(sheet.createRow(index), object, ++count) + 1;
             }
             if (objects.size() < size) {
                 break;
@@ -472,7 +510,26 @@ public final class ExcelUtils {
      */
     public static <T> int write(@NonNull Workbook workbook,
                                 @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
-                                @NonNull Writer<T> writer, @NonNull String... titles) {
+                                @NonNull MultipleConsumer<Row, T, Integer> writer, @NonNull String... titles) {
+        return write(workbook, provider, (row, object, count) -> {
+            writer.accept(row, object, count);
+            return row.getRowNum();
+        }, titles);
+    }
+
+    /**
+     * 将对象实例写入到Excel中
+     *
+     * @param workbook Excel工作薄
+     * @param provider 对象实例列表分页提供方法
+     * @param writer   Excel对象实例写入接口
+     * @param titles   表头数组
+     * @param <T>      数据类型
+     * @return 写入数量
+     */
+    public static <T> int write(@NonNull Workbook workbook,
+                                @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
+                                @NonNull MultipleFunction<Row, T, Integer, Integer> writer, @NonNull String... titles) {
         int page = 1, size = BATCH_FETCH_SIZE, index = 0, origin = titles.length == 0 ? 0 : 1, row = origin;
         int volume = workbook instanceof SXSSFWorkbook || workbook instanceof XSSFWorkbook ?
                 XLSX_SHEET_VOLUME : XLS_SHEET_VOLUME;
@@ -487,7 +544,7 @@ public final class ExcelUtils {
                     sheet = initializeSheet(workbook, titles);
                     row = origin;
                 }
-                row = writer.write(sheet.createRow(row), object, index) + 1;
+                row = writer.apply(sheet.createRow(row), object, index) + 1;
             }
             if (objects.size() < size) {
                 break;
@@ -510,36 +567,6 @@ public final class ExcelUtils {
         }
     }
 
-    /**
-     * Excel读接口
-     */
-    public interface Reader {
-        /**
-         * 读取Excel数据行并转换成对象实例
-         *
-         * @param row   数据行对象
-         * @param count 当前记录数(从1开始)
-         */
-        void read(Row row, int count);
-    }
-
-    /**
-     * Excel写接口
-     *
-     * @param <T> 数据模型
-     */
-    public interface Writer<T> {
-        /**
-         * 将对象实例写入到Excel数据行
-         *
-         * @param row    数据行对象
-         * @param object 对象实例
-         * @param count  当前记录数(从1开始)
-         * @return 当前行号
-         */
-        int write(Row row, T object, int count);
-    }
-
     /**
      * 基于XML的Excel行实现
      */
@@ -934,7 +961,7 @@ public final class ExcelUtils {
     /**
      * Excel数据读取处理器抽象实现
      */
-    public static abstract class AbstractExcelReader extends DefaultHandler implements Reader {
+    public static abstract class AbstractExcelReader extends DefaultHandler {
         /**
          * 开始行下标
          */
@@ -987,6 +1014,14 @@ public final class ExcelUtils {
             this.value = StringUtils.EMPTY;
         }
 
+        /**
+         * 读取Excel数据行并转换成对象实例
+         *
+         * @param row   数据行对象
+         * @param count 当前记录数(从1开始)
+         */
+        protected abstract void read(Row row, int count);
+
         /**
          * 构建XML数据读取处理器
          *

+ 44 - 4
framework-download/src/main/java/com/chelvc/framework/download/DownloadHandler.java

@@ -7,8 +7,10 @@ import java.util.function.BiFunction;
 import javax.servlet.http.HttpServletResponse;
 
 import com.chelvc.framework.common.function.Adapter;
+import com.chelvc.framework.common.function.MultipleConsumer;
+import com.chelvc.framework.common.function.MultipleFunction;
 import com.chelvc.framework.common.function.OutputAcceptor;
-import com.chelvc.framework.common.util.ExcelUtils;
+import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Workbook;
 
 /**
@@ -92,7 +94,25 @@ public interface DownloadHandler {
      * @return 下载任务ID
      */
     default <T> long async(String filename, BiFunction<Integer, Integer, Collection<T>> provider,
-                           ExcelUtils.Writer<T> writer, String... titles) {
+                           MultipleConsumer<Row, T, Integer> writer, String... titles) {
+        return this.async(filename, provider, (row, object, count) -> {
+            writer.accept(row, object, count);
+            return row.getRowNum();
+        }, titles);
+    }
+
+    /**
+     * 异步下载数据
+     *
+     * @param filename 文件名称
+     * @param provider 数据生产者
+     * @param writer   Excel对象实例写入接口
+     * @param titles   表头数组
+     * @param <T>      数据类型
+     * @return 下载任务ID
+     */
+    default <T> long async(String filename, BiFunction<Integer, Integer, Collection<T>> provider,
+                           MultipleFunction<Row, T, Integer, Integer> writer, String... titles) {
         return this.async(
                 filename,
                 (id, volume) -> {
@@ -101,6 +121,26 @@ public interface DownloadHandler {
         );
     }
 
+    /**
+     * 异步下载数据
+     *
+     * @param filename 文件名称
+     * @param listener 处理完成监听器
+     * @param provider 数据生产者
+     * @param writer   Excel对象实例写入接口
+     * @param titles   表头数组
+     * @param <T>      数据类型
+     * @return 下载任务ID
+     */
+    default <T> long async(String filename, BiConsumer<Long, Integer> listener,
+                           BiFunction<Integer, Integer, Collection<T>> provider,
+                           MultipleConsumer<Row, T, Integer> writer, String... titles) {
+        return this.async(filename, listener, provider, (row, object, count) -> {
+            writer.accept(row, object, count);
+            return row.getRowNum();
+        }, titles);
+    }
+
     /**
      * 异步下载数据
      *
@@ -113,8 +153,8 @@ public interface DownloadHandler {
      * @return 下载任务ID
      */
     <T> long async(String filename, BiConsumer<Long, Integer> listener,
-                   BiFunction<Integer, Integer, Collection<T>> provider, ExcelUtils.Writer<T> writer,
-                   String... titles);
+                   BiFunction<Integer, Integer, Collection<T>> provider,
+                   MultipleFunction<Row, T, Integer, Integer> writer, String... titles);
 
     /**
      * 销毁处理器

+ 3 - 1
framework-download/src/main/java/com/chelvc/framework/download/support/DefaultDownloadHandler.java

@@ -19,6 +19,7 @@ import com.chelvc.framework.base.context.ThreadContextHolder;
 import com.chelvc.framework.base.util.HttpUtils;
 import com.chelvc.framework.common.function.Adapter;
 import com.chelvc.framework.common.function.Executor;
+import com.chelvc.framework.common.function.MultipleFunction;
 import com.chelvc.framework.common.function.OutputAcceptor;
 import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.common.util.ExcelUtils;
@@ -32,6 +33,7 @@ import com.chelvc.framework.redis.context.RedisContextHolder;
 import com.google.common.collect.Lists;
 import lombok.NonNull;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.springframework.boot.context.event.ApplicationStartedEvent;
@@ -210,7 +212,7 @@ public class DefaultDownloadHandler implements DownloadHandler, ApplicationListe
     @Override
     public <T> long async(@NonNull String filename, @NonNull BiConsumer<Long, Integer> listener,
                           @NonNull BiFunction<Integer, Integer, Collection<T>> provider,
-                          @NonNull ExcelUtils.Writer<T> writer, @NonNull String... titles) {
+                          @NonNull MultipleFunction<Row, T, Integer, Integer> writer, @NonNull String... titles) {
         return this.async(filename, id -> {
             Workbook workbook = new SXSSFWorkbook();
             int volume = ExcelUtils.write(workbook, provider, writer, titles);