SpringBoot RedisMQ消息队列与发布订阅

SpringBoot简单整合RedisMQ消息队列和发布订阅

注:RedisMq消息队列使用redis数组实现,leftpush存一,rightpop取一。

1.application.properties

server.port=8080

#thymeleaf配置
#是否启用模板缓存。
spring.thymeleaf.cache=false
#是否为Web框架启用Thymeleaf视图解析。
spring.thymeleaf.enabled=true
#在SpringEL表达式中启用SpringEL编译器。
spring.thymeleaf.enable-spring-el-compiler=true
#模板文件编码。
spring.thymeleaf.encoding=UTF-8
#要应用于模板的模板模式。另请参见Thymeleaf的TemplateMode枚举。
spring.thymeleaf.mode=HTML5
#在构建URL时添加前缀以查看名称的前缀。
spring.thymeleaf.prefix=classpath:/templates/
#Content-Type写入HTTP响应的值。
spring.thymeleaf.servlet.content-type=text/html
#在构建URL时附加到视图名称的后缀。
spring.thymeleaf.suffix=.html

##单服务器
spring.redis.host=192.168.159.129
##单端口
spring.redis.port=6379
## 连接池最大连接数(使用负值表示没有限制) 
spring.redis.pool.max-active=300
## Redis数据库索引(默认为0) 
spring.redis.database=0
## 连接池最大阻塞等待时间(使用负值表示没有限制) 
spring.redis.pool.max-wait=-1
## 连接池中的最大空闲连接 
spring.redis.pool.max-idle=100
## 连接池中的最小空闲连接 
spring.redis.pool.min-idle=20
## 连接超时时间(毫秒) 
spring.redis.timeout=60000

2.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.szw.learn</groupId>
    <artifactId>redis_mq_01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>redis_mq_01</name>
    <description>redis mq example</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.16.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.test.skip>true</maven.test.skip>
        <skipTests>true</skipTests>
        <start-class>com.szw.learn.redis.RedisMqApplication</start-class>
    </properties>

    <dependencies>
        <!-- 使用web启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        
        <!-- redis artifactId与1.5之前版本变了 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>nexus-aliyun</id>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>nexus-aliyun</id>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <build>
        <plugins>
            <!-- 要将源码放上去,需要加入这个插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <configuration>
                    <attach>true</attach>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- 打包 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.RedisMqApplication.java启动类

package com.szw.learn.redis;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RedisMqApplication {
    public static void main(String[] args) {
        System.setProperty("spring.devtools.restart.enabled", "false");
        SpringApplication.run(RedisMqApplication.class, args);
    }
}

4.消息队列测试(生产者和消费者)

生产者:

package com.szw.learn.redis.mq;

import javax.annotation.PostConstruct;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import com.szw.learn.redis.RedisMqApplication;

/**
 * @author 七脉
 * 描述:生产者测试类
 */
@SpringBootTest(classes = RedisMqApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class MQProducerTest {
    @Autowired
    private StringRedisTemplate redisTemplate;
    //redis的消息队列直接使用redis数组实现
    private ListOperations<String, String> listRedis;
    
    /**
     * <br>描 述: 初始化时赋值
     * <br>作 者: shizhenwei 
     * <br>历 史: (版本) 作者 时间 注释
     */
    @PostConstruct
    private void init(){
        listRedis = redisTemplate.opsForList();
    }
    
    @Test
    public void test() {
        for(int i=1; i<=10; i++){
            //从左边向堆栈顺序存放1~10个消息
            listRedis.leftPush("storage", i+"");
        }
    }
}

消费者:

package com.szw.learn.redis.mq;

import javax.annotation.PostConstruct;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StringUtils;

import com.szw.learn.redis.RedisMqApplication;
/**
 * @author 七脉
 * 描述:消费者测试类
 */
@SpringBootTest(classes = RedisMqApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class MQConsumerTest {
    @Autowired
    private StringRedisTemplate redisTemplate;
    //redis的消息队列直接使用redis数组实现
    private ListOperations<String, String> listRedis;
    
    /**
     * <br>描 述: 初始化时赋值
     * <br>作 者: shizhenwei 
     * <br>历 史: (版本) 作者 时间 注释
     */
    @PostConstruct
    private void init(){
        listRedis = redisTemplate.opsForList();
    }
    
    @Test
    public void test() {
        while(true){
            //从右边取堆栈顺序取1~10个消息
            String msg = listRedis.rightPop("storage");
            if(StringUtils.isEmpty(msg)){
                System.out.println("消息已经全部取出了。。。。");
                break;
            }
            System.out.println(msg);
        }
    }
}

测试结果:

5.发布订阅

订阅监听类:

package com.szw.learn.redis.mq;

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;

/**
 * @author 七脉 描述:订阅监听类
 */
public class SubscribeListener implements MessageListener {
    /**
     * 订阅接收发布者的消息
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 缓存消息是序列化的,需要反序列化。然而new String()可以反序列化,但静态方法valueOf()不可以
        System.out.println(new String(pattern) + "主题发布:" + new String(message.getBody()));
    }
}

发布service:

package com.szw.learn.redis.mq;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @author 七脉 描述:发布service
 */
@Component
public class PublishService {
    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * @author 七脉 描述:发布方法
     * @param channel 消息发布订阅 主题
     * @param message 消息信息
     */
    public void publish(String channel, Object message) {
        // 该方法封装的 connection.publish(rawChannel, rawMessage);
        redisTemplate.convertAndSend(channel, message);
    }
}

添加定义监听主题:

package com.szw.learn.redis.mq;

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.jedis.JedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

@Configuration
public class RedisConfig {
    @Autowired
    private JedisConnectionFactory jedisConnectionFactory;

    /**
     * @author 七脉 描述:需要手动定义RedisMessageListenerContainer加入IOC容器
     * @return
     */
    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();

        container.setConnectionFactory(jedisConnectionFactory);

        /**
         * 添加订阅者监听类,数量不限.PatternTopic定义监听主题,这里监听dj主题
         */
        container.addMessageListener(new SubscribeListener(), new PatternTopic("dj"));
        return container;

    }
}

发布订阅测试:

package com.szw.learn.redis.mq;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.szw.learn.redis.RedisMqApplication;

/**
 * @author 七脉
 * 描述:消息发布
 */
@SpringBootTest(classes = RedisMqApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class PublishTest {

    @Autowired
    private PublishService publishService;

    @Test
    public void test() {
        for(int i=1; i<=10; i++){
            //向dj主题里发布10个消息
            publishService.publish("dj", "like "+i+" 次");
        }
    }
}

测试结果:

原文地址:https://www.cnblogs.com/zwcry/p/9719361.html