ActiveMQ 03 ActiveMQ基础

来源:互联网 发布:2017淘宝网店数量 编辑:程序博客网 时间:2024/06/01 19:00

1、安装ActiveMQ

⑴ 下载apache-activemq-5.15.1-bin.tar.gz

⑵ 解压缩

⑶ 到bin目录下启动和关闭
启动命令:./activemq start
关闭命令:./activemq stop

2、管理ActiveMQ

默认端口为8161,用户名和密码都为admin

3、队列模式

⑴ 特点

① 一个消息只能被一个消费者所消费
② 消费者可以随时消费消息

⑵ API

① ConnectionFactory

连接工厂

实现类:ActiveMQConnectionFactory
public ActiveMQConnectionFactory(String brokerURL) {}
需要传入ActiveMQ服务器的连接地址,端口默认为61616

② Connection

连接,由连接工厂所创建。通过连接可以创建会话(Session)
Connection createConnection() throws JMSException;

void start() throws JMSException;
打开连接。很重要

void close() throws JMSException;
关闭连接

③ Session

会话,可以创建目的地(Destination)、生产者(MessageProducer)和消费者(MessageConsumer)

Session createSession(boolean var1, int var2) throws JMSException;
第一个参数为是否开启事务,第二个参数为

      可以选择Session的常量:        int AUTO_ACKNOWLEDGE = 1;        int CLIENT_ACKNOWLEDGE = 2;        int DUPS_OK_ACKNOWLEDGE = 3;        int SESSION_TRANSACTED = 0;

MessageProducer createProducer(Destination var1) throws JMSException;
传入目的地

MessageConsumer createConsumer(Destination var1) throws JMSException;
传入目的地

④ Queue

队列,由Session创建
Queue createQueue(String var1) throws JMSException;
传入队列的名称

public interface Queue extends Destination {}
Destination就是目的地

⑤ TextMessage

文本类型的消息,由Session创建
TextMessage createTextMessage(String var1) throws JMSException;
需要传入消息的内容

⑥ send

void send(Message var1) throws JMSException;
发送消息,由MessageProducer调用

⑦ setMessageListener

void setMessageListener(MessageListener var1) throws JMSException;
传入一个消息监听器

  public interface MessageListener {      void onMessage(Message var1);  }

可以将Message对象强转为具体的消息对象,再调用具体的方法获取消息内容
例如:

  public interface TextMessage extends Message {      String getText() throws JMSException;  }

可以获得文本消息类型的消息内容

⑶ 示例

private static final String brokerURL = ???;private static final String QUEUE_NAME = ???;

【生产者】

    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);    Connection connection = connectionFactory.createConnection();    connection.start(); // 启动连接    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);    Destination destination = session.createQueue(QUEUE_NAME);    MessageProducer producter = session.createProducer(destination);    for (int i = 1; i <= 100; i++) {        TextMessage textMessage = session.createTextMessage("queue-message-" + i);        producter.send(textMessage);        System.out.println("发送消息" + textMessage.getText());    }    producter.close();    connection.close();

【消费者】

    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);    Connection connection = connectionFactory.createConnection();    connection.start(); // 启动连接    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);    Destination destination = session.createQueue(QUEUE_NAME);    MessageConsumer consumer = session.createConsumer(destination);    consumer.setMessageListener(new MessageListener() {        @Override        public void onMessage(Message message) {            TextMessage textMessage = (TextMessage) message;            try {                System.out.println(textMessage.getText());            } catch (JMSException e) {                e.printStackTrace();            }        }    });

注意消费者和连接都不能关闭,否则无法异步获取消息

4、主题模式

⑴ 特点

① 所有的消息都能被订阅者所消费
② 订阅者只能消费它所订阅的消息,订阅前的消息并不能被其消费

⑵ API

Topic createTopic(String var1) throws JMSException;
创建主题,由Session创建,需要传入主题的名称

⑶ 示例

private static final String brokerURL = "";private static final String TOPIC_NAME = "";

【发布者】

    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);    Connection connection = null;    try {        connection = connectionFactory.createConnection();        connection.start();        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        Destination destination = session.createTopic(TOPIC_NAME);        MessageProducer messageProducer = session.createProducer(destination);        for (int i = 1; i <= 100; i++) {            TextMessage message = session.createTextMessage("topic-message-" + i);            messageProducer.send(message);            System.out.println(message.getText());        }    } catch (JMSException e) {        e.printStackTrace();    } finally {        if (null != connection) {            try {                connection.close();            } catch (JMSException e) {                e.printStackTrace();            }        }    }

