2 缓存在 java 中的实现
在 Java 中,我们一般对调用方法进行缓存控制,比如我调用"findUserById(Long id)", 那么我应该在调用这个方法之前先从缓存中查找有没有,如果没有再掉该方法如从数据 库加载用户,然后添加到缓存中,下次调用时将会从缓存中获取到数据。Java 中广泛使 用的分布式缓存 Redis
2.1 缓存逻辑流程
流程图如下:
2.2 逻辑流程代码:
@Override
public Provinces detail(String provinceid) {
Provinces provinces = null;
//在redis查询
provinces = (Provinces)redisTemplate.opsForValue().get(provinceid);
if (null != provinces){
// redisTemplate.expire(provinceid,20000, TimeUnit.MILLISECONDS);
System.out.println("缓存中得到数据");
return provinces;
}
provinces = super.detail(provinceid);
if (null != provinces){
redisTemplate.opsForValue().set(provinceid,provinces);//set缓存
redisTemplate.expire(provinceid,2000000, TimeUnit.MILLISECONDS);//设置过期
}
return provinces;
}
3 基于注解的 Cache
Spring 3.1 起,提供了基于注解的对 Cache 的支持。使用 Spring Cache 的好处: 基于注解,代码清爽简洁;
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
//key的生成,springcache的内容,跟具体实现缓存器无关
//自定义本项目内的key的方式
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
//不支持过期时间
// @Bean
// public CacheManager cacheManager() {
// //jdk里,内存管理器
// SimpleCacheManager cacheManager = new SimpleCacheManager();
// cacheManager.setCaches(Collections.singletonList(new ConcurrentMapCache("province")));
// return cacheManager;
// }
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
return RedisCacheManager
.builder(connectionFactory)
.cacheDefaults(
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(200))) //缓存时间绝对过期时间20s
.transactionAware()
.build();
}
/**
* 序列化object对象为json字符串
*/
// @Bean
// public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// RedisTemplate<String, Object> template = new RedisTemplate<>();
// template.setConnectionFactory(factory);
//
// //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
// Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
// ObjectMapper mapper = new ObjectMapper();
// mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// serializer.setObjectMapper(mapper);
// template.setValueSerializer(serializer);
//
// //使用StringRedisSerializer来序列化和反序列化redis的key值
// template.setKeySerializer(new StringRedisSerializer());
// template.afterPropertiesSet();
// return template;
// }
/**
* JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口),无法转义成对象
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
//使用jdk的序列化
template.setValueSerializer(new JdkSerializationRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
//@Service("provincesService")
@CacheConfig(cacheNames="province") //通用配置
public class ProvincesServiceImpl2 extends ProvincesServiceImpl implements ProvincesService{
// @Cacheable(value = "province",
// key = "#root.targetClass.simpleName+':'+#root.methodName+':'+#provinceid")
@Cacheable// value指定当前接口,要使用哪一个缓存器 --- 如果该缓存器不存在,则创建一个
public Provinces detail(String provinceid) {//一个接口方法,对应一个缓存器
return super.detail(provinceid);
}
//这个AOP,是先删缓存,先改数据库?
@CachePut(key = "#entity.provinceid")
public Provinces update(Provinces entity) {
return super.update(entity);
}
@CacheEvict
public void delete(String provinceid) {
super.delete(provinceid);
}
//组合配置
@Caching(put = {
@CachePut(key = "#entity.provinceid"),
@CachePut(key = "#entity.provinceid")}
)
public Provinces add(Provinces entity) {
return super.add(entity);
}
}
接下来将推送几篇有关事务的文章。