简介

  异构集成是消息发挥作用的一个领域,大型公司内部可能会遇到很多的平台,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基础篇(二)的更多相关文章

  1. php基础篇-二维数组排序 array_multisort

    原文:php基础篇-二维数组排序 array_multisort 对2维数组或者多维数组排序是常见的问题,在php中我们有个专门的多维数组排序函数,下面简单介绍下: array_multisort(a ...

  2. JavaScript笔记基础篇(二)

    基础篇主要是总结一些工作中遇到的技术问题是如何解决的,应为本人属于刚入行阶段技术并非大神如果笔记中有哪些错误,或者自己的一些想法希望大家多多交流互相学习. 1.ToFixed()函数 今天在做Birt ...

  3. Qt入门之基础篇 ( 二 ) :Qt项目建立、编译、运行和发布过程解析

    转载请注明出处:CN_Simo. 题解: 本篇内容主讲Qt应用从创建到发布的整个过程,旨在帮助读者能够快速走进Qt的世界. 本来计划是讲解Qt源码静态编译,如此的话读者可能并不能清楚地知道为何要静态编 ...

  4. NIO相关基础篇二

    转载请注明原创出处,谢谢! 上篇NIO相关基础篇一,主要介绍了一些基本的概念以及缓冲区(Buffer)和通道(Channel),本篇继续NIO相关话题内容,主要就是文件锁.以及比较关键的Selecto ...

  5. docker+k8s基础篇二

    Docker+K8s基础篇(二) docker的资源控制 A:docker的资源限制 Kubernetes的基础篇 A:DevOps的介绍 B:Kubernetes的架构概述 C:Kubernetes ...

  6. Python基础篇(二)_基本数据类型

    Python基础篇——基本数据类型 数字类型:整数类型.浮点数类型.复数类型 整数类型:4种进制表示形式:十进制.二进制.八进制.十六进制,默认采用十进制,其他进制需要增加引导符号 进制种类 引导符号 ...

  7. node基础篇二:模块、路由、全局变量课堂(持续)

    今天继续更新node基础篇,今天主要内容是模块.路由和全局变量. 模块这个概念,在很多语言中都有,现在模块开发已经成为了一种潮流,它能够帮助我们节省很多的时间,当然咱们的node自然也不能缺少,看下例 ...

  8. Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较

    说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...

  9. C语言----输入输出语句(基础篇二)

    今天整理一下自己的基础篇输入和输出的理解,自己没有研究系统输入和输出函数,以后有时间在去深究,之前在别人的博客里面看到这么一句话分享给大家,“学习就是一个不断抄袭,模仿,练习和创新的一个过程”. 使用 ...

随机推荐

  1. UVA - 12050-Palindrome Numbers

    12050 - Palindrome Numbers Time limit: 3.000 seconds A palindrome is a word, number, or phrase that ...

  2. 微信小程序个人心得

    尊重原创:http://blog.csdn.net/qq_28832135/article/details/52796048 昨天看了一下微信小程序官方文档,总结一下自己学习的个人心得. 首先从官方文 ...

  3. Caused by: java.sql.SQLException: Couldn't perform the operation getAutoCommit: You can't perform any operations on this connection. It has been automatically closed by Proxool for some reason (see lo

    系统启动,一段时间不操作,然后在来操作时,报错如下: Caused by: java.sql.SQLException: Couldn't perform the operation getAutoC ...

  4. UVA 673 Parentheses Balance (栈)

    题意描述: 给出一段只包含()和[]的字符串,判断是否合法,合法输出YES,不合法输出NO 规则: 1.该串为空,则合法 2.若A合法,B合法,则AB合法 3.若A合法,则(A)和[A]均合法 解题思 ...

  5. 属性getter和setter

    我们知道,对象属性是由名字.值和一组特性(attribute)构成的.在ECMAScript5 中,属性值可以用一个或两个方法替代,这两个方法就是getter和setter.由getter和sette ...

  6. Spark算子--leftOuterJoin和rightOuterJoin

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/cb71cd3ac5d7965a2c61891659264d54.html leftOuterJoin和righ ...

  7. 关于VC++中virtual ~的含义

    我知道virtual 的虚函数定义,~CMainFrame( )是析构函数,用来释放内存.C++的继承和派生内容.所有可以被用作基类的类一般都用虚析构函数当基类对象的指针或引用调用派生类对象时,如果基 ...

  8. 优化表单数据的JS校验

    在平常的web开发中,我经常需要在客户端对表单的数据进行验证.比如,我们验证表单输入的内容不为空: ? <form action="" method="post&q ...

  9. python 实现词云

    拿现在比较火的小说<大主宰>做测试,看看其中的关键词词云是啥 代码 import matplotlib.pyplot as plt from wordcloud import WordCl ...

  10. 设置vs环境

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...