ActiveMQ快速入门

什么是ActiveMQ:
官方解释如下:
Apache ActiveMQ™是最流行的开源,多协议,基于Java的消息传递服务器。它支持行业标准协议,因此用户可以通过广泛的语言和平台从客户选择中受益。可以使用C,C ++,Python,.Net等进行连接。使用无处不在的AMQP协议集成您的多平台应用程序。在Websocket上使用STOMP在Web应用程序之间交换消息。使用MQTT管理您的IoT设备。支持您现有的JMS基础结构及其他。ActiveMQ提供了强大的功能和灵活性来支持任何消息传递用例。

ActiveMQ能干什么?
它是一种面向消息的中间件,利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型在分布式系统下提供应用解耦流量削峰异步通信,数据同步等功能

大致过程如下:
发送者把消息发送给消息服务器,消息服务器将消息存放在若干队列/主题中,在合适的时候,消息服务器会把消息转发给接受者。在这个过程中,发送和接受都是异步的。

ActiveMQ通讯方式:
1、点对点(queue)
类似QQ私聊,一对一,一个发送者,一个接受者(当然关联QQ的情况比较特殊哈,比如发送者发了一条消息:“今晚他加班,老地方见”,两个人都能收到,不太贴切了哈)
2、一对多(topic)
类似于群聊,微信公众号更贴切一些,只要关注了微信公众号的接受者,都能收到发送者的消息推送

废话不多说,按照JMS编码总体架构进行编码:
在这里插入图片描述
建Maven项目,在pom.xml中引入ActiveMQ依赖

<dependency>
  <groupId>org.apache.activemq</groupId>
  <artifactId>activemq-all</artifactId>
   <version>5.15.9</version>
</dependency>

队列生产者测试代码如下:

public class JmsProduce {
    public static final String  defaultURL = "tcp://192.168.23.128:61616";
    public static final String  QUEUE_NAME="queue";
    public static void main(String[] args) throws JMSException {
        //创建连接工厂   defaultURL = "tcp://" + DEFAULT_BROKER_HOST + ":" + DEFAULT_BROKER_PORT;制定ip+端口
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(defaultURL);
        //通过连接工厂,获得连接并启动
        Connection connection =  activeMQConnectionFactory.createConnection();
        connection.start();
        //创建会话session 第一个参数事务,第二个参数签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地(队列或主题)
        Queue queue = session.createQueue(QUEUE_NAME);
        //创建消息生产者
        MessageProducer producer = session.createProducer(queue);
        //生产五条消息,发送到MQ队列中
        for (int i =1; i <=5 ; i++) {
            TextMessage textMessage = session.createTextMessage("msg----" + i);
            producer.send(textMessage);
        }
        producer.close();
        session.close();
        connection.close();
        System.out.println("---------------消息发布到MQ完成---------------------");
    }
}

执行完成后看前台:
在这里插入图片描述

队列消费者测试代码如下:

public class JmsConsumer {
    public static final String  defaultURL = "tcp://192.168.23.128:61616";
    public static final String  QUEUE_NAME="queue";
    public static void main(String[] args) throws JMSException {
        //创建连接工厂   defaultURL = "tcp://" + DEFAULT_BROKER_HOST + ":" + DEFAULT_BROKER_PORT;制定ip+端口
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(defaultURL);
        //通过连接工厂,获得连接并启动
        Connection connection =  activeMQConnectionFactory.createConnection();
        connection.start();
        //创建会话session 第一个参数事务,第二个参数签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地(队列或主题)
        Queue queue = session.createQueue(QUEUE_NAME);
        //创建消费者
        MessageConsumer consumer = session.createConsumer(queue);
        while(true){
            //receive() 可以设置一个时间参数 
            TextMessage textMessage = (TextMessage) consumer.receive();
            if (textMessage!=null){
                System.out.println("消费者接收到消息----"+textMessage.getText());
            }else {
                break;
            }
        }
        consumer.close();
        session.close();
        connection.close();
    }
}

执行效果:
在这里插入图片描述
执行完成后看前台:
在这里插入图片描述
我们可以看到用receive()同步阻塞阻塞方式,receive方法在能够接收到消息之前或超时之前(设置超时时间)将一直阻塞。
用监听的方式:

public class JmsConsumer {
    public static final String  defaultURL = "tcp://192.168.23.128:61616";
    public static final String  QUEUE_NAME="queue";
    public static void main(String[] args) throws JMSException, IOException {
        //创建连接工厂   defaultURL = "tcp://" + DEFAULT_BROKER_HOST + ":" + DEFAULT_BROKER_PORT;制定ip+端口
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(defaultURL);
        //通过连接工厂,获得连接并启动
        Connection connection =  activeMQConnectionFactory.createConnection();
        connection.start();
        //创建会话session 第一个参数事务,第二个参数签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地(队列或主题)
        Queue queue = session.createQueue(QUEUE_NAME);
        //创建消费者
        MessageConsumer consumer = session.createConsumer(queue);
      //通过监听的方式来消费消息
        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();
    }
}

我们启动两个消费者,生产者发送消息,消费者消费消息默认采用轮询策略
在这里插入图片描述
主题消费者测试代码如下:

public class JmsConsumer_Topic {
    public static final String  defaultURL = "tcp://192.168.23.128:61616";
    public static final String  TOPIC_NAME="topic-test";
    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("我是二号消费者");
        //创建连接工厂   defaultURL = "tcp://" + DEFAULT_BROKER_HOST + ":" + DEFAULT_BROKER_PORT;制定ip+端口
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(defaultURL);
        //通过连接工厂,获得连接并启动
        Connection connection =  activeMQConnectionFactory.createConnection();
        connection.start();
        //创建会话session 第一个参数事务,第二个参数签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地(队列或主题)
        Topic topic = session.createTopic(TOPIC_NAME);
        //创建消费者
        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();
    }
}

主题生产者测试代码如下:

public class JmsProduce_Topic {
    public static final String  defaultURL = "tcp://192.168.23.128:61616";
    public static final String  TOPIC_NAME="topic-test";
    public static void main(String[] args) throws JMSException {
        //创建连接工厂   defaultURL = "tcp://" + DEFAULT_BROKER_HOST + ":" + DEFAULT_BROKER_PORT;制定ip+端口
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(defaultURL);
        //通过连接工厂,获得连接并启动
        Connection connection =  activeMQConnectionFactory.createConnection();
        connection.start();
        //创建会话session 第一个参数事务,第二个参数签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建目的地(队列或主题)
        Topic topic = session.createTopic(TOPIC_NAME);
        //创建消息生产者
        MessageProducer producer = session.createProducer(topic);
        //生产五条消息,发送到MQ队列中
        for (int i =1; i <=6 ; i++) {
            TextMessage textMessage = session.createTextMessage("msg----" + i);
            producer.send(textMessage);
        }
        producer.close();
        session.close();
        connection.close();
        System.out.println("---------------消息发布到MQ完成---------------------");
    }
}

首先要有订阅,微信公众号推送消息才能收到所以先启动两个消费者,然后生产者生产消息推送
在这里插入图片描述idea中启动多个main实例,如下图所示:
在这里插入图片描述
需要多次启动main 打上勾
在这里插入图片描述
现在看到前台显示是这样的
在这里插入图片描述
ActiveMQ整合spring
pom.xml中的部分核心依赖

<!--activemq对jms的支持-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jms</artifactId>
  <version>4.3.23.RELEASE</version>
</dependency>
<!--activemq所需要的的pool包配置-->
<dependency>
  <groupId>org.apache.activemq</groupId>
  <artifactId>activemq-pool</artifactId>
  <version>5.15.9</version>
</dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>4.3.23.RELEASE</version>
  </dependency>

applicationContext.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.aaa.activemq"></context:component-scan>

    <!-- 配置生产者 -->
    <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
          <property name="connectionFactory">
               <bean class="org.apache.activemq.ActiveMQConnectionFactory">
                     <property name="brokerURL" value="tcp://192.168.23.128:61616"/>
               </bean>
          </property>
        <property name="maxConnections" value="100"/>
    </bean>
    <!-- 配置队列目的地  点对点 -->
    <bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg index="0" value="spring-active-queue"/>
    </bean>
    <!-- 配置主题 -->
    <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
               <constructor-arg index="0" value="spring-active-topic"/>
    </bean>
    <!-- spring提供的JMS工具类 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="jmsFactory"/>
        <property name="defaultDestination" ref="destinationQueue"/>
        <property name="messageConverter">
            <bean class="org.springframework.jms.support.converter.SimpleMessageConverter"></bean>
        </property>

    </bean>
    <!-- 配置监听 -->
    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
     <property name="connectionFactory" ref="jmsFactory"/>
     <property name="destination" ref="destinationTopic"/>
     <property name="messageListener" ref="mymessageListener"/>
   </bean>
</beans>

队列生产者测试类

@Service
public class SpringMQ_Produce {
    @Autowired
    private JmsTemplate jmsTemplate;

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SpringMQ_Produce produce = (SpringMQ_Produce)ctx.getBean("springMQ_Produce");
        produce.jmsTemplate.send((session) -> {
            TextMessage texemsg = session.createTextMessage("spring整合");
            return texemsg;
        });
        System.out.println("---------------消息发布到MQ完成---------------------");
    }
}

前台显示没有问题:
在这里插入图片描述
队列消费者测试类:

@Service
public class SpringMQ_Consumer {
    @Autowired
    private JmsTemplate jmsTemplate;

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SpringMQ_Consumer consumer = (SpringMQ_Consumer)ctx.getBean("springMQ_Consumer");
        String  value = (String) consumer.jmsTemplate.receiveAndConvert();
        System.out.println("---------------收到的消息---------------------"+value);
    }
}

运行结果:
在这里插入图片描述
前台也没有问题
在这里插入图片描述
topic的话要把applicationContext.xml中目的地改为topic即可,代码不变 即:

 <property name="defaultDestination" ref="destinationTopic"/>

也可以使用监听的方式,applicationContext.xml中的监听配置
首先需要一个配置类:

@Component
public class MymessageListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        if(message!=null && message instanceof TextMessage){
            TextMessage textMessage = (TextMessage) message;
            try {
                System.out.println(textMessage.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

这时只需启动生产者即可
在这里插入图片描述
SpringBoot整合ActiveMQ
pom.xml添加主要依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-activemq</artifactId>
  <version>2.1.5.RELEASE</version>
</dependency>

application.yml

server:
  port: 8888

spring:
  activemq:
    broker-url: tcp://192.168.23.128:61616
    user: admin
    password: admin
  jms:
    pub-sub-domain: false    #false=Queue  true=Topic  默认false

myqueue: boot-active-queue

配置类:

@Component
@EnableJms
public class ConfigBean {
    @Value("${myqueue}")
    private String myQueue;

    public ActiveMQQueue queue(){
        return new ActiveMQQueue(myQueue);
    }
}

队列生产者测试类:

@Component
public class Queue_Produce {
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;
    @Autowired
    private Queue queue;

    public void produceMsg(){
        jmsMessagingTemplate.convertAndSend(queue,"*******"+ UUID.randomUUID().toString().substring(0,3));
    }
}

队列消费者测试

@Component
public class Queue_Consumer {
    @JmsListener(destination = "${myqueue}")
    public void receive(TextMessage textMessage) throws JMSException {
        System.out.println("消费者受到消息"+textMessage.getText());
    }
}

主题生产者消费者的代码差不太多,这里就不一一贴出来了

注意, pub-sub-domain改为true

ActiveMQ持久化

activemq默认持久化方式为kahadb,今天介绍jdbc持久化方式
将jdbc驱动包放在activemq安装目录lib文件夹下
在这里插入图片描述
进入conf文件夹编辑activemq.xml,替换默认持久化方式
将默认的

 <persistenceAdapter>
            <kahaDB directory="${activemq.data}/kahadb"/>
 </persistenceAdapter>

替换为:

 <persistenceAdapter>
                <jdbcPersistenceAdapter  dataSource="#mysql"/>
 </persistenceAdapter>

在这里插入图片描述
参照官网修改连接配置
在这里插入图片描述
修改activemq.xml

<bean id="mysql" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.1.7/activemq?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="poolPreparedStatements" value="true"/>
</bean>

在这里插入图片描述

注意,现在使用的数据库连接池是默认的,如果改为c3p0等,需要提供相应的Jar包,这段配置写在broker闭合标签和import标签之间

重启activemq之后,会在activemq数据库里新建三张表
activemq_msgs用于存储消息,Queue和Topic都存储在这个表中
activemq_acks用于存储订阅关系
表activemq_lock在集群环境中才有用,只有一个Broker可以获得消息,称为Master Broker

这里注意,不开启持久化,生产消息不会存储到activemq_msgs表中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值