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