springcache+redis实战
阅读原文时间:2023年09月06日阅读:5

前言

有兴趣的同学,可以看我上一篇文章,然后再过来看会比较清楚点: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, "武汉");  
}  

}