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. 佛祖保佑 永无BUG 永不改动

    //////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // / ...

  2. GPS 偏移校正(WGS-84) 至(GCJ-02) java版本号以实现

    public class EvilTransform { final static double pi = 3.14159265358979324; // // // a = 6378245.0, 1 ...

  3. ROM签名脚本[原创]

    下面的代码是bash脚本来的.需要保存为*.sh后序. # !/bin/bash #usage: signapk.sh [-hs] [zipfile-unsigned | update.zip] #A ...

  4. 重新想象 Windows 8 Store Apps (29) - 图片处理

    原文:重新想象 Windows 8 Store Apps (29) - 图片处理 [源码下载] 重新想象 Windows 8 Store Apps (29) - 图片处理 作者:webabcd介绍重新 ...

  5. 【SICP读书笔记(二)】使用过程来黏合数据 —— 酷炫吊的消息传递机制

    首先,让我们来看几个内建函数 (cons x y),作用是把x和y绑定成一个序对 (car z),作用是提取z序对的第一个元素 (cdr z),作用是提取z序对的第二个元素 容易看出,这个东西有点类似 ...

  6. js你真的了解offsetWidth吗

    offsetWidth是什么? 答:它可以获取物体宽度的数值 那么就只是这样吗! html部分 <div id="div1"></div> <styl ...

  7. Android运用自己的标题栏

    Android程序的标题栏TitleBar区域很单调,如果想个性化一些可以通过下面的方法来为自己软件的标题定制一个layout布局文件,比如浏览器的标题栏,它包含了网站的Favicon,自定义的进度条 ...

  8. [LeetCode53]Maximum Subarray

    问题: Find the contiguous subarray within an array (containing at least one number) which has the larg ...

  9. java提高篇(十)-----强制类型转换

    在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...

  10. ZenCoding for EmEditor Snippets 的安装

    ZenCoding for EmEditor的安装 你可以从这里下载所需文件Library under the Snippets category.安装前请确认你的EmEditor内置有代码片段(Sn ...