SpringBoot集成Redisson实现消息队列的示例代码

 更新时间:2024年10月10日 09:12:37   作者:入秋的大橘  
本文介绍了如何在SpringBoot中通过集成Redisson来实现消息队列的功能,包括RedisQueue、RedisQueueInit、RedisQueueListener、RedisQueueService等相关组件的实现和测试,感兴趣的可以了解一下

包含组件内容

  • RedisQueue:消息队列监听标识
  • RedisQueueInit:Redis队列监听器
  • RedisQueueListener:Redis消息队列监听实现
  • RedisQueueService:Redis消息队列服务工具

代码实现

RedisQueue

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Redis消息队列注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisQueue {
    /**
     * 队列名
     */
    String value();
}

RedisQueueInit

import jakarta.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.redisson.RedissonShutdownException;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 初始化Redis队列监听器
 *
 * @author 十八
 * @createTime 2024-09-09 22:49
 */
@Slf4j
@Component
public class RedisQueueInit implements ApplicationContextAware {

    public static final String REDIS_QUEUE_PREFIX = "redis-queue";
    final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
    @Resource
    private RedissonClient redissonClient;
    private ExecutorService executorService;

    public static String buildQueueName(String queueName) {
        return REDIS_QUEUE_PREFIX + ":" + queueName;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, RedisQueueListener> queueListeners = applicationContext.getBeansOfType(RedisQueueListener.class);
        if (!queueListeners.isEmpty()) {
            executorService = createThreadPool();
            for (Map.Entry<String, RedisQueueListener> entry : queueListeners.entrySet()) {
                RedisQueue redisQueue = entry.getValue().getClass().getAnnotation(RedisQueue.class);
                if (redisQueue != null) {
                    String queueName = redisQueue.value();
                    executorService.submit(() -> listenQueue(queueName, entry.getValue()));
                }
            }
        }
    }

