EJB_开发消息驱动bean

开发消息驱动bean

Java消息服务(Java MessageService)

Java 消息服务(Java Message Service,简称 JMS)是用于访问企业消息系统的开发商中立的API。企业消息系统可以协助应用软件通过网络进行消息交互。

JMS的编程过程很简单,概括为:应用程序A发送一条消息到消息服务器的某个目地(Destination),然后消息服务器把消息转发给应用程序B。因为应用程序A和应用程序B没有直接的代码关连,所以两者实现了解偶。

JMS中的消息

消息传递系统的中心就是消息。一条 Message 由三个部分组成:

头(header),属性(property)和主体(body)。

消息有下面几种类型,他们都是派生自 Message 接口。

StreamMessage:一种主体中包含 Java 基元值流的消息。其填充和读取均按顺序进行。

MapMessage:一种主体中包含一组名-值对的消息。没有定义条目顺序。

TextMessage:一种主体中包含 Java 字符串的消息(例如,XML 消息)。

ObjectMessage:一种主体中包含序列化 Java 对象的消息。

BytesMessage:一种主体中包含连续字节流的消息。

消息的传递模型

JMS 支持两种消息传递模型:点对点(point-to-point,简称 PTP)和发布/订阅(publish/subscribe,简称 pub/sub)。这两种消息传递模型非常相似,但有以下区别:

PTP 消息传递模型规定了一条消息只能传递给一个接收方。 采用javax.jms.Queue 表示。

Pub/sub 消息传递模型允许一条消息传递给多个接收方。采用javax.jms.Topic表示

这两种模型都通过扩展公用基类来实现。例如:javax.jms.Queue 和javax.jms.Topic 都扩展自javax.jms.Destination 类。

点对点PTP 消息传递模型

谁先监听,谁就先收到。

发布/订阅消息传递模型

 

配置目标地址

开始JMS编程前,我们需要先配置消息到达的目标地址(Destination),因为只有目标地址存在了,我们才能发送消息到这个地址。由于每个应用服务器关于目标地址的配置方式都有所不同,下面以jboss为例,配置一个queue类型的目标地址。

<?xml version="1.0"encoding="UTF-8"?>

<server>

<mbeancode="org.jboss.mq.server.jmx.Queue"

name="jboss.mq.destination:service=Queue,name=foshanshop">

 <attributename="JNDIName">queue/foshanshop</attribute>  

<dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>

</mbean>

</server>

Jboss使用一个XML文件配置队列地址,文件的取名格式应遵守*-service.xml

<attribute name="JNDIName">属性指定了该目标地址的全局JNDI名称。如果你不指定JNDIName属性,jboss会为你生成一个默认的全局JNDI,其名称由“queue”+“/”+目标地址名称组成。另外在任何队列或主题被部署之前,应用服务器必须先部署Destination Manager Mbean,所以我们通过<depends>节点声明这一依赖。

加粗自定义设置,黑色不用更改。

步骤:

在桌面新建一个hqu-service.xml复制上面xml代码修改加粗部分:

<?xml
version="1.0"encoding="UTF-8"?>

<server>

<mbean
code="org.jboss.mq.server.jmx.Queue"

name="jboss.mq.destination:service=Queue,name=hquQueue">

<attribute
name="JNDIName">queue/hquQueue</attribute>

<depends
optional-attribute-name="DestinationManager">

jboss.mq:service=DestinationManager</depends>

</mbean>

</server>

发布:拷贝到Jboss的server\default\deploy下就发布了。可以在控制台看到发布信息。

可以在Jboss管理页面看:http://localhost:8080/jmx-console/

jboss.mq.destination 下的name=hquQueue,service=Queue

目标地址建立完成后,我们就可以进行消息的发送。

在Java类中发送消息

一般发送消息有以下步骤:

(1) 得到一个JNDI初始化上下文(Context)

InitialContextctx = new InitialContext();

