Springcloud +redis 实现缓存
Springcloud +redis 实现缓存
1.Springboot操作redis。
引用pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.13.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
增加配置文件
spring.redis.host=localhost spring.redis.port=6379 spring.redis.database=0
这里做了最简单的配置,超时,密码自己可以按需求设置
#redis连接密码
password:
#redis连接池设置
pool:
#最大空闲连接
max-idle : 100
#最小空闲连接
min-idle : 1
#最大连接数(负数表示没有限制)
max-active : 1000
#最大阻塞等待时间(负数表示没有限制)
max-wait : -1
#连接超时时间(毫秒)
timeout : 0
以上基本配置完成了。可以在项目中使用redis了。
这里我用了一个例子
@Autowired private StringRedisTemplate stringRedisTemplate;
这个类集成RedisTemplate类。因为大多数针对Redis的操作都是基于字符串的,所以这个类提供一个专门的类,它最小化了更通用的配置。
StringRedisTemplate 和RedisTemplate在序列化方式上有这不通,
public StringRedisTemplate() { RedisSerializer<String> stringSerializer = new StringRedisSerializer(); setKeySerializer(stringSerializer); setValueSerializer(stringSerializer); setHashKeySerializer(stringSerializer); setHashValueSerializer(stringSerializer); }
使用RedisTemplate序列化的时候会二进制保存键值,具体下面缓存中还会遇到。
上述是集成redis的最简单的应用,
2.下面我们看下如何利用注解实现缓存
springboot中使用缓存注解,主要是这几个注解
1. @EnableCaching:申明应用开启缓存
2. @Cacheable:通常定已在方法头部,用来申明此方法可缓存,将返回结果缓存,并下次调用直接从缓存,不执行方法内容。常见的参数有以下几个,
value:缓存的名称,至少需要一个,可以配置多个@Cacheable(value=”user”) 或者
@Cacheable(value={”user1”,”user2”}
key:缓存的key,可以为空,
condition:缓存的条件,可以为空
sync:缓存同步,锁住底层操作。保证缓存数据安全性
3.@CachePut:通常定义在方法头部,用来申明此方法可缓存,将返回结果缓存,该方法用来更新缓存,每次执行方法内容,不从缓存中读取数据返回。常见参数和@Cacheable类似
4. @CacheEvict:通常定义在方法投标部,用来申明此方法可缓存,并根据条件删除缓存。每次都会执行方法内容,常见参数和@Cacheable类似。
上面的参数内容都支持SpringEL
需要注意的几个地方,
1.如果使用默认序列法方式的话, 缓存对象实现Serializable接口,否则会提示下面异常
Cannot serialize; nested exception is
org.springframework.core.serializer.support.SerializationFailedException:
Failed to serialize object using DefaultSerializer;
同时会发生key,value值显示:\xAC\xED\x00\x05t\x00\x011这样的现象,因为
spring-data-redis的RedisTemplate<K, V>模板类在操作redis时默认使用JdkSerializationRedisSerializer来进行序列化。
这里建议自定义redistemplate和cachemanager中的value的序列化方式;
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String,Object> template = new RedisTemplate<String,Object>(); template.setConnectionFactory(redisConnectionFactory); //使用JSON格式的序列化,保存 template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer 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 config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ZERO) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } }
2.使用CachePut注解,该方法每次都会执行,会清除对应的key值得缓存(或者更新),分为以下两种情况:
如果返回值null,此时会将该key值缓存更新为null。
如果返回值不为null,此时会进行该key值缓存的更新,更新缓存值为返回的数据;
代码如下:
配置文件配置
spring.cache.type==redis spring.redis.host=localhost spring.redis.port=6379 spring.redis.database=10
程序入口增加注解:
@EnableCaching
简单定义几个接口,service,在service方法上面添加缓存注解。
@Override @Cacheable(value = "user", key = "#name") public User name(String name) { System.out.println("未走缓存"); User user = new User(); user.setName(name); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return user; } @Override @CachePut(value = "user", key = "#user.name") public User save(User user) { System.out.println("保存用户"+user.toString()); return user; } @Override @CacheEvict(value = "user", key = "#name") public void delUser(String name) { System.out.println("删除用户"+name); }