JMS基础篇(二)
简介
异构集成是消息发挥作用的一个领域,大型公司内部可能会遇到很多的平台,Java,.net或者公司自己的平台等。
传送消息还应该支持异步机制,以提高系统整体的性能。异步传输一条消息意味着,发送者不必等到接收者接收或者处理消息,可以接着做后续的处理。
应用程序发送消息至另外一个应用程序,需要使用到消息中间件。消息中间件应提供容错,负载均衡,可伸缩的事务性等特性。
JMS与JDBC类似,是一种与厂商无关的API。应用程序开发者可以使用同样的API来访问不同的系统。
可以认为JMS是一种标准,各消息中间件(MOM)是JMS的具体实现。常见的MOM包括WebSphere MQ,Sonic MQ,ActiveMQ等。
JMS系统机构
消息传递系统可以分为集中式和分散式两种。
集中式的消息系统依赖于一个消息服务器,或者称为消息路由器或者代理(broker)来进行消息的接收及分发。
集中式的消息系统的结构最常见的是星形结构。
图1 集中式消息系统结构
分散式消息系统基于的是IP组播,整个结构又可以为分为多个组播组。每个组播组使用一个IP地址,客户端可以加入到一个或多个组播组。消息的传递不依赖于消息服务器,由网络自身来完成处理的。
图2 分散式消息系统结构
消息传送模型分为2种,点对点式和发布/订阅式。
图3 消息传输模型示意图
生产消息的客户端成为生产者,消费消息的客户端成为消费者。一个JMS的客户端可以既是生产者又是消费者。
点对点模型基于的是拉取(pull)或轮询(polling),消费者从队列中去取消息。发布/订阅基于的是推送(push),消息被主动地从生产者推送至消费者。
一个简单的例子
使用JMS编写一个简单的聊天程序,代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.NamingException; import jms.JndiFactoryForJMS; public class Chat implements MessageListener {
private TopicPublisher publisher;
private TopicSubscriber subscriber;
private TopicSession pubSession = null, subSession = null;
private TopicConnection connection = null; public Chat() throws JMSException, InterruptedException, NamingException {
TopicConnectionFactory factory = null; Context ctx = null;
try {
JndiFactoryForJMS factoryForJMS = new JndiFactoryForJMS();
ctx = factoryForJMS.getJndiContext(); // 获取连接工厂。
factory = (TopicConnectionFactory) ctx.lookup("con1");
} catch (NamingException e) {
e.printStackTrace();
} // 创建连接
connection = factory.createTopicConnection(); // 建立session
pubSession = connection.createTopicSession(false, pubSession.AUTO_ACKNOWLEDGE);
subSession = connection.createTopicSession(false, pubSession.AUTO_ACKNOWLEDGE);
// 指定消息队列 Topic topic = (Topic) ctx.lookup("MyTopic"); publisher = pubSession.createPublisher(topic);
subscriber = pubSession.createSubscriber(topic, null, true); subscriber.setMessageListener(this);
// 建立连接
connection.start();
} public static void main(String[] srgs) throws JMSException, InterruptedException, NamingException, IOException, CloneNotSupportedException {
Chat chat = new Chat();
BufferedReader commandLine = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String s = commandLine.readLine();
if (s.equalsIgnoreCase("exit")) {
chat.close();
System.exit(-1);
} else {
chat.writeMessage(s);
}
} } @Override
public void onMessage(Message message) {
TextMessage mes = (TextMessage) message;
try {
System.out.println(mes.getText());
} catch (JMSException e) {
e.printStackTrace();
} } private void writeMessage(String text) throws JMSException {
TextMessage mes = pubSession.createTextMessage(text);
publisher.publish(mes);
} private void close() throws JMSException {
connection.close();
}
}
将程序启动多份,在任意一个程序的console窗口中输入信息,可以看到另外程序的console窗口中出现了所输入的内容,就可以说明另外的程序收到了消息并将消息并打印出了消息内容。
分析上面基于JMS的聊天程序:
上面的JMS聊天程序是基于JNDI的,未使用JNDI的服务器,使用的是,因此需要一个配置文件,需要和上面的类放在同一级目录下。
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:61616
java.naming.security.principal=system
java.naming.security.credentials=manager
connectionFactoryNames=con1,con2
##queue.MyQueue=MyQueue
topic.MyTopic=MyTopic
topic.topic1=jms.topic1
JndiFactoryForJMS是一个初始化JNDI环境的工厂类,代码如下:
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JndiFactoryForJMS {
protected Context context = null; public void initalize() throws NamingException
{
Properties props = new Properties();
try{
org.apache.activemq.jndi.ActiveMQInitialContextFactory af = new org.apache.activemq.jndi.ActiveMQInitialContextFactory();
props.load(this.getClass().getResourceAsStream("jndi.properties"));
context = new InitialContext(props);
}catch(Exception ex){
ex.printStackTrace();
} } public Context getJndiContext() throws NamingException {
if(context == null){
initalize();
}
return context;
} }
分析代码中与JNDI相关的部分:
JndiFactoryForJMS factoryForJMS = new JndiFactoryForJMS();
ctx = factoryForJMS.getJndiContext();
// 获取连接工厂。
factory = (TopicConnectionFactory) ctx.lookup("con1");
JMS基础篇(二)的更多相关文章
- php基础篇-二维数组排序 array_multisort
原文:php基础篇-二维数组排序 array_multisort 对2维数组或者多维数组排序是常见的问题,在php中我们有个专门的多维数组排序函数,下面简单介绍下: array_multisort(a ...
- JavaScript笔记基础篇(二)
基础篇主要是总结一些工作中遇到的技术问题是如何解决的,应为本人属于刚入行阶段技术并非大神如果笔记中有哪些错误,或者自己的一些想法希望大家多多交流互相学习. 1.ToFixed()函数 今天在做Birt ...
- Qt入门之基础篇 ( 二 ) :Qt项目建立、编译、运行和发布过程解析
转载请注明出处:CN_Simo. 题解: 本篇内容主讲Qt应用从创建到发布的整个过程,旨在帮助读者能够快速走进Qt的世界. 本来计划是讲解Qt源码静态编译,如此的话读者可能并不能清楚地知道为何要静态编 ...
- NIO相关基础篇二
转载请注明原创出处,谢谢! 上篇NIO相关基础篇一,主要介绍了一些基本的概念以及缓冲区(Buffer)和通道(Channel),本篇继续NIO相关话题内容,主要就是文件锁.以及比较关键的Selecto ...
- docker+k8s基础篇二
Docker+K8s基础篇(二) docker的资源控制 A:docker的资源限制 Kubernetes的基础篇 A:DevOps的介绍 B:Kubernetes的架构概述 C:Kubernetes ...
- Python基础篇(二)_基本数据类型
Python基础篇——基本数据类型 数字类型:整数类型.浮点数类型.复数类型 整数类型:4种进制表示形式:十进制.二进制.八进制.十六进制,默认采用十进制,其他进制需要增加引导符号 进制种类 引导符号 ...
- node基础篇二:模块、路由、全局变量课堂(持续)
今天继续更新node基础篇,今天主要内容是模块.路由和全局变量. 模块这个概念,在很多语言中都有,现在模块开发已经成为了一种潮流,它能够帮助我们节省很多的时间,当然咱们的node自然也不能缺少,看下例 ...
- Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较
说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...
- C语言----输入输出语句(基础篇二)
今天整理一下自己的基础篇输入和输出的理解,自己没有研究系统输入和输出函数,以后有时间在去深究,之前在别人的博客里面看到这么一句话分享给大家,“学习就是一个不断抄袭,模仿,练习和创新的一个过程”. 使用 ...
随机推荐
- [bzoj2836] 魔法树
俩操作:增加路径上的点的权值.查询子树的权值和. 想了想似乎只能树链剖分了..好久没写链剖+数据结构了TAT 一开始没开LL炸了一发(明明有想到的..我果然是傻逼= = #include<cst ...
- 最长上升子序列(LIS) dp学习~3
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1087 Super Jumping! Jumping! Jumping! Time Limit: 200 ...
- 一步步教你创建自己的数字货币(代币)进行ICO
本文从技术角度详细介绍如何基于以太坊ERC20创建代币的流程. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以太坊是什么 ...
- [OpenCV学习笔记2][Mat数据类型和操作]
[Mat数据类型和基本操作] ®.运行环境:Linux(RedHat+OpenCV3.0) 1.Mat的作用: Mat类用于表示一个多维的单通道或者多通道的稠密数组.能够用来保存实数或复数的向量.矩阵 ...
- [国嵌攻略][171][V4L2图像编程接口深度学习]
V4L2摄像编程模型 1.打开摄像头设备文件 2.获取驱动信息-VIDIOC_QUERYCAP 3.设置图像格式-VIDIOC_S_FMT 4.申请帧缓冲-VIDIOC_REQBUFS 5.获取帧缓冲 ...
- element-ui中upload组件如何传递文件及其他参数
最近项目用到了vuethink,里面集成了element-ui,之前一直用的是bootstrap框架,对js也是一知半解,然后也用过vue.js,但也是学的不通透的,然后就各种入坑. 下面就分析一下我 ...
- url加密,一般只对参数加密
首先,很不推荐你使用get方式发送密码,最好是使用post. 原因是,你通过一个连接把用户名和密码发送到后台,即便密码不是明文,别人获取不到密码明文,但是,只要你这个连接成功登陆过,别人就可以拿这个连 ...
- CSS学习笔记day1
1.css的简介 css:层叠样式表 (层叠:一层一层的:样式表:很多的属性和属性值) 使页面显示效果更好 将页面内容和显示样式进行分离,提高了显示功能. 2.css和html的结合方式(4种) 在 ...
- iOS开发中一些有用的小代码
1.判断邮箱格式是否正确的代码: //利用正则表达式验证 -(BOOL)isValidateEmail:(NSString *)email { NSString *emailRegex = @&q ...
- MYSQL GROUP BY Optimization
GROUP BY Optimization 常规的匹配group by(分组)操作子句是扫整表并且创建包含连续的分组行的临时表, 利用临时表得到group数据,运用appregate function ...