消息驱动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.
随机推荐
- poj2449第K短路问题(A*算法)
启发函数:f(x)=g(x)+h(x); g(x)表示初始点到x状态的代价,h(x)表示从x的状态到目标状态的代价的估计值(并不是真实的),实际最小代价<=h(x); 起点s,终点t,x.v=s ...
- iOS:你App的设置做对了吗?
http://www.cocoachina.com/ios/20151217/14707.html iOS 8及以上版本最不为人知的一个特点是与应用设置的深层链接,用户可以根据APP的需要授权启用位置 ...
- python 定义子类
- QT语言翻译
QT中多语言的实现方式: 1.代码中tr运用 2.使用工具生成ts文件 3.翻译ts文件 4.生成qm文件 5.程序加载 以下内容程序加载时放入即可. QString appPath = QCoreA ...
- Request.Cookies和Response.Cookies
Request.Cookies创建的Cookie只能用于后台不能用于HTML的前台Response.Cookies操作过的Cookie,所有方法获取到的都是被更新过的值,也就是说Response.Co ...
- 人生苦短,LET'S GO! GO语言目录
1.Golang开山篇,GO就是NB! 1-1.go开发工具安装 2.go-人生第一个go程序和基本语法 3.go-流程控制 4.go-函数 5.go-流程控制 6.go-复合类型 7.go-面向对象 ...
- 修改oracle编码格式
文章参照:https://www.jb51.net/article/53078.htm 1.查看oracle当前编码格式: SELECT * FROM V$NLS_PARAMETERS WHERE P ...
- TreeSet的运用之使用内部比较器实现自定义有序(重要)
Student.java package com.sxt.set3; /* * TreeSet:有序 * implements Comparable<Student> * 如果用内部比较器 ...
- HZOJ Blue
Blue: 贪心. 我们不妨给蛤定一个先后顺序,则贪心策略即从右至左每只蛤依次往最远的石子跳. 证明: 如果最右的蛤不往最远的石子跳,而是选择了一个较近的石子,那么必然会存在一个该蛤左边的蛤越过了它跳 ...
- CF1238E.Keyboard Purchase 题解 状压/子集划分DP
作者:zifeiy 标签:状压DP,子集划分DP 题目链接:https://codeforces.com/contest/1238/problem/E 题目大意: 给你一个长度为 \(n(n \le ...