概述
在我负责的“医疗实时监控”项目中,前端页面会将今日与医疗相关的业务信息展示出来,在这展示的内容中,80%都会涉及到患者的相关信息。最开始为了得到这些信息,是通过患者id进行二次查询,对数据载体进行组装,这导致部分接口响应效果不佳。考虑到这些患者信息大都是和当日有关,如果能将特定信息缓存到内存,需要的时候直接获取,应该会快很多。
需求说明
我想要缓存的患者信息是部分的,而非所有的患者信息;并且这些患者信息在当天产生了相关业务,过来这一天,这些患者信息大概就不会用到了。基于需求,EhCache十分符合我的应用场景,能够定制数量,定制过期时间。
实现
1.导入依赖
<!-- 缓存支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
2.在启动类上开启缓存注解
@EnableCaching
3.编写EhCache配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="./ehcache"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="86400"
overflowToDisk="false"
diskPersistent="false"
clearOnFlush="true"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
<!--保存100000条患者信息,24小时后过期,使用最近最少使用算法清除-->
<cache name="patientInfo"
maxElementsInMemory="100000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="86400"
overflowToDisk="false"
clearOnFlush="true"
memoryStoreEvictionPolicy="LRU">
</cache>
<cache name="drugDict"
maxElementsInMemory="20000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="864000"
overflowToDisk="false"
clearOnFlush="true"
memoryStoreEvictionPolicy="LRU">
</cache>
<cache name="medicalDepart"
maxElementsInMemory="20000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="864000"
overflowToDisk="false"
clearOnFlush="true"
memoryStoreEvictionPolicy="LRU">
</cache>
<cache name="medicalStaff"
maxElementsInMemory="20000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="86400"
overflowToDisk="false"
clearOnFlush="true"
memoryStoreEvictionPolicy="LRU">
</cache>
<cache name="illCaseIndex"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
overflowToDisk="false"
clearOnFlush="true"
memoryStoreEvictionPolicy="LRU">
</cache>
</ehcache>
4.编写缓存业务类
@Service
public class CacheService {
Logger logger = LoggerFactory.getLogger(IllCaseServiceImpl.class);
@Autowired
PatientInfoMapper patientInfoMapper;
@Autowired
DrugDictMapper drugDictMapper;
@Autowired
MedicalDeparMapper medicalDeparMapper;
@Autowired
MedicalStaffInfoMapper medicalStaffInfoMapper;
@Autowired
CacheManager cacheManager;
@Cacheable(value = "patientInfo", key = "#institutionCode + '_' + #patientId", unless = "#result == null")
public PatientInfo getPatientInfo(String institutionCode, String patientId) {
return patientInfoMapper.selectKeyColumn(institutionCode, patientId);
}
@Cacheable(value = "drugDict", key = "#institutionCode + '_' + #drugCode", unless = "#result == null")
public DrugDict getDrugDict(String institutionCode, String drugCode) {
return drugDictMapper.selectKeyColumn(institutionCode, drugCode);
}
@Cacheable(value = "medicalDepart", key = "#institutionCode + '_' + #departCode", unless = "#result == null")
public MedicalDepar getMedicalDepar(String institutionCode, String departCode) {
return medicalDeparMapper.selectKeyColumn(institutionCode, departCode);
}
@Cacheable(value = "medicalStaff", key = "#institutionCode + '_' + #staffCode", unless = "#result != null")
public MedicalStaffInfo getMedicalStaffInfo(String institutionCode, String staffCode) {
return medicalStaffInfoMapper.selectKeyColumn(institutionCode, staffCode);
}
//用于项目启动加载部分数据
public void load() {
loadStaff();
loadDepart();
loadDrug();
}
private void loadStaff() {
List<MedicalStaffInfo> medicalStaffInfos = medicalStaffInfoMapper.selectName(20000);
Cache cache = cacheManager.getCache("medicalStaff");
for (MedicalStaffInfo medicalStaffInfo : medicalStaffInfos) {
cache.put(medicalStaffInfo.getMediStafName() + "_" + medicalStaffInfo.getMediStafCode(), medicalStaffInfo);
}
}
private void loadDepart() {
List<MedicalDepar> medicalDepars = medicalDeparMapper.selectName(20000);
Cache cache = cacheManager.getCache("medicalDepart");
for (MedicalDepar medicalDepar : medicalDepars) {
cache.put(medicalDepar.getMediInstCode() + "_" + medicalDepar.getDeptCode(), medicalDepar);
}
}
private void loadDrug() {
List<DrugDict> drugDicts = drugDictMapper.selectNeed(20000);
Cache cache = cacheManager.getCache("drugDict");
for (DrugDict drugDict : drugDicts) {
cache.put(drugDict.getMediInstCode() + "_" + drugDict.getDrugCode(), drugDict);
}
}
}
5.项目启动时,加载部分热点数据
@Component
public class ApplicationStartListener implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
CacheService cacheService;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent{
cacheService.load();
}
}
最后
使用缓存后,以前响应不理想的接口有了明显的改善。