一、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)发布订阅模式