JMS/JNDI 信息传递原理(转)

来源:互联网 发布:小米recovery清除数据 编辑:程序博客网 时间:2024/05/15 18:48

JNDI -- Java Naming and Directory Interface

JNDI API被用于执行名字和目录服务。它提供了一致的模型来存取和操作企业级的资源如DNS和LDAP,本地文件系统,后者在应用服务器中的对象。

sun只是提供了JNDI的接口(即规范),IBM, Novell, Sun 和 WebLogic 和JBOSS已经为 JNDI 提供了服务提供程序,

在JNDI中,在目录结构中的每一个结点称为context。每一个JNDI名字都是相对于context的。这里没有绝对名字的概念存在。对一个应用来说,它可以通过使用 InitialContext 类来得到其第一个context:  

    Context ctx = new InitialContext();

    ctx.bind("name", Object);

    ctx.lookup("name");

    

Context:上下文,我的理解是相当与文件系统的中的目录(JNDI的Naming Service是可以用操作系统的文件系统的,哈哈). 

entry/object:一个节点,相当与文件系统中的目录或文件. 

filter:查询/过滤条件是一个字符串表达式如:(&(objectClass=top)(cn=*))查询出objectClass属性为top,cn属性为所有情况的entry. 

Attribute:entry/object的属性可以理解成JAVA对象的属性,不同的是这个属性可以多次赋值.

A.将接口分为Context 和 DirContext   

   JNDI有两个核心接口Context和DirContext,Context中包含 了基本的名字操作,而DirContext则将这些操作扩展到目录服务。DirContext 对Context进行了扩展,提供了基本的目录服务操作, 对名字对象属性的维护、基于属性的名字查找等等。   

B.上下文列表的多种方法   

   一般来说有两种进行上下文列表的应用:上下文浏览应用和对上下文中的对象进行实际操作的应用。   

   上下文浏览应用一般只需要显示上下文中包含内容的名字,或者再获取一些诸如对象的类型之类的信息。这种类型的应用一般都是交互式的,可以允许用户在列举的上下文列表中选择一些进行进一步的显示。   

   另外有一些应用需要对上下文中的对象进行实际的操作,比如,一个备份程序需要对目录中所有文件的状态进行操作,或者某打印机管理员可能需要对大楼中的所有打印机进行复位。为了进行这样的操作,程序需要获取上下文中的实际对象。   

   对于这样两种类型的应用,Context接口提供了两种上下文列表方法list()和 listBindings()。其中list()只返回一系列名字/类映射,而listBindings() 则返回名字、类和对象本身。显然 list()用于上下文浏览应用而listBindings()用于那些需要对对象进行实际操作的应用。   

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory"); 

Context ctx = new InitialContext(env); 

Object obj = ctx.lookup("C:/aaa.txt");

Hashtable env = new Hashtable(); 

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); 

env.put(Context.PROVIDER_URL,"ldap://127.0.0.1:10389/"); 

DirContext ctx = new InitialDirContext(env);

    

JMS(Java Mes)是用于和面向消息的中间件相互通信的应用程序接口(API)。它既支持点对点的域,有支持发布/订阅(publish/subscribe)类型的域,并且提供对下列类型的支持:经认可的消息传递,事务型消息的传递,一致性消息和具有持久性的订阅者支持。

JMS标准是应用最广泛的消息接口标准。

