All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.kangaroohy.plugin.excel.handler.AbstractSheetWriteHandler Maven / Gradle / Ivy
package com.kangaroohy.plugin.excel.handler;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.kangaroohy.plugin.excel.annotation.*;
import com.kangaroohy.plugin.excel.aop.DynamicNameAspect;
import com.kangaroohy.plugin.excel.config.ExcelConfigProperties;
import com.kangaroohy.plugin.excel.converters.LocalDateStringConverter;
import com.kangaroohy.plugin.excel.converters.LocalDateTimeStringConverter;
import com.kangaroohy.plugin.excel.enhance.WriterBuilderEnhancer;
import com.kangaroohy.plugin.excel.head.HeadGenerator;
import com.kangaroohy.plugin.excel.head.HeadMeta;
import com.kangaroohy.plugin.excel.head.I18nHeaderCellWriteHandler;
import com.kangaroohy.plugin.excel.kit.ExcelException;
import com.kangaroohy.plugin.excel.vo.ExcelExportEnhancer;
import com.kangaroohy.plugin.excel.vo.ExcelSelectorResolver;
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;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.util.Assert;
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.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* @author hy
* @date 2020/3/31
*/
@RequiredArgsConstructor
public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, ApplicationContextAware {
private final ExcelConfigProperties configProperties;
private final ObjectProvider>> converterProvider;
private final WriterBuilderEnhancer excelWriterBuilderEnhance;
private ApplicationContext applicationContext;
@Getter
@Setter
@Autowired(required = false)
private I18nHeaderCellWriteHandler i18nHeaderCellWriteHandler;
@Override
public void check(ResponseExcel responseExcel) {
if (responseExcel.sheets().length == 0) {
throw new ExcelException("@ResponseExcel sheet 配置不合法");
}
}
@Override
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) {
name = UUID.randomUUID().toString();
}
String fileName = String.format("%s%s", URLEncoder.encode(name, StandardCharsets.UTF_8), responseExcel.suffix().getValue());
// 根据实际的文件类型找到对应的 contentType
String contentType = MediaTypeFactory.getMediaType(fileName)
.map(MediaType::toString)
.orElse("application/vnd.ms-excel");
response.setContentType(contentType);
response.setCharacterEncoding("utf-8");
response.addHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=" + fileName);
write(o, response, responseExcel);
}
/**
* 通用的获取ExcelWriter方法
*
* @param response HttpServletResponse
* @param responseExcel ResponseExcel注解
* @return ExcelWriter
*/
@SneakyThrows(IOException.class)
public ExcelWriter getExcelWriter(HttpServletResponse response, ResponseExcel responseExcel) {
ExcelWriterBuilder writerBuilder = EasyExcelFactory.write(response.getOutputStream())
.registerConverter(LocalDateStringConverter.INSTANCE)
.registerConverter(LocalDateTimeStringConverter.INSTANCE)
.autoCloseStream(true)
.excelType(responseExcel.suffix())
.inMemory(responseExcel.inMemory());
if (StringUtils.hasText(responseExcel.password())) {
writerBuilder.password(responseExcel.password());
}
if (responseExcel.include().length != 0) {
writerBuilder.includeColumnFieldNames(Arrays.asList(responseExcel.include()));
}
if (responseExcel.exclude().length != 0) {
writerBuilder.excludeColumnFieldNames(Arrays.asList(responseExcel.exclude()));
}
for (Class extends WriteHandler> clazz : responseExcel.writeHandler()) {
writerBuilder.registerWriteHandler(BeanUtils.instantiateClass(clazz));
}
// 开启国际化头信息处理
if (responseExcel.i18nHeader() && i18nHeaderCellWriteHandler != null) {
writerBuilder.registerWriteHandler(i18nHeaderCellWriteHandler);
}
// 自定义注入的转换器
registerCustomConverter(writerBuilder);
for (Class extends Converter> clazz : responseExcel.converter()) {
writerBuilder.registerConverter(BeanUtils.instantiateClass(clazz));
}
String templatePath = configProperties.getTemplatePath();
if (StringUtils.hasText(responseExcel.template())) {
ClassPathResource classPathResource = new ClassPathResource(
templatePath + File.separator + responseExcel.template());
InputStream inputStream = classPathResource.getInputStream();
writerBuilder.withTemplate(inputStream);
}
writerBuilder = excelWriterBuilderEnhance.enhanceExcel(writerBuilder, response, responseExcel, templatePath);
return writerBuilder.build();
}
/**
* 自定义注入转换器 如果有需要,子类自己重写
*
* @param builder ExcelWriterBuilder
*/
public void registerCustomConverter(ExcelWriterBuilder builder) {
converterProvider.ifAvailable(converters -> converters.forEach(builder::registerConverter));
}
/**
* 获取 WriteSheet 对象
*
* @param sheet sheet annotation info
* @param dataClass 数据类型
* @param template 模板
* @param bookHeadEnhancerClass 自定义头处理器
* @return WriteSheet
*/
public WriteSheet sheet(Sheet sheet, Class> dataClass, String template,
Class extends HeadGenerator> bookHeadEnhancerClass) {
// Sheet 编号和名称
Integer sheetNo = sheet.sheetNo() >= 0 ? sheet.sheetNo() : null;
String sheetName = sheet.sheetName();
// 是否模板写入
ExcelWriterSheetBuilder writerSheetBuilder = StringUtils.hasText(template) ? EasyExcelFactory.writerSheet(sheetNo)
: EasyExcelFactory.writerSheet(sheetNo, sheetName);
// 头信息增强 1. 优先使用 sheet 指定的头信息增强 2. 其次使用 @ResponseExcel 中定义的全局头信息增强
Class extends HeadGenerator> headGenerateClass = null;
if (isNotInterface(sheet.headGenerateClass())) {
headGenerateClass = sheet.headGenerateClass();
} else if (isNotInterface(bookHeadEnhancerClass)) {
headGenerateClass = bookHeadEnhancerClass;
}
// 定义头信息增强则使用其生成头信息,否则使用 dataClass 来自动获取
if (headGenerateClass != null) {
fillCustomHeadInfo(dataClass, bookHeadEnhancerClass, writerSheetBuilder);
} else if (dataClass != null) {
writerSheetBuilder.registerWriteHandler(new ExcelDataWriteHandler(getExcelExportEnhancer(dataClass)));
writerSheetBuilder.head(dataClass);
if (sheet.excludes().length > 0) {
writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.excludes()));
}
if (sheet.includes().length > 0) {
writerSheetBuilder.includeColumnFieldNames(Arrays.asList(sheet.includes()));
}
}
// sheetBuilder 增强
writerSheetBuilder = excelWriterBuilderEnhance.enhanceSheet(writerSheetBuilder, sheetNo, sheetName, dataClass,
template, headGenerateClass);
return writerSheetBuilder.build();
}
private void fillCustomHeadInfo(Class> dataClass, Class extends HeadGenerator> headEnhancerClass,
ExcelWriterSheetBuilder writerSheetBuilder) {
HeadGenerator headGenerator = this.applicationContext.getBean(headEnhancerClass);
Assert.notNull(headGenerator, "The header generated bean does not exist.");
HeadMeta head = headGenerator.head(dataClass);
writerSheetBuilder.head(head.getHead());
writerSheetBuilder.excludeColumnFieldNames(head.getIgnoreHeadFields());
}
/**
* 是否为Null Head Generator
*
* @param headGeneratorClass 头生成器类型
* @return true 已指定 false 未指定(默认值)
*/
private boolean isNotInterface(Class extends HeadGenerator> headGeneratorClass) {
return !Modifier.isInterface(headGeneratorClass.getModifiers());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 批注、头列颜色设置、下拉框增强
*
* @param clazz 类 class
* @return
*/
private ExcelExportEnhancer getExcelExportEnhancer(Class> clazz) {
Map requiredMap = new HashMap<>();
Map notationMap = new HashMap<>();
List notationList = new ArrayList<>();
Map selectedMap = new HashMap<>();
Field[] fields = clazz.getDeclaredFields();
int index = -1;
for (Field field : fields) {
if (field.isAnnotationPresent(ExcelProperty.class)) {
index++;
if (!field.isAnnotationPresent(ExcelRequired.class) && !field.isAnnotationPresent(ExcelNotation.class) && !field.isAnnotationPresent(ExcelSelector.class)) {
continue;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
int indexed = excelProperty.index();
if (indexed == -1) {
indexed = index;
}
ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class);
if (excelRequired != null) {
requiredMap.put(indexed, excelRequired.frontColor().getIndex());
}
ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class);
if (excelNotation != null) {
if (excelProperty.value().length <= 1) {
notationMap.put(indexed, excelNotation.value());
} else {
notationList.add(excelNotation);
}
}
ExcelSelector excelSelector = field.getAnnotation(ExcelSelector.class);
if (excelSelector != null) {
ExcelSelectorResolver resolve = new ExcelSelectorResolver(excelSelector, applicationContext);
if (resolve.getSelectorData().length > 0) {
selectedMap.put(indexed, resolve);
}
}
}
}
return ExcelExportEnhancer.builder()
.requiredMap(requiredMap)
.notationMap(notationMap)
.notationList(notationList)
.selectedMap(selectedMap)
.build();
}
}