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. Just4Fun - Comparaison between const and readonly in C#

    /* By Dylan SUN */ Today let us talk about const and readonly. const is considered as compile-time c ...

  2. [Elasticsearch] 控制相关性 (一) - 后面的相关度分值理论计算

    从第一章翻译Elasticsearch官方指南Controlling Relevance一章. 控制相关度(Controlling Relevance) 对于仅处理结构化数据(比方日期.数值和字符枚举 ...

  3. Codeforces Round #253 (Div. 1) B. Andrey and Problem

    B. Andrey and Problem time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  4. Type mismatch: cannot convert from Enumeration<String> to Enumeration<Object>

    完整的错误信息: Description Resource Path Location TypeType mismatch: cannot convert from Enumeration<St ...

  5. putty中的一些经常使用操作

    (和Linux中操作差点儿相同s) 删除文件夹 rm -rf /home/apache-tomcat-8.0.9 就会把home下的apache-tomcat-8.0.9目录给删除了 删除文件 rm ...

  6. C# 通过豆瓣网络编程API获取图书信息

    这篇文章主要是关于如何通过豆瓣API获取信息的书籍,起初,我看到了原来的想法的内容是"C# 网络编程之网页简单下载实现"中通过HttpWebResponse类下载源代码,再通过正則 ...

  7. 重新想象 Windows 8 Store Apps (22) - 文件系统: 访问文件夹和文件, 通过 AQS 搜索本地文件

    原文:重新想象 Windows 8 Store Apps (22) - 文件系统: 访问文件夹和文件, 通过 AQS 搜索本地文件 [源码下载] 重新想象 Windows 8 Store Apps ( ...

  8. Android 设计模式模式适配器

    自定义适配器模式:一类的接口,转换成客户的期望,也是一个接口.适配器使原本接口不是与类兼容可以无缝.下面两个图看起来更加清晰 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...

  9. Android程序猿学习路径

    而一些工作,而不仅仅是通信毕业生,很多学生没有工作或熟练Android工作人员指导的情况下,,如何学习Android而提高Android更多关注的水平. 享: 1.Android知识 1.1.站点资源 ...

  10. hdu 1251 统计拼图

    二手tire木: Basic应用程序 谈到很具体的 点击打开链接 #include<cstdio> #include<cstring> #include<iostream ...