<dependency>
<groupId>com.github.ben-manes.caffeinegroupId>
<artifactId>caffeineartifactId>
dependency>
注释:选择使用 Caffeine 作为缓存依赖,是因为它是一款性能卓越的本地缓存库,具有快速、高效和可配置的特点。
@Configuration
@EnableCaching
public class CacheConfig {
/**
* 配置Caffeine缓存管理器
*/
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
// 设置缓存过期时间为30分钟
.expireAfterWrite(30, TimeUnit.MINUTES)
// 设置最大缓存条目数
.maximumSize(1000)
.recordStats()
);
return cacheManager;
}
}
@Service
public class DictionaryService {
@Resource
private DocumentExpiredMapper documentExpiredMapper;
/**
* 通过@Cacheable注解将字典数据存入缓存
* @param dictionaryType 字典类型
* @return 字典数据的HashMap
*/
@Cacheable(value = "dictionaryCache", key = "#dictionaryType")
public HashMap<String, String> getDict(String dictionaryType) {
List<DictDTO> dictList = documentExpiredMapper.getDict(dictionaryType);
HashMap<String, String> dictMap = new HashMap<>(16);
for (DictDTO dictDTO : dictList) {
dictMap.put(dictDTO.getDictValue(), dictDTO.getDictName());
}
return dictMap;
}
}
@Cacheable
是 Spring 框架中用于声明一个方法要被缓存处理的注解。在上面这段代码中,它的用法是为 getDict
方法添加了缓存的支持。
具体到这个注解的属性解释如下:
value
:指定缓存的名称,可以理解为给缓存起一个名字,这样你可以在不同地方使用相同名字的缓存。在你的例子中,缓存的名称是 “dictionaryCache”。key
:指定缓存的键。缓存的键决定了缓存的唯一性。在你的例子中,"#dictionaryType"
表示缓存的键是方法的参数 dictionaryType
的值。这样就能够通过不同的 dictionaryType
值来区分不同的缓存数据。综合起来,@Cacheable(value = "dictionaryCache", key = "#dictionaryType")
的含义是:
dictionaryType
的值。流程解析
当这个方法被调用时,Spring 会先检查缓存中是否已经存在了相同键的缓存数据,如果存在就直接返回缓存的结果,而不执行方法体;如果不存在,就执行方法体,并将方法的结果缓存起来,以备后续相同参数的方法调用直接使用缓存数据,提高执行效率。这样,对于相同的 dictionaryType
参数,方法的执行结果只需要计算一次,之后就可以直接从缓存中获取,避免了重复计算。
public abstract class AbstractDictConverter implements Converter<String> {
/**
* 获取字典类型
* 使用protected修饰符可以将方法或变量限制在同一包中的类和子类中访问。
* @return
*/
protected abstract String getDictType();
@Override
public Class<?> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return cellData.getStringValue();
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
DictionaryService bean = SpringUtil.getBean(DictionaryService.class);
HashMap<String, String> dictMap = bean.getDict(getDictType());
String convertedValue = dictMap.get(context.getValue());
if (convertedValue != null) {
return new WriteCellData<>(convertedValue);
} else {
return new WriteCellData<>(context.getValue());
}
}
}
注意事项:
SpringUtil.getBean()
)第一个转换器:
public class AlertTypeConvert extends AbstractDictConverter {
@Override
protected String getDictType() {
return ALERT_TYPE;
}
}
第二个转换器:
public class DocumentDictConverter extends AbstractDictConverter {
@Override
protected String getDictType() {
return CERTIFICATE;
}
}
注意:在线上环境可能会遇到问题,比如测试环境正常运行,但在生产环境中无法进行字典转换,可能导致转换失败。为了解决这个问题,我们可以考虑使用自定义的静态变量 HashMap 来实现该功能,确保字典数据在各个环境中都能正确加载。
其他实现方式阅读:
文件导出之自定义字典映射转换器
Java 本地缓存之王Caffeine - 掘金 (juejin.cn)
程序员必备的Spring集成缓存知识:深入浅出的教程分享 - 掘金 (juejin.cn)
SpringBoot缓存注解@Cacheable之自定义key策略及缓存失效时间指定 - 掘金 (juejin.cn)
深入浅出@Cacheable-CSDN博客
Spring之缓存注解@Cacheable-CSDN博客