科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道快速应用JMS控件访问JMS资源

快速应用JMS控件访问JMS资源

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

JMS定义了Java中访问消息中间件的接口,是企业资源异步访问的主要形式。JMS可以和EJB技术集成使用,也就是常说的消息驱动BEAN。

来源:dev2dev 2007年12月10日

关键字: 应用 技术 java 中间件

  • 评论
  • 分享微博
  • 分享邮件

  JMS定义了Java中访问消息中间件的接口,是企业资源异步访问的主要形式。JMS可以和EJB技术集成使用,也就是常说的消息驱动BEAN。

  因为访问JMS和访问Entity EJB和SessionEJB的调用方法有很大的差异,所以Beehive中提供了专门的JMS控件来完成JMS资源的访问。

  创建JMS控件的典型步骤

  Beehive中提供的JMS控件无法直接用于访问JMS资源,使用者必须继承JMS控件来创建自己的访问控件,设置相关的环境后才能完成JMS资源的访问。一个继承控件中只能对应的访问唯一一个消息队列/主题,如果需要向多个消息队列/主题发送消息,必须针对每个消息队列/主题提供相应的控件。

  你可以使用下面的步骤来创建自己的控件实现对JMS资源的访问:

  创建新的Java接口,继承JMSControl接口

  用@ControlExtension关键字注释新创建的Java接口,通知解析器这个接口继承了另外的某个控件。

  使用@JMSControl.Destination注释新创建的Java接口,说明控件如何搜索消息队列/主题,同时使用sendType声明发送目标是消息队列还是消息主题。

  创建新的业务方法,使用JMSControl.Message注释来声明被发送消息的类型,或者使用不同的参数来区别不同的消息类型。

  使用控件访问消息队列的例子

  在本节中,我们将通过简单的例子演示如何使用JMS控件来访问监听消息队列的消息驱动Bean。我们假设存在一个消息驱动Bean,他接受用户传递的文本消息(TextMessage),随后将该文本消息打印在应用服务器的控制台上。该消息驱动Bean监听消息队列(jndiname=”queue/helloworld”)。

  Beehive并不仅仅限于WebLogic平台使用,我们这里以JBoss为例。我们使用Eclipse+WTP(Web Tools Platform)工具开发符合要求的消息驱动Bean以及JMS队列,发布在JBoss上。

  本文中所有例子的源代码可以在通过资源下载区中的连接完成下载。

  开发消息驱动Bean

  现在我们来开发提供上述功能的消息驱动Bean,使用WTP的向导完成消息驱动Bean的创建工作,剩下的工作就是根据业务的需求完成onMessage方法的编写了。

  根据演示实例的要求,我们修改onMessage方法,让它处理TextMessage类型的消息,并且将消息的内容打印在控制台上,清单1中列出了消息驱动Bean类的源代码。如何开发、编译和部署请参考JBoss的帮助文档,这里不提供详细的说明。

  接下来的JMS、EJB开发、部署和控件访问部分内容针对JBoss应用服务器。实际情况下,你可能根据不同情况选择其他的J2EE容器比如Websphere 、WebLogic、Geronimo、JOnAS等作为EJB容器,请根据下面的提示信息进行适当的调整。

  清单1 ejbsrcorgvivianjeehivecontrolsexamplesejbMessageBeanOnQueue.java

  1. package org.vivianj.beehive.controls.examples.ejb;

  2.

  3. import javax.ejb.*;

  4. import javax.jms.*;

  5.

  6. public class MessageBeanOnQueue

  7. implements MessageDrivenBean, MessageListener

  8. {

  9. public void onMessage(Message msg) {

  10. TextMessage tm = null;

  11. if (msg instanceof TextMessage){

  12. tm = (TextMessage) msg;

  13. try{

  14. System.out.println(tm.getText());

  15. }catch(Exception e){

  16. e.printStackTrace();

  17. }

  18. }

  19. }

  20. }

  

  在部署消息驱动Bean之前,我们还应该在JBoss服务器上配置一个JNDI名称为“queue/helloworld”的消息队列。请大家参考JBoss应用服务器的帮助文档完成这部分工作。

  JMS控件开发

  现在我们来使用JMS控件编写代码访问消息驱动Bean。由于消息驱动Bean没有本地或者远程访问方法,只能通过向JMS目标发送消息来完成消息驱动Bean资源的调用。

  清单2中的代码是访问一个JMS目标对列的简单例子,它提供sendTextMessage方法,接收String类型的参数msn,当sendTextMessage方法被调用时,控件负责连接到JMS对列(“queue/helloworld”),将接收到的参数msg发送到目标服务器上。

  清单2 srcorgvivianjeehivecontrolsexamplescontrols

  HelloWorldQueueJMSControl.java

  1. package org.vivianj.beehive.controls.examples.controls;

  2.

  3. import org.apache.beehive.controls.api.bean.ControlExtension;

  4. import org.apache.beehive.controls.system.jms.JMSControl;

  5.

  6. /**

  7. * HelloWorldQueueJMSControl 是访问JMS资源的控件

  

  8. * 可向JMS对列发送字符串类型的消息

  9. */

  10.

  11. @ControlExtension

  12. @JMSControl.Destination(sendJndiName = “queue/helloworld”,

  13. jndiConnectionFactory =

  14. “org.jnp.interfaces.NamingContextFactory”,

  15. jndiProviderURL=“jnp://localhost:1099”,

  16. sendType=DestinationType.Queue)

  17. public interface HelloWorldQueueJMSControl

  18. extends JMSControl {

  19. @JMSControl.Message(MessageType.Text)

  20. public void sendTextMessage(String msg);

  21. }

  

  JMS控件调用

  现在我们可以使用如下方法来完成上面所创建控件的调用。

  使用声明式控件实例化定义成员变量_jmsControl.

  @Control

  HelloWorldQueueJMSControl _jmsControl;

  调用控件的业务方法完成向JMS对列发送消息的功能。由于消息服务本身是没有返回内容的,所以我们只需要完成业务方法的调用即可。

  下面的调用代码可以实现向服务器发送”Hello World!”字符串的功能。

  _jmsControl.sendTextMessage(“Hello World!”);

  测试控件

  一切准备就绪后,启动JBoss服务器,参考《控件入门》中“使用JUnit测试控件”部分的内容,编写单元测试TestCase测试新创建的JMS控件。

  实例分析

  从上面的例子中我们可以看到,访问JMS资源的时候,开发者的工作被大大的简化了。开发者只需要开发一个继承自JMS控件的控件,使用JMS控件中规定的注释提供访问JMS资源所需要的一些环境参数,随后便可以使用声明式控件实例化方式完成控件的实例化,通过调用该控件实例的相关业务方法完成JMS资源的访问。

  现在我们来分析一下上面创建的EJB控件-- HelloWorldQueueJMSControl (参见清单2)中的主要代码。

  11. @ControlExtension

  在控件例子的11行,我们通过@ControllerExcention关键词来说明接下来声明的这个接口是另外一个控件的扩展。

  12. @JMSControl.Destination(sendJndiName = “queue/helloworld”,

  13. jndiConnectionFactory =

  14. “org.jnp.interfaces.NamingContextFactory”,

  15. jndiProviderURL=“iiop://localhost:7001”,

  16. sendType=DestinationType.Queue))

  

  在第12~16行代码中我们使用JMSControl.Destination关键词和它的sendJndiName、jndiConnectionFactory、jndiProviderURL和sendType属性来设置我们要访问消息队列/主题在目标服务器中发布时使用的jndiName和访问目标服务器需要提供的相关环境变量。

  17. public interface HelloWorldQueueJMSControl

  18. extends JMSControl {

  在第17~18行中,我们声明该控件继承了JMSControl接口。

  19. @JMSControl.Message(MessageType.Text)

  在第19行,我们使用@JMSControl.Message关键字来声明接下来的这个业务方法发送消息的类型是TextMessage。

  20. public void sendTextMessage(String msg);

  

  第20行代码我们声明了一个方法,这个方法需要向目标消息队列/主题发送参数msg提供的字符串。

  完成这些工作,我们就可以调用该控件声明的方法实现向目标消息队列/主题发送JMS消息了,如何与目标应用服务器交互的工作由控件来辅助完成。

  使用注释定制JMS控件

  在上面的内容中,我们已经新建了一个JMS控件,它提供sendTextMessage方法,调用该方法能够向消息对列”queue/helloworld”发送消息。在JMS控件代码中,我们使用了@JMSControl.Destination我们使用了@JMSControl.Destination和@JMSControl.Message两个注释来提供访问JMS资源的参数。

  JMS控件支持10个注释,他们分别是@JMSControl.CorrelationId、@JMSControl.Delivery 、@JMSControl.Destination 、@JMSControl.Expiration 、@JMSControl.Message 、@JMSControl.Priority 、@JMSControl.Properties 、@JMSControl.Property 、@JMSControl.PropertyValue 、@JMSControl.Type

  下面我们详细的介绍其中最常用的@JMSControl.Destination和@JMSControl.Message两个注释的属性和用法,了解如何用这注释定制JMS控件的更多细节。

  Destination注释

  Destination注释是类级别的注释,用于定制JMS控件发送消息的目标消息队列/主题的jndiName和它们所在目标容器的相关参数。Destination注释提供了八个参数用于用户定制,下面将介绍常用的四个:sendJndiName、jndiConnectionFactory、 sendType、jndiProviderURL,其中sendJndiName和jndiConnectionFactory是必须的,其他的可以根据不同的情况选择性的使用。

  sendJndiName

  字符串类型的属性,用于设置目标消息队列或者主题的JNDI名称。

  sendType

  JMSControl.DestinationType类型的属性,可选值有三个:DestinationType.Auto(自动适配类型),DestinationType.Topic(主题)和DestinationType.Queue(队列),如果使用DestinationType.AUTO,控件将根据sendJndiName中指定的目标消息类型进行适配。

  jndiConnectionFactory

  字符串类型的属性,设置访问EJB JNDI上下文环境需要使用工厂类,和具体的目标EJB服务器相关。比如访问JBoss服务器上的JMS资源时可以设置jndiConnectionFactory为“org.jnp.interfaces.NamingContextFactory”。

  jndiProviderURL

  字符串类型的属性,设置目标EJB容器的相关属性,包括访问JNDI上下文环境使用的协议、目标服务器IP地址、服务端口等,比如访问JBoss容器中消息队列时,providerURL可以写成”jnp://localhost:1099”。

  Message注释

  Message注释是JMS控件中方法级别的注释,它的参数为JMSControl.MessageType类型,用于注释新创建JMS控件的业务方法,声明该业务方法发送消息的类型,可选参数包括MessageType.Text、MessageType. Bytes(字节类型)、MessageType.Object(对象类型), MessageType.Map (Map类型)、MessageType.JMSMessage(JMS消息类型)、MessageType.Auto(自动适配类型),默认的消息类型是MessageType.Auto。

  如果使用默认的消息类型或者设置被发送消息的类型为MessageType.Auto,控件将根据被发送消息的类型来决定发送消息时使用的消息类型:

  如果被发送的消息是字符串内容或者是XML对象,控件将发送TextMessage类型的消息给目标消息队列/主题;

  如果被发送的消息内容是字节数组,控件将发送StreamMessage类型的消息给目标消息队列/主题;

  如果被发送的消息内容是字节数组,控件将发送StreamMessage类型的消息给目标消息队列/主题;

  如果被发送的消息内容是Map对象,控件将发送MapMessage类型的消息给目标消息队列/主题;

  如果被发送的消息内容是JMSMessage对象,控件将发送JMSMessage类型的消息给目标消息队列/主题;

  如果被发送的消息内容实现了Serializable接口,控件将发送ObjectMessage类型的消息给目标消息队列/主题;

  其他的消息内容,控件将不发送消息,而是抛出一个违例。

  JMS控件内置的方法

  JMS控件提供了很多可以在运行时对JMS控件进行定制的Java方法,开发者使用这些内置的方法可以在使用JMS控件的过程中根据不同的情况灵活的加以应用,以便能够完成各种复杂的业务逻辑。

  getSession()

  获取当前访问消息队列/主题的会话对象。

  getDestination()

  获取当前访问消息队列/主题的目标服务的相关信息。

  getConnection()

  获取当前访问消息队列/主题和目标服务器之间的连接。

  setHeaders(Map)

  setHeader(HeaderType,Object)

  这两个方法都用于设置被发送消息的头信息,只有调用了这两个方法后接着发送的消息才使用这部分头信息,其他的消息不具备这些头信息。如果发送的消息中也设置了同样的信息,使用setHeaderX方法设置的参数将覆盖消息中设置的参数。

  被设置的头信息包括JMSCorrelationID、JMSExpriation 、Priority 、JMSType,用于发送消息时标识身份或者提供消息发送所需要的路由。

  setProperties(Map)

  setProperty(String,Object)

  这两个方法用于在发送消息的同时提供更多的属性信息,可以用于在应用中作为扩展头信息而使用,可发送的类型可以是boolean, byte, short, int, long, float, double, or String等基本Java数据类型。

  结束语

  JMS是J2EE框架中最重要的部分,也是企业应用中提供异步消息访问的技术实现,然而JMS的客户端编写对于开发者而言不是一件轻松的事情。控件架构中的JMS控件大大的简化了JMS资源的复杂性、难度,开发者只需要通过简单的继承org.apache.beehive.controls.system.jms.JMSControl,然后通过提供相应的注释就可以完成JMS资源的访问。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章