Spring Boot对很多NoSQL数据库提供了自动化配置的支持,包括为Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra、Couchbase和LDAP。本文主要介绍,SpringBoot整合Redis的配置以及本人在SpringBoot项目中使用Redis遇到的问题和解决方法。
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,Spring Boot为Lettuce和Jedis客户端库提供了基本的自动配置,并提供了由它们提供的抽象Spring Data Redis。本文选取Jedis进行介绍。
org.springframework.boot
spring-boot-starter-data-redis
redis.clients
jedis
spring:
redis:
database: 0
host: localhost
port: 6379
password: 123456
timeout: 2000
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
具体参数配置可以参考:org.springframework.boot.autoconfigure.data.redis.RedisProperties
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testStringRedis() throws Exception {
stringRedisTemplate.opsForValue().set("aaa", "111");
Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));
}
}
上面简单的测试演示了如何通过SpringBoot自动配置的StringRedisTemplate
对象进行Redis的读写操作,该对象从命名中就可确定支持的是String类型。如果有使用过spring-data-redis一定熟悉RedisTemplate
接口,StringRedisTemplate
就相当于RedisTemplate
的实现。源码如下:
public class StringRedisTemplate extends RedisTemplate {
/**
* Constructs a new StringRedisTemplate
instance. {@link #setConnectionFactory(RedisConnectionFactory)}
* and {@link #afterPropertiesSet()} still need to be called.
*/
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
/**
* Constructs a new StringRedisTemplate
instance ready to be used.
*
* @param connectionFactory connection factory for creating new connections
*/
public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
setConnectionFactory(connectionFactory);
afterPropertiesSet();
}
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return new DefaultStringRedisConnection(connection);
}
}
除了String类型,实战中我们还经常会在Redis中存储对象,这时候我们就会想是否可以使用类似RedisTemplate
来初始化并进行操作。
@Data
public class Person implements Serializable {
private static final long serialVersionUID = -3958394023121991038L;
private String username;
private long age;
public Person() {
}
public Person(String username, long age) {
this.username = username;
this.age = age;
}
}
@Configuration
public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
public RedisTemplate personRedisTemplate() {
RedisTemplate personRedisTemplate = new RedisTemplate();
personRedisTemplate.setConnectionFactory(jedisConnectionFactory());
// 设置key序列化和反序列化类型
personRedisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置value序列化和反序列化类型
personRedisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Person.class));
return personRedisTemplate;
}
}
注意:在实例化RedisTemplate可以不用指定其序列化和反序列化的类型,默认是JdkSerializationRedisSerializer
Spring提供了多个序列化类型,按照项目需求灵活选取,如下:
@Repository
public class PersonCache {
@Autowired
private RedisTemplate personRedisTemplate;
protected ValueOperations valueOperations;
@PostConstruct
public void init() {
valueOperations = personRedisTemplate.opsForValue();
}
public void add(Person person) {
valueOperations.set(person.getUsername(), person, 10L, TimeUnit.MINUTES);
}
public Person load(String key) {
return valueOperations.get(key);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
@Autowired
private PersonCache personCache;
@Test
public void testPersonCache() {
Person person = new Person("张三", 10000);
personCache.add(person);
person = new Person("李四", 10001);
personCache.add(person);
Assert.assertEquals(10001, personCache.load("李四").getAge());
}
}
至此SpringBoot整合Redis及简单是用演示结束。但是在实际项目中我们需要缓存的对象往往不只一个,如果我们还想保存缓存其它对象,这里只需要在RedisConfig配置类里实例化对应的RedisTemplate,例如加一个Cilent对象,添加如下代码:
@Bean
public RedisTemplate clientRedisTemplate() {
RedisTemplate clientRedisTemplate = new RedisTemplate();
clientRedisTemplate.setConnectionFactory(jedisConnectionFactory());
clientRedisTemplate.setConnectionFactory(jedisConnectionFactory());
clientRedisTemplate.setKeySerializer(new StringRedisSerializer());
clientRedisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Client.class));
return clientRedisTemplate;
}
// 示例代码一
@Autowired
private RedisTemplate redisTemplate;
protected ValueOperations valueOperations;
@PostConstruct
public void init() {
valueOperations = redisTemplate.opsForValue();
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 使用JDK自带的序列化
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
// 省略操作代码
}
// 示例代码二
@Autowired
private RedisTemplate redisTemplate;
protected ValueOperations valueOperations;
@PostConstruct
public void init() {
valueOperations = redisTemplate.opsForValue();
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 使用JSON序列化
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Map.class));
}
示例代码一和示例代码二中都使用@Autowired注入redisTemplate(SpringBoot自动装配的),这样两个地方使用的是同一个RedisTemplate实例,这样就可能造成反序列化失败
java: 无法访问com.fasterxml.jackson.databind.JavaType
错误,需要添加spring-boot-starter-json依赖:
org.springframework.boot
spring-boot-starter-json
我的代码中没有报错是因为spring-boot-starter-web中引用了spring-boot-starter-json
github:https://github.com/shallynever/SpringBootStudy/tree/master/SpringBootRedis
【ZhoujEndless】至此!感觉您的阅读,如有任何问题,欢迎打扰!如有表述错误,劳烦指出!
参考文章:http://blog.didispace.com/springbootredis/