ActiveMQ(二)使用 Java 操作 ActiveMQ

使用 Java 操作 ActiveMQ

导入 maven 依赖

<dependency>
    <groupId>org.apache.activemqgroupId>
    <artifactId>activemq-allartifactId>
    <version>5.16.2version>
dependency>

现在的消息队列大概分为队列模型和发布订阅模型

队列 Queue

队列模型:

  • 消费者之间是竞争的关系,每个消费者只能收到队列中的一部分消息
  • 如果需要将一份数据发送给多个消费者,单个队列满足不了需求,可以为每个消费者创建一个单独的队列

生产者代码

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.util.Date;

public class JmsProduce {

    private static final String DEFAULT_BROKER_HOST = "tcp://IP:61616";

    public static void main(String[] args) throws JMSException {
        // 创建连接工厂
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(DEFAULT_BROKER_HOST);
        // 获取 connection
        final Connection connection = connectionFactory.createConnection("admin", "admin");
        // 启动
        connection.start();
        // 创建会话 session,参数第一个是事务,第二个是签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 创建目的地,queue 或者 topic
        Queue queue = session.createQueue("queueName");
        // 创建消息的生产者
        MessageProducer producer = session.createProducer(queue);
        // 创建消息
        TextMessage textMessage = session.createTextMessage("这是一条消息" + new Date());
        // 发送消息给 mq
        producer.send(textMessage);
        // 关闭
        session.close();
        connection.close();
        System.out.println("消息发送成功~");
    }

}

消费者代码

1、同步阻塞,使用 receive() 方法进行消费,receive() 方法不带参数会一直等待,receive(Long timeout) 会等待指定时间后退出等待

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class JmsConsumer {
    public static void main(String[] args) throws JMSException {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://IP:61616");
        Connection connection = connectionFactory.createConnection("admin", "admin");
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue("queueName");
        // 创建消费者
        MessageConsumer consumer = session.createConsumer(queue);
        while (true) {
            // 同步阻塞方式使用 receive(),超时之前一直等待
            // receive() 方法不带参数会一直等待
            // receive(Long timeout) 会等待指定时间后退出等待
            TextMessage receive = (TextMessage) consumer.receive();
            if (receive != null) {
                System.out.println("接收到消息:" + receive);
            }else {
                break;
            }
        }
        consumer.close();
        session.close();
        connection.close();
    }
}

2、异步阻塞,使用监听方式消费消息,订阅者或接收者通过 MessageConsumer 的 setMessageListener(MessageListenner listener) 注册一个消息监听器,消息到达后自动调用监听器的 MessageListener 的 onMessage(Message message) 方法

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.IOException;

public class JmsConsumer {
    public static void main(String[] args) throws JMSException, IOException {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://82.156.227.150:61616");
        Connection connection = connectionFactory.createConnection("admin", "admin");
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue("queueName");
       // 创建消费者
        MessageConsumer consumer = session.createConsumer(queue);
        // 通过监听方式消费消息
        consumer.setMessageListener((message) -> {
            if (null != message && message instanceof TextMessage) {
                TextMessage message1 = (TextMessage) message;
                try {
                    System.out.println("消费者接收到消息:" + message1.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
        System.in.read(); // 保证控制台存活状态
        consumer.close();
        session.close();
        connection.close();
    }
}

主题 Topic

订阅-发布模式

  • 消息的发送方称为发布者(Publisher),消息接收者称为订阅者(Subscriber),服务端存放消息的容器称为(Topic)
  • 发布者将消息发送到 Topic 中,订阅者需要订阅主题,每个订阅者都可以接收到订阅之后主题发布所有的消息
  • 生产者和消费者有时间上的相关性,生产者生产时,topic 不保存消息它是无状态的,应该先启动消费者再启动生产者
  • JMS 允许客户创建持久订阅,持久订阅允许消费者消费未激活状态时发送的消息

生产者代码

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.util.Date;

public class JmsProduceTopic {
    public static void main(String[] args) throws Exception{
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://IP:61616");
        Connection connection = connectionFactory.createConnection("admin", "admin");
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = session.createTopic("topicName");
        MessageProducer producer = session.createProducer(topic);
        TextMessage textMessage = session.createTextMessage("message--" + new Date());
        producer.send(textMessage);
        producer.close();
        session.close();
        connection.close();
        System.out.println("消息发送成功~");
        
    }
}

消费者代码

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.util.Date;

public class JmsConsumerTopic {
    public static void main(String[] args) throws Exception{
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://IP:61616");
        Connection connection = connectionFactory.createConnection("admin", "admin");
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = session.createTopic("topicName");
        MessageConsumer consumer = session.createConsumer(topic);
        consumer.setMessageListener((message) -> {
            if (message != null && message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                try {
                    System.out.println("消费者接收到消息:" + textMessage.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
        System.in.read();
        consumer.close();
        session.close();
        connection.close();

    }
}

Topic 模式队列和 Queue 模式队列比较

Topic 模式队列 Queue 模式队列
订阅,发布模式,当前没有订阅者,消息会被放弃,如果有多个订阅者,所有订阅者都会收到消息 如果没有消费者,消息也不会丢弃,多个消费者,消息只会发送给其中一个消费者,并且要求消费者 ACK 信息
无状态 默认在 mq 服务器上以文件形式保存,也可以配置成 DB 存储
没有订阅者消息丢弃 消息不会丢弃
消息按照订阅者数量进行赋值,性能随着订阅者数量增加降低 每个消息只发送个一个消费者,性能不会明显降低

ActiveMQ Broker

Broker 相当于一个 ActiveMQ 实例

ActiveMQ 实现了用代码的形式启动 ActiveMQ 将 MQ 嵌入到 Java 代码中

导入 maven 依赖

<dependency>
    <groupId>com.fasterxml.jackson.coregroupId>
    <artifactId>jackson-databindartifactId>
    <version>2.12.3version>
dependency>

启动 Broker 代码

public static void main(String[] args) throws Exception {
    BrokerService brokerService = new BrokerService();
    brokerService.setUseJmx(true);
    brokerService.addConnector("tcp://localhost:61616");
    brokerService.start();
}

你可能感兴趣的:(中间件,分布式技术,activemq,java,中间件)