1. MDB作为异步消费者的本质

2. MDB的运行机制

3. 使用@MessageDriven修饰MDB(需要messageListenerInterface)

4. 实现MessageListener

5. MDB的生命周期

6. 在MDB中使用依赖注入

7. MDB中的事务管理和异常管理

------------------------------------------------

1. MDB作为异步消费者的本质

MDB存在于EJB容器之中,可以利用EJB提供的事务、安全和并发性等系统服务。MDB并不直接与客户端交互,只是一个JMS消息的异步消费者。

EAO: Entiry Access Object

2. MDB的运行机制

MDB是由无状态Session Bean变化而来的,因此在用法上与其相似,不会保存客户端的调用状态,可被多个客户端共享。客户端需要以同步方式来调用无状态Session Bean,MDB不允许直接调用,它只是一个消息监听者。

消息生产者(发送消息)-->JMS消息目的(触发onMessage()方法)-->MDB(调用业务方法)-->Session Bean

3. 使用@MessageDriven修饰MDB

#1. EJB开发(Net Beans创建EJB Module, 项目名称:SimpleMDB)

SimpleMDB.java

package org.crazyit.jms;

import javax.ejb.*;
import javax.jms.*; @MessageDriven(activationConfig
= {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "MessageQueue")
} ,
messageListenerInterface = javax.jms.MessageListener.class,
mappedName = "MessageQueue"
)
public class SimpleMDB { public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
TextMessage txt = (TextMessage) msg;
String content = txt.getText();
System.out.println("JMS信息中信息为:" + content);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

#2. 消息发送(Net Beans创建Java Project, 项目名称:SendMsg)

SendMsg.java

package lee;

import javax.jms.*;
import javax.naming.*;
import java.util.Properties; public class SendMsg { public void sendMessage() throws NamingException, JMSException {
//定义WebLogic默认连接工厂的JNDI
final String CONNECTION_FACTORY_JNDI = "weblogic.jms.ConnectionFactory";
//获取JNDI服务所需的Context
Context ctx = getInitialContext();
//通过JNDI查找获取连接工厂
ConnectionFactory connFactory = (ConnectionFactory) ctx.lookup(CONNECTION_FACTORY_JNDI);
//通过JNDI查找获取消息目的
Destination dest = (Destination) ctx.lookup("MessageQueue");
//连接工厂创建连接
Connection conn = connFactory.createConnection();
//JMS连接创建JMS会话
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
//JMS会话创建消息生产者
MessageProducer sender = session.createProducer(dest);
//设置消息生产者生产出来的消息的传递模式、有效时间。
sender.setDeliveryMode(DeliveryMode.PERSISTENT);
sender.setTimeToLive(20000);
//通过JMS会话创建一个文本消息
TextMessage msg = session.createTextMessage();
  //msg.setStringProperty("ConType","txt");
//设置消息内容
msg.setText("Hello");
//发送消息
sender.send(msg);
msg.setText("Welcome to JMS");
//再次发送消息
sender.send(msg);
//关闭资源
session.close();
conn.close();
} //工具方法,用来获取命名服务的Context对象
private Context getInitialContext() {
// 参见(4)
} public static void main(String[] args) throws Exception {
SendMsg sender = new SendMsg();
sender.sendMessage();
}
}

SendMapMsg.java

package lee;

import javax.jms.*;
import javax.naming.*;
import java.util.Properties; public class SendMapMsg { public void sendMessage() throws NamingException, JMSException {
//定义WebLogic默认连接工厂的JNDI
final String CONNECTION_FACTORY_JNDI = "weblogic.jms.ConnectionFactory";
//获取JNDI服务所需的Context
Context ctx = getInitialContext();
//通过JNDI查找获取连接工厂
ConnectionFactory connFactory = (ConnectionFactory) ctx.lookup(CONNECTION_FACTORY_JNDI);
//通过JNDI查找获取消息目的
Destination dest = (Destination) ctx.lookup("MessageQueue");
//连接工厂创建连接
Connection conn = connFactory.createConnection();
//JMS连接创建JMS会话
Session session = conn.createSession(false/*不是事务性会话*/, Session.AUTO_ACKNOWLEDGE);
//JMS会话创建消息生产者
MessageProducer sender = session.createProducer(dest);
//设置消息生产者生产出来的消息的传递模式、有效时间。
sender.setDeliveryMode(DeliveryMode.PERSISTENT);
sender.setTimeToLive(20000);
//通过JMS会话创建一个文本消息
MapMessage msg = session.createMapMessage();
//设置消息内容
msg.setString("name", "孙悟空");
msg.setString("gender", "男");
msg.setInt("age", 500);
//发送消息
sender.send(msg);
//关闭资源
session.close();
conn.close();
} //工具方法,用来获取命名服务的Context对象
private Context getInitialContext() {
// 参见(4)
} public static void main(String[] args) throws Exception {
SendMapMsg sender = new SendMapMsg();
sender.sendMessage();
}
}

4. 实现MessageListener

#1. EJB开发(Net Beans创建EJB Module, 项目名称:SimpleMDBListener)

SimpleMDB.java

package org.crazyit.jms;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage; @MessageDriven(activationConfig ={
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "MessageQueue")
},
     mappedName = "MessageQueue"
)
public class SimpleMDB implements MessageListener { @Override
public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
TextMessage txt = (TextMessage) msg;
String content = txt.getText();
System.out.println("JMS信息中信息为:" + content);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

5. MDB的生命周期

#1. EJB开发(Net Beans创建EJB Module, 项目名称:Lifecycle)

LifecycleMDB.java

package org.crazyit.jms;

import javax.ejb.*;
import javax.jms.*;
import javax.annotation.*; @MessageDriven(activationConfig
= {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "MessageQueue")
},
mappedName = "MessageQueue"
)
public class LifecycleMDB implements MessageListener { public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
TextMessage txt = (TextMessage) msg;
String content = txt.getText();
System.out.println("JMS信息中信息为:" + content);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
} @PostConstruct
public void myInit() {
System.out.println("--初始化方法--");
} @PreDestroy
public void myDestroy() {
System.out.println("--销毁之前的方法--");
}
}

