1. 功能介绍
在EJB的分类中还有一个就是消息驱动Bean(MessageDrivenBean),百度的说明其实很到位。
消息驱动Bean(MDB) 是设计用来专门处理基于消息请求的组件。一个MDB类必须实现MessageListener接口。当容器检测到bean守候的队列一条消息时,就调用onMessage()方法,将消息作为参数传入。MDB在OnMessage()中决定如何处理该消息。你可以用注释来配置MDB监听哪一条队列。当MDB 部署时,容器将会用到其中的注释信息。当一个业务执行的时间很长,而执行结果无需实时向用户反馈时,很适合使用消息驱动Bean。如订单成功后给用户发送一封电子邮件或发送一条短信等。消息驱动bean是一个异步消息使用者。当JMS消息到达时,容器激发消息驱动bean。消息驱动bean既没有本地接口也没有组件接口。消息驱动bean实例是一个消息驱动bean类的实例。对客户机来说,消息驱动bean是一个在服务器上实现某些业务逻辑的JMS消息使用者。客户机通过JMS发送消息到JMS Destination (Queue或Topic)来访问消息驱动bean,而消息驱动bean类是JMS Destination的MessageListener。 消息驱动bean实例没有会话状态。这意味着当不涉及服务客户机消息时,所有的bean实例都是等同的。消息驱动bean是匿名的。它们没有客户机可视的标识。容器创建消息驱动bean实例来进行消息处理,而消息驱动bean是这些消息的使用者。其生命周期由容器控制。 消息驱动bean实例没有特定于客户机的状态。然而,通过处理客户机信息,消息驱动bean实例的实例变量可以包含状态。这些状态的示例包括一个开放的数据库连接和一个EJB对象的对象引用。 |
其实核心的问题就是我们什么情况下使用消息驱动Bean
1):当一个业务方法需要很长时间处理的时候,而且处理时间十分不确定
2):客户端调用后无需服务端立刻返回结果
而我们在这里不得不再说一下,消息驱动Bean实际上就是一个异步的JMS消费者。而这个消费者一般需要做以下2件事情就够了。
1):通过实现onMessage()方法来获取消息目的的消息对象
2):调用业务逻辑EJB组件,对获取的信息执行业务逻辑
在EJB容器中,和SessionBean一样都是有一个对象池来维护消息驱动Bean的生命周期的。
2. 实例代码
首先我们在JBoss的控制台上配置一个新的Queue类型的JMS消息目的,如下所示:
如上所示,在JBoss中新增了一个叫做InsertUserQueue的消息目的。下面我们在服务器端开发消息驱动Bean以及和消息驱动Bean有关的类。
UserDTO类代表了表person的实体
package ejb.messageDrivenBean.dto;
import java.io.Serializable;
/** * 表person的数据模型 * @author liuyan * */ public class UserDTO implements Serializable {
/** * */ private static final long serialVersionUID = -4153158445872587565L; private int id; private String name;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
} |
真正的消息驱动Bean
package ejb.messageDrivenBean;
/** * 消息驱动Bean * * @author liuyan */ @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "InsertUserQueue") }) public class UserDTOMessageDrivenBean implements MessageListener {
/** * 注入其他EJB组件 */ @EJB(beanName = "UserServiceEAOImpl") private UserService userService;
/** * 消息接到后的处理方法 */ @Override public void onMessage(Message message) { // TODO Auto-generated method stub if (message != null) { if (message instanceof ObjectMessage) {
// 获得消息 ObjectMessage objectMessage = (ObjectMessage) message; try {
// 强制转型 UserDTO userDTO = (UserDTO) objectMessage.getObject();
// 插入数据 userService.insertUser(userDTO);
System.out.println("执行插入业务完毕"); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
} |
这个类是真正的消息驱动Bean,这里需要说明的就是此类必须实现接口MessageListener以及它的onMessage方法,在方法中会获得消息目的的消息,从而进行消息的消费。此处是调用了一个被注入的EJB组件——SessionBean。
还有一个需要重点说明的就是@MessageDriven注解,@MessageDriven注解有activationConfig属性配置,它是对该驱动Bean监听的JMS消息的一些配置信息,使用@ActivationConfigProperty注解作为配置项,每个配置项都是由propertyName和propertyValue这种键值对儿作为属性的配置。
1):destinationType:表示消费目的类型,是PTP类型或者定制
2):acknowledgeMode:JMS消息的确认模式,是否回复,还是自动回复
3):destination:表示监听的消息目的JNDI名,此属性只对JBoss容器生效