springboot2.x简单详细教程--消息队列介绍及整合ActiveMQ (第十三章)

一、JMS介绍和使用场景及基础编程模型


    简介:讲解什么是小写队列,JMS的基础知识和使用场景
    1、什么是JMS: Java消息服务(Java Message Service),Java平台中关于面向消息中间件的接口

    2、JMS是一种与厂商无关的 API,用来访问消息收发系统消息,它类似于JDBC(Java Database Connectivity)。这里,JDBC 是可以用来访问许多不同关系数据库的 API

    3、使用场景:

        1)跨平台 

        2)多语言 

        3)多项目

        4)解耦

        5)分布式事务(业务涉及多个表比如:转账

        6)流量控制(访问量)
        7)最终一致性
        8)RPC调用
            上下游对接,数据源变动->通知下属

4.案例分析

1)网购支付流程:不用消息中间件服务(使用用户流量少的情况

2)当用户非常多的时候显然我们的支付网关容易崩溃,同时支付网关之后的系统等待时间可能过长,所以需要用到消息服务

分析:支付网关将信息放到消息服务之后不需要等待积分或是订单系统的执行提高了系统的并发性和承受的流量(积分订单系统订阅消息

5、概念    
        JMS提供者:Apache ActiveMQ、RabbitMQ、Kafka、Notify、MetaQ、RocketMQ
        JMS生产者(Message Producer)
        JMS消费者(Message Consumer)
        JMS消息
        JMS队列
        JMS主题

        JMS消息通常有两种类型:点对点(Point-to-Point)、发布/订阅(Publish/Subscribe)

3)消息点对点类型(单个系统

4)发布/订阅(Publish/Subscribe)

微信支付就是这种模式


   6、编程模型
        MQ中需要用的一些类
        ConnectionFactory :连接工厂,JMS 用它创建连接
        Connection :JMS 客户端到JMS Provider 的连接
        Session: 一个发送或接收消息的线程
        Destination :消息的目的地;消息发送给谁.
        MessageConsumer / MessageProducer: 消息接收者,消费者

二、ActiveMQ5.x消息队列基础介绍和安装
    


    简介:介绍ActiveMQ5.x消息队列基础特性和本地快速安装
        特点:
            1)支持来自Java,C,C ++,C#,Ruby,Perl,Python,PHP的各种跨语言客户端和协议
            2)支持许多高级功能,如消息组,虚拟目标,通配符和复合目标
            3) 完全支持JMS 1.1和J2EE 1.4,支持瞬态,持久,事务和XA消息
            4) Spring支持,ActiveMQ可以轻松嵌入到Spring应用程序中,并使用Spring的XML配置机制进行配置
            5) 支持在流行的J2EE服务器(如TomEE,Geronimo,JBoss,GlassFish和WebLogic)中进行测试
            6) 使用JDBC和高性能日志支持非常快速的持久化(重要消息放到mysql或是日志作为备份
            ...

        1、下载地址:http://activemq.apache.org/activemq-5153-release.html


        2、快速开始:http://activemq.apache.org/getting-started.html
        3、如果我们是32位的机器,就双击win32目录下的activemq.bat,如果是64位机器,则双击win64目录下的activemq.bat
        4、bin目录里面启动 选择对应的系统版本和位数,activeMQ start 启动


        5、启动后访问路径http:// 127.0.0.1:8161/

          127.0.0.1是activeMq安装的服务器,默认端口号8161

  

 

        6、用户名和密码默认都是admin验证这是消息服务的保护措施

登入后的页面:ActiveMQ控制台

1)Home | Queues | Topics | Subscribers | Connections | Network | Scheduled | Send
Support

主页| 队列| 主题| 订阅者| 连接| 网络| 预定| 发送
支持

2)Queues创建

    面板说明:    
        Name:队列名称。
        Number Of Pending Messages:等待消费的消息个数。
        Number Of Consumers:当前连接的消费者数目
        Messages Enqueued:进入队列的消息总个数,包括出队列的和待消费的,这个数量只增不减。
        Messages Dequeued:已经消费的消息数量。

3)向消息队列发送消息

结果


        7、官方案例集合
            https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples
    


