有关JMS的一点看法

  1月份不知道在做什么,就没写,忽然觉得一个月没写好像缺了点什么,正好这几天研究了一下JMS,就写一点自己的心得.

  JMS,全称是JAVA MESSAGE SERVICE,从名字可以看出来,就是一个消息服务,也就是说可以用来发送和接受消息的一个服务,我也是刚开始学习,所以就记录下这两天的一些收获.

  至于JMS的一些背景我就没有兴趣去细看了,反正我的目的就是学他的实现过程.我在这里不会详细介绍每一个接口的方法,详细内容可以去SUN网站下载JMSAPI文档.

   首先要看的就是JMS的体系结构.

JMS 应用程序由以下元素组成:

  • JMS 客户机。 JMS API 发送和接收消息的 Java 程序。
  • JMS 客户机。 认识到传统程序通常整个 JMS 应用程序的一部分是非常重要的,在规划时必须优先考虑它们的存在。
  • 消息。JMS 应用程序设计而言,通过JMS 和非 JMS 客户机所交换的消息的格式和内容是完整的。
  • JMS 提供者。 如前所述,JMS 定义了一组接口,供应者必须提供特定于其 MOM 产品的具体实现。
  • 管理对象。 消息系统提供者的管理员创建的、独立于提供者的专有技术的对象。

JMS 提供者必须提供允许创建受管理对象及它们在 JNDI 名字空间中的存放地的工具。 有两种受管理对象:

  • ConnectionFactory:用于创建到提供者的底层消息系统的连接。
  • Destination:用 JMS 客户机来指定正发送消息的目的地或正接收消息的来源。

尽管受管理对象本身就是特定于提供者实现的类的例子,但可以使用可移植机制(JNDI)检索它们,并且可以通过可移植接口(JMS)访问它们。JMS 程序只需要知道管理对象的 JNDI 名称和 JMS 接口类型即可,无需了解特定于提供者的知识。

高级接口包括:

  • ConnectionFactory:一个创建 Connection 的受管理对象。
  • Connection:连接到提供者的活动连接。
  • Destination:一个封装消息目的地的身份的受管理对象,如消息的来源地和发送地。
  • Session:发送和接收消息的单线程环境。为了简化,并且因为 Session 控制事务的缘故,通过多个线程进行并发访问受到了限制。可以将多个 Session 用于多线程应用程序。
  • MessageProducer:用于发送消息。
  • MessageConsumer:用于接收消息。

一个典型的 JMS 程序要经过以下步骤才能开始产生和使用消息:

  1. 通过 JNDI 查询 ConnectionFactory
  2. 通过 JNDI 查询一个或者多个 Destination
  3. ConnectionFactory 创建一个 Connection
  4. Connection 创建一个或者多个 Session
  5. SessionDestination 创建所需要的 MessageProducerMessageConsumer
  6. 启动 Connection

这里我有必要介绍一些名称:

ConnectionFactory: ConnectionFactory 是一个可以从JNDI检索的受管理对象,它建立了到提供者的连接。它包含 createConnection() 方法,该方法返回了一个 Connection 对象。

Connection 封装了一个连接到提供者的活动连接。它的一些方法包括:

  • createSession(boolean, int):返回一个 Session 对象。boolean 参数指出 Session 是否被处理, int 则指出确认模式.
  • start():激活提供者发送消息。
  • stop():临时停止消息的发送,可以用 start() 重新开始发送。
  • close():关闭到提供者的连接,并释放以它的名义占用的所有资源。

Session 是用来发送和接收消息的单线程的上下文。它的一些方法包括:

  • createProducer(Destination):返回一个 MessageProducer 对象,向指定的 Destination 发送消息。
  • createConsumer(Destination):返回一个 MessageConsumer 对象来接收来自指定 Destination 的消息。
  • commit():提交当前事务的所有使用的或者产生的消息。
  • rollback():回滚当前事务所有使用的或者产生的消息。
  • create<MessageType>Message(...):一组返回 <MessageType>Message 的方法——例如,MapMessageTextMessage 等。

 

Destination: 封装消息的目的地。它是一个从 JNDI 检索的受管理对象。

MessageProducer:用来发送信息.

MessageConsumer:用来接受信息.

MessageListener

MessageListener 是有一个单一方法——onMessage(Message)——的接口,它提供了消息的异步接收和处理。

 

再讲一个概念,”确认

确认是通知提供者已经成功接收到消息的一种机制。

如果被处理的是接收消息的 Session ,则确认的处理是自动的。如果被处理的不是 Session ,则在创建 Session 时确定确认的类型。

有三种类型的确认:

  • Session.DUPS_OK_ACKNOWLEDGE:消息发送的延迟回执,它通过最小化工作的重复来减少开销,只有在可以预计和处理重复消息时,才可以使用这种确认。
  • Session.AUTO_ACKNOWLEDGE:在完成接收消息的方法时自动确认消息的发送。
  • Session.CLIENT_ACKNOWLEDGE:通过调用 Messageacknowledge() 方法显式确认消息发送。

我这里附上一些代码实例,来源于IBM的教程.我自己添加了一些注释.