(2) 根据上下文查找一个连接工厂QueueConnectionFactory 。该连接工厂是由JMS提供的,不需我们自己创建,每个厂商都为它绑定了一个全局JNDI,我们通过它的全局JNDI便可获取它;

QueueConnectionFactoryfactory = (QueueConnectionFactory)

ctx.lookup("QueueConnectionFactory");

(3) 从连接工厂得到一个连接QueueConnection

conn= factory.createQueueConnection();

(4) 通过连接来建立一个会话(Session);

session= conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);

这句代码意思是:建立不需要事务的并且能自动确认消息已接收的会话。

(5) 查找目标地址:

例子对应代码:Destinationdestination = (Destination ) ctx.lookup("queue/hquQueue");

(6) 根据会话以及目标地址来建立消息生产者MessageProducer(QueueSender和TopicPublisher都扩展自MessageProducer接口)

例子对应代码:

MessageProducer producer =session.createProducer(destination);

TextMessage msg =session.createTextMessage("您好,这是我的第一个消息驱动Bean");

producer.send(msg);

步骤:

新建一个消息驱动bean项目,新建JavaProject:MessageDrivenBean,添加EJB需的jar文件, 新建一个java类:QueueSender在cn.hqu.app下,用于发送queue。

package cn.hqu.app;

import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.naming.InitialContext;

