消息驱动bean是专门用来处理基于消息请求的组件。MDB负责处理消息,而EJB容器则负责处理服务(事务,安全,并发,消息确认等),使Bean的开发者集中精力在处理消息的业务逻辑上。

消息驱动Bean。消息驱动Bean允许J2EE应用程序异步的接收Java消息服务(JMS)的消息。消息驱动Bean包含处理接受到的消息的事务逻辑,主要作用是处理消息。它与其他Bean(实体Bean和会话Bean)的区别主要在于以下几点:

  a) 消息驱动Bean没有任何接口,客户程序不是通过接口来访问消息驱动Bean的,它处理的消息可以来自任何消息客户程序。

  b) 消息驱动Bean类似于无状态会话Bean,是没有状态的,它的实例不保持特定客户程序的会话状态。

  c) 消息驱动Bean不需要返回任何数值给他的客户程序,也不能向客户程序返回异常,因为消息驱动Bean是异步地处理消息的。

Java消息服务是用于访问企业消息系统的开发商中立的API。

JMS应用由两部分组成:
多个JMS客户端,包含消息生成器客户端和消息使用者客户端。
一个JMS Provider。

Message消息由三部分组成:
头,用户包含路由和识别消息的值。
属性,由属性名和属性值对的形式组成。
主体,发送给接收者的内容。
所有的消息类型都派生值Message接口。

JMS消息的传递模型:

JMS支持两种消息传递模型:点对点(PTP)、发布订阅(pub/sub)。

(1).PTP:

一条消息只能传递给一个接收方,采用javax.jms.Queue表示。

每个消息被发送到一个特定的消息队列中,接收者从消息队列中获取消息,队列保留着消息直到消息被消费或者超时,当发送时如果接收方不在线,则当接收方上线时还可以接收到消息。

发送者和接收者之间在时间上没有依赖性,即当发送者发送了消息之后,不管接收者是否在运行,都不会影响消息被发送到消息队列,接收者在成功接收消息之后需要向队列应答成功,若希望发送的每条消息都应该被成功接收处理的话,应该使用PTP方式。

(2).pub/sub:

一条消息可以传递给多个接收方,采用javax.jms.Topic表示。

每条消息可以有多个接收者,发布者和订阅者有时间上的依赖性,针对某个主题的订阅者必须创建一个订阅之后才能消费发布者发布的消息,而且为了接收消息,订阅者必须保持运行。发布订阅模式的消息不支持离线消息,即当发生消息时,接收方如果不在线,当接收再次上线时就无法接收到已经发送过的消息。

为了缓和这种严格的时间相关性,jms运行订阅者创建一个可持久化的订阅,这样,即使订阅者没有被激活(运行),也能接收到发布者发布的消息。

若希望发送的消息可以不被做任何处理,或者被一个消费者处理,或者可以被多个消费者处理,应该使用pub/sub模型。

JMS消息组成:

JMS中一条消息的组成:消息头(header)、属性(property)、消息体(body)。

所有的消息都派生自Message接口,有以下几种类型:

(1).StreamMessage:一种主体中包含java二进制流的消息,其填充和读取均按顺序进行。

(2).MapMessage:一种主体中包含一组键值对的消息,没有定义条目顺序。

(3).TextMessage:一种主体中java字符串的消息(如,普通文本,xml文件等)。

(4).ObjectMessage:一种主体中包含序列化java对象的消息。

(5).ByteMessage:一种主体中包含连续字节流的消息。

classpath下配置jndi.properties

 java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099

配置消息到达目的地地址(Destination):jbossmq-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<server>
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=fwjpubsubtestDestination">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean> <mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=fwjptptestDestination">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="MessageCounterHistoryDayLimit">-1</attribute>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="noacc" read="false" write="false" create="false"/>
</security>
</attribute>
</mbean>
</server>

发送JMS消息过程

