Skip to content

Commit

Permalink
refactor(字典转换): 导出过程中只查询一次字典,提升性能
Browse files Browse the repository at this point in the history
类似与 TTL 的控制,文件导出后即清空  ,使用方完全不需要采用缓存的方式
  • Loading branch information
lltx committed Aug 31, 2024
1 parent a5917f8 commit 9b6bed8
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import com.pig4cloud.plugin.excel.aop.RequestExcelArgumentResolver;
import com.pig4cloud.plugin.excel.aop.ResponseExcelReturnValueHandler;
import com.pig4cloud.plugin.excel.config.ExcelConfigProperties;
import com.pig4cloud.plugin.excel.handler.DefaultDictDataProvider;
import com.pig4cloud.plugin.excel.handler.DictDataProvider;
import com.pig4cloud.plugin.excel.kit.SpringContextKit;
import com.pig4cloud.plugin.excel.processor.NameProcessor;
import com.pig4cloud.plugin.excel.processor.NameSpelExpressionProcessor;
Expand Down Expand Up @@ -87,10 +85,4 @@ public void setRequestExcelArgumentResolver() {
requestMappingHandlerAdapter.setArgumentResolvers(resolverList);
}

@Bean
@ConditionalOnMissingBean
public DictDataProvider dictDataProvider() {
return new DefaultDictDataProvider();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.alibaba.excel.EasyExcel;
import com.pig4cloud.plugin.excel.annotation.RequestExcel;
import com.pig4cloud.plugin.excel.converters.*;
import com.pig4cloud.plugin.excel.handler.DictCacheClearAnalysisEventListener;
import com.pig4cloud.plugin.excel.handler.ListAnalysisEventListener;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
Expand Down Expand Up @@ -77,6 +78,7 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m
.registerConverter(LongStringConverter.INSTANCE)
.registerConverter(StringArrayConverter.INSTANCE)
.registerConverter(DictTypeConvert.INSTANCE)
.registerReadListener(new DictCacheClearAnalysisEventListener())
.ignoreEmptyRow(requestExcel.ignoreEmptyRow())
.sheet()
.headRowNumber(requestExcel.headRowNumber())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
import com.pig4cloud.plugin.excel.kit.SpringContextKit;
import com.pig4cloud.plugin.excel.vo.DictEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
Expand Down Expand Up @@ -47,6 +50,8 @@ public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}

public static final Map<String, DictEnum[]> cache = new HashMap<>();

