前文
ActiveMQ —— Java 连接 ActiveMQ(点对点)
ActiveMQ —— Java 连接 ActiveMQ(发布订阅 Topic)
ActiveMQ —— Spring 整合 ActiveMQ
队列
队列生产者
新建 Maven 工程
先创建一个 Maven 工程,这个非常简单,这里就不详细写了
pom.xml
添加相关的依赖,主要是 spring-boot-starter-activemq
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.yml
进行相关的配置
server:
port: 7777
spring:
activemq:
broker-url: tcp://localhost:61616 # 自己的 MQ 服务器地址
user: admin
password: admin
jms:
pub-sub-domain: false # false = Queue || true = Topic
# 自定义队列名称
myQueue: boot-activemq-queue
配置 Bean
在这个 Bean 中记得加上 @EnableJms (重点)
package com.java.activemq_produce.config;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
/**
* @author Woo_home
* @create 2020/5/22 16:04
*/
@Component
@EnableJms // 开启 JMS 的注解
public class ConfigBean {
// 读取 application.yml 的值
@Value("${myQueue}")
private String myQueue;
@Bean
public Queue queue() {
return new ActiveMQQueue(myQueue);
}
}
消息生产者代码
主要就是发送消息到 ActiveMQ
package com.java.activemq_produce.produce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
import java.util.UUID;
/**
* @author Woo_home
* @create 2020/5/22 16:07
*/
@Component
public class Queue_Produce {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Queue queue;
public void produceMsg() {
jmsMessagingTemplate.convertAndSend(queue, "****** : " + UUID.randomUUID().toString().substring(0, 6));
System.out.println("send over");
}
}
主启动类
package com.java.activemq_produce;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ActivemqProduceApplication {
public static void main(String[] args) {
SpringApplication.run(ActivemqProduceApplication.class, args);
}
}
测试单元
package com.java.activemq_produce;
import com.java.activemq_produce.produce.Queue_Produce;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.web.WebAppConfiguration;
import javax.annotation.Resource;
@SpringBootTest(classes = ActivemqProduceApplication.class)
@WebAppConfiguration
class ActivemqProduceApplicationTests {
@Resource
private Queue_Produce queue_produce;
@Test
public void testSend() throws Exception {
queue_produce.produceMsg();
}
@Test
void contextLoads() {
}
}
运行 testSend() 方法,每运行一次就发送一条消息(当然,启动主启动类也是一样的)
OK,然后刷新一下 Queue 界面,成功往 ActiveMQ 发送了一条消息
定时推送消息
修改 Queue_Produce 新增定时投递方法
package com.java.activemq_produce.produce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.jms.Queue;
import java.util.UUID;
/**
* @author Woo_home
* @create 2020/5/22 16:07
*/
@Component
public class Queue_Produce {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Queue queue;
public void produceMsg() {
jmsMessagingTemplate.convertAndSend(queue, "****** : " + UUID.randomUUID().toString().substring(0, 6));
System.out.println("send over");
}
// 间隔时间 3s 定投
@Scheduled(fixedDelay = 3000)
public void produceMsgScheduled() {
jmsMessagingTemplate.convertAndSend(queue, "Scheduled****** : " + UUID.randomUUID().toString().substring(0, 6));
System.out.println("send over");
}
}
主要增加以下代码
修改主启动类
package com.java.activemq_produce;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ActivemqProduceApplication {
public static void main(String[] args) {
SpringApplication.run(ActivemqProduceApplication.class, args);
}
}
主要增加以下注解,开启定时器
直接开始主启动类,间隔发消息
队列消费者
创建 Maven 工程
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.yml
server:
port: 8888
spring:
activemq:
broker-url: tcp://localhost:61616 # 自己的 MQ 服务器地址
user: admin
password: admin
jms:
pub-sub-domain: false # false = Queue || true = Topic
# 自定义队列名称
myQueue: boot-activemq-queue
配置 Bean
package com.java.activemq_consumer.consumer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.TextMessage;
/**
* @author Woo_home
* @create 2020/5/22 20:59
*/
@Component
public class Queue_Consumer {
// 消息监听
@JmsListener(destination = "${myQueue}") // 队列名称
public void receive(TextMessage textMessage) throws JMSException {
System.out.println("****** 消费者收到消息 " + textMessage.getText());
}
}
主启动类
package com.java.activemq_consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ActivemqConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ActivemqConsumerApplication.class, args);
}
}
启动主启动类
可以发现接收到 22 条消息(这里由于图太长,知道一下就好了)
刷新 Queue 界面,可以发现 22 条消息全部出队
发布订阅
Topic 生产者
创建 Maven 工程
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.yml
server:
port: 6666
spring:
activemq:
broker-url: tcp://localhost:61616 # 自己的 MQ 服务器地址
user: admin
password: admin
jms:
pub-sub-domain: true # false = Queue || true = Topic
# 自定义主题名称
myTopic: boot-activemq-topic
配置 Bean
都是非常简单的
package com.java.activemq.topic.produce.config;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.jms.Topic;
/**
* @author Woo_home
* @create 2020/5/22 21:34
*/
@Component
public class ConfigBean {
@Value("${myTopic}")
private String topicName;
@Bean
public Topic topic() {
return new ActiveMQTopic(topicName);
}
}
Topic_Produce
package com.java.activemq.topic.produce.produce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.jms.Topic;
import java.util.UUID;
/**
* @author Woo_home
* @create 2020/5/22 21:36
*/
@Component
public class Topic_Produce {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Topic topic;
@Scheduled(fixedDelay = 3000)
public void produceTopic() {
jmsMessagingTemplate.convertAndSend(topic, "主题消息:" + UUID.randomUUID().toString().substring(0,6));
}
}
主启动类
package com.java.activemq.topic.produce;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ProduceApplication {
public static void main(String[] args) {
SpringApplication.run(ProduceApplication.class, args);
}
}
Topic 消费者
创建 Maven 工程
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.yml
server:
port: 5555
spring:
activemq:
broker-url: tcp://localhost:61616 # 自己的 MQ 服务器地址
user: admin
password: admin
jms:
pub-sub-domain: true # false = Queue || true = Topic
# 自定义主题名称
myTopic: boot-activemq-topic
Topic_Consumer
package com.java.activemq.topic.consumer.consumer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.TextMessage;
/**
* @author Woo_home
* @create 2020/5/22 21:42
*/
@Component
public class Topic_Consumer {
@JmsListener(destination = "${myTopic}")
public void receive(TextMessage textMessage) {
try {
System.out.println("消费者收到订阅的主题:" + textMessage.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
}
主启动类
package com.java.activemq.topic.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
测试
模拟两个订阅者主启动类,先启动订阅者再启动发布者
怎么模拟呢?很简单,先启动一个消费者(端口号为 5555)
然后把 application.yml 文件的 5555 改为 5556 然后再启动一下主程序即可(之前的不用关掉)
刷新一下 Topic 界面,现在有两个消费者在等待消费
然后我们再启动一下生产者端,可以发现两个消费者接收到的消息是一样的
再刷新一下 Topic 界面,这里说明一下,因为截图之前关掉程序了,所以这里的队列为 0 了,但是可以从消息入队和出队可以知道,生产者生产了 30 条消息,两个消费者一共消费了 60 条消息
以上的代码已上传至码云,代码下载地址