JMS入门


在不同系统之间交换信息的一大障碍是如何在精确交换和格式化数据方面取得一致。Java Message Service( Java消息服务,简称JMS)通过提供一种与J2EE应用程序或传统系统交互的方法部分的解决了这个问题。


较详细的介绍在:http://java.sun.com/developer/technicalArticles/Ecommerce/jms/

在此将英文翻译为中文,方便中文使用者,翻译难免出错,请对照原网址阅读。


远程过程调用(RPC)系统,包括Java RMI,是同步调用的。调用者会阻塞直到调用方法执行完毕,这样在不使用多线程的情况下就无法开发松耦合的企业应用程序。也就是说,RPC系统需要客户端和服务器端同时可用。这样的紧耦合在某些应用中是无法实现的,而面向消息的中间件(MOM)提供了对这些问题的解决方案。MOM基于异步交互模式,且提供了一个可以在网络上访问的抽象化的消息队列。这里的消息一般指的是企业级的异步请求或者事件,而不是由人类发出的如电子邮件之类的消息。这些消息包含格式化的描述具体业务操作的数据。

 

Java消息服务(JMS),是由SunMicroSystems公司和其他几个在JavaCommunity Process下的如JSR 914等公司共同设计出来的第一个企业级的消息API,至今已经获得广发的业界支持。JMS的设计目的是为了更容易地开发能够进行异步收发业务数据和事件的业务应用程序。它定义了一个通用的企业消息传递API,这个API可以很广泛地支持企业消息传递产品。JMS支持点对点(队列)和发布-订阅两种消息模型。

 

JMS允许Java应用程序使用企业级消息传递系统。更重要的是,它提供了一个通用的方式来为Java应用程序传递消息。JMS中间件属于MOM,作为中间件,JMS可运行在数据库、应用程序适配器、事件处理以及业务流程的自动化等层次。MOM已经成为系统整合公司内部业务方面必不可少的组件。

 

JMS定义了一组用来完成Java应用程序与其他消息实现(messageimplementations)进行通信的接口和语义。一个JMS实现指的就是JMS提供者。JMS最大限度地减少新概念的数目,这样使得学习JMS能够更加容易。它同时最大限度地提高了消息应用程序的可移植性。

 

结构

JMS应用一般包含以下部分:

l        JMS提供者:消息传递系统,实现了JMS规范。

l        JMS客户端:收发消息的Java应用程序。

l        消息:在JMS客户端之间通信的对象。

l        管理的对象:由JMS客户端管理员创建的预配置的JMS对象。

 

消息传递模型

JMS支持两种不同的消息传递模型:

l        点对点(队列目的地):在这种模式下,消息从一个提供者传递给一个消费者。这些消息传递到一个目的地(队列),然后传送到一个注册到该队列的消费者。任何消息提供者都可以向队列发送消息,该信息被保证传输,然后被一个消费者消费。如果没有注册的消费者,则这些消息将保存,直到有注册的消费者来消费。

l        发布-订阅(主题目的地):在该模式下,消息会传递给任意数量的消费者。消息先传递到目的地(主题),然后传递给所有订阅了该主题的消费者。任何消息提供者都可以给一个主题目的地发送消息,而消息也可以被任意数量的订阅消费者接收。如果没有注册消费者,主题目的地不会保存消息,除非它有长期订阅的但不活动的消费者。长期订阅不活动的消费者是指那些注册到主题目的地,且能在消息发送到主题时不活动的消费者。

 

JMS编程模型

一个JMS应用由一组程序定义好的消息和一组交换消息的客户端组成。客户端使用JMS API进行交互。一个消息由三部分组成:消息头,属性和主体组成。

 

l        消息头是消息必须包含的信息,消息头包含了用于路由和标识消息的信息。其中一些字段是由消息提供者在生成和发送下消息时自动设置的,其余字段则由客户端进行设置。

l        属性是可选的,客户端可以使用它的值来过滤消息。它提供了数据的一些额外信息,比如哪个进程创建了它,它的创建时间等。属性可以认为是消息头的扩展,包含属性名/值对。使用属性,客户端可以精细调整它们的消息选择标准。