public class QueueSender {
	public static void main(String[] args) {
		try {
			//1.首先初始化一个JNDI上下文对象
			InitialContext ctx = new InitialContext();
			//2.根据上下文查找一个连接工厂 QueueConnectionFactory
			QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");
			//3.通过连接工厂可以创建一个queue连接QueueConnection。
			QueueConnection conn = factory.createQueueConnection();
			//4.通过连接创建一个到目的地址的会话
			QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
			//5.查找目标地址
			Destination destination = (Destination) ctx.lookup("queue/hquQueue");
			//6.得到消息的发送者
			MessageProducer producer = session.createProducer(destination);
			//通过这个发送者我们就可以发送消息了:
			producer.send(session.createTextMessage("你好,苏志达"));
			session.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

在方法内部,编写发送代码,

1.      首先初始化一个JNDI上下文对象:

拷贝上一个项目的jdni.properties到src下,在类QueueSender的mian里面

try {

InitialContextctx = newInitialContext();

}catch(NamingException e) {

e.printStackTrace();

}

2.根据上下文查找一个连接工厂 QueueConnectionFactory

查找到queue类型的连接工厂,

QueueConnectionFactory factory =(QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");

3.通过连接工厂可以创建一个queue连接QueueConnection。

QueueConnectionconn = factory.createQueueConnection();

4.通过连接创建一个到目的地址的会话:第一个参数指定是否需要事务,第二个参数指定消息确定模式。

QueueSession session= conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);

5.查找目标地址:

Destination destination= (Destination) ctx.lookup("queue/hquQueue");

6.得到消息的发送者

MessageProducerproducer = session.createProducer(destination);

通过这个发送者我们就可以发送消息了:

producer.send(session.createTextMessage("你好,苏志达"));

调用程序往目标地址发送一条消息,运行main。消息发送完,接下来编写消息接收者。

采用消息驱动Bean接收消息

可以采用Java类的形式进行接收, 这里采用消息驱动Bean(Message Driven Bean)接收消息,因为消息驱动Bean(MDB)是设计用来专门处理基于消息请求的组件。它和无状态Session Bean一样也使用了实例池技术,容器可以使用一定数量的Bean实例并发处理成百上千个JMS消息。正因为MDB具有处理大量并发消息的能力,所以非常适合应用在一些消息网关产品。如果一个业务执行的时间很长,而执行结果无需实时向用户反馈时,也很适合使用MDB。如订单成功后给用户发送一封电子邮件或发送一条短信等。

一个MDB通常要实现MessageListener接口,该接口定义了onMessage()方法。Bean通过它来处理收到的JMS消息。

package javax.jms;

public interface MessageListener {

public void onMessage(Message message);

}

当容器检测到Bean守候的目标地址有消息到达时,容器调用onMessage()方法,将消息作为参数传入MDB。MDB在onMessage()中决定如何处理该消息。你可以使用注释指定MDB监听哪一个目标地址(Destination)。当MDB部署时,容器将读取其中的配置信息。

步骤:

新建一个消息驱动Bean:MessageDrivenBean在cn.hqu.message下实现MessageListener。

当容器检测到这个JavaBean所监听的目标地址有消息到达的时候,会帮我们获得这个消息传到onMessage这个方法。

通过注解可以指定消息驱动bean它监听目标地址的类型是什么类型,和目标地址的JNDI名称。

@MessageDriven(activationConfig=

{

@ActivationConfigProperty(propertyName="destinationType",

propertyValue="javax.jms.Queue"),

@ActivationConfigProperty(propertyName="destination",

propertyValue="queue/hquQueu"),

@ActivationConfigProperty(propertyName="acknowledgeMode",

propertyValue="Auto-acknowledge")

})

public
class
MessageDrivenBean implements MessageListener{

从queue类型的目标地址去寻找JNDI为queue/hquQueu所绑定的目的地址。消息接收到的时候消息的确认模式为自动确认。acknowledgeMode是默认的所以这个可以去掉。

在onMessage方法里面处理接收到的消息

public
void
onMessage(Message msg) {

TextMessage message = (TextMessage) msg;

try {

System.out.println(message.getText());

} catch (JMSException e) {

e.printStackTrace();

}

}

进行打包,部署。拷贝上一个项目的ant,修改配置文件build.xml的name为

MessageDrivenBean

执行deploy,把消息驱动bean发布到Jboss中。在控制台打印

16:07:57,999 INFO  [JmxKernelAbstraction] installing MBean:jboss.j2ee:jar=Messa

geDrivenBean.jar,name=MessageDrivenBean,service=EJB3with dependencies:

16:07:58,015 INFO  [EJBContainer] STARTED EJB:cn.hqu.message.MessageDrivenBean

ejbName: MessageDrivenBean

16:07:58,039 INFO  [EJB3Deployer] Deployed:file:/F:/Java/jboss-4.2.2.GA/server/

default/deploy/MessageDrivenBean.jar

16:07:58,060 INFO  [STDOUT] 你好,苏志达

接收到了消息。

Jms允许发送者和接收方可以不同时在线。两者之间没有代码的关联,实现了很好的解耦。

代码:http://pan.baidu.com/s/1bn2DgPT

关于queue类型的发送就完了,接下来关于

Topic的发送和接收。

第一步配置目标地址,类型不是queue类型,是Topic类型,在配置文件hqu-service.xml加一个Topic配置

<mbean code="org.jboss.mq.server.jmx.Topic"

name="jboss.mq.destination:service=Topic,name=hquTopic">

<attribute name="JNDIName">topic/hquTopic</attribute>

<depends optional-attribute-name="DestinationManager">

jboss.mq:service=DestinationManager</depends>

</mbean>

配置好,将它发布到Jboss中(复制进去)。

新建类TopicSender在cn.hqu.app下,用于发布topic 类型的消息。JNDI名称可以在发布后的控制台看到。

package cn.hqu.app;

import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.naming.InitialContext;

public class TopicSender {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			//1.首先初始化一个JNDI上下文对象
			InitialContext ctx = new InitialContext();
			//2.根据上下文查找一个连接工厂 QueueConnectionFactory
			TopicConnectionFactory factory = (TopicConnectionFactory) ctx.lookup("TopicConnectionFactory");
			//3.通过连接工厂可以创建一个queue连接QueueConnection。
			TopicConnection conn = factory.createTopicConnection();
			//4.通过连接创建一个到目的地址的会话
			TopicSession session = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
			//5.查找目标地址
			Destination destination = (Destination) ctx.lookup("topic/hquTopic");
			//6.得到消息的发送者
			MessageProducer producer = session.createProducer(destination);
			//通过这个发送者我们就可以发送消息了:
			producer.send(session.createTextMessage("你好,苏志达"));
			session.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

运行main。

开发消息的接收方。因为会被多方接收,所以建立两个消息驱动Bean

新建ReceiveBean实现MessageListener在cn.hqu.message下。

package cn.hqu.message;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(activationConfig =
{
  @ActivationConfigProperty(propertyName="destinationType",
    propertyValue="javax.jms.Topic"),
  @ActivationConfigProperty(propertyName="destination",
    propertyValue="topic/hquTopic")
})
public class ReceiveBean implements MessageListener {

	@Override
	public void onMessage(Message msg) {
		TextMessage message = (TextMessage) msg;
		try {
			System.out.println(this.getClass()+message.getText());
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}

}

另外一个消息驱动Bean:ReceiveOtherBean

package cn.hqu.message;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(activationConfig =
{
  @ActivationConfigProperty(propertyName="destinationType",
    propertyValue="javax.jms.Topic"),
  @ActivationConfigProperty(propertyName="destination",
    propertyValue="topic/hquTopic")
})
public class ReceiveOtherBean implements MessageListener {

	@Override
	public void onMessage(Message msg) {
		TextMessage message = (TextMessage) msg;
		try {
			System.out.println(this.getClass()+message.getText());
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}

}

发布运行Ant deploy

发布完成并没有看到刚才发送的topic消息,因为对于topic类型的消息,如果当时接收方没有监听着这个topic类型的消息,他就获取不到这个消息,尽管我们现在把它部署到Jboss,因为当时它并没有监听topic目标地址,所以他也是无法得到这个消息的。

现在我们再执行一下topic的发送,就可以在控制台看到多个接收方接受到发送的消息了。

代码:http://pan.baidu.com/s/1nthubNF

EJB_开发消息驱动bean

时间: 2024-10-06 19:22:51

EJB_开发消息驱动bean的相关文章

EJB3.0 EJB开发消息驱动bean

(7)EJB3.0 EJB开发消息驱动bean JMS 一: Java消息服务(Java Message Service) 二:jms中的消息 消息传递系统的中心就是消息.一条 Message 由三个部分组成:             头(header),属性(property)和主体(body). 消息有下面几种类型,他们都是派生自 Message 接口.           StreamMessage:一种主体中包含 Java 基元值流的消息.其填充和读取均按顺序进行.          

消息驱动bean(MDB)实例

到目前为止前面介绍的有关JavaEE的东西都是同步的,也就是说调用者调用某个方法,那么这个方法必须立即执行并返回执行结果.用官方一些的语言来说就是"客户端通过业务接口调用一个方法,在将控制权返回给客户端之前,服务器完成该方法调用".对于我们接触到的大多数操作而言这是最自然也是最容易实现的方法.然而,有些情况下客户端并不需要等待服务器响应,而只需要告诉服务器应该做什么就可以了,在完成"告知"任务之后客户端能够继续工作,而服务器则默默的在一旁处理客户端的请求(通常会是很

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

除了同步方式的调用之外,有时还需要异步调用,用来处理不需要即时处理的信息,例如短信.邮件等,这需要使用EJB中的独特组件——消息驱动Bean(Message-Driven Bean,MDB),它提供了Java消息服务JMS(Java Messaging Service)的处理能力,由消息驱动Bean来处理JMS消息.JMS的消息由客户端程序产生,并被发布到服务器的消息队列,消息驱动Bean随之检索消息并执行其内容.这种事件或者数据的通信就称为异步形式,客户端或者服务端Bean都无须依赖对方的直接

(j2ee)消息驱动bean

消息驱动bean的主要用于接受和处理异步消息,这些信息可能来自一个外部的系统或者同一个应用中的其它组件,之所以称它们为异步,那时因为这些消息可以在任何时候到达,而不同于一般的远程方法调用的结果,是立马直接得到的.同UI的事件处理工作方式类似,消息驱动bean用于监听发送给它的异步消息.值得注意的是,与远程调用方法不同,异步消息的发送者不会停下来去等待对方的响应. 消息驱动bean是J2EE中的一个标准服务(工具),全称是Java Message Service API,简称为JMS.Java M

消息驱动Bean

消息驱动Bean.消息驱动Bean允许J2EE应用程序异步的接收Java消息服务(JMS)的消息.消息驱动Bean包含处理接受到的消息的事务逻辑,主要作用是处理消息.它与其他Bean(实体Bean和会话Bean)的区别主要在于以下几点: a) 消息驱动Bean没有任何接口,客户程序不是通过接口来访问消息驱动Bean的,它处理的消息可以来自任何消息客户程序. b) 消息驱动Bean类似于无状态会话Bean,是没有状态的,它的实例不保持特定客户程序的会话状态. c) 消息驱动Bean不需要返回任何数

EJB_消息驱动发展bean

消息驱动发展bean Java信息服务(Java MessageService) Java 信息服务(Java Message Service,简称 JMS)是用于訪问企业消息系统的开发商中立的API. 企业消息系统能够协助应用软件通过网络进行消息交互. JMS的编程过程非常easy,概括为:应用程序A发送一条消息到消息server的某个目地(Destination),然后消息server把消息转发给应用程序B. 由于应用程序A和应用程序B没有直接的代码关连,所以两者实现了解偶. JMS中的消息

消息驱动EJB(一)JMS与EJB

本文 主要从两方面进行讲述: 1.为什么使用MDB 2.使用MDB的设计原则 先来看一下消息之间是如何通信的? 应用的一个组件将JMS消息发送指定消息目的,应用的另一个组件从消息目的读取消息并解析出消息的内容.这样就实现了两个组件之间的通信. 1.发送消息的一方,称为消息生产者 2.接收消息的一方,称为消息消费者 消息生产者和消息消费者无须直接耦合,甚至不需要知道对方的存在,这就是JMS规范所实现的效果. (一)JMS和EJB 1.消息生产者 要实现的功能比较单一,只要获取与消息目的的JMS会话

SpringCloud学习之Stream消息驱动【默认通道】(十)

在实际开发过程中,服务与服务之间通信经常会使用到消息中间件,而以往使用了中间件比如RabbitMQ,那么该中间件和系统的耦合性就会非常高,如果我们要替换为Kafka那么变动会比较大,这时我们可以使用SpringCloudStream来整合我们的消息中间件,来降低系统和中间件的耦合性. 一.消息中间的几大应用场景 1.异步处理 比如用户在电商网站下单,下单完成后会给用户推送短信或邮件,发短信和邮件的过程就可以异步完成.因为下单付款是核心业务,发邮件和短信并不属于核心功能,并且可能耗时较长,所以针对

面向对象设计步骤二-------指定属性的类型和可见性,分配职责(GRASP),消息驱动,设计模式进行局部设计

增加遗漏的属性,指定属性的类型和可见性: 在面向对象设计阶段,需要对每个类进行详细设计,不全过程中遗漏的属性,并且确定每个属性的数据类型,指定每个属性的可见性:属性的可见性指外部对象对属性的访问权限,一般包括私有,保护和共有几种类型: 在实际开发中,除了那些比较简单且不常发生变化的属性可以直接暴露给客户以外,其他属性最好设置为私有或者保护并且最好都能用GetXXX()和SetXXX()等访问方法封装一下 分配职责,定义执行每个职责的方法: 职责:是一个类或者类型的契约或者义务 面向对象系统中的类