Spring Boot Redis Cluster的相关配置

搭建 Redis Cluster

直接使用docker创建一个Redis Cluster。

1
2
3
#docker-compose.yml
redisCluster:
image: grokzen/redis-cluster:3.2.13

这个Image默认将创建端口号从7000-7005的3Master3Slave的的Redis Cluster。

在SpringBoot的configuration中配置端口。

1
2
3
4
5
6
7
#application.properties
spring.redis.cluster.nodes[0]=notification_redis:7000
spring.redis.cluster.nodes[1]=notification_redis:7001
spring.redis.cluster.nodes[2]=notification_redis:7002
spring.redis.cluster.nodes[3]=notification_redis:7003
spring.redis.cluster.nodes[4]=notification_redis:7004
spring.redis.cluster.nodes[5]=notification_redis:7005

Java Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class RedisClusterConf {

List<String> nodes;

@Bean
public RedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory(new RedisClusterConfiguration(nodes));
}
@Bean
public RedisTemplate<String, MyObject> redisKvTemplate(@Qualifier("connectionFactory") RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate <>();
template.setConnectionFactory(factory);

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =new Jackson2JsonRedisSerializer<>(MyObject.class);

StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
//template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
//template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}

}

public RedisTemplate<String, MyObject> redisKvTemplate(@Qualifier("connectionFactory") RedisConnectionFactory factory)
定义一个将MyObject对象序列化然后保存到Redis中的Template。

Spring-boot-starter-redis默认使用JdkSerializationRedisSerializer将value序列化(而Key则是默认使用StringRedisSerializer),
这样的结果就是我们直接在redis-cli中查看value的内容极其不方便。

具体可以参考这里

我们需要根据实际的需要,将Key和Value以肉眼可以理解的形式序列化。所以就有了

1
2
3
4
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =new Jackson2JsonRedisSerializer<>(MyObject.class);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);

这样,我们的Key直接以plain的String进行存储,Value被序列化成Json的String进行存储。

那么setHashKeySerializersetHashValueSerializer分别是什么呢?
原来是当value中包含HashMap的时候,我们需要将HashMap的Key和Value也进行序列化,
这个时候,我们也需要制定Key和Value的序列化方式。
在没有用到HashMap的情况下,我们自然就不需要指定了。

1
2
//template.setHashKeySerializer(stringRedisSerializer);
//template.setHashValueSerializer(jackson2JsonRedisSerializer);

另外参考

 

Spring Boot 使用RabbitMQ的实例

目标

Publisher将Json消息发送至RabbitMQ中,
Comsumer能够将RabbitMQ中的消息自动映射成对应的Java POJO。

准备

使用docker-compose迅速运行RabbitMQ。

1
2
3
4
5
rabbitmq:
image: rabbitmq:management
ports:
- "5672:5672"
- "15672:15672"

添加spring-boot-starter-amqp

1
2
3
4
5
6
7
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-amqp'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.springframework.amqp:spring-rabbit-test'
}

添加AMQP的Java Configuration。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@EnableRabbit
public class AmqpConf implements RabbitListenerConfigurer {

@Bean
public MappingJackson2MessageConverter jackson2Converter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
return converter;
}

@Bean
public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setMessageConverter(jackson2Converter());
return factory;
}

@Override
public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
}

}

添加Message Listener。

1
2
3
4
5
6
7
8
9
10
class Receiver {
@RabbitListener(queues = "queue")
public void receiveMessage(Foo foo) {
System.out.println("Received <" + foo.name + ">");
}
}

class Foo {
public String name;
}

解说

mappingJackson2MessageConverter能将接受到的Quque中的Message转换成对应的POJO。

Spring使用PayloadArgumentResolver去提取,转换Message为对应标记@RabbitListener Method中的Parameter。

我们需要自己实现一个RabbitListenerConfigurer,将Message converter设置成mappingJackson2MessageConverter。

具体参考这里