当前页面位置: » 丰搜网 » 文档中心 » 详细内容
enterprise javabeans distilled
消息驱动bean(续)
topicconnectionfactory 和 topic
为发送jms消息,需要一个到jms供应者的连接和用于消息的目的地地址。使用jms连接工厂可以建立到jms供应者的连接。同时,使用topic对象来标识消息的目的地地址。这两者都可通过travelagent ejb的jndi enc服务获得:
t
opicconnectionfactory factory = (topicconnectionfactory)
jndicontext.lookup("java:comp/env/jms/topicfactory");
topic topic = (topic)
jndicontext.lookup("java:comp/env/jms/tickettopic");
其中,
jms中的topicconnectionfactory在功能上类似于jdbc中的datasource。正如datasource提供对
数据库的连接一样,topicconnectionfactory提供对消息路由器的
jms连接。(这种类推并不完美。也可以说topicsession类似于datasource,因为这两者都是事务资源连接。)
topic对象本身表示了独立于网络的目的地,即消息的地址。在
jms中,消息被发送到目的地,或者是topic,或者queue,而不是直接给其他的应用程序。topic类似于邮件列表或新闻组。任何订阅了该topic消息服务的应用程序可以发送和接收来自该topic的消息。当
jms客户收到来自topic的消息时,可以说,这个客户订阅了该topic。
jms使得,应用借助于目的地来互发消息,从而降低了应用的耦合度。其中的,目的地起着虚拟通道(virtual channel)的作用。
当然,
jms也支持另外一种目的地类型,queue。后面的内容将解释这两者的区别。
topicconnection 和 topicsession
在这里,使用topicconnectionfactory来创建topicconnection,一种对
jms供应者的实际连接:
topicconnection connect = factory.createtopicconnection();
topicsession session = connect.createtopicsession(true,0);
一旦获得topicconnection,就可以使用它创建topicsession。topicsession对象使得
java开发者能够组合发送和接收消息动作。在这种情形下,只需要单个topicsession。然而,提供多个topicsession对象经常会带来很多好处:如果使用多
线程生产和消费消息,需要创建不同的session以满足每个
线程对它的访问。这是因为
jms session对象使用单
线程模型,从而阻止了多个
线程对单个session的并发访问。创建topicsession的
线程通常是使用该session的生产者和消费者(即,topicpublisher和topicsubsriber对象)。如果想使用多
线程技术来生产和消费消息,则需要创建每个
线程使用的session对象。
其中,createtopicsession()有两个参数:
createtopicsession(boolean transacted, int acknowledgemode)
在
ejb 2.0规范中给出,运行时会对这些参数视而不见,因为
ejb容器管理事务,并从jndi enc中得到任何
jms资源的确认
模式。规范建议开发者分别使用true和0作为transacted和acknowledgemode参数的值。但既然规范是这样规定的,如何给出这些参数值不会有任何关系。但不幸的是,并不是所有的产品厂商会遵循这部分内容。有些厂商会遵循规范,但有些不会。参考产品文档以寻求在容器管理和bean管理事务中这些参数的正确取值。
在使用完topicconnection后释放它以节省资源,是一个良好的编程习惯。
topicconnection connect = factory.createtopicconnection();
...
connect.close();
topicpublisher
使用topicsession创建topicpublisher,从而可以从travelagent
ejb中发送消息到topic对象给定的目的地中。任何订阅该topic的
jms客户都将收到该消息的拷贝:
topicpublisher publisher = session.createpublisher(topic);
textmessage textmsg = session.createtextmessage();
textmsg.settext(ticketdescription);
publisher.publish(textmsg);
消息类型
in jms, a message is a java object with two parts: a header and a message body. the header is composed of delivery information and metadata, while the message body carries the application data, which can take several forms: text, serializable objects, byte streams, etc. the jms api defines several message types (textmessage, mapmessage, objectmessage, and others) and provides methods for delivering messages to and receiving messages from other applications. 在
jms中,消息是由两部分构成的
java对象:消息头(header)和消息体。消息头由分发信息和原数据组成,而消息体是应用程序数据,现支持的消息体格式有:文本、序列化对象、字节流等等。
jms api定义了几种消息类型(textmessage、mapmessage、objectmessage等)并提供了用于在应用间分发和接收消息的方法。
比如,将travelagent
ejb作如下改变,使得它发送mapmessage而不是textmessage消息:
ticketdo ticket = new ticketdo(customer,cruise,cabin,price);
...
topicpublisher publisher = session.createpublisher(topic);
mapmessage mapmsg = session.createtextmessage();
mapmsg.setint("customerid", ticket.customerid.intvalue());
mapmsg.setint("cruiseid", ticket.cruiseid.intvalue());
mapmsg.setint("cabinid", ticket.cabinid.intvalue());
mapmsg.setdouble("price", ticket.price);
publisher.publish(mapmsg);
其中,接收该消息的
jms客户能够通过名字访问mapmessage的属性(customerid、cruiseid、cabinid、和price)。
换过一种做法,在travelagent
ejb中使用objectmessage类型的消息,从而可以发送完整的ticketdo对象。其中,该消息实现了
java序列化。
ticketdo ticket = new ticketdo(customer,cruise,cabin,price);
...
topicpublisher publisher = session.createpublisher(topic);
objectmessage objectmsg = session.createobjectmessage();
objectmsg.setobject(ticket);
publisher.publish(objectmsg);
除了textmessage、mapmessage和objectmessage,
jms还提供了两种其他的消息类型:streammessage和bytesmessage。streammessage把i/o流的内容作为消息有效载荷。同时,bytesmessage操作字节数组,即opaque data。
xml配置描述符
when a
jms resource is used, it must be declared in the bean's
xml deployment descriptor, in a manner similar to the jdbc resource used by the ship
ejb in chapter 10:
使用
jms资源时,必须在
ejb的
xml配置描述符中声明。其操作方式类似于第10章ship
ejb中的jdbc资源的声明。
<enterprise-beans>
<session>
<ejb-name>travelagentbean</ejb-name>
...
<resource-ref>
<res-ref-name>jms/topicfactory</res-ref-name>
<res-type>javax.jms.topicconnectionfactory</res-type>
<res-auth>container</res-auth>
</resource-ref>
<resource-ref>
<res-ref-name>jdbc/titandb</res-ref-name>
<res-type>javax.sql.datasource</res-type>
<res-auth>container</res-auth>
</resource-ref>
<resource-env-ref>
<resource-env-ref-name>jms/tickettopic</resource-env-ref-name>
<resource-env-ref-type>javax.jms.topic</resource-env-ref-type>
</resource-env-ref>
...
</session>
其中,用于
jms topicconnectionfactory的<resource-ref>,类似于jdbc datasource中的<resource-ref>声明:声明jndi enc名字、接口类型和授权协议。除了<resource-ref>之外,travelagent
ejb还必须声明<resource-env-ref>,这项元素列举出和< resource-ref >相关的任何“被管理对象”。在这里,声明topic以用于发送ticket消息。在部署阶段,部署者将把<resource-ref>和<resource-ref>中声明的
jms topicconnectionfactory和topic映射到
jms工厂和topic。
待续。。。。。。。。
bill-转自:csdn