SpringCache初窥

SpringCache初窥

本文的所有实现均基于博客

引入

Q:为啥要使用缓存?
A:对于机器而言,每一次的访问,程序都会按照步骤去执行一遍。但是比如同一个请求,对于服务器而言每次反馈的内容都是一样的,为了避免这种资源的浪费,对于一些重复的操作,而且结果往往是稳定不变的,可以使用缓存。缓存操作就是将第一真实查询的结果进行存储,后续的操作,就直接返回结果,而不再去真正的查询。

内存作为缓存

代码清单

CacheManager是用来配置cache缓存相关的信息。

@Bean
public CacheManager cacheManager(){
    SimpleCacheManager simpleCacheManager=new SimpleCacheManager();
      //name的作用,开的是工作空间
    simpleCacheManager.setCaches(Collections.singletonList(new ConcurrentMapCache("models")));
    return simpleCacheManager;
}

Controller用来测试缓存的赋予,删除以及更新。
重要注解解释:
@Cacheable:缓存相关的内存,value指定的是上面我设定的(cacheNames也可以),condition可以设定缓存条件,key可以用来设置缓存的key值(默认为空,key的相关设置可以在解决的问题里面看)
@CacheEvict:消除相关的缓存,特殊的键是allEntries,可以指定是不是全部消除
@CachePut:更新相关缓存
NOTE:三个相关的注解可以使用的键几乎相同,如果想了解更多可以去看看注解的相关源码或者查询相关东西哈

    @GetMapping("/get")
//    @Cacheable(key="#person.name")
    @Cacheable(value="models",key="#person.name")
    public Person getPerson(Person person){
        System.out.println("Person.address:"+person.getAddress());
        return person;
    }

    //    无条件全部cache,不带key,默认是空?这个测试过了,没有设置过的value会报错的
    @PostMapping("/get/new")
    @Cacheable(value="new")
    public Person getNewCache(Person Person){
        Person.setName(Person.getName().toUpperCase());
        return Person;
    }

    //删除cache
    @DeleteMapping("/delete/{name}")
    @CacheEvict(value="models",key="#name")
    public String deleteCache(@PathVariable("name") String name){
        System.out.println("system input name:"+name);
        return "delete Cache success!";
    }

    @PutMapping("/put")
    @CachePut(value="models",key="#person.name")
    public Person putCache(Person person){
        System.out.println("key:"+person.getName()+","+"address:"+person.getAddress());
        return person;
    }

每次都需要手动删除的话,很麻烦的,所以定制了一个定时任务,默认删除所有的key值。

    @Scheduled(fixedRate=10000)
    @CacheEvict(value="models", allEntries = true)
    public void cacheRemove(){
    }

存在的问题

  使用SimpleCacheManager中的cache(hashmap或者是ConcurrentHashMap)会存储会出现一个问题,那就是在缓存一直在变多的时候内存一直会增长,那就可能会crash掉了;解决这个的办法就是自己remove掉,调用或者是schedule都可以。
  解决的办法:使用GuavaCache,可以自定义内存使用多少个键值和过期时间等,具体使用看博客

解决的问题

  1. cache使用系统内存,默认存在CacheManager中;获取内容需要getNativeCache,这样才能取出数据
  2. springcache的加载机制:默认是用的SimpleCacheManager,使用的是ConcurrentHashMap
  3. spring-cache在spring-web程序中带有了重要的context包,本项目功能不需要重新maven加载,其他功能暂时不了解。
  4. spring-cache中key使用的是Spring Expression Language
  5. springcache中不存在的键,delete的时候会报错,需要handle???
  6. 用redis去做缓存后面实现了

遗留的问题

redis的序列化和反序列化的技术和是实现方式。

额外内容

redis作为缓存

这个现在只是copy其他博客的一些实现,暂时还没有自己理解redis的序列化和反序列化的东西,这个需要以后研究一下(可能是下一篇博客吧)
主要实现的代码:

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        Set<String> cacheName=new HashSet<>();
//        一定要有cacheName,不然存储不了
        cacheName.add("models1");
        cacheName.add("models2");
        cacheName.add("models");
        //解决查询缓存转换异常的问题
//        ObjectMapper om = new ObjectMapper();
//        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//        jackson2JsonRedisSerializer.setObjectMapper(om);
        //配置序列化
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMillis(10))    //设置时间10分钟
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues()
                .disableKeyPrefix();

        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
                .initialCacheNames(cacheName)
                .cacheDefaults(config)
                .build();
        return cacheManager;

多cacheManager实现

这是重写cacheConfig就可以实现,这个等有需求再实现吧。
有看博客的小伙伴如果需要我实现的话,我也可以去试试,哈哈哈。(起码要用动力,你说是不?)

源码地址:
https://gitee.com/eason93/SpringCacheDemo

猜你喜欢

转载自blog.csdn.net/zrqsyh/article/details/89375249