2020.3.11追加
如果有多个缓存需要CacheManager
1. 缓存系统设计逻辑
按照数据表来分,一个数据表一个Mapper一个Service(除非巨傻逼的表设计有问题才一个Mapper放多个表)。
如果涉及到多张表的话,非要是用缓存,那就再封一个Service,然后调用刚才只有一张表的那个低层Service。
低层Service的方法,基本也就是表增删改,然后在相应的方法上面,打上那三个注解,这样这个表一变,肯定缓存也就跟着更新了。
2. 注解
@Service
public class DemoServiceImpl implements DemoService {
@Autowired
PersonRepository personRepository;
@Cacheable(value = "people", key = "#person.id")
@Override
public Person findOne(Person person) {
Person p = personRepository.findOne(person.getId());
System.out.println("为id、key为" + p.getId() + "数据做了缓存");
return p;
}
@CacheEvict(value = "people")
@Override
public void remove(Long id) {
System.out.println("删除了id、key为" + id + "的数据缓存");
personRepository.delete(id);
}
@CachePut(value = "people", key = "#person.id")
@Override
public Person save(Person person) {
Person p = personRepository.save(person);
System.out.println("为id、key为" + p.getId() + "数据做了缓存");
return p;
}
}
img
注解里面的value就是缓存名字
3. @CacheConfig
所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了,所以,有了@CacheConfig这个配置。
@CacheConfig(cacheNames = {"myCache"})
public class BotRelationServiceImpl implements BotRelationService {
@Cacheable(key = "targetClass + methodName +#p0")
public List<BotRelation> findAllLimit(int num) {
return botRelationRepository.findAllLimit(num);
}
}
4. key生成策略
看到下面的这个key生成策略,基本上key一定要自己指定了。
如果自己写了key是多少的话,就按照写的来;如果没写的话,这个自动生成,大概流程是,method名+字段名+字段值,封成一个Map,然后再转成Json,再做Md5加密。
(如果生成的话,基本不可能再人为操纵它了)
public class CacheKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
// 关键点也就这三行!!!
Map<String, Object> map = new HashMap<String, Object>();
map.put("target", target.getClass().toGenericString());//放入target的名字
map.put("method", method.getName());//放入method的名字
if (params != null && params.length > 0) {//把所有参数放进去
int i = 0;
for (Object o : params) {
map.put("params-" + i, o);
i++;
}
}
String str = JSONObject.toJSON(map).toString();
byte[] hash = null;
String s = null;
try {
hash = MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s=MD5Encoder.encode(hash);//使用MD5生成位移key
return s;
}
}
5. 如果没有按照每张表一个服务这种设计
如果没有按照每张表一个服务这种设计,那么就很难用注解来写了,至少我目前没想到怎么用注解。不过这种情况下可以自己注册RedisService,里面封好get / set / delete方法,然后自己手动缓存啊。(这种情况比较复杂,因为如果一旦涉及到多张表,变数可能就比较大)
再分两种情况吧:
- 一张表对应了好几个功能
那就把这好几个功能一起来做缓存 - 好几张表对应了好几个功能
这种情况下要不咱们就别缓存了。。。就是只要这个功能对应了好几张表,几张表还变,那要不别考虑了。。。
网友评论