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. 什么是 CGI,什么是 IIS,什么是VPS

    该公司来到天.我们所从事的事情在网站上.这对我来说确实是一个很大的挑战.个人一直从事Android,对于web而一个开发网站server知识的几乎为零.在这里应该说,现在我只是有一个技术人员,昨天相遇 ...

  2. listary文件查找程序下载和使用

    资源:PHP开发学习门户网站 地址:http://bbs.phpthinking.com/forum.php?mod=viewthread&tid=173 Listary 是一款有用的国产Wi ...

  3. 如何设置一个activity透明(转)

    1.在AndroidManifest.xml文件中设置: ? 1 android:theme="@android:style/Theme.Translucent 此代码固定为全背景透明. 2 ...

  4. T-SQL基础(2) - 单表查询

    开窗函数over select orderid, custid, val, SUM(val) over() as totalvalue, SUM(val) over(partition by cust ...

  5. W5500 keep-alive的用途及使用

    大家是否遇到过这种问题,W5500作为server已经建立连接,突然网线掉了,然后再去连接W5500.就连不上了. 为什么?以下对这个问题进行解释说明,并提出解决的方法. 图1中的上位机程序作为cli ...

  6. 生活中的大数据 hadoop

    大数据和我有关吗?大数据就是大量的数据吗?只有互联网公司才有大数据吗?想盘活大数据必须买昂贵的软硬件吗?大数据怎么存储计算?大数据,这个时下最火热的互联网词语,你了解多少呢?

  7. [Windows Phone] 以多国语言做为开发前提 (2)

    原文:[Windows Phone] 以多国语言做为开发前提 (2) ? 前言 在先前的文章 [Windows Phone 开发 - 以多国语言做为开发前提 (1)] 中说明了简单的多国语言范例,今天 ...

  8. Aix db2 经user a using b连接时报SQL30082N Security processing failed with reason "42"

    db2inst1登录 输入实例文件夹:/opt/ibm/db2/V9.7/instance 关闭实例:db2stop 更新示例:./db2iupdt db2inst1 启动实例:db2start 再次 ...

  9. 【数据库摘要】4_Sql_Like

    SQL LIKE 操作符 LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式. SQL LIKE 语法 SELECT column_name(s) FROM table_name WHERE ...

  10. 读书时间《JavaScript高级程序设计》三:函数,闭包,作用域

    上一次看了第6章,面向对象.这里接着看第7章. 第7章:函数表达式 定义函数有两种方式:函数声明.函数表达式 //函数声明 function functionName(arg0,arg1,arg2){ ...