JMS(java消息服务)

JMS(java消息服务)是java平台关于面向消息中间件的api接口,用于在应用程序和分布式系统中发送消息,进行异步通信。JMS提供了一套类似JDBC的技术规范,服务的实现由具体的实现提供商提供。

使用JMS,可以解决诸多的体系结构性问题,比如异构系统集成通信,缓解系统瓶颈,提高系统的伸缩性(异步、非点对点的模式使得处理消息的应用可以水平扩展),增强系统用户体验,使得系统模块化和组件化变得可行并更加灵活。

使用JMS的集群系统有以下两个角色:消息传送客户端和消息传送服务器。客户端向服务器端发送消息,服务器随后再将消息发送给一个或者多个消息接收的客户端。

JMS支持两类消息传送模型:点对点模式和发布/订阅模式。点对点适用于一对一的消息传送,而发布/订阅模型则适用于消息组播的场景。点对点模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消息推送到客户端。这个模型的特点是发送到队列的消息被一个且只有一个接收者接收处理,即使有多个消息监听者也是如此。基于这一点,JMS可以使用这种消息传送模型做负载均衡。点对点模型还可以允许接收者在接收消息之前查看消息的内容,而发布订阅模型则不行。

发布订阅模型则是一个基于推送的消息传送模型。发布订阅模型可以用多种不同的订阅者,临时订阅者只在主动监听主题时才接收消息,而持久订阅者则监听主题的所有消息,即时当前订阅者不可用,处于离线状态。

JMS API中提供的公共接口ConnectionFactory需要从JMS提供者出用JNDI的方式获取,有了ConnectionFactory,就可以获取连接JMS服务器的链接(Connection)、会话(Session)等。

这里要讲一下JNDI,JNDI是一组在java应用中访问命名和目录服务的api。它可以使应用程序使用者用api从网络上的JNDI提供者中获取命名服务对象。它的一个可能实现是:将对象实例绑定到jnpserver后,当远程端采用context.lookup()方式获取远程对象实例并开始调用时,jnp server获取对象实例,将其序列化回本地,然后在本地进行反序列化,之后在本地进行类属性访问。通过这个机制,就可以知道了,本地其实是必须有绑定到jboss上的对象实例的class的,否则反序列化的时候肯定就失败了。

一般的JMS服务器也提供了JNDI的支持,会将ConnectionFactory对象以jndi的方式发布出来,JMS客户端通过这种方式获取到链接之后,就可以创建会话来和JMS服务器进行消息传递了。

使用ActiveMQ并测试一个简单的聊天室程序的步骤:

