diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ExcelHandlerConfiguration.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ExcelHandlerConfiguration.java index a1a6d92fa..fa2635aca 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ExcelHandlerConfiguration.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ExcelHandlerConfiguration.java @@ -1,6 +1,6 @@ package com.pig4cloud.pigx.common.excel; -import cn.idev.excel.converters.Converter; +import org.apache.fesod.sheet.converters.Converter; import com.pig4cloud.pigx.common.excel.aop.ResponseExcelReturnValueHandler; import com.pig4cloud.pigx.common.excel.config.ExcelConfigProperties; import com.pig4cloud.pigx.common.excel.enhance.DefaultWriterBuilderEnhancer; @@ -29,6 +29,8 @@ public class ExcelHandlerConfiguration { private final ObjectProvider>> converterProvider; + private final ObjectProvider i18nHeaderProvider; + /** * ExcelBuild增强 * @return DefaultWriterBuilderEnhancer 默认什么也不做的增强器 @@ -45,7 +47,8 @@ public class ExcelHandlerConfiguration { @Bean @ConditionalOnMissingBean public SingleSheetWriteHandler singleSheetWriteHandler() { - return new SingleSheetWriteHandler(configProperties, converterProvider, writerBuilderEnhancer()); + return new SingleSheetWriteHandler(configProperties, converterProvider, writerBuilderEnhancer(), + i18nHeaderProvider); } /** @@ -54,7 +57,8 @@ public class ExcelHandlerConfiguration { @Bean @ConditionalOnMissingBean public ManySheetWriteHandler manySheetWriteHandler() { - return new ManySheetWriteHandler(configProperties, converterProvider, writerBuilderEnhancer()); + return new ManySheetWriteHandler(configProperties, converterProvider, writerBuilderEnhancer(), + i18nHeaderProvider); } /** diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ResponseExcelAutoConfiguration.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ResponseExcelAutoConfiguration.java index 952a3fbdb..759c1434c 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ResponseExcelAutoConfiguration.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/ResponseExcelAutoConfiguration.java @@ -6,7 +6,7 @@ import com.pig4cloud.pigx.common.excel.aop.ResponseExcelReturnValueHandler; import com.pig4cloud.pigx.common.excel.config.ExcelConfigProperties; import com.pig4cloud.pigx.common.excel.processor.NameProcessor; import com.pig4cloud.pigx.common.excel.processor.NameSpelExpressionProcessor; -import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -14,9 +14,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import jakarta.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; @@ -27,15 +27,10 @@ import java.util.List; * 配置初始化 */ @AutoConfiguration -@RequiredArgsConstructor @Import(ExcelHandlerConfiguration.class) @EnableConfigurationProperties(ExcelConfigProperties.class) public class ResponseExcelAutoConfiguration { - private final RequestMappingHandlerAdapter requestMappingHandlerAdapter; - - private final ResponseExcelReturnValueHandler responseExcelReturnValueHandler; - /** * SPEL 解析处理器 * @return NameProcessor excel名称解析器 @@ -58,30 +53,41 @@ public class ResponseExcelAutoConfiguration { } /** - * 追加 Excel返回值处理器 到 springmvc 中 + * 注册 Excel 请求参数解析器。 */ - @PostConstruct - public void setReturnValueHandlers() { - List returnValueHandlers = requestMappingHandlerAdapter - .getReturnValueHandlers(); + @Bean + public WebMvcConfigurer excelWebMvcConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new RequestExcelArgumentResolver()); + } + }; + } - List newHandlers = new ArrayList<>(); - newHandlers.add(responseExcelReturnValueHandler); - assert returnValueHandlers != null; - newHandlers.addAll(returnValueHandlers); - requestMappingHandlerAdapter.setReturnValueHandlers(newHandlers); - } - - /** - * 追加 Excel 请求处理器 到 springmvc 中 - */ - @PostConstruct - public void setRequestExcelArgumentResolver() { - List argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers(); - List resolverList = new ArrayList<>(); - resolverList.add(new RequestExcelArgumentResolver()); - resolverList.addAll(argumentResolvers); - requestMappingHandlerAdapter.setArgumentResolvers(resolverList); + /** + * 将 Excel 返回值处理器放到 Spring MVC 处理链最前面,确保 @RestController 的 + * + * @param requestMappingHandlerAdapter Spring MVC 方法适配器 + * @param responseExcelReturnValueHandler Excel 返回值处理器 + * @return 容器初始化完成后的处理器注册回调 + * @ResponseBody 处理器不会先消费 @ResponseExcel 返回值。 + */ + @Bean + public SmartInitializingSingleton excelReturnValueHandlerInitializer( + RequestMappingHandlerAdapter requestMappingHandlerAdapter, + ResponseExcelReturnValueHandler responseExcelReturnValueHandler) { + return () -> { + List returnValueHandlers = requestMappingHandlerAdapter + .getReturnValueHandlers(); + if (returnValueHandlers == null || returnValueHandlers.contains(responseExcelReturnValueHandler)) { + return; + } + List newHandlers = new ArrayList<>(returnValueHandlers.size() + 1); + newHandlers.add(responseExcelReturnValueHandler); + newHandlers.addAll(returnValueHandlers); + requestMappingHandlerAdapter.setReturnValueHandlers(newHandlers); + }; } } diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/RequestExcel.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/RequestExcel.java index 0df77ffa5..1fdbb4f48 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/RequestExcel.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/RequestExcel.java @@ -30,7 +30,7 @@ public @interface RequestExcel { /** * 是否跳过空行 - * @return 默认跳过 + * @return 默认不跳过 */ boolean ignoreEmptyRow() default false; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/ResponseExcel.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/ResponseExcel.java index fe0f76fc3..bdc8cc1ec 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/ResponseExcel.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/annotation/ResponseExcel.java @@ -1,8 +1,8 @@ package com.pig4cloud.pigx.common.excel.annotation; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.support.ExcelTypeEnum; -import cn.idev.excel.write.handler.WriteHandler; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.support.ExcelTypeEnum; +import org.apache.fesod.sheet.write.handler.WriteHandler; import com.pig4cloud.pigx.common.excel.head.HeadGenerator; import java.lang.annotation.*; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java index af34accb2..83e1e6852 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java @@ -1,16 +1,17 @@ package com.pig4cloud.pigx.common.excel.aop; -import cn.idev.excel.EasyExcel; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.read.builder.ExcelReaderBuilder; import com.pig4cloud.pigx.common.excel.annotation.RequestExcel; -import com.pig4cloud.pigx.common.excel.converters.*; +import com.pig4cloud.pigx.common.excel.converters.BuiltinConverters; import com.pig4cloud.pigx.common.excel.handler.ListAnalysisEventListener; import jakarta.servlet.http.HttpServletRequest; -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.ui.ModelMap; +import org.springframework.util.Assert; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.WebDataBinderFactory; @@ -39,9 +40,8 @@ public class RequestExcelArgumentResolver implements HandlerMethodArgumentResolv } @Override - @SneakyThrows(Exception.class) public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer modelAndViewContainer, - NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) { + NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { Class parameterType = parameter.getParameterType(); if (!parameterType.isAssignableFrom(List.class)) { throw new IllegalArgumentException( @@ -50,17 +50,17 @@ public class RequestExcelArgumentResolver implements HandlerMethodArgumentResolv // 处理自定义 readListener RequestExcel requestExcel = parameter.getParameterAnnotation(RequestExcel.class); - assert requestExcel != null; + Assert.notNull(requestExcel, "@RequestExcel annotation must not be null"); Class> readListenerClass = requestExcel.readListener(); ListAnalysisEventListener readListener = BeanUtils.instantiateClass(readListenerClass); // 获取请求文件流 HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); - assert request != null; + Assert.notNull(request, "HttpServletRequest must not be null"); InputStream inputStream; - if (request instanceof MultipartRequest) { - MultipartFile file = ((MultipartRequest) request).getFile(requestExcel.fileName()); - assert file != null; + if (request instanceof MultipartRequest multipartRequest) { + MultipartFile file = multipartRequest.getFile(requestExcel.fileName()); + Assert.notNull(file, "Multipart file [" + requestExcel.fileName() + "] must not be null"); inputStream = file.getInputStream(); } else { @@ -71,13 +71,9 @@ public class RequestExcelArgumentResolver implements HandlerMethodArgumentResolv Class excelModelClass = ResolvableType.forMethodParameter(parameter).getGeneric(0).resolve(); // 这里需要指定读用哪个 class 去读,然后读取第一个 sheet 文件流会自动关闭 - EasyExcel.read(inputStream, excelModelClass, readListener) - .registerConverter(LocalDateStringConverter.INSTANCE) - .registerConverter(LocalTimeStringConverter.INSTANCE) - .registerConverter(LocalDateTimeStringConverter.INSTANCE) - .registerConverter(LongStringConverter.INSTANCE) - .registerConverter(StringArrayConverter.INSTANCE) - .ignoreEmptyRow(requestExcel.ignoreEmptyRow()) + ExcelReaderBuilder readerBuilder = FesodSheet.read(inputStream, excelModelClass, readListener); + BuiltinConverters.registerTo(readerBuilder); + readerBuilder.ignoreEmptyRow(requestExcel.ignoreEmptyRow()) .sheet() .headRowNumber(requestExcel.headRowNumber()) .doRead(); diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/BuiltinConverters.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/BuiltinConverters.java new file mode 100644 index 000000000..328b82499 --- /dev/null +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/BuiltinConverters.java @@ -0,0 +1,44 @@ +package com.pig4cloud.pigx.common.excel.converters; + +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.read.builder.ExcelReaderBuilder; +import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder; + +import java.util.List; + +/** + * 内置 Converter 集合,集中管理避免读写两侧重复注册。 + * + * @author lengleng + */ +public final class BuiltinConverters { + + private BuiltinConverters() { + } + + /** + * 读写 Excel 时默认启用的转换器列表。 + */ + private static final List> INSTANCES = List.of(LocalDateStringConverter.INSTANCE, + LocalTimeStringConverter.INSTANCE, LocalDateTimeStringConverter.INSTANCE, LongStringConverter.INSTANCE, + StringArrayConverter.INSTANCE); + + /** + * 注册内置转换器到 Excel 写构造器。 + * + * @param builder Excel 写构造器 + */ + public static void registerTo(ExcelWriterBuilder builder) { + INSTANCES.forEach(builder::registerConverter); + } + + /** + * 注册内置转换器到 Excel 读构造器。 + * + * @param builder Excel 读构造器 + */ + public static void registerTo(ExcelReaderBuilder builder) { + INSTANCES.forEach(builder::registerConverter); + } + +} diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateStringConverter.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateStringConverter.java index 8d0cf30a2..d6d8ff4ae 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateStringConverter.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateStringConverter.java @@ -1,11 +1,11 @@ package com.pig4cloud.pigx.common.excel.converters; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import java.text.ParseException; import java.time.LocalDate; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateTimeStringConverter.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateTimeStringConverter.java index a054e1a57..593287a27 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateTimeStringConverter.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalDateTimeStringConverter.java @@ -1,12 +1,12 @@ package com.pig4cloud.pigx.common.excel.converters; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; -import cn.idev.excel.util.DateUtils; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.util.DateUtils; import java.text.ParseException; import java.time.LocalDateTime; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalTimeStringConverter.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalTimeStringConverter.java index 9ea705d78..d689f6d50 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalTimeStringConverter.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LocalTimeStringConverter.java @@ -1,11 +1,11 @@ package com.pig4cloud.pigx.common.excel.converters; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import java.text.ParseException; import java.time.LocalTime; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java index fc452b1b1..1b6aceb2b 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java @@ -1,11 +1,11 @@ package com.pig4cloud.pigx.common.excel.converters; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import java.text.ParseException; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/StringArrayConverter.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/StringArrayConverter.java index b09e5728a..34a3e5821 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/StringArrayConverter.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/StringArrayConverter.java @@ -1,18 +1,15 @@ package com.pig4cloud.pigx.common.excel.converters; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; - -import java.text.ParseException; -import java.util.Arrays; -import java.util.stream.Collectors; +import cn.hutool.core.util.StrUtil; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; /** - * LocalDate and string converter + * String[] and string converter * * @author L.cm */ @@ -24,7 +21,7 @@ public enum StringArrayConverter implements Converter { INSTANCE; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String[].class; } @@ -34,15 +31,15 @@ public enum StringArrayConverter implements Converter { } @Override - public String[] convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) throws ParseException { - return cellData.getStringValue().split(","); + public String[] convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + return StrUtil.splitToArray(cellData.getStringValue(), StrUtil.COMMA); } @Override public WriteCellData convertToExcelData(String[] value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new WriteCellData<>(Arrays.stream(value).collect(Collectors.joining())); + return new WriteCellData<>(String.join(StrUtil.COMMA, value)); } } diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/DefaultWriterBuilderEnhancer.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/DefaultWriterBuilderEnhancer.java index c3284d93e..994a899c0 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/DefaultWriterBuilderEnhancer.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/DefaultWriterBuilderEnhancer.java @@ -1,7 +1,7 @@ package com.pig4cloud.pigx.common.excel.enhance; -import cn.idev.excel.write.builder.ExcelWriterBuilder; -import cn.idev.excel.write.builder.ExcelWriterSheetBuilder; +import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder; +import org.apache.fesod.sheet.write.builder.ExcelWriterSheetBuilder; import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.excel.head.HeadGenerator; import jakarta.servlet.http.HttpServletResponse; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/WriterBuilderEnhancer.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/WriterBuilderEnhancer.java index 0ff4ee50c..05b93dd21 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/WriterBuilderEnhancer.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/enhance/WriterBuilderEnhancer.java @@ -1,7 +1,7 @@ package com.pig4cloud.pigx.common.excel.enhance; -import cn.idev.excel.write.builder.ExcelWriterBuilder; -import cn.idev.excel.write.builder.ExcelWriterSheetBuilder; +import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder; +import org.apache.fesod.sheet.write.builder.ExcelWriterSheetBuilder; import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.excel.head.HeadGenerator; import jakarta.servlet.http.HttpServletResponse; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java index 4f106778d..ecbc0a718 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java @@ -1,31 +1,28 @@ package com.pig4cloud.pigx.common.excel.handler; -import cn.idev.excel.EasyExcel; -import cn.idev.excel.ExcelWriter; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.write.builder.ExcelWriterBuilder; -import cn.idev.excel.write.builder.ExcelWriterSheetBuilder; -import cn.idev.excel.write.handler.WriteHandler; -import cn.idev.excel.write.metadata.WriteSheet; +import cn.hutool.core.util.StrUtil; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.ExcelWriter; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder; +import org.apache.fesod.sheet.write.builder.ExcelWriterSheetBuilder; +import org.apache.fesod.sheet.write.handler.WriteHandler; +import org.apache.fesod.sheet.write.metadata.WriteSheet; import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.excel.annotation.Sheet; import com.pig4cloud.pigx.common.excel.aop.DynamicNameAspect; import com.pig4cloud.pigx.common.excel.config.ExcelConfigProperties; -import com.pig4cloud.pigx.common.excel.converters.*; +import com.pig4cloud.pigx.common.excel.converters.BuiltinConverters; import com.pig4cloud.pigx.common.excel.enhance.WriterBuilderEnhancer; import com.pig4cloud.pigx.common.excel.head.HeadGenerator; import com.pig4cloud.pigx.common.excel.head.HeadMeta; import com.pig4cloud.pigx.common.excel.head.I18nHeaderCellWriteHandler; import com.pig4cloud.pigx.common.excel.kit.ExcelException; import jakarta.servlet.http.HttpServletResponse; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; import lombok.SneakyThrows; import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.io.ClassPathResource; @@ -37,15 +34,13 @@ import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; import java.lang.reflect.Modifier; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; -import java.util.Objects; import java.util.UUID; /** @@ -53,7 +48,6 @@ import java.util.UUID; * @author L.cm * @date 2020/3/31 */ -@RequiredArgsConstructor public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, ApplicationContextAware { private final ExcelConfigProperties configProperties; @@ -62,12 +56,18 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap private final WriterBuilderEnhancer excelWriterBuilderEnhance; + private final ObjectProvider i18nHeaderProvider; + private ApplicationContext applicationContext; - @Getter - @Setter - @Autowired(required = false) - private I18nHeaderCellWriteHandler i18nHeaderCellWriteHandler; + protected AbstractSheetWriteHandler(ExcelConfigProperties configProperties, + ObjectProvider>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance, + ObjectProvider i18nHeaderProvider) { + this.configProperties = configProperties; + this.converterProvider = converterProvider; + this.excelWriterBuilderEnhance = excelWriterBuilderEnhance; + this.i18nHeaderProvider = i18nHeaderProvider; + } @Override public void check(ResponseExcel responseExcel) { @@ -77,22 +77,21 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap } @Override - @SneakyThrows(UnsupportedEncodingException.class) public void export(Object o, HttpServletResponse response, ResponseExcel responseExcel) { check(responseExcel); RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - String name = (String) Objects.requireNonNull(requestAttributes) - .getAttribute(DynamicNameAspect.EXCEL_NAME_KEY, RequestAttributes.SCOPE_REQUEST); - if (name == null) { + String name = requestAttributes == null ? null + : (String) requestAttributes.getAttribute(DynamicNameAspect.EXCEL_NAME_KEY, + RequestAttributes.SCOPE_REQUEST); + if (!StringUtils.hasText(name)) { name = UUID.randomUUID().toString(); } - String fileName = String.format("%s%s", URLEncoder.encode(name, "UTF-8"), responseExcel.suffix().getValue()); - // 根据实际的文件类型找到对应的 contentType + String fileName = URLEncoder.encode(name, StandardCharsets.UTF_8) + responseExcel.suffix().getValue(); String contentType = MediaTypeFactory.getMediaType(fileName) .map(MediaType::toString) .orElse("application/vnd.ms-excel"); response.setContentType(contentType); - response.setCharacterEncoding("utf-8"); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName); write(o, response, responseExcel); } @@ -105,16 +104,13 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap */ @SneakyThrows(IOException.class) public ExcelWriter getExcelWriter(HttpServletResponse response, ResponseExcel responseExcel) { - ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream()) - .registerConverter(LocalTimeStringConverter.INSTANCE) - .registerConverter(LocalDateStringConverter.INSTANCE) - .registerConverter(LocalDateTimeStringConverter.INSTANCE) - .registerConverter(LongStringConverter.INSTANCE) - .registerConverter(StringArrayConverter.INSTANCE) + ExcelWriterBuilder writerBuilder = FesodSheet.write(response.getOutputStream()) .autoCloseStream(true) .excelType(responseExcel.suffix()) .inMemory(responseExcel.inMemory()); + BuiltinConverters.registerTo(writerBuilder); + if (StringUtils.hasText(responseExcel.password())) { writerBuilder.password(responseExcel.password()); } @@ -132,8 +128,8 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap } // 开启国际化头信息处理 - if (responseExcel.i18nHeader() && i18nHeaderCellWriteHandler != null) { - writerBuilder.registerWriteHandler(i18nHeaderCellWriteHandler); + if (responseExcel.i18nHeader()) { + i18nHeaderProvider.ifAvailable(writerBuilder::registerWriteHandler); } // 自定义注入的转换器 @@ -146,7 +142,7 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap String templatePath = configProperties.getTemplatePath(); if (StringUtils.hasText(responseExcel.template())) { ClassPathResource classPathResource = new ClassPathResource( - templatePath + File.separator + responseExcel.template()); + templatePath + StrUtil.SLASH + responseExcel.template()); InputStream inputStream = classPathResource.getInputStream(); writerBuilder.withTemplate(inputStream); } @@ -180,8 +176,8 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap String sheetName = sheet.sheetName(); // 是否模板写入 - ExcelWriterSheetBuilder writerSheetBuilder = StringUtils.hasText(template) ? EasyExcel.writerSheet(sheetNo) - : EasyExcel.writerSheet(sheetNo, sheetName); + ExcelWriterSheetBuilder writerSheetBuilder = StringUtils.hasText(template) ? FesodSheet.writerSheet(sheetNo) + : FesodSheet.writerSheet(sheetNo, sheetName); // 头信息增强 1. 优先使用 sheet 指定的头信息增强 2. 其次使用 @ResponseExcel 中定义的全局头信息增强 Class headGenerateClass = null; @@ -201,7 +197,7 @@ public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, Ap writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.excludes())); } if (sheet.includes().length > 0) { - writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.includes())); + writerSheetBuilder.includeColumnFieldNames(Arrays.asList(sheet.includes())); } } diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/DefaultAnalysisEventListener.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/DefaultAnalysisEventListener.java index 3a5a2f42a..0f4804330 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/DefaultAnalysisEventListener.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/DefaultAnalysisEventListener.java @@ -1,6 +1,7 @@ package com.pig4cloud.pigx.common.excel.handler; -import cn.idev.excel.context.AnalysisContext; +import cn.hutool.core.util.ReflectUtil; +import org.apache.fesod.sheet.context.AnalysisContext; import com.pig4cloud.pigx.common.excel.annotation.ExcelLine; import com.pig4cloud.pigx.common.excel.kit.Validators; import com.pig4cloud.pigx.common.excel.vo.ErrorMessage; @@ -9,8 +10,10 @@ import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -23,6 +26,11 @@ import java.util.stream.Collectors; @Slf4j public class DefaultAnalysisEventListener extends ListAnalysisEventListener { + /** + * 缓存带 @ExcelLine 标记的 Long 类型行号字段,避免逐行读取时重复反射扫描。 + */ + private static final ConcurrentHashMap, Field[]> LINE_FIELDS_CACHE = new ConcurrentHashMap<>(); + private final List list = new ArrayList<>(); private final List errorMessageList = new ArrayList<>(); @@ -39,22 +47,13 @@ public class DefaultAnalysisEventListener extends ListAnalysisEventListener getErrors() { return errorMessageList; + } + + private static Field[] resolveLineFields(Class clazz) { + return LINE_FIELDS_CACHE.computeIfAbsent(clazz, c -> Arrays.stream(c.getDeclaredFields()) + .filter(f -> f.isAnnotationPresent(ExcelLine.class) && f.getType() == Long.class) + .toArray(Field[]::new)); } } diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ListAnalysisEventListener.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ListAnalysisEventListener.java index 2324e4c69..88b31cd14 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ListAnalysisEventListener.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ListAnalysisEventListener.java @@ -1,6 +1,6 @@ package com.pig4cloud.pigx.common.excel.handler; -import cn.idev.excel.event.AnalysisEventListener; +import org.apache.fesod.sheet.event.AnalysisEventListener; import com.pig4cloud.pigx.common.excel.vo.ErrorMessage; import java.util.List; diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ManySheetWriteHandler.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ManySheetWriteHandler.java index da10be7e9..e7e35c369 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ManySheetWriteHandler.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/ManySheetWriteHandler.java @@ -1,13 +1,14 @@ package com.pig4cloud.pigx.common.excel.handler; -import cn.idev.excel.EasyExcel; -import cn.idev.excel.ExcelWriter; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.write.metadata.WriteSheet; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.ExcelWriter; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.write.metadata.WriteSheet; import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.excel.annotation.Sheet; import com.pig4cloud.pigx.common.excel.config.ExcelConfigProperties; import com.pig4cloud.pigx.common.excel.enhance.WriterBuilderEnhancer; +import com.pig4cloud.pigx.common.excel.head.I18nHeaderCellWriteHandler; import com.pig4cloud.pigx.common.excel.kit.ExcelException; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.ObjectProvider; @@ -23,8 +24,9 @@ import java.util.List; public class ManySheetWriteHandler extends AbstractSheetWriteHandler { public ManySheetWriteHandler(ExcelConfigProperties configProperties, - ObjectProvider>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance) { - super(configProperties, converterProvider, excelWriterBuilderEnhance); + ObjectProvider>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance, + ObjectProvider i18nHeaderProvider) { + super(configProperties, converterProvider, excelWriterBuilderEnhance, i18nHeaderProvider); } /** @@ -54,7 +56,7 @@ public class ManySheetWriteHandler extends AbstractSheetWriteHandler { List eleList = (List) objList.get(i); if (CollectionUtils.isEmpty(eleList)) { - sheet = EasyExcel.writerSheet(responseExcel.sheets()[i].sheetName()).build(); + sheet = FesodSheet.writerSheet(responseExcel.sheets()[i].sheetName()).build(); } else { // 有模板则不指定sheet名 diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/SingleSheetWriteHandler.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/SingleSheetWriteHandler.java index 518983283..61985d6af 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/SingleSheetWriteHandler.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/SingleSheetWriteHandler.java @@ -1,12 +1,13 @@ package com.pig4cloud.pigx.common.excel.handler; -import cn.idev.excel.EasyExcel; -import cn.idev.excel.ExcelWriter; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.write.metadata.WriteSheet; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.ExcelWriter; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.write.metadata.WriteSheet; import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.excel.config.ExcelConfigProperties; import com.pig4cloud.pigx.common.excel.enhance.WriterBuilderEnhancer; +import com.pig4cloud.pigx.common.excel.head.I18nHeaderCellWriteHandler; import com.pig4cloud.pigx.common.excel.kit.ExcelException; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.ObjectProvider; @@ -24,8 +25,9 @@ import java.util.List; public class SingleSheetWriteHandler extends AbstractSheetWriteHandler { public SingleSheetWriteHandler(ExcelConfigProperties configProperties, - ObjectProvider>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance) { - super(configProperties, converterProvider, excelWriterBuilderEnhance); + ObjectProvider>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance, + ObjectProvider i18nHeaderProvider) { + super(configProperties, converterProvider, excelWriterBuilderEnhance, i18nHeaderProvider); } /** @@ -51,7 +53,7 @@ public class SingleSheetWriteHandler extends AbstractSheetWriteHandler { WriteSheet sheet; if (CollectionUtils.isEmpty(eleList)) { - sheet = EasyExcel.writerSheet(responseExcel.sheets()[0].sheetName()).build(); + sheet = FesodSheet.writerSheet(responseExcel.sheets()[0].sheetName()).build(); } else { // 有模板则不指定sheet名 diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/head/I18nHeaderCellWriteHandler.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/head/I18nHeaderCellWriteHandler.java index bd5d46ef5..347a3ebb8 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/head/I18nHeaderCellWriteHandler.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/head/I18nHeaderCellWriteHandler.java @@ -1,9 +1,9 @@ package com.pig4cloud.pigx.common.excel.head; -import cn.idev.excel.metadata.Head; -import cn.idev.excel.write.handler.CellWriteHandler; -import cn.idev.excel.write.metadata.holder.WriteSheetHolder; -import cn.idev.excel.write.metadata.holder.WriteTableHolder; +import org.apache.fesod.sheet.metadata.Head; +import org.apache.fesod.sheet.write.handler.CellWriteHandler; +import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder; +import org.apache.fesod.sheet.write.metadata.holder.WriteTableHolder; import lombok.RequiredArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.ss.usermodel.Row; @@ -51,7 +51,7 @@ public class I18nHeaderCellWriteHandler implements CellWriteHandler { // 国际化处理 List i18nHeadNames = originHeadNameList.stream() .map(headName -> propertyPlaceholderHelper.replacePlaceholders(headName, placeholderResolver)) - .toList(); + .toList(); head.setHeadNameList(i18nHeadNames); } }