activemq有订阅模式,该模式是直接群发,消息不保存。
生产者:
先写个生成者的demo
package org.example.activemqtest;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.util.Scanner;
public class Provider {
public static String username = "admin";
public static String password = "admin";
public static String url ="tcp://localhost:61616";//采用openwire
public static String name="test_topic_1";
private ConnectionFactory connectionFactory;
private Connection connection;
private Session session;
{
try {
/**
* 1.创建连接工厂
* 创建工厂,构造方法有三个参数:分别是用户名、密码、连接地址
* 无参构造:有默认的连接地址,localhost
* 一个参数:无验证模式,无用户的认证
* 三个参数:有认证和连接地址
*/
connectionFactory = new ActiveMQConnectionFactory(username,password,url);
connection = connectionFactory.createConnection();
/**
* 3.启动连接
* 生产者可以不启动,因为在发送消息的时候回进行检查
* 如果未启动连接,会自动启动
* 如果有特殊配置,需要配置完成后再启动连接
*/
connection.start();
/**
* 4.用连接创建会话
* 有两个参数:是否需要事务、消息确认机制
* 如果支持事务,对于生产者来说第二个参数就无效了,建议传入Session.SESSION_TRANSACTED
* 如果不支持事务,第二个参数必须传递且有效
*
* AUTO_ACKNOWLEDGE:自动确认,消息处理后自动确认(商业开发不推荐)
* CLIENT_ACKNOWLEDGE:客户端手动确认,消费者处理后必须手动确认
* DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认,消息可以多次处理(不建议)
*/
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
System.out.println("clientID = " + connection.getClientID());
} catch (JMSException e) {
e.printStackTrace();
}
}
private void send(String text) throws JMSException {
Destination queue = session.createTopic(name);
MessageProducer producer = session.createProducer(queue);
producer.send(session.createTextMessage(text));
}
public static void main(String[] args) throws Exception {
Provider provider = new Provider();
Scanner scan = new Scanner(System.in);
// 判断是否还有输入
while (scan.hasNextLine()) {
String str2 = scan.nextLine();
System.out.println("发送的数据为:" + str2);
provider.send(str2);
}
scan.close();
}
}
可以看到,代码实际上就是new Provicder().send(text)
普通代码块里创建了连接,send方法往test_topic_1里发送数据.然后发送者就结束了,就不再管了.
至于Scanner是为了屏幕输入然后发送
我们启动这个main方法,发送一条数据
1111
发送的数据为:1111
然后观察active后台控制台里:
可以发现test_topic_1这个队列里已经有了一条数据。
消费者:
package org.example.activemqtest;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.time.LocalDateTime;
public class Receiver {
public static final String username ="admin";
private static final String password ="admin";
public static final String url ="tcp://localhost:61616";
public static String name="test_topic_1";
Connection connection;
Session session;
{
try {
/**
* 1.创建连接工厂
* 创建工厂,构造方法有三个参数:分别是用户名、密码、连接地址
* 无参构造:有默认的连接地址,localhost
* 一个参数:无验证模式,无用户的认证
* 三个参数:有认证和连接地址
*/
ConnectionFactory factory = new ActiveMQConnectionFactory(username,password,url);
connection = factory.createConnection();
/**
* 3.启动连接
* 生产者可以不启动,因为在发送消息的时候回进行检查
* 如果未启动连接,会自动启动
* 如果有特殊配置,需要配置完成后再启动连接
*/
connection.start();
/**
* 4.用连接创建会话
* 有两个参数:是否需要事务、消息确认机制
* 如果支持事务,对于生产者来说第二个参数就无效了,建议传入Session.SESSION_TRANSACTED
* 如果不支持事务,第二个参数必须传递且有效
*
* AUTO_ACKNOWLEDGE:自动确认,消息处理后自动确认(商业开发不推荐)
* CLIENT_ACKNOWLEDGE:客户端手动确认,消费者处理后必须手动确认
* DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认,消息可以多次处理(不建议)
*/
session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
} catch (JMSException e) {
e.printStackTrace();
}
}
public void receive() throws JMSException {
Destination queue = session.createTopic(name);
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
try{
TextMessage m = (TextMessage)message;
String text = m.getText();
System.out.println(LocalDateTime.now() +" : " +text);
}catch (Exception e){
e.printStackTrace();
}
}
});
}
public static void main(String[] args) throws JMSException {
new Receiver().receive();
}
}
可以看到,在连接到消息中间件后,客户端就加了一个而监听器而已,监听器里打印了发来的数据
然后我们运行,发现没有打印任何数据,没有获得刚刚发的1111,因为订阅模式消息不保存,直接抛弃了。如果当时没有订阅就接不到。
我们再看到控制台:
发现多了一个接收者,但是消息订阅数还是0,并没有增加。
进一步测试
我们再发一条222消息进行测试,发现消费者接到了消息。控制台如下:
发现生产的消息多了一条,消费总数也多了一条。
由于订阅模式特征就是群发,那么再启动一个消费者,然后再发一条333,发现两个消费者都接到了。控制台如下:
发现消费者多了一个,消息多了一个,但是消费总数居然多了两个,原因在于消费总数就是消费总数,刚刚两个消费者消费了所以+2,如果是3个消费者,那么要加3