快捷搜索:  汽车  科技

springboot的一些新特性及用法(springboot2.x入门四)

springboot的一些新特性及用法(springboot2.x入门四)@Target({ElementType.TYPE ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Cacheable { @AliasFor("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; String key() default ""; String keyGenerator() default ""; String cacheManager() default "

晚上去参加了一个本田的车友会,一水的思域,虽然我不是本田车主啊,但是因为我非常喜欢车,所以有这种聚会都会去凑凑热闹,两厢思域红色是真的帅,哈哈哈,晚上快十点才到家,这篇文章写完都十二点了,磨磨蹭蹭的。好了,废话不多说了进入正题。

今天是springboot2.x整合redis的第二节,基于注解实现缓存,其实spring的CacheManager支持多种缓存组件,像ehcache,jcache,redis,但是Redis最火嘛,所以我们就拿它来举例了,另外正是因为支持多种缓存数据库,各数据库的ttl机制又不一样,所以spring 提供的注解并没有ttl的设置参数,在实际应用当中很不方便,所以今天我们就通过复写CacheManager增加注解的ttl配置。

spring 从3.1开始就基于JSR107规范实现了自己的缓存注解,其中包含Cacheable、CachePut、CacheEvict三个常用注解。

首先要想开启缓存管理器,需要在启动类上增加@EnableCaching注解

@EnableCaching @SpringBootApplication public class SpringbootRedisApplication { public static void main(String[] args) { SpringApplication.run(SpringbootRedisApplication.class args); } }

springboot的一些新特性及用法(springboot2.x入门四)(1)

@Cacheable
该注解可以作用在类或方法上 在类上表示所有方法返回对象都加入缓存 如果在方法上则指定该方法返回对象加入缓存。

@CachePut
该注解与 @Cacheable 类似,区别在于它会每次都执行,并且替换缓存中相同名称,一般用来更新缓存。

@CacheEvict
该注解用来清除缓存,它的属性与 @Cacheable 相比多了两个,allEntries 默认 false,根据 key 来清除指定缓存,如果为 true 则表示忽略 key 属性,对所有缓清除。beforeInvocation 属性为 true 时表示,在执行该方法之前执行清除缓存操作。

解释完了,我们进入实操阶段,今天我们只展开讲@Cacheable,会用这个了,另外两个也就会用了。

@Target({ElementType.TYPE ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Cacheable { @AliasFor("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; String key() default ""; String keyGenerator() default ""; String cacheManager() default ""; String cacheResolver() default ""; String condition() default ""; String unless() default ""; boolean sync() default false; }

springboot的一些新特性及用法(springboot2.x入门四)(2)

以上是@Cacheable注解的参数,常用的是key、value、condition、unless这四个key就是redis键值,value是缓存的命名空间,condition是前置条件,unless是后置条件,过滤数据。在注解的参数中可以使用SpEl表达式进行动态拼接,下面我提供一些测试代码,给大家演示一下。

@Service public class TestServiceImpl implements TestService{ //常规姿势 @Override @Cacheable(value = {"test"} key = "#id") public String test(Integer id) { return "test"; } //带有字符串拼接 @Override @Cacheable(value = {"test1"} key = "'id-' #id") public String test1(Integer id) { return "test"; } //只缓存id>1的 @Override @Cacheable(value = {"test2"} key = "'hash' #id" condition = "#id > 1") public String test2(Integer id) { return "test"; } //结果为null的不缓存 @Override @Cacheable(value = {"test3"} key = "#id" unless = "#result != null") public String test3(Integer id) { return null; } }

springboot的一些新特性及用法(springboot2.x入门四)(3)

以上就是Cacheable的使用方法,是不是很方便,但是就是不能设置缓存的失效时间,接下来我们就来实现CacheManager来实现。接下来我们要对上一节的RedisConfig类进行改造,上代码!!!!!!

import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.cache.CacheManager; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.lang.reflect.Method; import java.time.Duration; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @Configuration public class RedisConfig { @Bean public RedisTemplate<String Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String Object> template = new RedisTemplate<String Object>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ObjectMapper.DefaultTyping.NON_FINAL JsonTypeInfo.As.PROPERTY); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { return new RedisCacheManager( RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory) this.getRedisCacheConfigurationWithTtl(30 * 60) // 默认策略,未配置的 key 会使用这个 this.getRedisCacheConfigurationMap() // 指定 key 策略 ); } private Map<String RedisCacheConfiguration> getRedisCacheConfigurationMap() { Map<String RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(); //SsoCache和BasicDataCache进行过期时间配置 redisCacheConfigurationMap.put("test" this.getRedisCacheConfigurationWithTtl(24 * 60 * 60)); return redisCacheConfigurationMap; } private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) { Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig(); redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith( RedisSerializationContext .SerializationPair .fromSerializer(jackson2JsonRedisSerializer) ).entryTtl(Duration.ofSeconds(seconds)); return redisCacheConfiguration; } @Bean public KeyGenerator wiselyKeyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target Method method Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append("." method.getName()); if (params == null || params.length == 0 || params[0] == null) { return null; } String join = String.join("&" Arrays.stream(params).map(Object::toString).collect(Collectors.toList())); String format = String.format("%s{%s}" sb.toString() join); return format; } }; } }

springboot的一些新特性及用法(springboot2.x入门四)(4)

上面代码中,我们在CacheManager中进行了缓存时间的配置,对统一命名空间的缓存进行了统一的失效时间处理。我们在使用中,只需要将注解中的value配置在RedisConfig类中,就完成了失效时间的配置。

猜您喜欢: