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编码总体架构进行编码:
ActiveMQ快速入门_第1张图片
建Maven项目,在pom.xml中引入ActiveMQ依赖


  org.apache.activemq
  activemq-all
   5.15.9

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

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完成---------------------");
    }
}

执行完成后看前台:
ActiveMQ快速入门_第2张图片

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

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();
    }
}

执行效果:
ActiveMQ快速入门_第3张图片
执行完成后看前台:
ActiveMQ快速入门_第4张图片
我们可以看到用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();
    }
}

我们启动两个消费者,生产者发送消息,消费者消费消息默认采用轮询策略
ActiveMQ快速入门_第5张图片
主题消费者测试代码如下:

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完成---------------------");
    }
}

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



  org.springframework
  spring-jms
  4.3.23.RELEASE



  org.apache.activemq
  activemq-pool
  5.15.9

  
      org.springframework
      spring-core
      4.3.23.RELEASE
  

applicationContext.xml如下:



    
    

    
    
          
               
                     
               
          
        
    
    
    
        
    
    
    
               
    
    
    
        
        
        
            
        

    
    
    
     
     
     
   

队列生产者测试类

@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);
    }
}

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

 

也可以使用监听的方式,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();
            }
        }
    }
}

这时只需启动生产者即可
ActiveMQ快速入门_第10张图片
SpringBoot整合ActiveMQ
pom.xml添加主要依赖


  org.springframework.boot
  spring-boot-starter-parent
  2.1.5.RELEASE


  org.springframework.boot
  spring-boot-starter-activemq
  2.1.5.RELEASE

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文件夹下
ActiveMQ快速入门_第11张图片
进入conf文件夹编辑activemq.xml,替换默认持久化方式
将默认的

 
            
 

替换为:

 
                
 

ActiveMQ快速入门_第12张图片
参照官网修改连接配置
ActiveMQ快速入门_第13张图片
修改activemq.xml








ActiveMQ快速入门_第14张图片

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

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

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

你可能感兴趣的:(java)