上一节我们了解了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入门(二)的更多相关文章

  1. Java消息中间件----ActiveMQ入门①

    一 首先到ActiveMQ下载安装包 Active官网地址http://activemq.apache.org/activemq-5150-release.html 如图所示,有两个下载的链接,我们下 ...

  2. 消息中间件-ActiveMQ入门实例

    1.下载ActiveMQ: http://activemq.apache.org/download-archives.html 2.运行ActiveMQ 解压缩apache-activemq-5.5. ...

  3. 深入浅出 JMS(二) - ActiveMQ 入门指南

    深入浅出 JMS(二) - ActiveMQ 入门指南 上篇博文深入浅出 JMS(一) – JMS 基本概念,我们介绍了消息通信的规范JMS,这篇博文介绍一款开源的 JMS 具体实现-- Active ...

  4. ActiveMQ入门系列二:入门代码实例(点对点模式)

    在上一篇<ActiveMQ入门系列一:认识并安装ActiveMQ(Windows下)>中,大致介绍了ActiveMQ和一些概念,并下载.安装.启动他,还访问了他的控制台页面. 这篇,就用代 ...

  5. ActiveMQ之一--ActiveMQ入门

    MQ的消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息,而另一端则可以读取或者订阅队列中的消息.MQ和JMS类似,但不同的是JMS是SUN JAVA消息中间件服务的一个标准和API定义 ...

  6. 关于消息中间件ActiveMQ的企业级应用

    几个月前看到项目中配置了activeMq,于是想通透的掌握activeMq,便去网上学习搜寻资料,找到这一篇博客挺不错的,解释的比较清楚,包括原理使用和配置,特此把它分享给大家. 众所周知,消息中间件 ...

  7. ActiveMQ入门练习

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久 ...

  8. 消息中间件ActiveMQ使用详解

    消息中间件ActiveMQ使用详解 一.消息中间件的介绍 介绍 ​ 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数据交流,并基于 数据通信 来进行分布式系统的集成. 特点(作用) ...

  9. ActiveMQ 入门和与 Spring 整合

    ActiveMQ 入门演示 activemq 依赖 <dependency> <groupId>org.apache.activemq</groupId> < ...

随机推荐

  1. Vue技术点整理-Vue CLI安装详解

     一,脚手架安装 Node 版本要求 Vue CLI 需要 Node.js +).你可以使用 nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本. 1,全局安装Vue CLI ...

  2. 深入学习Spring框架(二)- 注解配置

    1.为什么要学习Spring的注解配置? 基于注解配置的方式也已经逐渐代替xml.所以我们必须要掌握使用注解的方式配置Spring. 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯 ...

  3. Easy doesn't enter into grown-up life

    Hi xinlu, good afternoon, my name is xx, you can also call me andrew. i'm 31 years old, and i'm from ...

  4. ZigBee按键中断

    何为按键中断? 在了解按键中断之前,我们先来了解一下什么是中断?中断就是程序执行当前代码,当前任务的时候: 突然有自身函数或外部的影响,而使程序执行到别的任务再回来. 举个栗子: 当你在做饭的时候,电 ...

  5. .Net项目中NLog的配置与使用

    引言: 因为之前在项目开发中一直都是使用的Log4Net作为项目的日志记录框架,最近忽然感觉对它已经有点腻了,所以尝试着使用了NLog作为新项目的日志记录框架(当然作为一名有志向的攻城狮永远都不能只局 ...

  6. c++学习书籍推荐《The C++ Programming Language第四版》下载

    百度云及其他网盘下载地址:点我 作者简介 Bjarne Stroustrup is the designer and original implementer of C++, the author o ...

  7. centos7 添加用户,组

    centos7添加用户,组. groupadd projectUsers //添加组,组名projectUser. cat /etc/group //查看最后一行是projectUser. 添加用户并 ...

  8. Your project specifies TypeScriptToolsVersion 2.3, but a matching compiler ...... 出现这种警告解决方式

  9. Android基础知识复习之打开照相机拍照并获取照片

    对于我来说,做一件事情: 首先要理清我的思路,我要打开照相机,我能想到的是:在Android中我要打开系统应用,肯定需要一个隐式意图,那就要查询Android照相机的源码,查看并找到意图过滤器的书写方 ...

  10. php laravel5.6引入geetest 行为验证

    php laravel5.6引入geetest 行为验证 使用必要性 网站和APP,在所有可能被机器行为攻击的场景,例如但不限于注册.登录.短信接口.查询接口.营销活动.发帖评论等等,都可以部署使用「 ...