import java.io.*;
   
   
import javax.jms.*;
   
   
import javax.naming.*;
   
   
 
   
   
public class Sender {
   
   
 
   
   
    public static void main(String[] args) {
   
   
 
   
   
        new Sender().send();
   
   
    }
   
   
 
   
   
    public void send() {
   
   
 
   
   
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   
   
 
   
   
        try {
   
   
            //Prompt for JNDI names
   
   
            System.out.println("Enter ConnectionFactory name:");
   
   
            String factoryName = reader.readLine();
   
   
            System.out.println("Enter Destination name:");
   
   
            String destinationName = reader.readLine();
   
   
//Look up administered objects
   
   
            InitialContext initContext = new InitialContext();
   
   
            ConnectionFactory factory =
   
   
                (ConnectionFactory) initContext.lookup(factoryName);//lookup(String) return object,so have to convert by force
   
   
            Destination destination = (Destination) initContext.lookup(destinationName);
   
   
            initContext.close();
   
   
//Create JMS objects
   
   
            Connection connection = factory.createConnection();
   
   
            Session session =
   
   
                connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
   
   
            MessageProducer sender = session.createProducer(destination);
   
   
//Send messages,if you input “quit”,the programe will be end.
   
   
            String messageText = null;
   
   
            while (true) {
   
   
                System.out.println("Enter message to send or 'quit':");
   
   
                messageText = reader.readLine();
   
   
                if ("quit".equals(messageText))
   
   
                    break;
   
   
                TextMessage message = session.createTextMessage(messageText);
   
   
                sender.send(message);
   
   
            }
   
   
//Exit,close Connection ,will close Session and Destination automatic.
   
   
            System.out.println("Exiting...");
   
   
            reader.close();
   
   
            connection.close();
   
   
            System.out.println("Goodbye!");
   
   
 
   
   
        } catch (Exception e) {
   
   
            e.printStackTrace();
   
   
            System.exit(1);
   
   
        }
   
   
    }
   
   
}
   
   
 
   
   

Receiver 类与 Sender 类非常类似,都有一个 main(String[]) 方法,它只是举例说明了 Receiver 并调用它的主要方法 receive()

提示输入 JNDI 的名称并查找受管理对象的代码与 Sender 中的代码完全一样。

不过,在这个类中有两处不一样的地方:

  • boolean stop 实例变量用来指出程序应该退出。
  • Receiver 实现了 MessageListener 接口,为了异步接收消息。

 

import java.io.*;
   
   
import javax.jms.*;
   
   
import javax.naming.*;
   
   
 
   
   
public class Receiver implements MessageListener {
   
   
 
   
   
    private boolean stop = false;
   
   
 
   
   
    public static void main(String[] args) {
   
   
 
   
   
        new Receiver().receive();
   
   
    }
   
   
 
   
   
    public void receive() {
   
   
 
   
   
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   
   
 
   
   
        try {
   
   
            //Prompt for JNDI names
   
   
            System.out.println("Enter ConnectionFactory name:");
   
   
            String factoryName = reader.readLine();
   
   
            System.out.println("Enter Destination name:");
   
   
            String destinationName = reader.readLine();
   
   
            reader.close();
   
   
 
   
   
            //Look up administered objects
   
   
            InitialContext initContext = new InitialContext();
   
   
            ConnectionFactory factory =
   
   
                (ConnectionFactory) initContext.lookup(factoryName);
   
   
            Destination destination = (Destination) initContext.lookup(destinationName);
   
   
            initContext.close();
   
   
//Create JMS objects
   
   
            Connection connection = factory.createConnection();
   
   
            Session session =
   
   
                connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
   
   
            MessageConsumer receiver = session.createConsumer(queue);
   
   
            receiver.setMessageListener(this);
   
   
            connection.start();
   
   
//Wait for stop
   
   
            while (!stop) {
   
   
                Thread.sleep(1000);
   
   
            }
   
   
 
   
   
            //Exit
   
   
            System.out.println("Exiting...");
   
   
            connection.close();
   
   
            System.out.println("Goodbye!");
   
   
 
   
   
        } catch (Exception e) {
   
   
            e.printStackTrace();
   
   
            System.exit(1);
   
   
        }
   
   
    }
   
   
public void onMessage(Message message) {
   
   
 
   
   
        try {
   
   
            String msgText = ((TextMessage) message).getText();
   
   
            System.out.println(msgText);
   
   
            if ("stop".equals(msgText))
   
   
                stop = true;
   
   
        } catch (JMSException e) {
   
   
            e.printStackTrace();
   
   
            stop = true;
   
   
        }
   
   
    }
   
   
}
   
   

在运行这个程序之前,需要使用 JMS 提供者提供的管理工具创建受管理对象 ConnectionFactoryDestination ,并将它们放到 JNDI 名字空间中。

对于点对点编程和pub/sub,是JMS的扩展,目前首选仍然是公共接口,所以, JMS还有很多内容,有兴趣的话可以去SUN网站下载API文档,我也是在初学阶段,先写这么多吧.

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值