SpringBoot 中使用Redis Stream 实现消息监听优化

在之前的文章SpringBoot 中使用Redis Stream 实现消息监听中的demo代码写的比较乱,而且也有部分问题,随着最近有些小伙伴的交流我整理了一下代码,后续还会继续优化,感兴趣的可以在码云里拉取后实验和修改——码云地址hlove/redismq

整理部分

整理后的代码我将redis的stream名称配置和组名通过配置文件的方式进行配置,application.yml文件如下:

spring:
  redis:
    host: 127.0.0.1
    password: yourpassword
    port: 6379
#stream 相关配置
redis-stream:
  #stream 名称数组
  names: mystream1,mystream2
  #stream 群组名称
  groups: group1

stream名称和组名都可以设置为数组的形式,监听多个stream或组,接收消息的 ListenerMessage 类整理如下:

@Slf4j
public class ListenerMessage implements StreamListener<String, MapRecord<String, String, String>> {

    RedisUtil redisUtil;

    public ListenerMessage(RedisUtil redisUtil){
        this.redisUtil = redisUtil;
    }

    @Override
    public void onMessage(MapRecord<String, String, String> entries) {
        try{
            log.info("接受到来自redis的消息");
            System.out.println("message id "+entries.getId().getValue());
            System.out.println("stream "+entries.getStream());
            System.out.println("body "+entries.getValue());
            redisUtil.delField(entries.getStream(),entries.getId().getValue());
        }catch (Exception e){
            log.error("error message:{}",e.getMessage());
        }
    }

}

onMessage方法用于接收消息,最后调用的delField方法用于删除读取后的消息,这里可以根据业务需求来决定你需不需要删除。
接下来就是需要将监听启动注入到spring中,对应的类为——RedisStreamConfig,代码如下:

@Slf4j
@Configuration
public class RedisStreamConfig {

    private final ListenerMessage streamListener;
    private final RedisUtil redisUtil;

    @Value("${redis-stream.names}")
    private String[]redisStreamNames;
    @Value("${redis-stream.groups}")
    private String[]groups;

    @Autowired
    public RedisStreamConfig(RedisUtil redisUtil){
        this.redisUtil = redisUtil;
        this.streamListener = new ListenerMessage(redisUtil);
    }

    @Bean
    public List<Subscription> subscription(RedisConnectionFactory factory){
        List<Subscription> resultList = new ArrayList<>();
        var options = StreamMessageListenerContainer
                .StreamMessageListenerContainerOptions
                .builder()
                .pollTimeout(Duration.ofSeconds(1))
                .build();
        for (String redisStreamName : redisStreamNames) {
            initStream(redisStreamName,groups[0]);
            var listenerContainer = StreamMessageListenerContainer.create(factory,options);
            Subscription subscription = listenerContainer.receiveAutoAck(Consumer.from(groups[0], this.getClass().getName()),
                    StreamOffset.create(redisStreamName, ReadOffset.lastConsumed()), streamListener);
            resultList.add(subscription);
            listenerContainer.start();
        }
        return resultList;
    }


    private void initStream(String key, String group){
        boolean hasKey = redisUtil.hasKey(key);
        if(!hasKey){
            Map<String,Object> map = new HashMap<>();
            map.put("field","value");
            RecordId recordId = redisUtil.addStream(key, map);
            redisUtil.addGroup(key,group);
            //将初始化的值删除掉
            redisUtil.delField(key,recordId.getValue());
            log.info("stream:{}-group:{} initialize success",key,group);
        }
    }
}

首先将配置中的stream和group获取到,然后在注入的方法中循环启动监听,注意里面的 this.getClass().getName() ,这个只是我使用这个类的名称作为消费者,大家可以根据实际需求修改这里。
下面的方法——initStream方法用于初始化stream,这也是之前代码中存在的一个问题,有的小伙伴在没有通过命令建立stream时启动会报错,就是因为没有对应的stream,这次通过这个方法可以避免这样的问题。

代码运行

如果你拉取了我的这个demo的话启动也是很简单的,只需要修改application.yml中的相关配置后就可以直接启动,注意的是你的redis版本应该大于5,然后直接启动就可以了。通过下面的测试接口进行测试发送消息