    private ExecutorService createThreadPool() {
        return new ThreadPoolExecutor(
                Runtime.getRuntime().availableProcessors() * 2,
                Runtime.getRuntime().availableProcessors() * 4,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                new NamedThreadFactory(REDIS_QUEUE_PREFIX),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    private void listenQueue(String queueName, RedisQueueListener redisQueueListener) {
        queueName = buildQueueName(queueName);
        RBlockingQueue<?> blockingQueue = redissonClient.getBlockingQueue(queueName);
        log.info("Redis队列监听开启: {}", queueName);
        while (!shutdownRequested.get() && !redissonClient.isShutdown()) {
            try {
                Object message = blockingQueue.take();
                executorService.submit(() -> redisQueueListener.consume(message));
            } catch (RedissonShutdownException e) {
                log.info("Redis连接关闭,停止监听队列: {}", queueName);
                break;
            } catch (Exception e) {
                log.error("监听队列异常: {}", queueName, e);
            }
        }
    }

    public void shutdown() {
        if (executorService != null) {
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException ex) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
        shutdownRequested.set(true);
        if (redissonClient != null && !redissonClient.isShuttingDown()) {
            redissonClient.shutdown();
        }
    }

    private static class NamedThreadFactory implements ThreadFactory {
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        public NamedThreadFactory(String prefix) {
            this.namePrefix = prefix;
        }

        @Override
        public Thread newThread(@NotNull Runnable r) {
            return new Thread(r, namePrefix + "-" + threadNumber.getAndIncrement());
        }
    }

}

RedisQueueListener

/**
 * Redis消息队列监听实现
 *
 * @author 十八
 * @createTime 2024-09-09 22:51
 */
public interface RedisQueueListener<T> {

    /**
     * 队列消费方法
     *
     * @param content 消息内容
     */
    void consume(T content);
}

RedisQueueService

import jakarta.annotation.Resource;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

/**
 * Redis 消息队列服务
 *
 * @author 十八
 * @createTime 2024-09-09 22:52
 */
@Component
public class RedisQueueService {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 添加队列
     *
     * @param queueName 队列名称
     * @param content   消息
     * @param <T>       泛型
     */
    public <T> void send(String queueName, T content) {
        RBlockingQueue<T> blockingQueue = redissonClient.getBlockingQueue(RedisQueueInit.buildQueueName(queueName));
        blockingQueue.add(content);
    }

    /**
     * 添加延迟队列
     *
     * @param queueName 队列名称
     * @param content   消息类型
     * @param delay     延迟时间
     * @param timeUnit  单位
     * @param <T>       泛型
     */
    public <T> void sendDelay(String queueName, T content, long delay, TimeUnit timeUnit) {
        RBlockingQueue<T> blockingFairQueue = redissonClient.getBlockingQueue(RedisQueueInit.buildQueueName(queueName));
        RDelayedQueue<T> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
        delayedQueue.offer(content, delay, timeUnit);
    }

    /**
     * 发送延迟队列消息(单位毫秒)
     *
     * @param queueName 队列名称
     * @param content   消息类型
     * @param delay     延迟时间
     * @param <T>       泛型
     */
    public <T> void sendDelay(String queueName, T content, long delay) {
        RBlockingQueue<T> blockingFairQueue = redissonClient.getBlockingQueue(RedisQueueInit.buildQueueName(queueName));
        RDelayedQueue<T> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
        delayedQueue.offer(content, delay, TimeUnit.MILLISECONDS);
    }
}

测试

创建监听对象

import cn.yiyanc.infrastructure.redis.annotation.RedisQueue;
import cn.yiyanc.infrastructure.redis.queue.RedisQueueListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author 十八
 * @createTime 2024-09-10 00:09
 */
@Slf4j
@Component
@RedisQueue("test")
public class TestListener implements RedisQueueListener<String> {
    @Override
    public void invoke(String content) {
        log.info("队列消息接收 >>> {}", content);
    }
}

测试用例

import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 十八
 * @createTime 2024-09-10 00:11
 */
@RestController
@RequestMapping("queue")
public class QueueController {

    @Resource
    private RedisQueueService redisQueueService;

    @PostMapping("send")
    public void send(String message) {
        redisQueueService.send("test", message);
        redisQueueService.sendDelay("test", "delay messaege -> " + message, 1000);
    }

}

测试结果

到此这篇关于SpringBoot集成Redisson实现消息队列的示例代码的文章就介绍到这了,更多相关SpringBoot Redisson消息队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot bean的多种加载方式示例详解

    SpringBoot bean的多种加载方式示例详解

    本文详细介绍了在SpringBoot中加载Bean的多种方式,包括通过xml配置文件、注解定义、特殊方式如FactoryBean、@ImportResource、ApplicationContext以及使用@Import注解导入bean的方法,感兴趣的朋友跟随小编一起看看吧
    2024-10-10
  • Java多线程之CAS算法实现线程安全

    Java多线程之CAS算法实现线程安全

    这篇文章主要介绍了java中如何通过CAS算法实现线程安全,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面小编和大家一起来学习一下吧
    2019-05-05
  • Java进阶之走进RESTful接口

    Java进阶之走进RESTful接口

    RESTful是代表REST化,或者说设计遵从REST架构的,所以要了解RESTful就需要了解REST.文中详细介绍了Java RESTful,需要的朋友可以参考下
    2021-05-05
  • 用Java实现简单画板功能

    用Java实现简单画板功能

    这篇文章主要为大家详细介绍了用Java实现简单画板功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 详解Nacos配置中心的实现

    详解Nacos配置中心的实现

    Spring Cloud Alibaba 是阿里巴巴提供的一站式微服务开发解决方案。而 Nacos 作为 Spring Cloud Alibaba 的核心组件之一,提供了两个非常重要的功能:注册中心和配置中心,我们今天来了解和实现一下二者
    2022-08-08
  • spring boot动态加载Echart饼状图

    spring boot动态加载Echart饼状图

    这篇文章主要为大家详细介绍了spring boot动态加载Echart饼状图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • springboot 全局异常处理和统一响应对象的处理方式

    springboot 全局异常处理和统一响应对象的处理方式

    这篇文章主要介绍了springboot 全局异常处理和统一响应对象,主要包括SpringBoot 默认的异常处理机制和SpringBoot 全局异常处理,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Spring 实现excel及pdf导出表格示例

    Spring 实现excel及pdf导出表格示例

    本篇文章主要介绍了Spring 实现excel及pdf导出表格示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Java中的MultipartFile接口和File类解读

    Java中的MultipartFile接口和File类解读

    本文主要介绍了Java中的File类和Spring框架中的MultipartFile接口,File类提供了对文件和目录操作的方法,如创建、删除、重命名、判断文件是否存在等,MultipartFile接口用于处理文件上传,提供了获取上传文件信息和保存上传文件的方法
    2025-02-02
  • Java实现的properties文件动态修改并自动保存工具类

    Java实现的properties文件动态修改并自动保存工具类

    这篇文章主要介绍了Java实现的properties文件动态修改并自动保存工具类,可实现针对properties配置文件的相关修改与保存功能,需要的朋友可以参考下
    2017-11-11

最新评论