三、SpringBoot2.x整合ActiveMQ实战之点对点消息(p2p)
   消息 消费者和消息生产者可以在一个工程也可以在不同的工程


    简介:SpringBoot2.x整合ActiveMQ实战之点对点消息

    1、官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-activemq

    2、加入依赖
        <!-- 整合消息队列ActiveMQ -->
     

        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-activemq</artifactId>  
        </dependency>  
        
        <!-- 如果配置线程池则加入 -->
        <dependency>  
            <groupId>org.apache.activemq</groupId>  
            <artifactId>activemq-pool</artifactId>  
        </dependency>

     3、application.properties配置文件配置
     

#整合jms测试,安装在别的机器,防火墙和端口号记得开放
spring.activemq.broker-url=tcp://127.0.0.1:61616
#集群配置,61616:开启对外连接的默认端口号
#spring.activemq.broker-url=failover:(tcp://localhost:61616,tcp://localhost:61617)

spring.activemq.user=admin
spring.activemq.password=admin
#下列配置要增加依赖:消息队列连接池 max-connections,50,100,500根据需要写
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=100

      4、springboot启动类 @EnableJms,开启支持jms

1)service接口

package com.itcast.demo.service;

import javax.jms.Destination;

/**
 * 
* <p>Title: ProducerService</p>  
* <p>Description: </p>  
* @author shenlan  
* @date 2018年11月4日
 */

public interface ProducerService {
    /**
     * 指定消息队列还有消息
     * @param destination
     * @param message
     */
	public void sendMessage(Destination destination,final String message );
	/**
	 * 
	 * 使用默认消息队列发送消息
	 * @param message
	 */
	public void sendMessage(final String message );
}

    2)实现

package com.itcast.demo.service.impl;

import javax.jms.Destination;
import javax.jms.Queue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

import com.itcast.demo.service.ProducerService;


@Service
public class ProducerServiceImpl implements ProducerService{
	 //用来发送消息到broker的对象
	@Autowired
   private JmsMessagingTemplate jmsTemplate ;
	
	@Autowired
	private Queue queue;//程序入口有了
	//发送消息,destination是发送到的队列,message是待发送的消息
	@Override
	public void sendMessage(Destination destination, String message) {
		jmsTemplate.convertAndSend(destination,message);
		
	}

	//发送消息,destination是发送到的队列,message是待发送的消息
	@Override
	public void sendMessage(String message) {
		jmsTemplate.convertAndSend(this.queue,message);
	}

}

3)controller

package com.itcast.demo.controller;

import javax.jms.Destination;


import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.itcast.demo.domain.JsonData;
import com.itcast.demo.service.ProducerService;

/**
 * 功能描述:模拟微信支付回调
 *
 *
 *@作者 llj  小D
 */
@RestController
@RequestMapping("/api/v1")
public class OrderController {
	
	@Autowired
	private ProducerService producerService;
	/**
	 * 功能描述:微信支付回调接口
	 * @param msg 支付信息
	 * @return
	 */
	@GetMapping("order")
	public Object order(String msg){//实际开发msg是html需要document解析
		
		Destination destination = new ActiveMQQueue("order.queue");
		
		producerService.sendMessage(destination, msg);
	
       return JsonData.buildSuccess();
	}
	
	
	
	@GetMapping("common")
	public Object common(String msg){
		producerService.sendMessage(msg);	
       return JsonData.buildSuccess();
	}
	
	
	
	
}

 4)控制台创建队列

5)启动工程访问

6)刷新

7)再发送

消息变成两条

     5、消费者:实时监听对应的队列()
          @JmsListener(destination = "order.queue")
     1)     建立一个jms包下面建立OrderConsumer 类

package com.itcast.demo.jms;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component  //spring可以扫描
public class OrderConsumer {
    /**
     * 
     * @JmsListener监听order.queue队列有没有消息进来
     * @param text
     */
	@JmsListener(destination="order.queue")
	public void receiveQueue(String text){
		System.out.println("OrderConsumer收到的报文为:"+text);
	}
}

2)启动工程之前写的报文都收到了

3)刷新控制台

4)再添加消息

6.测一下默认的队列comment.queue

1)和OrderConsumer 类一样

package com.itcast.demo.jms;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class CommonConsumer {
    
	@JmsListener(destination="comment.queue")
	public void receiveQueue(String text){
		System.out.println("CommonConsumer收到的报文为:"+text);
	}
	
}

