消息驱动Bean
消息驱动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的更多相关文章
- Intellij IDEA 创建消息驱动Bean - 接收JMS消息
除了同步方式的调用之外,有时还需要异步调用,用来处理不需要即时处理的信息,例如短信.邮件等,这需要使用EJB中的独特组件——消息驱动Bean(Message-Driven Bean,MDB),它提供了 ...
- JMS和消息驱动Bean(MDB)
一.说明 本示例使用的ActiveMQ作为消息中间件,服务器为Glassfish,使用JMS发送消息,在MDB接收到消息之后做打印输出. 二.ActiveMQ安装配置 1.安装console war包 ...
- EJB_开发消息驱动bean
开发消息驱动bean Java消息服务(Java MessageService) Java 消息服务(Java Message Service,简称 JMS)是用于访问企业消息系统的开发商中立的API ...
- 菜鸟调错(二)——EJB3.0部署消息驱动Bean抛javax.naming.NameNotFoundException异常
在部署EJB的消息驱动Bean时遇到了如下的错误: ERROR [org.jboss.resource.adapter.jms.inflow.JmsActivation] (WorkManager(2 ...
- EJB3.0 EJB开发消息驱动bean
(7)EJB3.0 EJB开发消息驱动bean JMS 一: Java消息服务(Java Message Service) 二:jms中的消息 消息传递系统的中心就是消息.一条 Message 由三个 ...
- 消息驱动bean(MDB)实例
到眼下为止前面介绍的有关JavaEE的东西都是同步的.也就是说调用者调用某个方法.那么这种方法必须马上运行并返回运行结果. 用官方一些的语言来说就是"client通过业务接口调用一个方法,在 ...
- 3.开发Java消息驱动bean实例代码
java消息服务(JMS)是用于访问企业消息系统的开发商中立的API.企业消息系统可以协助应用软件通过网络进行消息交互.应用程序A发送一条消息到消息服务器的某个目的地(Destination),然后消 ...
- EJB_消息驱动发展bean
消息驱动发展bean Java信息服务(Java MessageService) Java 信息服务(Java Message Service,简称 JMS)是用于訪问企业消息系统的开发商中立的API ...
- 基于Kafka消息驱动最终一致事务(二)
实现用例分析 上篇基于Kafka消息驱动最终一致事务(一)介绍BASE的理论,接着我们引入一个实例看如何实现BASE,我们会用图7显示的算法实现BASE.
随机推荐
- Directx11教程(12) 禁止alt+enter全屏窗口
原文:Directx11教程(12) 禁止alt+enter全屏窗口 在D3D11应用程序中,我们按下alt+enter键,会切换到全屏模式.有时候,我们在WM_SIZE中有一些代码,全 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二章:矩阵代数
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二章:矩阵代数 学习目标: 理解矩阵和与它相关的运算: 理解矩阵的乘 ...
- H5+ 分享到微信、朋友圈代码示例
h5+分享到微信.朋友圈代码示例 在使用分享功能的时候会莫名的分享失败,debug时发现是图片过大的问题. 图片过大时ios平台上返回错误码-8,安卓上返回错误码-3(我测试是这样) 因此如果第一次分 ...
- Centos7.3-mysql5.7复制安装过程
一.环境 192.168.56.102 为主服务器 192.168.56.101 为从服务器 Mysql5.7.20 二进制安装包环境 1. 下载免编译安装包并进行安装 从官网下载 mysql-5.7 ...
- P2532 [AHOI2012]树屋阶梯
题目:P2532 [AHOI2012]树屋阶梯 思路: 打表之后不难看出是裸的Catalan数.简单证明一下: 对于任意一种合法方案,都可以表示为在左下角先放一个\(k*(n+1-k),k\in[1, ...
- 自动编码(AE)器的简单实现
一.目录 自动编码(AE)器的简单实现 一.目录 二.自动编码器的发展简述 2.1 自动编码器(Auto-Encoders,AE) 2.2 降噪自编码(Denoising Auto-Encoders, ...
- Java发送邮件的工具类
package com.csice.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNot ...
- oracle函数 TRIM(c1 from c2)
[功能]删除左边和右边出现的字符串 [参数]C2 删除前字符串 c1 删除字符串,默认为空格 [返回]字符型 [示例] select TRIM('X' from 'XXXgao qian jingXX ...
- Oracle数据字典全解
一.概念: 1.数据字典(data dictionary)是 Oracle 数据库的一个重要组成部分,这是一组用于记录数据库信息的只读(read-only)表. 数据字典里存有用户信息.用户的权限信息 ...
- Activity学习(二):Activity的启动模式(转载)
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...