JMS大体被分为两个功能块,消息生产和消息消费.由消息驱动的bean提供了异步消费消息的能力

  Spring中JMSTemplate主要功能是产生消息

  JMS所提供的消息服务包括两种机制  

         1.点对点 p2p   单个消息者消费掉(Queue队列)

             Client1发送消息给消息服务器中的一个队列,而Client2则从这个队列中取出消息

         2.发布/订阅  publish/Subscribe  如为持久的订阅者则会保存到于MQ并处于监听状态。(Topic主题)

             类似于广播,Client1向服务器中的一个消息主题发送消息,对这个消息主题感兴趣的客户端可以预约这个消息主题,当主题存在数据时,所以预约过这个主题的客户端都会接收到。

  sun出了两个jms的版本

           1.02 主要分为两个目的地类型  TopicConnectionFactory   QueueConnectionFactory

           1.1   中统称为 ConnectionFactory

           

 理解一下JMS中的基本概念

     Destination目的地

         例如消息队列的资源,就要通过JNDI方式查找,目的地用来表示这些管理对象的抽象目的地资源。

     Session会话

         一个会话对象是一个单线程的上下文对象,用于产生消息和消费消息,它是JVM向外提供的资源,也是一个JMS的对象。

         会话是产生消息生产者和消费者的工厂

             TopicPublisher publisher = session.createPublisher(topic);

             TopicSubscriber subscriber = session.createSubscriber(topic);

             QueueSender sender = session.createSender(queue);

             QueueReceiver receiver = session.createReceiver(queue);

         会话也是创建主题消息对象和点对点消息对象的工厂

             TextMessage msg = publisher.session.CreateTextMessage();

             TextMessage msg = sender.session.CreateTextMessage();

     

     Connection 连接

          一个连接对象是由客户端激活的客户端与服务提供者之间的连接

     Message消息

          指的是服务提供者与客户端之间传递信息所使用的信息单元。

          每个消息都是由消息头(Headers),消息属性(Properties),消息体(Body)三个部分组成.

          A.消息头有关消息的元数据和消息的路由信息.

              jmsDeliveryMode 发送模式 DeliveryMode.NON_PERSISTENT 当服务器出错时,消息会丢失  DeliveryMode.PERSISTENT   当服务器出错时,消息也不会丢失

              jmsExpiration 消息过期时限 控制消息在服务器容器中存活的时间 0时则不会过期

              jmsPriority 消息优先级, 0-4为普通级别,5-9属于需要迅速发送

              jmsRedelivered 是否重新分发给接收者  为true时,如果一个消息接收者接收失败,则该消息会重新分发给这个消息的接收者

              jmsMessageID 消息的ID,不必设置,会被容器指定一个字符数值

              jmsTimestamp long型的值,消息时间戳,被容器设置

          B.消息属性由JMS的发送端定义,是一堆键值对..对于接收端是只读的!

              可以通过getPropertyNames()返回所有的属性名称

              setBooleanProperty("name", boolean);

                  .(八种基本类型)

              可以通过以下方法过滤接收者只接收name为silent的属性的值

              QueueReceiver receiver = session.createReceiver(queue, "name = 'silent'");

              

          C.消息体负责装载消息数据内容,对于接收端是只读的!

              Message TextMessage ObjectMessage BytesMessage StreamMessage MapMessage

              其都是通过session.createXXXMessage();来创建

              注:全部为接口.其实现有SpyXXXMessage...由session来管理

          

          

     

     MessageProducer消息生产者

           消息产生由JMS客户端完成,服务提供者只负责管理这些消息。

           通过 void publish(Message message)和 void send(Message message)

     MessageConsumer消息消费者

           一个消息的消费者可以接收来自某个队列的消息

           都是通过Message receiver()来从消息队列中接收消息

JMS使用步骤:(9个步骤)

         利用JNDI找到创建连接使用的工厂类 ConnectionFactory,使用这些工厂类创建一个连接的实例(Connection) ,由连接的实例创建一个会话Session,这个会话 类代表一个会话资源,得用会话类我们可以产生创建新消息的消息生产者(Producer),也可以产生接收消息的消费者(Consumer),而不管发消 息还是接收消息都需要访问JMS的目标对象(Destination)。

     在使用消费方式时,还可以建立消息的监者(Listener),当一个新的消息产生时,监听者会得到通知,

1) 创建JNDI上下文,并且查找创建JMS连接使用的工厂类

Hashtable env = new Hashtable(); 

env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory"); 

env.put(Context.PROVIDER_URL,"ldap://192.168.1.106:1039/"); 

Context iniCtx = new InitialContext(env);

TopicConnectionFactory tcf = (TopicConnectionFactory)iniCtx.lookup("ConnectionFactory");

2) 查找JMS的目标对象

Topic topic = (Topic)iniCtx.lookup("topic/testTopic");

3) 创建JMS连接

TopicConnection conn = tcf.createTopicConnection(); 只要在这里加入user,pass参数,该消息则为持久性消息

4) 创建会话

   TopicSession session = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

5) 创建消息的生产者和消费者

    TopicPublisher publisher = session.createPublisher(topic);

    TopicSubscriber subscriber = session.createSubscriber(topic);

6) 注册消息的监听者:

    TextListener listener = new TextListener();

    subscriber.setMessageListener(listener);

    

7) 开始JMS的连接

    conn.start();

8) 发送消息和接收消息

publisher.publish(Message message);

Message message = subscriber.receive();

9) 停止和关闭JMS连接

conn.stop();

session.close();

conn.close();

 

Spring 中对JMS进行了封装,另使用编写变得更简单.对于1.1的JMS其有JmsTemplate,而对于1.02其有JmsTemplate102

      而Spring中的JMS对于Queue和Topic方式并不关心,都整合到一起用了!!

   这里的JMSTemp需要指定 connectionFactory(org.springframework.jndi.JndiObjectFactoryBean)和 defaultDestination(org.springframework.jndi.JndiObjectFactoryBean)    注意 1.02中必须要设置pubsubDomain属性,是否以主题形式发送

   

   JMS发送方法

       jmsTemplate.send(new MessageCreator() {

             public Message createMessage(Session session) throws JMSException {

                  //利用Session创建消息并返回该消息实例就行了

             }

    }

    

   JMS接收方法

      Message Msg = jmsTemplate.receive();

原创粉丝点击