1.在activemq官网(http://activemq.apache.org/)上下载activemq应用包,解压,在bin目录下使用启动脚本启动。

2.创建测试工程,测试工程要引入activemq的jar包,如:activemq-all-5.7.0.jar,然后编写聊天室程序Chat.java:

packagecn.com.hanmfree;

import java.io.*;

import javax.jms.*;

import javax.naming.*;

public class Chat implementsjavax.jms.MessageListener{

private TopicSessionpubSession;

private TopicPublisherpublisher;

private TopicConnectionconnection;

private String username;

/* Constructor used toInitialize Chat */

public Chat(StringtopicFactory, String topicName, String username)

throwsException {

//Obtain a JNDI connection using the jndi.properties file

InitialContextctx = new InitialContext();

// Look up aJMS connection factory

TopicConnectionFactory conFactory =

(TopicConnectionFactory)ctx.lookup(topicFactory);

// Create aJMS connection

TopicConnection connection = conFactory.createTopicConnection();

// Create twoJMS session objects

TopicSessionpubSession = connection.createTopicSession(

false,Session.AUTO_ACKNOWLEDGE);

TopicSessionsubSession = connection.createTopicSession(

false,Session.AUTO_ACKNOWLEDGE);

// Look up aJMS topic

TopicchatTopic = (Topic)ctx.lookup(topicName);

// Create aJMS publisher and subscriber

TopicPublisherpublisher =

pubSession.createPublisher(chatTopic);

TopicSubscriber subscriber =

subSession.createSubscriber(chatTopic, null, true);

// Set a JMSmessage listener

subscriber.setMessageListener(this);

// Intializethe Chat application variables

this.connection = connection;

this.pubSession = pubSession;

this.publisher= publisher;

this.username= username;

// Start theJMS connection; allows messages to be delivered

connection.start( );

}

/* Receive Messages FromTopic Subscriber */

public voidonMessage(Message message) {

try {

TextMessage textMessage = (TextMessage) message;

String text = textMessage.getText( );

System.out.println(text);

} catch(JMSException jmse){ jmse.printStackTrace( ); }

}

/* Create and Send MessageUsing Publisher */

protected voidwriteMessage(String text) throws JMSException {

TextMessagemessage = pubSession.createTextMessage( );

message.setText(username+": "+text);

publisher.publish(message);

}

/* Close the JMS Connection*/

public void close( ) throwsJMSException {

connection.close( );

}

/* Run the Chat Client */

public static voidmain(String [] args){

try{

if (args.length!=3)

System.out.println("Factory, Topic, or usernamemissing");

// args[0]=topicFactory; args[1]=topicName; args[2]=username

Chat chat = new Chat(args[0],args[1],args[2]);

// Read from command line

BufferedReader commandLine = new

java.io.BufferedReader(new InputStreamReader(System.in));

// Loop until the word "exit" is typed

while(true){

String s = commandLine.readLine( );

if (s.equalsIgnoreCase("exit")){

chat.close( ); // close down connection

System.exit(0);// exit program

} else

chat.writeMessage(s);

}

} catch(Exception e){ e.printStackTrace( ); }

}

}

3.在测试工程的classpath中增加jndi配置文件jndi.properties,具体内容如下:

java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory

java.naming.provider.url=tcp://localhost:61616

java.naming.security.principal=system

connectionFactoryNames=TopicCF

topic.topic1=jms.topic1

其中org.apache.activemq.jndi.ActiveMQInitialContextFactory是JMS接口TopicConnectionFactory的ActiveMQ实现,

tcp://localhost:61616是activemq的jndi服务的默认地址,connectionFactoryNames是jndi对象的名字,topic.topic1是配置的topic,配置的具体值可以自行配置。

4.运行多个Chat程序,传入TopicCF topic1<name>三个入参,可以实现在控制台上和其他程序进行通信,一个程序输出的内容会被推送到其他程序中。

5.这个程序演示了使用activemq实现发布/订阅模型的消息传送方式。Chat类即是发布者角色又是订阅者角色,Chat类的构造方法中演示了从jndi从获取TopicConnectionFactory对象,根据TopicConnectionFactory获取connection,进而获取session上的publisher和subscriber,publisher对象用来实现发布的逻辑,subscriber则用来实现订阅的逻辑。注意到,获得subscriber之后还需要设置这个subscriber对象的监听器,监听器对象需要是一个javax.jms.MessageListener类的子类对象,实现了MessageListener类上的onMessage方法,当消息接受到时,会调用对象的onMessage。

http://blog.csdn.net/e5945/article/details/8592875

另注:JMS模型

1、点到点模型(队列模型)

1.发送方将消息发送至指定队列。

2.消息保存在队列中,直至它们被接收或过期。

3.每个消息只有一个接收者。

4.发送和接收过程是异步的。

2、发布/订阅模型

1.发布者将消息发布至特定主题(topic)。

2.发布者和订阅者彼此不知道对方。

3.存在多个(也可以没有)订阅者。

借鉴自:http://blog.chinaunix.net/uid-354915-id-4260161.html每个人心中,都会有一个古镇情怀,流水江南,烟笼人家。

JMS(java消息服务)

相关文章:

你感兴趣的文章:

标签云: