緩存筆記二(代碼實踐)

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);
    }


}

接下來將推送幾篇有關事務的文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章