消息中间件-activemq入门(二)
上一节我们了解了JMS规范并且知道了JMS规范的良好实现者-activemq。今天我们就去了解一下activemq的使用。另外我们应该抱着目的去学习,别忘了我们为什么要使用消息中间件:解耦系统之间的联系,同步或异步的消息传输,尤其是异步的消息传输,分布式环境下,可靠、高效的消息传输,可以保证消息的重发性和顺序性。即解决业务系统比较多或者是分布式环境下的系统之间安全有效通信的问题,带着这样的目的我们来学习消息中间件就有了方向。
1. 为什么用activemq
在设计分布式应用程序时,应用程序间的耦合(或称集成)方式很重要。耦合意味着两个或者多个应用程序或系统的相互依赖关系。一种简单的方式是在所有的应用程序中从架构上设计他们与其他应用程序间的交叉实现。这样必然导致,一个应用程序的改变,直接导致另一个应用程序的改变。
ActiveMQ采用松耦合方式,应用程序将消息发送给ActiveMQ而并不关心什么时间以何种方式消息投递给接收者。同样的,消息接收者也不会关心消息来源于哪里和消息是怎样投递给ActiveMQ的。对于多语言编写的复杂应用环境中,允许客户端使用不同的编程语言甚至不同的消息包装协议。ActiveMQ作为消息的中间件,允许复杂的多语言应用程序以一种一步的方式集成和交互。所以说,ActiveMQ是一种好的,提供松散耦合的,能够为多语言交叉应用提供集成的中间件。
2. 什么时候用activemq
ActiveMQ的设计目标是提供标准的,面向消息的,能够跨越多语言和多系统的应用集成消息通信中间件。大多数情况下ActiveMQ被用于做系统之间的数据交换。
只要是两个应用程序间需要通信的情况,都可以考虑使用JMS,不论这种通信是在本地的(就是通信的两个应用程序在同一台主机上),还是分布在不同机器上。尽管是在同一个主机上的两个应用程序需要通信也可以使用ActiveMQ。ActiveMQ可以确保消息投递成功并采用异步方式通信。
3. activemq特性
支持JMS规范:ActiveMQ完全实现了JMS1.1规范。
连接方式的多样化:ActiveMQ提供了广泛的连接模式,包括HTTP/S、JGroups、JXTA、muticast、SSL、TCP、UDP、XMPP等。提供了如此多的连接模式表明了ActiveMQ具有较高的灵活性。
与其他的Java容器紧密集成:ActiveMQ提供了和其它流行的Java容器的结合,包括Apache Geronimo、Apache Tomcat、JBoss、Jetty等。
客户端API:ActiveMQ提供了多种客户端可访问的API,包括Java、C/C++,.NET,Perl、PHP、Python、Ruby等。当然,ActiveMQ中介必须运行在Java虚拟机中,但是使用它的客户端可以使用其他的语言来实现。
中介集群:多个ActiveMQ中介可以一起协同工作,来完成某项复杂的工作,这被称为网络型中介(network of brokers),这种类型的中介将会支持多种拓扑类型。
4. 使用activemq
首先我们去apache上下载activemq,点此下载。
接下来我是使用maven来管理jar的,如果你不用maven的话就去刚下载的activemq包中找到jar包导入即可。maven引入jar:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.14.5</version>
</dependency>
然后我们进入刚下载的activemq,我进入的路径如下:apache-activemq-5.14.5-bin\apache-activemq-5.14.5\bin\win64\activemq.bat
,我用的是64位的系统,如果你是32位的同理进入相应文件夹下点击activemq.bat启动activemq客户端,启动完成之后,直接访问ActiveMQ管理页面http://localhost:8161/admin/ 默认用户名密码admin/admin。
客户端界面如下:

