基于项目对jedis代码的重构,对redisTemplate以及redis集群写法研究了一点点,于是有了本文主要是springboot整合redis单机和集群,通过redisTemplate实现redis的操作。
redis单机与集群配置代码
(一)单机相关配置代码
RedisCacheConfig
redis单机模式实现自定义redisTemplate,里面还添加了redis队列监听和redis缓存器相关代码
package com.jae.redistest.config.redis;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author pinter
* @date Create on: 2021/4/12 21:22
* @ConditionalOnProperty 从配置文件中获取某个值,与定义的值比较,决定Bean是否创建
* 类说明
*/
@Slf4j
@Configuration
@EnableCaching
@ConditionalOnProperty(value = "spring.redis.mode", havingValue = "standalone")
public class RedisCacheConfig {
public RedisCacheConfig() {
log.info("redis正在初始化单机配置模式......");
}
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
// 可以添加多个messageListener,配置不同的交换机
container.addMessageListener(listenerAdapter, new PatternTopic("channel:test"));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(RedisReceiver receiver) {
System.out.println("消息适配器1");
return new MessageListenerAdapter(receiver, "onMessage");
}
@Bean
StringRedisTemplate template(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisSerializer<Object> serializer = redisSerializer();
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public RedisSerializer<Object> redisSerializer() {
//创建JSON序列化器 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
serializer.setObjectMapper(objectMapper);
return serializer;
}
}
RedisReceiver
RedisReceiver 类:redis作为队列使用时候,消费处理消息
package com.jae.redistest.config.redis;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
/**
* @author 13108
* @date Create on: 2021/4/12 21:20
* 类说明
*/
@Component
public class RedisReceiver implements MessageListener {
/**
* 继承MessageListener,就能拿到消息体和频道名
*
* @param message
* @param bytes
*/
@Override
public void onMessage(Message message, byte[] bytes) {
System.out.println(new String(message.getBody()) + "---" + new String(message.getChannel()));
}
}
(二)集群相关配置代码
RedisClusterConfigProperties
package com.jae.redistest.config.rediscluster;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* redisCluster配置
* @author Jae
*/
@Data
@Component
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class RedisClusterConfigProperties {
private List<String> nodes;
private Integer maxAttempts;
private Integer connectionTimeout;
private Integer soTimeout;
private String password;
}
RedisConfig
RedisConfig类:redis集群模式的配置类
```java
package com.jae.redistest.config.rediscluster;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import java.util.HashSet;
import java.util.Set;
/**
* @author 13108
*/
@Slf4j
@Configuration
@ConditionalOnProperty(value = "spring.redis.mode", havingValue = "cluster")
public class RedisConfig extends CachingConfigurerSupport {
@Autowired
private RedisClusterConfigProperties clusterProperties;
public RedisConfig() {
log.info("redis正在初始化集群配置模式....");
}
@Bean
public RedisClusterConfiguration getClusterConfig() {
log.info("即将输出集群节点信息....");
clusterProperties.getNodes().forEach(log::info);
RedisClusterConfiguration rcc = new RedisClusterConfiguration(clusterProperties.getNodes());
rcc.setMaxRedirects(clusterProperties.getMaxAttempts());
rcc.setPassword(RedisPassword.of(clusterProperties.getPassword()));
return rcc;
}
@Bean
public JedisCluster getJedisCluster() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 截取集群节点
String[] cluster = clusterProperties.getNodes().toArray(new String[0]);
// 创建set集合
Set<HostAndPort> nodes = new HashSet<>();
// 循环数组把集群节点添加到set集合中
for (String node : cluster) {
String[] host = node.split(":");
//添加集群节点
nodes.add(new HostAndPort(host[0], Integer.parseInt(host[1])));
}
return new JedisCluster(
nodes,
clusterProperties.getConnectionTimeout(),
clusterProperties.getSoTimeout(),
clusterProperties.getMaxAttempts(),
clusterProperties.getPassword(),
poolConfig);
}
@Bean
public LettuceConnectionFactory lettuceConnectionFactory(RedisClusterConfiguration redisClusterConfiguration) {
return new LettuceConnectionFactory(redisClusterConfiguration);
}
/**
* RedisTemplate配置
* key 和 value 都为String类型
* 都使用Jackson2JsonRedisSerializer进行序列化
*/
@Bean(name = "redisTemplate1")
public RedisTemplate<String, String> redisTemplate1(RedisConnectionFactory lettuceConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate(lettuceConnectionFactory);
template.setValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* RedisTemplate配置
* key 为String类型
* value 为 Object 类型
* 都使用Jackson2JsonRedisSerializer进行序列化
*/
@Bean(name = "redisTemplate2")
public RedisTemplate<String, Object> redisTemplate2(RedisConnectionFactory lettuceConnectionFactory) {
RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = jackson2JsonRedisSerializer();
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(lettuceConnectionFactory);
template.afterPropertiesSet();
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public Jackson2JsonRedisSerializer jackson2JsonRedisSerializer() {
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);
return jackson2JsonRedisSerializer;
}
}