简介
在互联网的应用中,redis被广泛地使用。而在spring boot中使用redis,是非常简单的。
spring boot 中的redis
要在spring boot中使用redis,在pom中加入spring-boot-starter-redis依赖。maven会添加spring-data-redis包,其中包含了jedis,jredis,lettuce,srp几种实现。spring boot缺省选择jedis实现使用。
jedis配置
缺省使用localhost的redis配置,如果你没有修改任何配置,在本机上测试,不需要做任何配置。但在生成环境,必须配置真实的环境。
spring:
# REDIS (RedisProperties)
redis:
# Redis数据库索引(默认为0)
database:0
# Redis服务器地址
host:localhost
# Redis服务器连接端口
port:6379
# Redis服务器连接密码(默认为空)
password:
# 连接池最大连接数(使用负值表示没有限制)
pool.max-active:8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
pool.max-wait:-1
# 连接池中的最大空闲连接
pool.max-idle:8
# 连接池中的最小空闲连接
pool.min-idle:0
# 连接超时时间(毫秒)
timeout:0
使用StringRedisTemplate来处理String
在spring-data-redis中提供了StringRedisTemplate,可以直接用来处理String数据了。
// 可以直接使用,spring会绑定
@Autowired
private StringRedisTemplate template;
@RequestMapping("/foo")
@ResponseBody
public String foo() {
ValueOperations<String, String> ops = template.opsForValue();
String key = "spring.boot.redis.test";
if (!this.template.hasKey(key)) {
String str = "not found the key, now set it";
log.info(str);
ops.set(key, str);
return str;
} else {
String str = "Found key " + key + ", value=" + ops.get(key);
log.info(str);
return str;
}
}
可以看一下spring中的实现类:
/*
* Copyright 2011-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.core;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* String-focused extension of RedisTemplate. Since most operations against Redis are String based, this class provides
* a dedicated class that minimizes configuration of its more generic {@link RedisTemplate template} especially in terms
* of serializers.
* <p/>
* Note that this template exposes the {@link RedisConnection} used by the {@link RedisCallback} as a
* {@link StringRedisConnection}.
*
* @author Costin Leau
*/
public class StringRedisTemplate extends RedisTemplate<String, String> {
/**
* Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
* and {@link #afterPropertiesSet()} still need to be called.
*/
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setValueSerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
setHashValueSerializer(stringSerializer);
}
/**
* Constructs a new <code>StringRedisTemplate</code> 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);
}
}
在实现中,RedisTemplate和其子类中包含了几种不同的Serializer,分别对应Key,Value,Hash……,而最简单的String类型,在stringSerializer变量上实例化为StringRedisSerializer。
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
private boolean enableTransactionSupport = false;
private boolean exposeConnection = false;
private boolean initialized = false;
private boolean enableDefaultSerializer = true;
private RedisSerializer<?> defaultSerializer;
private ClassLoader classLoader;
private RedisSerializer keySerializer = null;
private RedisSerializer valueSerializer = null;
private RedisSerializer hashKeySerializer = null;
private RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = new StringRedisSerializer();
...
/**
* Constructs a new <code>RedisTemplate</code> instance.
*/
public RedisTemplate() {}
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<K>(this);
}
initialized = true;
}
}
可以看到spring boot应用在启动时,如果没有检查到对应的对象配置,则最后实例化defaultSerializer对象为JdkSerializationRedisSerializer了。
可以看一下运行时的对象
使用RedisTemplate
在程序中使用 RedisTemplate,如上所说,需要配置对应的serializer,否则对对应的数据处理时,要么serializer对象为null,要么使用的缺省的则使用JdkSerializationRedisSerializer。
要配置我们的redisTemplate对象,可以在配置类中定义一个redisTemplate 的bean。
@Bean
public RedisTemplate<String, ? extends Object> redisTemplate(
RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
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);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
在配置类中,定义了Jackson2JsonRedisSerializer,来作为ValueSerializer对象,对Model对象进行序列化和反序列化。
然后在程序处理的地方,可以使用这个bean对象了。
@Autowired
private RedisTemplate redisTemplate;
@RequestMapping("/user/{id}")
@ResponseBody
public String getUser(@PathVariable("id") long id) {
log.info("---- getUser");
//
User user = new User(id, "aa@126.com", "aa", "aa123456", "aa", "123");
ValueOperations<String, User> operations = redisTemplate.opsForValue();
operations.set("com.dcloud.user", user);
// 有超时时间的redis set..
operations.set("com.dcloud.user.ex", user, 10, TimeUnit.SECONDS);
//
boolean exists = redisTemplate.hasKey("com.dcloud.user");
if (exists) {
log.info("exists is true");
} else {
log.info("exists is false");
}
return "finished";
}
@RequestMapping(value = "/query")
@ResponseBody
public String query() {
log.info("query from redis");
ValueOperations<String, User> operations = redisTemplate.opsForValue();
//
User ret = operations.get("com.dcloud.user");
if (null == ret) {
log.info("not exist user");
return "finished query, and not exists";
}
log.info(ret.toString());
return "finished query";
}
现在可以看一下运行时的redisTemplate对象