首页 > 技术文章 > springcache+redis实战

yhc-910 2021-08-31 16:17 原文

前言

有兴趣的同学,可以看我上一篇文章,然后再过来看会比较清楚点:https://www.cnblogs.com/yhc-910/p/14884678.html

springcache,简单说,就是用来根据条件缓存请求的结果,从而提高整体服务性能和请求速度。

 

springcache有四种注解

@Cacheable:核心注解,请求的返回值会进行缓存,下次请求前,会直接从缓存获取后返回,如缓存不存在,就进入请求并缓存返回(一般用于查询)
@CachePut:对请求的返回值进行缓存(一般用户更新)
@CacheEvict:清理缓存
@Cacheing:用户以上多个注解的组合,一般不会使用,有兴趣的同学可以查下相关资料

下面简单描述下,@Cacheable里的一些属性,其它注解基本字段一样
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {
    @AliasFor("cacheNames")
    String[] value() default {};

    // cache别名
    @AliasFor("value")
    String[] cacheNames() default {};

    // cache的key
    String key() default "";

    // 指定key的生成器,自定义需实现KeyGenerator
    String keyGenerator() default "";

    // cache管理器,文章使用redis进行存储
    String cacheManager() default "";

    // cache解析器,管理cache管理器
    String cacheResolver() default "";

    // 请求时条件判断,如符合则取缓存,若无缓存,则执行代码,返回时进行缓存
    String condition() default "";

    // 去除符合条件的数据
    String unless() default "";

    // 是否同步缓存
    boolean sync() default false;
}

keyGenerator:key生成器,springcache提供了默认的生成器org.springframework.cache.interceptor.SimpleKeyGenerator,其实无非就是根据注解、方法、参数来生成。当然,我们也可以自定义,只需实现org.springframework.cache.interceptor.KeyGenerator即可

cacheManager:缓存管理器,默认使用ConCurrentHashMap来进行缓存,当然,如果接入redis,则默认使用redis来进行存储,cache已自动集成,如需自定义redis配置,可通过org.springframework.data.redis.cache.RedisCacheManager实现

cacheResolver:缓存解析器,与cacheManager冲突,只需配置一个,有兴趣可自学

condition:请求时判断参数,如符合,则取缓存返回(正则表达式可自行前往官网查看)

unless:返回时判断结果,如符合,则从返回结果中过滤不进行缓存(正则表达式可自行前往官网查看)

sync:并发请求下,只会有一个请求进行缓存处理,其它请求等待

 

实战

1、添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>    

2、启动类添加注解@EnableCaching,接入springcache

3、添加redis配置(redis的信息,请自行配置)

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);

        // 指定序列化器
        RedisSerializer<?> stringRS = new StringRedisSerializer();
        RedisSerializer<?> objectRS = new GenericJackson2JsonRedisSerializer();
        template.setKeySerializer(stringRS);
        template.setHashKeySerializer(stringRS);
        template.setValueSerializer(objectRS);
        template.setHashValueSerializer(objectRS);

        // 初始化redis配置
        template.afterPropertiesSet();

        return template;
    }

4、自定义缓存配置,设置RedisCacheManager

@Configuration
public class CacheConfig extends CachingConfigurerSupport {

    // 指定cachemanager【因cache默认指定的是RedisTemplate,所以此处进行指定设置】(引入redis时,spring会自动引入redis作为存储)[否则,使用cafficeCache或者其它,比如guavacache]
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()   // 创建默认缓存配置对象
                        .disableCachingNullValues() // 如果值为空,则不进行缓存
                        .entryTtl(Duration.ofMinutes(30))   // 设置缓存失效时间
                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();
    }
}

5、测试

返回String测试

@RestController
@RequestMapping("single")
public class SingleCacheTest {

    private static final String CACHE_KEY = "single";

    protected final Log logger = LogFactory.getLog(this.getClass());

    @GetMapping("test")
    public String test() throws Exception {
        logger.info("single test come in");
        return "success";
    }

    @Cacheable(value = CACHE_KEY,sync = true)
    @GetMapping("set")
    public String set() throws Exception {
        logger.info("single set come in");
        return "success";
    }

    @CachePut(value = CACHE_KEY)
    @GetMapping("put")
    public String put() throws Exception {
        logger.info("single put come in");
        return "success";
    }

    @CacheEvict(CACHE_KEY)
    @GetMapping("delete")
    public String delete() throws Exception {
        logger.info("single delete come in");
        return "success";
    }
    
}

返回对象测试

@RestController
@RequestMapping("object")
public class ObjectCacheTest {

    private static final String CACHE_KEY = "object";

    protected final Log logger = LogFactory.getLog(this.getClass());

    @GetMapping(value = "test")
    public People test() throws Exception {
        logger.info("object test come in");
        return new People("yhc", 30, "武汉");
    }


    @Cacheable(value = CACHE_KEY, condition = "#name.equals('yhc')")
    @GetMapping("put1")
    public People put1(@RequestParam String name) throws Exception {
        logger.info("object put1 come in");
        return new People("yhc", 30, "武汉");
    }

    @Cacheable(value = CACHE_KEY, unless = "#result.address.equals('武汉')")
    @GetMapping("put2")
    public People put2(@RequestParam String name) throws Exception {
        logger.info("object put2 come in");
        return new People("yhc", 30, "武汉");
    }

    @Cacheable(value = CACHE_KEY, condition = "#name.equals('yhc')", unless = "#result.address.equals('武汉1')")
    @GetMapping("put")
    public People put(@RequestParam String name) throws Exception {
        logger.info("object put come in");
        return new People("yhc", 30, "武汉");
    }

    @CacheEvict(CACHE_KEY)
    @GetMapping("delete")
    public People delete() throws Exception {
        logger.info("object delete come in");
        return new People("yhc", 30, "武汉");
    }
}

 

推荐阅读