l        主体,也是可选的,包含了要进行交换的实际数据。JMS规定了JMS提供者必须支持的六类消息:

Ø        Message:没有消息主体的消息。

Ø        StreamMessage:消息主体包含Java原始类型的数据流,按顺序写入与读取。

Ø        MapMessage:消息主体包含一组名称/值对,条目的顺序没有定义。

Ø        TextMessage:消息主体包含Java字符串如XML消息。

Ø        ObjectMessage:消息主体包含序列化的Java对象。

Ø        ByteMessage:消息主体包含一个未被解释的字节流。

 

制造与消费消息

下图包含制造和消费消息必要步骤。如果客户端即制造消息,也消费消息,这里有一些步不能够重复。

 

制造消息的客户端

1.      使用JNDI查找一个ConnectionFactory对象,或者直接创建一个ConnectionFactory对象,然后设置它的属性。这个ConnectionFactory对象是一个QueueConnectionFactory 或者TopicConnectionFactory 的实例。下面的代码显示了使用JNDI创建连接工厂对象:

Context ctx = new InitialContext();
ConnectionFactory cf1 = (ConnectionFactory) ctx.lookup("jms/QueueConnectionFactory");
ConnectionFactory cf2 = (ConnectionFactory) ctx.lookup("/jms/TopicConnectionFactory");

       或者直接创建:

ConnectionFactory connFactory = new com.sun.messaging.ConnectionFactory();

 

2.      使用ConnectionFactory对象来创建一个Connection对象:

Connection connection = connFactory.createConnection();

 

3.      使用Connection对象来创建一个或多个Session对象,它提供了一个将发送和接收组织成原子工作单元的事务上下文。

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

CreateSession方法包含两个参数,第一个参数(这里为fasle)表示会话没有被处理,第二个参数表示会话会自动确认消息的接收。

 

4.      使用JNDI找到目的地,或者直接创建目的地对象:

Destination dest = (Queue) ctx.lookup("jms/SomeQueue");
Queue q = new com.sun.messaging.Queue("world");

 

5.      使用目的地对象和会话对象来创建一个消息制造者,然后使用制造者发送消息:

MessageProducer producer = session.createProducer(SomeQueue OR SomeTopic);
 
producer.send(message);

 

消费消息的客户端

前四步与上面一致。

5.      使用会话对象和目的地对象来创建一个消息消费者对象:

MessageConsumer consumer = session.createConsumer(SomeQueue or SomeTopic);

在创建消费者对象后,就可以启动连接对象,来进行消息的收发了:

connection.start();
Message msg = consumer.receive();

 

6.      如果需要进行异步通信,则需要使用一个MessageComsumer对象来实例化一个MessageListener对象,并进行注册。MessageListener对象作为一个消息的异步事件处理程序,该接口对象包含一个OnMessage方法,用来实现接收和处理消息。代码如下:

MessageListener listener = new MyListener();
consumer.setMessageListener(listener);

 

7.      启动Connection,使用start方法。


一个简单的实例如下,它来自:http://blog.csdn.net/zhangxs_3/article/details/4034775


import javax.jms.Connection;  
import javax.jms.ConnectionFactory;
import javax.jms.Message;  
import javax.jms.MessageConsumer;  
import javax.jms.MessageProducer;  
import javax.jms.Queue;  
import javax.jms.Session;  
import javax.jms.TextMessage;  
import org.apache.activemq.ActiveMQConnectionFactory;  
import org.apache.activemq.command.ActiveMQQueue;
 
public class MainApp {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        ConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");  
        
        Connection connection = factory.createConnection();  
        connection.start();  
         
        Queue queue = new ActiveMQQueue("testQueue");  
         
        final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
        Message message = session.createTextMessage("Hello JMS!");  
         
        MessageProducer producer = session.createProducer(queue);  
        producer.send(message);  
     
        System.out.println("Send Message Completed!");  
         
        MessageConsumer comsumer = session.createConsumer(queue);  
        Message recvMessage = comsumer.receive();  
        System.out.println(((TextMessage)recvMessage).getText());  
        
        connection.stop();
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值