mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-10 21:19:00 +08:00
refactor(pigx-common-excel): 重构 Excel 模块,引入内置转换器注册机制并优化 Excel 读写流程
This commit is contained in:
1 parent
1d9bfd866f
commit
87a1ea1ae0
19 files changed
+226
-174
No files matched your search
+7
-3
@@ -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<List<Converter<?>>> converterProvider;
|
||||
|
||||
private final ObjectProvider<I18nHeaderCellWriteHandler> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+35
-29
@@ -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<HandlerMethodReturnValueHandler> returnValueHandlers = requestMappingHandlerAdapter
|
||||
.getReturnValueHandlers();
|
||||
@Bean
|
||||
public WebMvcConfigurer excelWebMvcConfigurer() {
|
||||
return new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
resolvers.add(new RequestExcelArgumentResolver());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<>();
|
||||
newHandlers.add(responseExcelReturnValueHandler);
|
||||
assert returnValueHandlers != null;
|
||||
newHandlers.addAll(returnValueHandlers);
|
||||
requestMappingHandlerAdapter.setReturnValueHandlers(newHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加 Excel 请求处理器 到 springmvc 中
|
||||
*/
|
||||
@PostConstruct
|
||||
public void setRequestExcelArgumentResolver() {
|
||||
List<HandlerMethodArgumentResolver> argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();
|
||||
List<HandlerMethodArgumentResolver> 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<HandlerMethodReturnValueHandler> returnValueHandlers = requestMappingHandlerAdapter
|
||||
.getReturnValueHandlers();
|
||||
if (returnValueHandlers == null || returnValueHandlers.contains(responseExcelReturnValueHandler)) {
|
||||
return;
|
||||
}
|
||||
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<>(returnValueHandlers.size() + 1);
|
||||
newHandlers.add(responseExcelReturnValueHandler);
|
||||
newHandlers.addAll(returnValueHandlers);
|
||||
requestMappingHandlerAdapter.setReturnValueHandlers(newHandlers);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -30,7 +30,7 @@ public @interface RequestExcel {
|
||||
|
||||
/**
|
||||
* 是否跳过空行
|
||||
* @return 默认跳过
|
||||
* @return 默认不跳过
|
||||
*/
|
||||
boolean ignoreEmptyRow() default false;
|
||||
|
||||
|
||||
+3
-3
@@ -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.*;
|
||||
|
||||
+13
-17
@@ -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<? extends ListAnalysisEventListener<?>> 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();
|
||||
|
||||
+44
@@ -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<Converter<?>> 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);
|
||||
}
|
||||
|
||||
}
|
||||
+6
-6
@@ -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;
|
||||
|
||||
+7
-7
@@ -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;
|
||||
|
||||
+6
-6
@@ -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;
|
||||
|
||||
+6
-6
@@ -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;
|
||||
|
||||
|
||||
+13
-16
@@ -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<String[]> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Class supportJavaTypeKey() {
|
||||
public Class<?> supportJavaTypeKey() {
|
||||
return String[].class;
|
||||
}
|
||||
|
||||
@@ -34,15 +31,15 @@ public enum StringArrayConverter implements Converter<String[]> {
|
||||
}
|
||||
|
||||
@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<String> convertToExcelData(String[] value, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
return new WriteCellData<>(Arrays.stream(value).collect(Collectors.joining()));
|
||||
return new WriteCellData<>(String.join(StrUtil.COMMA, value));
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+35
-39
@@ -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<I18nHeaderCellWriteHandler> i18nHeaderProvider;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Autowired(required = false)
|
||||
private I18nHeaderCellWriteHandler i18nHeaderCellWriteHandler;
|
||||
protected AbstractSheetWriteHandler(ExcelConfigProperties configProperties,
|
||||
ObjectProvider<List<Converter<?>>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance,
|
||||
ObjectProvider<I18nHeaderCellWriteHandler> 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<? extends HeadGenerator> 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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-17
@@ -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<Object> {
|
||||
|
||||
/**
|
||||
* 缓存带 @ExcelLine 标记的 Long 类型行号字段,避免逐行读取时重复反射扫描。
|
||||
*/
|
||||
private static final ConcurrentHashMap<Class<?>, Field[]> LINE_FIELDS_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
private final List<Object> list = new ArrayList<>();
|
||||
|
||||
private final List<ErrorMessage> errorMessageList = new ArrayList<>();
|
||||
@@ -39,22 +47,13 @@ public class DefaultAnalysisEventListener extends ListAnalysisEventListener<Obje
|
||||
.map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.toSet());
|
||||
errorMessageList.add(new ErrorMessage(lineNum, messageSet));
|
||||
}
|
||||
else {
|
||||
Field[] fields = o.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (field.isAnnotationPresent(ExcelLine.class) && field.getType() == Long.class) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(o, lineNum);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
list.add(o);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (Field field : resolveLineFields(o.getClass())) {
|
||||
ReflectUtil.setFieldValue(o, field, lineNum);
|
||||
}
|
||||
list.add(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,6 +69,12 @@ public class DefaultAnalysisEventListener extends ListAnalysisEventListener<Obje
|
||||
@Override
|
||||
public List<ErrorMessage> 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));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+9
-7
@@ -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<List<Converter<?>>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance) {
|
||||
super(configProperties, converterProvider, excelWriterBuilderEnhance);
|
||||
ObjectProvider<List<Converter<?>>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance,
|
||||
ObjectProvider<I18nHeaderCellWriteHandler> 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名
|
||||
|
||||
+9
-7
@@ -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<List<Converter<?>>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance) {
|
||||
super(configProperties, converterProvider, excelWriterBuilderEnhance);
|
||||
ObjectProvider<List<Converter<?>>> converterProvider, WriterBuilderEnhancer excelWriterBuilderEnhance,
|
||||
ObjectProvider<I18nHeaderCellWriteHandler> 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名
|
||||
|
||||
+5
-5
@@ -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<String> i18nHeadNames = originHeadNameList.stream()
|
||||
.map(headName -> propertyPlaceholderHelper.replacePlaceholders(headName, placeholderResolver))
|
||||
.toList();
|
||||
.toList();
|
||||
head.setHeadNameList(i18nHeadNames);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user