Redis操作--RedisTemplate(二)StringRedisTemplate

一、介绍

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)
相关推荐
搬码后生仔7 分钟前
SQLite 是一个轻量级的嵌入式数据库,不需要安装服务器,直接使用文件即可。
数据库·sqlite
码农君莫笑9 分钟前
Blazor项目中使用EF读写 SQLite 数据库
linux·数据库·sqlite·c#·.netcore·人机交互·visual studio
江上挽风&sty10 分钟前
【Django篇】--动手实践Django基础知识
数据库·django·sqlite
向阳121814 分钟前
mybatis 动态 SQL
数据库·sql·mybatis
胡图蛋.16 分钟前
什么是事务
数据库
小黄人软件18 分钟前
20241220流水的日报 mysql的between可以用于字符串 sql 所有老日期的,保留最新日期
数据库·sql·mysql
张声录123 分钟前
【ETCD】【实操篇(三)】【ETCDCTL】如何向集群中写入数据
数据库·chrome·etcd
无为之士29 分钟前
Linux自动备份Mysql数据库
linux·数据库·mysql
小汤猿人类42 分钟前
open Feign 连接池(性能提升)
数据库
呆呆小雅1 小时前
C#关键字volatile
java·redis·c#