消息中间件-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> < ...
随机推荐
- Java设计模式学习笔记(一) 设计模式概述
前言 大约在一年前学习过一段时间的设计模式,但是当时自己的学习方式比较低效,也没有深刻的去理解.运用所学的知识. 所以现在准备系统的再重新学习一遍,写一个关于设计模式的系列博客. 废话不多说,正文开始 ...
- MySql中的SHOW INDEX 查出的结果列代表的意义
MySQL SHOW INDEX语法的实际操作用法以及其实际查看索引状态(语法)的具体内容的描述,如果你对这一技术,心存好奇的话,以下的文章将会揭开它的神秘面纱. INDEX FROM tbl_nam ...
- .Net Core 学习使用Session、和Cookie验证身份
一.使用Session 1.1 Status.cs 中配置 public void ConfigureServices(IServiceCollection services) { services. ...
- windows中实现python,redis服务自动重启(任务计划程序+bat脚本)
需求:银行电脑无法自动开机,只能 通过 应用相关服务每天自动重启的方式实现 服务更新并且防止服务假死,内存过大 等情况 相关工具:win10系统中,使用windows自带的任务计划程序 和 bat脚本 ...
- android布局几点随想
1. 正式布局界面时,先在纸上画出整个布局,并考虑用什么布局比较适合: 2. 布局界面先做出框架,并用不同的背景颜色标记出来,确保大的布局框架式正确的: 3. 接着在每个大的布局框架内布局小的布局: ...
- springboot快速入门02--Controller编写和测试
02springboot快速入门--Controller编写和测试 1.新建一个HelloController import org.springframework.boot.SpringApplic ...
- drop、truncate和delete的区别 [转载]
drop.truncate和delete的区别 本文转载自: https://www.cnblogs.com/zhizhao/p/7825469.html (1)DELETE语句执行删除的过程 ...
- 个人永久性免费-Excel催化剂功能第89波-批量多图片转PDF
前一篇展示了从PDF中提取到有用信息如图片.文本.表格等功能,部分人可能对自己手中的转PDF格式的保护性有所顾虑,此篇从反向角度,提供数据保护作用,让PDF文件的数据保护更彻底,让文本型的PDF文件彻 ...
- mui.storage 将数据持久化到本地
在一个用mui做得app中,要求把历史记录放在本地(感觉...无法言喻的sd),但最终还是做了,以下来记录本次的学习到的内容 mui.plusReady(function() { //这里是一开始定义 ...
- c语言进阶11-算法设计思想
一. 算法设计的要求: 为什么要学算法? /* 输出Hello word! */ #include "stdio.h" void main() { printf("He ...