登陆

没想到SpringCache还能够这么玩

admin 2020-02-14 144人围观 ,发现0个评论

假如在作业遇到依靠体系回来耗时十分长,有时还不安稳,可是回来的成果数据又改变不大,这时咱们该怎么办?下面我向咱们引荐一下,运用SpringCache来构建办法级缓存,让咱们的服务变的顺利起来,一起进步咱们服务的响应速度。在进行SpringCache实战之前先给咱们整理一下思路。

运用SpringCache的思路

1.运用@EnableCaching或许来敞开缓存服务

2.完结Cache接口来构建自己的缓存处理器(完结查询和增加的功用)

3.能够运用SimpleCacheManager缓存管理器,也能够承继AbstractCacheManager来完结自己的缓存管理器

4.将缓存处理器注册到缓存管理器中,由缓存管理器来统一管理缓存

5.在办法上能够运用@Cacheable,@CachePut,@CacheEvict加载办法上

  • @Cacheable 用于先查后做,假如依据相应的key查到成果就直接回来, 不在履行办法, 假如没有则履行完办法后将办法的回来成果放入到缓存中
  • @CachePut 用于设置缓存,先履行办法,再缓存办法的成果
  • @CacheEvict用于删去缓存。在办法履行前,删去缓存

SpringCache实战

咱们这运用数据库来当缓存的中间件,假如想运用Redis或许其他的中间件只需替换数据的完结或许从头完结缓存处理器,然后在用的运用指定缓存称号即可。

1.界说缓存处理器

@Slf4j
public class DBCache implements Cache {
/**
* 缓存的命名特点
**/
private String name;
@Autowired
private DBCacheRepository dbCacheRepository;

@Override
public String getName() {
return this.name;
}
@Override
public Object getNativeCache() {
return this.dbCacheRepository;
}
@Override
//查询办法
public ValueWrapper get(Object key) {
Value没想到SpringCache还能够这么玩Wrapper result =没想到SpringCache还能够这么玩 null;
try {
//查询缓存中间件
DBCachePO dbCachePO = dbCacheRepository.get(key.toString());
String value = dbCachePO == null ? null : dbCachePO.getValue();
//处理缓存中间件回来的值
if (value != null) {
Class valueType = Class.forName(dbCachePO.getValueClassType());
result = new SimpleValueWrapper(new Gson().fromJson(value, valueType));
}
} catch (Exception e) {
log.warn("get value from DBCache error, key={}", key, e);
}
return result;
}

//增加办法
@Override
public void put(Object key, Object value) 没想到SpringCache还能够这么玩{
try {
String[] keyArray = key.toString().split("#");
if (ArrayUtils.isEmpty(keyArray) || keyArray.length < 2) {
throw new RuntimeException("illegalKey, use: className.methodName#businessId#other, currentKey=" + key.toString());
}
String businessId = keyArray[1];
DBCachePO dbCachePO = new DBCachePO();
dbCachePO.setBusinessId(businessId);
dbCachePO.setKey(key.toString());
dbCachePO.setValue(new Gson().toJson(value));
dbCachePO.setValueClassType(value.getClass().getTypeName());
dbCacheRepository.add(dbCachePO);
} catch (Exception e) {
log.warn("DBCache set value error, key={}, value={}", key, value, e);
}
}

public void setName(String name) {
this.name = name;
}
}

2.敞开缓存和将缓存处理器注册到缓存管理器

@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public DBCache dbCache(){
DBCache dbCache = new DBCache();
dbCache.setName("dbCache");
return dbCache;
}
@Bean
public SimpleCacheManager cacheManager(){
SimpleCacheManager selfCacheManager = new SimpleCacheManager();
Set caches = new HashSet<>();
caches.add(dbCache());
selfCacheManager.setCaches(caches);
return selfCacheManager;
}
}

3.应用到办法上,构建办法级缓存,在cacheNames中能够指定你想运用的缓存处理器,这儿对应的值便是缓存处理器里name的值,key值的生成支撑SpringEL(SpEL)

@Service
@Slf4j
public class UserService {

@Cacheable(cacheNames = {"dbCache"},key = "#root.targetClass.simpleName + '.' + #root.methodName + '#' + #id")
public UserDto getUserFromUserCenter(Long id){
//模仿调用RPC
log.info("========================RPC调用开端===================");
UserDto userDto = buildUserDto();
log.info("========================RPC调用完结===================");
return userDto;
}
private UserDto buildUserDto(){
UserDto userDto = new UserDto();
userDto.setAge(18);
userDto.setPassword("121321");
userDto.setUserName("txw");
userDto.setPhone("211656778");
return userDto;
}

作用显现

1.刺进数据库的结构,如下图所示:

2.代码履行进程分析图

缓存存在时的履行图,直接回来

缓存不存在的履行图,先履行办法,在缓存成果

附数据库脚本

CREATE TABLE `db_cache_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Id',
`business_id` char(30) NOT NULL COMMENT '事务ID',
`key` varchar(200) NOT NULL COMMENT 'key',
`value` text COMMENT 'Value',
`没想到SpringCache还能够这么玩value_class_type` varchar(200) NOT NULL COMMENT '缓存value的java类型,用于反序列化',
`add_time` datetime王诗龄当杨颖花童 DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_UNIQUE` (`key`),
KEY `idx_business_id` 没想到SpringCache还能够这么玩(`business_id`),
KEY `idx_addtime` (`add_time`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
请关注微信公众号
微信二维码
不容错过
Powered By Z-BlogPHP