接下来该我们写代码的时候了,首先我们还是先写一个P2P(点对点)模式的客户端。代码如下:
Sender.java
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Sender {
public static void main(String[] args) {
//ConnectionFactory是连接工厂,JMS用它创建连接
ConnectionFactory connectionFactory;
//Connection JMS客户端到JMS provider的连接
Connection connection = null;
//Session 一个发送或者接收消息的线程
Session session;
//Destination 消息发送目的地,消息发送给谁接收
Destination destination;
//MessageProducer 消息发送者
MessageProducer messageProducer;
//构造ConnectionFactory 实例对象,此处采用ActiveMQ的实现jar
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
//构造工厂得到连接对象
connection = connectionFactory.createConnection();
//启动
connection.start();
//获取操作连接
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//创建一个Queue,名称为FirstQueue
destination = session.createQueue("FirstQueue");
//得到消息生产者【发送者】
messageProducer = session.createProducer(destination);
//设置不持久化,根据实际情况而定
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//创建一个消息对象
TextMessage message = session.createTextMessage();
//把我们的消息写入msg对象中
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
while(true) {
System.out.println("Enter Msg, end to terminate:");
String s=b.readLine();
if (s.equals("end"))
break;
message.setText(s);
//发送消息
messageProducer.send(message);
System.out.println("Message successfully sent.");
}
session.commit();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(null != connection){
connection.close();
}
} catch (Throwable ignore) {
}
}
}
}
Receiver.java
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Receiver {
public static void main(String[] args) {
//connectionFactory 连接工厂,JMS用它创建连接
ConnectionFactory connectionFactory;
//connection JMS客户端到JMS provider 的连接
Connection connection = null;
//session一个发送或者接收的线程
Session session;
//destination 消息目的地,发送给谁接收
Destination destination;
//消费者消息接收者
MessageConsumer consumer;
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
//构造工厂得到连接对象
connection = connectionFactory.createConnection();
//启动
connection.start();
//获取操作连接
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("FirstQueue");
consumer = session.createConsumer(destination);
while(true){
//设置接收者收消息的时间,为了方便测试,这里暂定设置为100s
TextMessage message = (TextMessage)consumer.receive(100);
if(null != message){
System.out.println("收到消息==="+message.getText());
}else{
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(null != connection){
connection.close();
}
} catch (Throwable ignore) {
}
}
}
}
代码已经注释过了,就不多做解释,接着我们先运行Sender,需要你在控制台输入你要发送的消息,当你输入”end”的时候才会结束输入,否则你每一次输入按回车都是发送一条消息。然后去看一下activemq的控制台,点击一下菜单栏上的Queues:

