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);
}
}
接下來將推送幾篇有關事務的文章。