【订阅者】

    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);    Connection connection = connectionFactory.createConnection();    connection.start();    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);    Destination destination = session.createTopic(TOPIC_NAME);    MessageConsumer consumer = session.createConsumer(destination);    consumer.setMessageListener((message) -> {        TextMessage textMessage = (TextMessage) message;        try {            System.out.println("接收消息:" + textMessage.getText());        } catch (JMSException e) {            e.printStackTrace();        }    });

注意订阅者和连接都不能关闭,否则无法异步获取消息

5、整合Spring

⑴ pom依赖

<dependencies>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>        <version>${spring.version}</version>    </dependency>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-jms</artifactId>        <version>${spring.version}</version>    </dependency>    <dependency>        <groupId>org.apache.activemq</groupId>        <artifactId>activemq-core</artifactId>        <version>${activemq.version}</version>        <!-- 排除ActiveMQ自身的Spring-Context的依赖 -->        <exclusions>            <exclusion>                <groupId>org.springframework</groupId>                <artifactId>spring-context</artifactId>            </exclusion>        </exclusions>    </dependency></dependencies>

⑵ API

① SingleConnectionFactory

由Spring-Jms提供的整合消息中间件的连接工厂(连接池)。它有一个ConnectionFactory targetConnectionFactory的属性,用于指定目标连接工厂,可以引用ActiveMQConnectionFactory

② CachingConnectionFactory

继承自SingleConnectionFactory,它可以缓存会话(Session),当然也包括生产者和消费者

③ ActiveMQQueue

由ActiveMQ提供的队列。需要指定消息的name属性,可以通过set注入或者构造注入

④ ActiveMQTopic

由ActiveMQ提供的主题。需要指定消息的physicalName,可以通过set注入或者构造注入

⑤ JmsTemplate

用于发送和接收消息的模版类。需要指定connectionFactory属性,可以set注入或者构造注入
它每次发送消息时,都会重新创建连接、会话和生产者
同时它也是线程安全的,可以在整个应用中使用它

⑥ MessageListener

消息监听器。接口,消费者可以实现它,并实现
void onMessage(Message message);方法,通过将Message对象强转为相应的消息对象,并获取对应的消息

⑦ DefaultMessageListenerContainer

消息监听容器。需要指定connectionFactory,destination以及messageListener

⑶ 示例

由于生产者和消费者都需要配置连接池、连接工厂、消息,所以可以将这些提取出来,再通过import引用即可复用

【common.xml】

<!-- 启用注解 --><context:annotation-config /><!-- 引入配置文件 --><context:property-placeholder location="classpath:activemq.properties" /><!-- ActiveMQ --><bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">    <property name="brokerURL" value="${activemq.brokerUrl}" /></bean><!-- 连接池 --><bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">    <property name="targetConnectionFactory" ref="activeMQConnectionFactory" /></bean><!-- Queue队列 --><bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">    <constructor-arg value="${activemq.queueName}" /></bean><!-- Topic主题 --><bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">    <property name="physicalName" value="${activemq.topicName}" /></bean>

【producer.xml】

<import resource="classpath:common.xml" /><!-- JmsTemplate --><bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">    <property name="connectionFactory" ref="connectionFactory" /></bean><!-- 生产者实现类 --><bean class="???" />

【consumer.xml】

<import resource="classpath:common.xml" /><!-- 消息监听器实现类 --><bean id="messageListener" class="???" /><!-- 消息监听容器 --><bean id="messageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">    <property name="connectionFactory" ref="connectionFactory" />    <!-- 引入队列【仅能选择一个】 -->    <property name="destination" ref="queueDestination" />    <!-- 引入主题【仅能选择一个】 -->    <property name="destination" ref="topicDestination" />    <property name="messageListener" ref="messageListener" /></bean>

【生产者接口】

public interface Producer {    void sendMessage(String message);}

【生产者实现类】

public class Producer implements Producer {    @Autowired    private JmsTemplate jmsTemplate;    @Resource(name = "消息的id属性,队列或主题")    private Destination destination;    @Override    public void sendMessage(String name) {        jmsTemplate.send(destination, new MessageCreator(Session session) throws JMSException {            return session.createTextMessage(name);        });    }}

【消费者】

public class Consumer implements MessageListener {    @Override    public void onMessage(Message message) {        TextMessage textMessage = (TextMessage) message;        try {            System.out.println("接收消息" + textMessage.getText());        } catch (JMSException e) {            e.printStackTrace();        }    }}

队列模式和主题模式的切换在于生产者/发布者通过@Resource所引用的消息,以及消息模式的配置和消息监听器容器所引用的消息模式