package com.joyen.messagedriven.sender;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException; public class QueueSender { public static void main(String[] args) {
try {
//得到一个JNDI初始化上下文:
InitialContext context = new InitialContext();
//根据上下文查找JMS连接工厂:该连接工厂是由JMS提供的,每个javaEE服务器厂商都为它绑定一个全局的JNDI。
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("QueueConnectionFactory");
//从连接工厂得到一个JMS连接:
QueueConnection conn = factory.createQueueConnection();
//通过jms连接创建一个jms会话:以QueueSession(TopicSession类似)为例:第一个参数表示:不需要事物。第二个参数表示:自动确认消息已接收的会话。
QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
//查找消息目标地址:
Destination destination = (Destination)context.lookup("queue/fwjptptestDestination");
//根据会话及目标地址来建立消息生产者
MessageProducer producer = session.createProducer(destination);
TextMessage msg = session.createTextMessage("hello fwj Queue");
producer.send(msg); //消息发送完毕后,关闭会话和连接:
conn.close();
session.close();
} catch (NamingException e) {
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
package com.joyen.messagedriven.sender;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException; public class TopicSender { public static void main(String[] args) {
try {
//得到一个JNDI初始化上下文:
InitialContext context = new InitialContext();
//根据上下文查找JMS连接工厂:该连接工厂是由JMS提供的,每个javaEE服务器厂商都为它绑定一个全局的JNDI。
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("TopicConnectionFactory");
//从连接工厂得到一个JMS连接:
QueueConnection conn = factory.createQueueConnection();
//通过jms连接创建一个jms会话:以QueueSession(TopicSession类似)为例:第一个参数表示:不需要事物。第二个参数表示:自动确认消息已接收的会话。
QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
//查找消息目标地址:
Destination destination = (Destination)context.lookup("topic/fwjpubsubtestDestination");
//根据会话及目标地址来建立消息生产者
MessageProducer producer = session.createProducer(destination);
TextMessage msg = session.createTextMessage("hello fwj topic");
producer.send(msg); //消息发送完毕后,关闭会话和连接:
conn.close();
session.close();
} catch (NamingException e) {
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
}
} }

使用消息驱动bean(MDB)接收消息

package com.joyen.messagedriven;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage; /**
* Message-Driven Bean implementation class for: PTPMessageDriven
*/
@MessageDriven(
activationConfig = {
@ActivationConfigProperty
(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),//监听目标地址类型
@ActivationConfigProperty
(propertyName="destination",propertyValue="queue/fwjptptestDestination")//目标地址JNDI名称
})
public class PTPMessageDriven implements MessageListener { /**
* Default constructor.
*/
public PTPMessageDriven() {
} /**
* @see MessageListener#onMessage(Message)
*/
public void onMessage(Message message) {
TextMessage msg = (TextMessage)message;
try {
System.out.println("1:"+msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
} }
package com.joyen.messagedriven;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage; @MessageDriven(
activationConfig = {
@ActivationConfigProperty
(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),//监听目标地址类型
@ActivationConfigProperty
(propertyName="destination",propertyValue="topic/fwjpubsubtestDestination")//目标地址JNDI名称
})
public class PubSubMessageDriven implements MessageListener { public void onMessage(Message message) {
TextMessage msg = (TextMessage)message;
try {
System.out.println("1:" + msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
} }
package com.joyen.messagedriven;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage; @MessageDriven(
activationConfig = {
@ActivationConfigProperty
(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),//监听目标地址类型
@ActivationConfigProperty
(propertyName="destination",propertyValue="topic/fwjpubsubtestDestination")//目标地址JNDI名称
})
public class PubSub2MessageDriven implements MessageListener { public void onMessage(Message message) {
TextMessage msg = (TextMessage)message;
try {
System.out.println("2:" + msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
} }

JMS中消息的两种接收方式:

(1).同步方式:订阅者或接收者调用receive方法来接收消息,此方法在接收到消息之前一直阻塞。

(2).异步方式:订阅者或接收者可以注册为一个消息监听器,当消息到达之后,系统自动调用监听器的onMessage方法。

当一个业务执行的时间很长,而执行结果无需实时向用户反馈时,很适合使用消息驱动Bean。如订单成功后给用户发送一封电子邮件或发送一条短信等。

参考:

http://baike.baidu.com/link?url=0POLqcCnVw38b5_bG3LE6uQZYZJZuQcOlm96UTWF3ms2kLFNv5iYa-Vv1Kvui504v2fd3Nfe5hLWiPMD4hz4SK

http://blog.csdn.net/chjttony/article/details/6072775

消息驱动Bean的更多相关文章

  1. Intellij IDEA 创建消息驱动Bean - 接收JMS消息

    除了同步方式的调用之外,有时还需要异步调用,用来处理不需要即时处理的信息,例如短信.邮件等,这需要使用EJB中的独特组件——消息驱动Bean(Message-Driven Bean,MDB),它提供了 ...

  2. JMS和消息驱动Bean(MDB)

    一.说明 本示例使用的ActiveMQ作为消息中间件,服务器为Glassfish,使用JMS发送消息,在MDB接收到消息之后做打印输出. 二.ActiveMQ安装配置 1.安装console war包 ...

  3. EJB_开发消息驱动bean

    开发消息驱动bean Java消息服务(Java MessageService) Java 消息服务(Java Message Service,简称 JMS)是用于访问企业消息系统的开发商中立的API ...

  4. 菜鸟调错(二)——EJB3.0部署消息驱动Bean抛javax.naming.NameNotFoundException异常

    在部署EJB的消息驱动Bean时遇到了如下的错误: ERROR [org.jboss.resource.adapter.jms.inflow.JmsActivation] (WorkManager(2 ...

  5. EJB3.0 EJB开发消息驱动bean

    (7)EJB3.0 EJB开发消息驱动bean JMS 一: Java消息服务(Java Message Service) 二:jms中的消息 消息传递系统的中心就是消息.一条 Message 由三个 ...

  6. 消息驱动bean(MDB)实例

    到眼下为止前面介绍的有关JavaEE的东西都是同步的.也就是说调用者调用某个方法.那么这种方法必须马上运行并返回运行结果. 用官方一些的语言来说就是"client通过业务接口调用一个方法,在 ...

  7. 3.开发Java消息驱动bean实例代码

    java消息服务(JMS)是用于访问企业消息系统的开发商中立的API.企业消息系统可以协助应用软件通过网络进行消息交互.应用程序A发送一条消息到消息服务器的某个目的地(Destination),然后消 ...

  8. EJB_消息驱动发展bean

    消息驱动发展bean Java信息服务(Java MessageService) Java 信息服务(Java Message Service,简称 JMS)是用于訪问企业消息系统的开发商中立的API ...

  9. 基于Kafka消息驱动最终一致事务(二)

    实现用例分析 上篇基于Kafka消息驱动最终一致事务(一)介绍BASE的理论,接着我们引入一个实例看如何实现BASE,我们会用图7显示的算法实现BASE.

随机推荐

  1. compass与css sprite(雪碧图)

    什么是css sprite? css sprite,中文叫雪碧图,也有人喊CSS精灵,就是一种背景拼合的技术,然后通过background-position来显示雪碧图中需要显示的图像. MDN相关链 ...

  2. 2019.9.19登陆注册猜数字给奖品combo

    #注册函数 def register(): registor_count = 0 while registor_count < 3: username_inp = input('user nam ...

  3. HZOJ 连连看

    考场几乎想到了正解,然而我也不知道当时在想啥,在没有证伪的情况下只是觉得无法实现就否了…… 最后打的好象是达哥说的O(4*15*n*m),复杂度不是很会证反正T成了暴力…… 题解: 对于测试点8,9, ...

  4. java对象转化为json字符串并传到前台

    package cc.util; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import ...

  5. 从零学React Native之06flexbox布局

    前面我们接触了好多React Native代码, 并没有介绍RN中的组件具体是如何布局的,这一篇文章,重点介绍下flexbox布局. 什么是flexbox布局 React中引入了flexbox概念,f ...

  6. CNN滤波器

    CNN 的第一步是把图片分成小块.我们通过选取一个给定宽度和高度的滤波器来实现这一步. 滤波器会照在图片的小块 patch (图像区块)上.这些 patch 的大小与滤波器一样大.   如之前视频所示 ...

  7. Twitter 宣布抛弃 Mesos,全面转向Kubernetes

    摘要: 从最早Mesos“代言人”到如今的全面转向“Kubernetes Native”,Twitter的举动再一次佐证了‘Kuberentes已经成为容器编排事实标准’这一断言. 本文作者:张磊 阿 ...

  8. @loj - 2288@「THUWC 2017」大葱的神力

    目录 @description@ @solution@ @data - 1@ @data - 2@ @data - 3@ @data - 4@ @data - 5@ @data - 6@ @data ...

  9. OO第四单元博客作业

    OO第四单元博客作业 BUAA_1706_HugeGun 目录 第四单元作业架构设计 四个单元架构设计及OO方法理解 四个单元测试理解与实践演进 课程收获 一点建议 第四单元作业架构设计 ### 第十 ...

  10. iptables 详细使用

    检查状态 先检查是否安装了iptables $ service iptables status 安装iptables $ yum install iptables 升级iptables $ yum u ...