/**
* 转换为 Java 数据
* @param cellData 单元格数据
Expand All @@ -58,7 +63,7 @@ public CellDataTypeEnum supportExcelTypeKey() {
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws Exception {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
if (contentProperty == null) {
return cellData.getStringValue();
}
Field field = contentProperty.getField();
Expand All @@ -69,16 +74,28 @@ public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty c
}

if (declaredAnnotation.enums().length != 0) {

DictEnum[] enums = declaredAnnotation.enums()[0].getEnumConstants();
return DictEnum.getValueByLabel(enums, cellData.getStringValue());
}

DictEnum[] cacheEnums = cache.get(declaredAnnotation.value());
if (cacheEnums != null) {
return DictEnum.getValueByLabel(cacheEnums, cellData.getStringValue());
}

Map<String, DictDataProvider> beansOfType = SpringContextKit.getBeansOfType(DictDataProvider.class);
if (MapUtils.isEmpty(beansOfType)) {
log.error("请实现 DictDataProvider 接口,提供字典数据: https://www.yuque.com/pig4cloud/ogf9nv/pkxq8xqe9r6ax4fg");
return cellData.getStringValue();
}

DictDataProvider dictDataProvider = SpringContextKit.getBean(DictDataProvider.class);
DictEnum[] dictEnums = dictDataProvider.getDict(declaredAnnotation.value());
if (dictEnums == null) {
log.warn("字典数据为空:{},自动字典转换失败", declaredAnnotation.value());
return cellData.getStringValue();
}
cache.put(declaredAnnotation.value(), dictEnums);
return DictEnum.getValueByLabel(dictEnums, cellData.getStringValue());
}

Expand All @@ -104,15 +121,31 @@ public WriteCellData<String> convertToExcelData(String value, ExcelContentProper
return new WriteCellData<>(DictEnum.getLabelByValue(enums, value));
}

DictEnum[] cacheEnums = cache.get(declaredAnnotation.value());
if (cacheEnums != null) {
String labelByValue = DictEnum.getLabelByValue(cacheEnums, value);
if (labelByValue != null) {
return new WriteCellData<>(labelByValue);
}
}

Map<String, DictDataProvider> beansOfType = SpringContextKit.getBeansOfType(DictDataProvider.class);
if (MapUtils.isEmpty(beansOfType)) {
log.error("请实现 DictDataProvider 接口,提供字典数据: https://www.yuque.com/pig4cloud/ogf9nv/pkxq8xqe9r6ax4fg");
return new WriteCellData<>(value);
}

DictDataProvider dictDataProvider = SpringContextKit.getBean(DictDataProvider.class);
DictEnum[] dictEnums = dictDataProvider.getDict(declaredAnnotation.value());

if (dictEnums == null) {
log.warn("字典数据为空:{},自动字典转换失败", declaredAnnotation.value());
return new WriteCellData<>(value);
}

String labelByValue = DictEnum.getLabelByValue(dictEnums, value);
if (labelByValue != null) {
cache.put(declaredAnnotation.value(), dictEnums);
return new WriteCellData<>(labelByValue);
}
return new WriteCellData<>(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ public ExcelWriter getExcelWriter(HttpServletResponse response, ResponseExcel re
writerBuilder.registerConverter(BeanUtils.instantiateClass(clazz));
}

// 注册 Workbook 清空Dict处理器
writerBuilder.registerWriteHandler(new DictCacheClearSheetWriteHandler());

String templatePath = configProperties.getTemplatePath();
if (StringUtils.hasText(responseExcel.template())) {
ClassPathResource classPathResource = new ClassPathResource(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.pig4cloud.plugin.excel.handler;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.pig4cloud.plugin.excel.converters.DictTypeConvert;

/**
* dict cache clear analysis 事件监听器
*
* @author lengleng
* @date 2024/08/31
*/
public class DictCacheClearAnalysisEventListener implements ReadListener<Object> {

@Override
public void invoke(Object o, AnalysisContext analysisContext) {
}

@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
DictTypeConvert.cache.clear();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.pig4cloud.plugin.excel.handler;

import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext;
import com.pig4cloud.plugin.excel.converters.DictTypeConvert;

/**
* dict 缓存清空
*
* @author lengleng
* @date 2024/08/31
*/
public class DictCacheClearSheetWriteHandler implements WorkbookWriteHandler {

/**
* Called after all operations on the workbook have been completed
* @param context
*/
@Override
public void afterWorkbookDispose(WorkbookWriteHandlerContext context) {
DictTypeConvert.cache.clear();
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package com.pig4cloud.plugin.excel.handler;

import com.pig4cloud.plugin.excel.vo.DictEnum;
import org.apache.commons.lang3.ArrayUtils;

import java.util.HashMap;
import java.util.Map;

/**
* dict 数据提供程序
Expand All @@ -14,68 +10,11 @@
*/
public interface DictDataProvider {

static Map<String, DictEnum[]> cache = new HashMap<>();

/**
* 获取缓存
* @return {@link Map }<{@link String }, {@link DictEnum[] }>
*/
default Map<String, DictEnum[]> getCache() {
return cache;
}

/**
* 获取 dict
* @param type 类型
* @return {@link DictEnum[] }
*/
default DictEnum[] getDict(String type) {
return cache.get(type);
}

/**
* 添加 dict
* @param type 类型
* @param key key
* @param value value
*/
default void addDict(String type, String key, String value) {
// 1. 获取当前已有的 DictEnum 数组
DictEnum[] existingEnums = cache.get(type);

// 2. 创建新的 DictEnum 对象
DictEnum newEnum = new DictEnum() {
@Override
public String getValue() {
return key;
}

@Override
public String getLabel() {
return value;
}
};

// 3. 使用 ArrayUtils.add 将新元素添加到数组中
DictEnum[] newEnums = ArrayUtils.add(existingEnums, newEnum);

// 4. 将新数组放入 cache 中
cache.put(type, newEnums);
}

/**
* 删除 dict
* @param type 类型
*/
default void delDict(String type) {
cache.remove(type);
}

/**
* 重新加载 dict
*/
default void clear() {
cache.clear();
}
DictEnum[] getDict(String type);

}
41 changes: 41 additions & 0 deletions src/main/java/com/pig4cloud/plugin/excel/vo/DictEnum.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.pig4cloud.plugin.excel.vo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
Expand Down Expand Up @@ -59,4 +61,43 @@ static <E extends DictEnum> String getValueByLabel(E[] enums, String label) {
.orElse(null);
}

/**
* 构建枚举类目
* @param value 价值
* @param label 标签
* @return {@link DictEnum }
*/
static DictEnum of(String value, String label) {
return new DictEnum() {
@Override
public String getValue() {
return value;
}

@Override
public String getLabel() {
return label;
}
};
}

static Builder builder() {
return new Builder();
}

class Builder {

private final List<DictEnum> items = new ArrayList<>();

public Builder add(String value, String label) {
items.add(DictEnum.of(value, label));
return this;
}

public DictEnum[] build() {
return items.toArray(new DictEnum[0]);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public List<IndexOrNameData3> test2() {
}

@PostMapping("/upload")
public void upload(@RequestExcel List<IndexOrNameData2> dataList, BindingResult bindingResult) {
public void upload(@RequestExcel List<IndexOrNameData3> dataList, BindingResult bindingResult) {
// JSR 303 校验通用校验获取失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.pig4cloud.plugin.excel.enums;

import com.pig4cloud.plugin.excel.handler.DictDataProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -56,18 +55,12 @@ void testFileDownloadAndSave() throws Exception {
saveFileToResources("downloaded-example.xlsx", fileContent);
}

@Autowired
private DictDataProvider dictDataProvider;

/**
* 单元测试,写出excel 字段指定枚举 type
* @throws Exception
*/
@Test
void test2FileDownloadAndSave() throws Exception {
dictDataProvider.addDict("sex_type", "0", "男");
dictDataProvider.addDict("sex_type", "1", "女");

MvcResult result = mockMvc.perform(get("/demo/test2")).andExpect(status().isOk()).andReturn();

MockHttpServletResponse response = result.getResponse();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.pig4cloud.plugin.excel.enums;

import com.pig4cloud.plugin.excel.handler.DictDataProvider;
import com.pig4cloud.plugin.excel.vo.DictEnum;

/**
* @author lengleng
* @date 2024/8/31
*/
// @Service
public class DictDataProviderImpl implements DictDataProvider {

/**
* 获取 dict
* @param type 类型
* @return {@link DictEnum[] }
*/
@Override
public DictEnum[] getDict(String type) {
// 查询数据库组装返回对应的字典数据
return DictEnum.builder().add("1", "男").add("0", "女").build();
}

}
Loading

0 comments on commit 9b6bed8

Please sign in to comment.