2)

3)

四、SpringBoot整合ActiveMQ实战之发布订阅模式(pub/sub)


    简介:SpringBoot整合ActiveMQ实战之发布订阅模式(pub/sub),及同时支持点对点和发布订阅模型

        1、需要加入配置文件,支持发布订阅模型,默认只支持点对点
            #default point to point
            spring.jms.pub-sub-domain=true

    注意点:
        
        1、默认消费者并不会消费订阅发布类型的消息,这是由于springboot默认采用的是p2p模式进行消息的监听
           1) 修改配置:spring.jms.pub-sub-domain=true
         2)在程序入口处加入topic对象,好处是启动程序new 一次可以多次使用

package com.itcast.demo;

import javax.jms.Queue;
import javax.jms.Topic;
import javax.servlet.MultipartConfigElement;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableJms
public class Application {
	//交个spring进行管理,方便后续进行注入
    @Bean
	public Queue queue(){
		return new ActiveMQQueue("comment.queue");
	}
   //主题对象交给spring管理
    @Bean
   	public Topic topic(){
   		return new ActiveMQTopic("video.topic");
   	}
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
	
}

    3)ProducerService接口添加如下代码

    /**
	 * 
	 * 消息发布者
	 * @param message
	 */
	public void publish(String msg) ;

  4)实现类ProducerServiceImpl

    //=======发布订阅相关代码=========
	
	@Autowired
	private Topic topic;
	
	 @Override
	public void publish(String msg) {
		this.jmsTemplate.convertAndSend(this.topic, msg);
		
	}

5)controller

    @GetMapping("topic")
	public Object topic(String msg){
		producerService.publish(msg);
       return JsonData.buildSuccess();
	}
	

6)启动程序,访问

7)

8)TopicSub  :模拟一个订阅者

package com.itcast.demo.jms;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class OrderConsumer {
    /**
     * 
     * @JmsListener监听order.queue队列有没有消息进来
     * @param text
     */
	@JmsListener(destination="order.queue")
	public void receiveQueue(String text){
		System.out.println("OrderConsumer收到的报文为:"+text);
	}
}

9)启动访问



控制台

10)模拟三个订阅者

package com.itcast.demo.jms;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class TopicSub {
    //模拟出三个订阅者
	
	@JmsListener(destination="video.topic")
	public void receive1(String text){
		System.out.println("video.topic 消费者:receive1="+text);
	}
	
	
	@JmsListener(destination="video.topic")
	public void receive2(String text){
		System.out.println("video.topic 消费者:receive2="+text);
	}
	@JmsListener(destination="video.topic")
	public void receive3(String text){
		System.out.println("video topic 消费者:receive3="+text);
	}
	
	
}

 11)访问

12)此时存在一个问题:点对点模式没有生效

我们测点对点时,并没有消费者

 

13)@JmsListener如果不指定独立的containerFactory的话是只能消费queue消息
       也就是只支持一种模式

 

            //需要给topic定义独立的JmsListenerContainer
            

          a)  在配置文件里面,注释掉 #spring.jms.pub-sub-domain=true

         b)在程序入口加入

@Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory   activeMQConnectionFactory) {
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setPubSubDomain(true);//支持订阅模式
        bean.setConnectionFactory(activeMQConnectionFactory);
        return bean;
    }

c)   修改订阅者container:containerFactory="jmsListenerContainerTopic"

package com.itcast.demo.jms;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class TopicSub {
    //模拟出三个订阅者
	
	@JmsListener(destination="video.topic",containerFactory="jmsListenerContainerTopic")
	public void receive1(String text){
		System.out.println("video.topic 消费者:receive1="+text);
	}
	
	
	@JmsListener(destination="video.topic",containerFactory="jmsListenerContainerTopic")
	public void receive2(String text){
		System.out.println("video.topic 消费者:receive2="+text);
	}
	@JmsListener(destination="video.topic",containerFactory="jmsListenerContainerTopic")
	public void receive3(String text){
		System.out.println("video topic 消费者:receive3="+text);
	}
	
	
}

14)order点对点模式,

15)发布订阅模式


 

猜你喜欢

转载自blog.csdn.net/jianchilu/article/details/83715238