因为我刚发送了两条消息在这里会显示,消息会由activemq这个中间人统一管理,当接受者需要接受消息的时候,他会来请求activemq,从这里获取消息而不是发送端一直等着接收端。
下面你可以运行一下Receiver,这时候就把刚才这两条消息消费了。消息队列此刻就是空的。之所以强调这一点是为了和接下来的 发布/订阅 模式做一个比较,限于篇幅我就不截图了,大家可以尝试。
下面我们接着写一个Pub/Sub模式的例子,并没有多大的变化,在创建消息队列的时候改为topic模式:
TopicSender.java
import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* Created by Administrator on 2017/4/25.
*/
public class TopicSender {
public static void main(String[] args) {
//ConnectionFactory是连接工厂,JMS用它创建连接
ConnectionFactory connectionFactory;
//Connection JMS客户端到JMS provider的连接
Connection connection = null;
//Session 一个发送或者接收消息的线程
Session session;
//Destination 消息发送目的地,消息发送给谁接收
Topic destination;
//MessageProducer 消息发送者
MessageProducer messageProducer;
//构造ConnectionFactory 实例对象,此处采用ActiveMQ的实现jar
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
//构造工厂得到连接对象
connection = connectionFactory.createConnection();
//启动
connection.start();
//获取操作连接
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//创建一个Queue,SecondQueue 此处使用的是Topic模式
destination = session.createTopic("SecondQueue");
//得到消息生产者【发送者】
messageProducer = session.createProducer(destination);
//设置不持久化,根据实际情况而定
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//创建一个消息对象
TextMessage message = session.createTextMessage();
//把我们的消息写入msg对象中
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
message.setText("你好");
//发送消息
messageProducer.send(message);
System.out.println("Message successfully sent.");
session.commit();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(null != connection){
connection.close();
}
} catch (Throwable ignore) {
}
}
}
}
同理接受方也是如此:
TopicReciever.java
public class TopicReciever {
public static void main(String[] args) {
//connectionFactory 连接工厂,JMS用它创建连接
ConnectionFactory connectionFactory;
//connection JMS客户端到JMS provider 的连接
Connection connection = null;
//session一个发送或者接收的线程
final Session session;
//destination 消息目的地,发送给谁接收 这里注意改成Topic类型的
Topic destination;
//消费者消息接收者
final MessageConsumer consumer;
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
//构造工厂得到连接对象
connection = connectionFactory.createConnection();
//启动
connection.start();
//获取操作连接
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//此处使用的是Topic模式
destination = session.createTopic("SecondQueue");
consumer = session.createConsumer(destination);
while(true){
//设置接收者收消息的时间
TextMessage message = (TextMessage)consumer.receive(10000);
if(null != message){
System.out.println("收到消息==="+message.getText());
}else{
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里我们可以把Reciever同样的代码再复制一份Reciever1,然后我们先把两个接收端启动,再启动发送端,这时候我们发现消息被接受到了;但是如果我们先启动发送端再启动接收端,这时候虽然消息是被发送出去了,但是接收端并未收到,这是为什么呢?这就是我前面在讲P2P模式的时候留下的一个对比点:
P2P模式是1V1的,我发送只对当前声明的这个标识,接受者也只接受该标识所对应的消息。一旦接受者获取该消息,该标识对应的消息即从消息队列中移除;
Pub/Sub模式是1 V N 的,1个发送端发出的消息,可以有多个接收端去消费,但是有一个前提:想消费这条消息的接收端必须先注册,即先启动接收端去activemq的客户端注册,发送端就根据注册的情况主动把消息推送到订阅过该消息的消费者。
我们看到消息队列里面有一条消息,然后有两位消费者来订阅这一条消息,上面我们看到两个消费者分别取队列取一次消息,然后activemq会创建两个临时生产者去他们服务把消息给他们。
好拉,这一节的入门知识就讲到这里,既然是入门我们就不必太深刻,不然适得其反啊!哈哈。下面开始我们就详细的探讨activemq的一些特性以及消息中间件在集群环境中的应用。
消息中间件-activemq入门(二)的更多相关文章
- Java消息中间件----ActiveMQ入门①
一 首先到ActiveMQ下载安装包 Active官网地址http://activemq.apache.org/activemq-5150-release.html 如图所示,有两个下载的链接,我们下 ...
- 消息中间件-ActiveMQ入门实例
1.下载ActiveMQ: http://activemq.apache.org/download-archives.html 2.运行ActiveMQ 解压缩apache-activemq-5.5. ...
- 深入浅出 JMS(二) - ActiveMQ 入门指南
深入浅出 JMS(二) - ActiveMQ 入门指南 上篇博文深入浅出 JMS(一) – JMS 基本概念,我们介绍了消息通信的规范JMS,这篇博文介绍一款开源的 JMS 具体实现-- Active ...
- ActiveMQ入门系列二:入门代码实例(点对点模式)
在上一篇<ActiveMQ入门系列一:认识并安装ActiveMQ(Windows下)>中,大致介绍了ActiveMQ和一些概念,并下载.安装.启动他,还访问了他的控制台页面. 这篇,就用代 ...
- ActiveMQ之一--ActiveMQ入门
MQ的消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息,而另一端则可以读取或者订阅队列中的消息.MQ和JMS类似,但不同的是JMS是SUN JAVA消息中间件服务的一个标准和API定义 ...
- 关于消息中间件ActiveMQ的企业级应用
几个月前看到项目中配置了activeMq,于是想通透的掌握activeMq,便去网上学习搜寻资料,找到这一篇博客挺不错的,解释的比较清楚,包括原理使用和配置,特此把它分享给大家. 众所周知,消息中间件 ...
- ActiveMQ入门练习
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久 ...
- 消息中间件ActiveMQ使用详解
消息中间件ActiveMQ使用详解 一.消息中间件的介绍 介绍 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数据交流,并基于 数据通信 来进行分布式系统的集成. 特点(作用) ...
- ActiveMQ 入门和与 Spring 整合
ActiveMQ 入门演示 activemq 依赖 <dependency> <groupId>org.apache.activemq</groupId> < ...
随机推荐
- Linux 运行jar包命令(Cent OS 7后台运行jar包)
Linux 运行jar包命令如下: 方式一 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 java -jar shareniu. ...
- HDU 4819:Mosaic(线段树套线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=4819 题意:给出一个矩阵,然后q个询问,每个询问有a,b,c,代表(a,b)这个点上下左右c/2的矩形区域内的( ...
- ifream子页面与父页面互调
function a1(x){ alert('父页面:' + x); } function acc(){ var frames = document.getElementById("dial ...
- 花5分钟时间来了解一下高性能网关Kong会有意外收获
前言 前几天开源发布了 Kong.Net 项目,收到了大量园友的反馈,开源当天就突破了 100 个star ,可喜可贺,但是从侧面也说明,我们 .NetCore 阵营真的非常需要拥抱开源,应该敞开心扉 ...
- mybatis-generator生成数据表中注释
0.git clone https://github.com/backkoms/mybatis-generator-comments.git,编译打包,install到本地或delopy私服库中均可. ...
- 基于webpack4+vue-cli3项目的换肤功能
起因 最近因公司需求,需要实现主题换肤功能,不仅仅是颜色的更改,还需要包括图片,字体等文件等更换,因此在百度里各种实现方案后,决定根据scss+style-loader/useable做换肤. 项目开 ...
- Java 源码学习系列(三)——Integer
Integer 类在对象中包装了一个基本类型 int 的值.Integer 类型的对象包含一个 int 类型的字段. 此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还 ...
- 重新认识 async/await 语法糖
提起.Net中的 async/await,相信很多.neter 第一反应都会是异步编程,其本质是语法糖,但继续追查下去,既然是语法糖,那么经过编译之后,真正的代码是什么样的,如何执行的?带着这些疑问, ...
- ASP.NET MVC ActionFilterAttribute 方法解释(区别)
1.OnActionExecuting 在Action方法调用前使用,使用场景:如何验证登录等. 2.OnActionExecuted 在Action方法调用后,result方 ...
- 个人永久性免费-Excel催化剂功能第50波-批量打印、导出PDF、双面打印功能
在倡导无纸化办公的今天,是否打印是一个碍眼的功能呢,某些时候的确是,但对于数据的留存,在现在鼓吹区块链技术的今天,仍然不失它的核心价值,数据报表.单据打印出来留存,仍然是一种不可或缺的数据存档和防篡改 ...