范培忠 2018-04-18
Spring Boot2.0.0.RELEASE在2018年3月1日正式发布。2.0下对Redis的使用与之前略有不同。具体实现如下:
一、Maven依赖和配置
添加3个依赖:
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<!--spring2.0集成redis所需common-pool2--> <dependency>
<groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId>
<version>2.5.0</version> </dependency> <!-- 将作为Redis对象序列化器 --> <dependency>
<groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId>
<version>1.2.47</version> </dependency>
application.yml配置:
spring: redis: #数据库索引 database: 0 host: 127.0.0.1 port: 6379 password: 123
lettuce: pool: #最大连接数 max-active: 8 #最大阻塞等待时间(负数表示没限制) max-wait: -1 #最大空闲
max-idle: 8 #最小空闲 min-idle: 0 #连接超时时间 timeout: 10000
fastjson.properties配置:
本配置是为了解决在1.2.24后因修复漏洞导致的autotype is not support错误。
具体解决办法为声明fastjson.properties文件,将需要打包的类设置白名单等,如下代码所示。
可参考官方通告:https://github.com/alibaba/fastjson/wiki/enable_autotype
<https://github.com/alibaba/fastjson/wiki/enable_autotype>
fastjson.parser.autoTypeAccept=cn.fanpz.springbootdemoredis3.domain.entity.User
二、自定义序列化器
若要实现对象的缓存,最好定义自己的序列化和反序列化器。使用阿里的fastjson来实现的比较多。
package cn.fanpz.springbootdemoredis3.util; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; import
org.springframework.data.redis.serializer.RedisSerializer; import
org.springframework.data.redis.serializer.SerializationException; import
java.nio.charset.Charset; public class FastJsonRedisSerializer<T> implements
RedisSerializer<T> { private static final Charset DEFAULT_CHARSET =
Charset.forName("UTF-8"); private Class<T> clazz; public
FastJsonRedisSerializer(Class<T> clazz) { super(); this.clazz = clazz; }
@Override public byte[] serialize(T t) throws SerializationException { if (null
== t) { return new byte[0]; } return JSON.toJSONString(t,
SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } @Override public
T deserialize(byte[] bytes) throws SerializationException { if (null == bytes
|| bytes.length <= 0) { return null; } String str = new String(bytes,
DEFAULT_CHARSET); return (T) JSON.parseObject(str, clazz); } }
三、添加RedisConfig配置
在RedisConfig类里定义RedisTemplate的bean和Redis的CacheManager。
package cn.fanpz.springbootdemoredis3.config; import
cn.fanpz.springbootdemoredis3.util.FastJsonRedisSerializer; import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import
org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager; import
org.springframework.cache.annotation.CachingConfigurerSupport; import
org.springframework.cache.annotation.EnableCaching; import
org.springframework.context.annotation.Bean; import
org.springframework.context.annotation.Configuration; import
org.springframework.data.redis.cache.RedisCacheManager; import
org.springframework.data.redis.connection.RedisConnectionFactory; import
org.springframework.data.redis.core.RedisOperations; import
org.springframework.data.redis.core.RedisTemplate; import
org.springframework.data.redis.serializer.StringRedisSerializer; @EnableCaching
@Configuration @ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class) public class RedisConfig
extends CachingConfigurerSupport { @Bean(name = "redisTemplate")
@SuppressWarnings("unchecked") @ConditionalOnMissingBean(name =
"redisTemplate") public RedisTemplate<Object, Object>
redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>(); //使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new
FastJsonRedisSerializer(Object.class); // value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer); //
key的序列化采用StringRedisSerializer template.setKeySerializer(new
StringRedisSerializer()); template.setHashKeySerializer(new
StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory); return template; }
/*@Bean @ConditionalOnMissingBean(StringRedisTemplate.class) public
StringRedisTemplate stringRedisTemplate(RedisConnectionFactory
redisConnectionFactory) { StringRedisTemplate template = new
StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory);
return template; }*/ //缓存管理器 @Bean public CacheManager
cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
.RedisCacheManagerBuilder .fromConnectionFactory(redisConnectionFactory);
return builder.build(); } }
四、定义用于测试的User类和UserService
User类:
package cn.fanpz.springbootdemoredis3.domain.entity; import
java.io.Serializable; public class User implements Serializable { private
static final long serialVersionUID = -1L; private String username; private
Integer age; public User(String username, Integer age) { this.username =
username; this.age = age; } //getter和setter省略 }
UserService:
package cn.fanpz.springbootdemoredis3.service.impl; import
cn.fanpz.springbootdemoredis3.domain.entity.User; import
cn.fanpz.springbootdemoredis3.service.UserService; import
org.springframework.cache.annotation.Cacheable; import
org.springframework.stereotype.Service; @Service public class UserServiceImpl
implements UserService { @Override @Cacheable(value = "user", key =
"'user_'+#username") public User getUser(String username) {
System.out.println(username + "进入实现类获取数据!"); return new User("Ttomm", 22); } }
五、编写测试类
package cn.fanpz.springbootdemoredis3; import
cn.fanpz.springbootdemoredis3.domain.entity.User; import
cn.fanpz.springbootdemoredis3.service.UserService; import org.junit.Assert;
import org.junit.Test; import org.junit.runner.RunWith; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.boot.test.context.SpringBootTest; import
org.springframework.data.redis.core.RedisTemplate; import
org.springframework.test.context.junit4.SpringRunner;
@SuppressWarnings("unchecked") @RunWith(SpringRunner.class) @SpringBootTest
public class SpringBootDemoRedis3ApplicationTests { @Autowired private
RedisTemplate redisTemplate; @Autowired private UserService userService; @Test
//直接使用redisTemplate存取字符串 public void setAndGet() {
redisTemplate.opsForValue().set("test:set", "testValue1");
Assert.assertEquals("testValue1", redisTemplate.opsForValue().get("test:set"));
} @Test //直接使用redisTemplate存取对象 public void setAndGetAUser() { User user = new
User("Tom", 10); redisTemplate.opsForValue().set("test:setUser", user);
Assert.assertEquals(user.getUsername(), ((User)
redisTemplate.opsForValue().get("test:setUser")).getUsername()); } @Test
//使用Redis缓存对象,getUser只会被调用一次 public void testCache() { User user; user =
userService.getUser("Ttomm"); user = userService.getUser("Ttomm"); user =
userService.getUser("Ttomm"); } }
六、执行效果
testCache()的执行效果如下,可见后台日志显示方法仅被实际调用了一次,缓存成功:
热门工具 换一换