6. 在MDB中使用依赖注入

#1. EJB开发(Net Beans创建EJB Module, 项目名称:Injection)

Injection.java

package org.crazyit.jms;

import javax.ejb.*;
import javax.jms.*; import org.crazyit.service.*; @MessageDriven(activationConfig
= {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "MessageQueue")
},
mappedName = "MessageQueue"
)
public class Injection implements MessageListener { @EJB(name = "StudentBean")
private Student student; public void onMessage(Message msg) {
try {
if (msg instanceof MapMessage) {
MapMessage map = (MapMessage) msg;
String name = map.getString("name");
String gender = map.getString("gender");
int age = map.getInt("age");
//调用Session Bean的方法添加学生。
student.add(name, gender, age);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

Student.java

package org.crazyit.service;

import javax.ejb.*;

@Remote
public interface Student {
void add(String name, String gender, int age) throws Exception;
}

StudentBean.java

package org.crazyit.service;

import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.annotation.*; @Stateless(name = "StudentBean")
public class StudentBean implements Student { //采用依赖注入获取数据源
@Resource(name = "javaee")
private DataSource ds; public void add(String name, String gender, int age) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//通过数据源获取数据库连接
conn = ds.getConnection();
//使用PreparedStatement执行SQL语句
pstmt = conn.prepareStatement("insert into student values(null , ? , ? , ?)");
pstmt.setString(1, name);
pstmt.setString(2, gender);
pstmt.setInt(3, age);
pstmt.executeUpdate();
}
finally {
pstmt.close();
conn.close();
}
}
}

7. MDB中的事务管理和异常管理

MDB同样支持CMT和BMT,使用CMT,采用如下两种Annotation来修饰MDB的Bean实现类或方法:

@TransactionManagement:配置事务管理类型

@TransactionAttribute:配置事务管理属性

如果希望CMT事务管理机制遇到自定义异常时也能回滚事务,有两种处理方式:

#1. 定义该自定义异常类时使用@ApplicationException(rollback=true)

#2. 程序中显式捕获该异常,然后调用ctx.setRollback(true);代码来控制事务回滚。

JavaEE(11) - 消息驱动EJB的更多相关文章

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

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

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

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

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

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

  4. 消息驱动Bean

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

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

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

  6. EJB_消息驱动发展bean

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

  7. EJB_开发消息驱动bean

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

  8. SpringCloud实战9-Stream消息驱动

    官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架. 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互 ...

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

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

随机推荐

  1. 【Android接口实现】ActionBar利用整理的一些细节

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 关于ActionBar的使用,非常多大神早就已经写了非常好的文章进行了介绍,所以ActionBar的基本使用 ...

  2. HTTP请求WebTool

    /// <summary> /// 执行HTTP POST请求. /// </summary> /// <param name="url">请求 ...

  3. Hdu 5256 系列转换

    主题链接: HDU5236 代码: #include<iostream> #include<cstdio> #include<cstring> #include&l ...

  4. NLB+Application Request Route 网路负载均衡

    NLB网路负载均衡管理器详解   序言 在上一篇配置iis负载均衡中我们使用啦微软的ARR,我在那篇文章也中提到了网站的高可用性,但是ARR只能做请求入口的消息分发服务,这样如果我们的消息分发服务器给 ...

  5. 达到J2EE在后台action控制接待javascript弹出的对话框

    1.后台Action于: request.setAttribute("message", "这项username要么password错误,请重新输入!"); 2 ...

  6. 开源NetWorkSocket通讯组件

    开源NetWorkSocket通讯组件   前言 在<化茧成蝶,开源NetWorkSocket通讯组件>发表之后,收到大家很多个star,在此感谢!更可贵的是,一些网友提出了许多好建议,经 ...

  7. JFileChooser

    http://www.cnblogs.com/dyllove98/archive/2012/03/05/2461895.html package swing.choose; import java.a ...

  8. HDU 5050 Divided Land(进制转换)

    题意  给你两个二进制数m,n   求他们的最大公约数  用二进制表示  0<m,n<2^1000 先把二进制转换为十进制  求出最大公约数  再把结果转换为二进制  数比較大要用到大数 ...

  9. Spark SQL源代码分析之核心流程

    /** Spark SQL源代码分析系列文章*/ 自从去年Spark Submit 2013 Michael Armbrust分享了他的Catalyst,到至今1年多了,Spark SQL的贡献者从几 ...

  10. Zen Coding css,html缩写替换大观 快速写出html,css

    阅读本文,先仔细阅读网站文章. Zen Coding 快速编写HTML/CSS代码的实现 复制代码 代码如下:E 元素名称(div, p); E#id 使用id的元素(div#content, p#i ...