一、介绍
1、简介
由于存储在 Redis 中的 key 和 value 通常是很常见的 String 类型,Redis模块提供了 RedisConnection 和 RedisTemplate 的扩展,分是 StringRedisConnection 和 StringRedisTemplate,作为字符串操作的解决方案。
通过源码可以看见对于Key、Value、HashKey、HashValue都是进行String类型的序列化。
因此对于一些复杂类型,如对象在StringRedisTemplate的时候往往需要自己手动序列化将对象转为JSON再存入Redis。
二、集成
使用StringRedisTemplate,不需要(写RedisConfig)额外设置序列化。不过存取对象需要自己序列化、反序列化。
三、使用
1、存取string
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testString(){
String key = "string-name";
//存
String value = "这是value123";
stringRedisTemplate.opsForValue().set(key,value);
//取
Object valueObj = stringRedisTemplate.opsForValue().get(key);
System.out.println("value为:" + valueObj);
}
输出:value为:这是value123,
查看可视化工具也没有乱码
2、存取对象
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testUser(){
String key = "user-key";
//存
UserDTO userDTO = new UserDTO();
userDTO.setUserAccount("zhangsan");
userDTO.setAge(18);
userDTO.setUserName("张三");
stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(userDTO));
//取
String valueObj = stringRedisTemplate.opsForValue().get(key);
UserDTO redisUser = JSON.parseObject(valueObj, UserDTO.class);
System.out.println("value为:" + redisUser);
}
输出:value为:UserDTO(userName=张三, age=18, userAccount=zhangsan)
查看可视化工具没有乱码:
3、广播消息
(1)发送消息:
stringRedisTemplate.convertAndSend
(2)接收消息:
① implements MessageListener来实现一个监听器;
② 注册监听器到RedisMessageListenerContainer中。
demo:
(1)监听器:如我有两个监听器
package org.example.listen;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.example.dto.UserDTO;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RedisBroadcastUserMsgHandler implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
String consumerChannel = RedisSerializer.string().deserialize(message.getChannel());
if(!consumerChannel.equals("user-topic")){
return;
}
byte[] body = message.getBody();
String json = RedisSerializer.string().deserialize(body);
UserDTO userDTO = JSON.parseObject(json,UserDTO.class);
log.info("handle接收到:"+userDTO);
}
}
package org.example.listen;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.example.dto.UserDTO;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RedisBroadcastUserMsgTwoHandler implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
String consumerChannel = RedisSerializer.string().deserialize(message.getChannel());
if(!consumerChannel.equals("user-topic-two")){
return;
}
byte[] body = message.getBody();
String json = RedisSerializer.string().deserialize(body);
UserDTO userDTO = JSON.parseObject(json,UserDTO.class);
log.info("handle接收到:"+userDTO);
}
}
(2)注册监听器
package org.example.config;
import lombok.extern.slf4j.Slf4j;
import org.example.listen.RedisBroadcastUserMsgHandler;
import org.example.listen.RedisBroadcastUserMsgTwoHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import java.util.List;
@Slf4j
@Configuration
public class RedisListenerConfig {
@Autowired
private RedisBroadcastUserMsgHandler userMsgHandler;
@Autowired
private RedisBroadcastUserMsgTwoHandler twoHandler;
@Bean
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(userMsgHandler, new ChannelTopic("user-topic"));
container.addMessageListener(twoHandler, new ChannelTopic("user-topic-two"));
return container;
}
}
(3)发送消息
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testSendMsg(){
UserDTO userDTO = new UserDTO();
userDTO.setUserAccount("zhangsan");
userDTO.setAge(18);
userDTO.setUserName("张三");
String channel = "user-topic";
stringRedisTemplate.convertAndSend(channel,JSON.toJSONString(userDTO));
//
String channelTwo = "user-topic-two";
stringRedisTemplate.convertAndSend(channelTwo,JSON.toJSONString(userDTO));
}
执行控制台打印:
2024-08-13T16:04:31.630+08:00 INFO 10496 --- [edisContainer-2] o.e.l.RedisBroadcastUserMsgTwoHandler : handle接收到:UserDTO(userName=张三, age=18, userAccount=zhangsan)
2024-08-13T16:04:31.630+08:00 INFO 10496 --- [edisContainer-1] o.e.listen.RedisBroadcastUserMsgHandler : handle接收到:UserDTO(userName=张三, age=18, userAccount=zhangsan)
改进demo
如果有多个消费者,注册会比较麻烦,因此对上述监听器代码封装下:
(1)监听器:
package org.example.listen;
import org.springframework.data.redis.connection.MessageListener;
public abstract class RedisListener implements MessageListener {
public abstract String getTopic();
}
package org.example.listen;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.example.dto.UserDTO;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RedisBroadcastUserMsgHandler extends RedisListener {
@Override
public String getTopic() {
return "user-topic";
}
@Override
public void onMessage(Message message, byte[] pattern) {
byte[] body = message.getBody();
String json = RedisSerializer.string().deserialize(body);
UserDTO userDTO = JSON.parseObject(json,UserDTO.class);
log.info("handle接收到:"+userDTO);
}
}
package org.example.listen;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.example.dto.UserDTO;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RedisBroadcastUserMsgTwoHandler extends RedisListener {
@Override
public void onMessage(Message message, byte[] pattern) {
byte[] body = message.getBody();
String json = RedisSerializer.string().deserialize(body);
UserDTO userDTO = JSON.parseObject(json,UserDTO.class);
log.info("handle接收到:"+userDTO);
}
@Override
public String getTopic() {
return "user-topic-two";
}
}
(2)注册监听器:
package org.example.config;
import lombok.extern.slf4j.Slf4j;
import org.example.listen.RedisBroadcastUserMsgHandler;
import org.example.listen.RedisBroadcastUserMsgTwoHandler;
import org.example.listen.RedisListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import java.util.List;
@Slf4j
@Configuration
public class RedisListenerConfig {
@Autowired
private RedisBroadcastUserMsgHandler userMsgHandler;
@Autowired
private List<RedisListener> redisListeners;
@Bean
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
for(RedisListener listener : redisListeners) {
container.addMessageListener(listener, new ChannelTopic(listener.getTopic()));
}
return container;
}
}
执行Test:
@Test
public void testSendMsg(){
UserDTO userDTO = new UserDTO();
userDTO.setUserAccount("zhangsan");
userDTO.setAge(18);
userDTO.setUserName("张三");
String channel = "user-topic";
stringRedisTemplate.convertAndSend(channel,JSON.toJSONString(userDTO));
//
userDTO.setUserAccount("zhangsan-two");
userDTO.setUserName("张三-two");
String channelTwo = "user-topic-two";
stringRedisTemplate.convertAndSend(channelTwo,JSON.toJSONString(userDTO));
}
打印:
2024-08-13T16:25:10.725+08:00 INFO 88872 --- [edisContainer-1] o.e.listen.RedisBroadcastUserMsgHandler : handle接收到:UserDTO(userName=张三, age=18, userAccount=zhangsan)
2024-08-13T16:25:10.725+08:00 INFO 88872 --- [edisContainer-2] o.e.l.RedisBroadcastUserMsgTwoHandler : handle接收到:UserDTO(userName=张三-two, age=18, userAccount=zhangsan-two)