@GetMapping("/sendTest/{streamName}")
    public String addStream(@PathVariable String streamName){
        Map<String,Object> message = new HashMap<>();
        message.put("test","hello redismq");
        message.put("send time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        return redisUtil.addStream(streamName, message).getValue();
    }

采用restful请求格式例如:

http://localhost:8080/test/sendTest/mystream1

观察控制台打印会发现有对应的消息打印出来说明运行成功!

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 好的,我可以给你一些关于在 Spring Boot 使用 Redis 的指导。 首先,你需要在你的项目添加对 Redis 的依赖。在你的 `build.gradle` 文件添加如下依赖: ``` compile 'org.springframework.boot:spring-boot-starter-data-redis' ``` 然后,在你的配置文件(例如 `application.properties`)添加 Redis 的连接信息: ``` # Redis configuration spring.redis.host=localhost spring.redis.port=6379 ``` 接下来,你需要创建一个 RedisTemplate 和一个 StringRedisTemplate,用来对 Redis 进行操作。你可以在你的配置类创建这两个 Bean。 ``` @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); return template; } @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) { return new StringRedisTemplate(connectionFactory); } ``` 最后,你就可以在你的代码使用这两个 Bean 来对 Redis 进行操作了。例如: ``` @Autowired private StringRedisTemplate stringRedisTemplate; public void set(String key, String value) { stringRedisTemplate.opsForValue().set(key, value); } public String get(String key) { return stringRedisTemplate.opsForValue().get(key); } ``` 希望这些内容能对你有帮助。 ### 回答2: Spring Boot使用Redis可以通过两个步骤来实现。 第一步是引入Redis的依赖。在pom.xml文件添加以下依赖项以使用Redis: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 第二步是配置Redis连接属性。在application.properties(或application.yml)文件添加以下属性: ``` spring.redis.host=hostname spring.redis.port=port spring.redis.password=password ``` 其,`hostname`是Redis服务器的主机名,`port`是Redis服务器的端口号,`password`是Redis服务器的密码(如果有密码的话)。 配置完成后,就可以在Spring Boot的应用程序使用Redis了。可以使用`@Autowired`注解将`RedisTemplate`或`StringRedisTemplate`注入到需要使用Redis的类。例如: ```java @Service public class UserService { @Autowired private StringRedisTemplate stringRedisTemplate; public void saveUser(String id, String name) { stringRedisTemplate.opsForValue().set(id, name); } public String getUser(String id) { return stringRedisTemplate.opsForValue().get(id); } } ``` 上述示例,`StringRedisTemplate`是通过依赖注入得到的,可以使用其提供的`opsForValue()`方法来操作Redis的字符串值。 通过以上步骤,就可以在Spring Boot应用程序使用Redis进行数据存储和检索了。 ### 回答3: Spring Boot是一个开源的Java框架,可以轻松创建独立的、生产级别的Spring应用程序。在Spring Boot使用Redis,可以提供高性能的缓存和数据存储解决方案。 首先,我们需要在项目的pom.xml文件添加Redis相关的依赖项。可以使用Spring Boot的starters来简化这个过程,只需添加以下依赖即可: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 接下来,我们需要在application.properties或application.yaml文件配置Redis连接。以下是一个示例配置: ``` spring.redis.host=localhost spring.redis.port=6379 spring.redis.password=123456 ``` 其,host表示Redis服务器的主机名,port表示端口号,password表示连接密码(如果有的话)。 接着,我们可以在Spring Boot应用程序使用RedisTemplate或者注解来访问Redis。例如,我们可以使用注解@Autowired将RedisTemplate注入到我们的服务或控制器: ``` @Autowired private RedisTemplate<String, Object> redisTemplate; ``` 然后,我们可以使用redisTemplate来执行各种操作,比如存储和检索数据: ``` redisTemplate.opsForValue().set("key", "value"); String value = (String) redisTemplate.opsForValue().get("key"); ``` 另外,我们还可以使用Spring Boot的缓存注解简化对Redis的访问。通过在方法上添加@Cacheable、@CachePut或@CacheEvict等注解,可以自动将方法的结果存储到Redis缓存。 总之,Spring Boot提供了简单方便的集成Redis的方式,我们可以通过配置文件或者注解的方式来使用Redis,从而提升应用程序的性能和扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@胡海龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值