上一篇博客我们将了SessionBean的有状态的会话bean和无状态的会话Bean,那么今天我们再将一下他的第二种Bean,消息驱bean(MDB)
MDB
JMS
JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。
p2p
在p2p模型中,有消息队列(Queue),发送者(sender),接收者(Receiver)。每个消息都会被发送到一个特定的队列,接收者从队列中获取消息,知道他们被消费或者超时。
• 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再队列中了)
• 发送者和接收者之间没有以来,也就是说当发送者发送了消息只有,不管接收者有没有正在运行,他不会影响到消息被发送到队列
• 接收者成功接受消息只有须向队列应答成功
如果你希望发动的消息都被成功处理,那么你需要p2p模型
Pub/Sub
在Pub/Sub模型中,有主题(Topic),发布者(Publisher),订阅者(Subscriber),客户端将消息发送到主题,多个发布者将消息发送到Topic,系统将这些消息传递个多个订阅者
• 每个消息可以有多个消费者
• 发布者和订阅者之间的以来,订阅者必须在线
但是EJB的MDB对JMS的安全性和事务性都进行了很好的封装,我们只需要直接用就可以。
JMS实现
新建要给EJB项目,src下新建包com.tgb.ejbmdb,报下新建MyQueueMDBBean ,实现MessageListener ,代码如下:
@MessageDriven(
activationConfig={
@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",propertyValue="queue/myqueue")
}
)
public class MyQueueMDBBean implements MessageListener {
public void onMessage(Message msg) {
TextMessage textMessage = (TextMessage)msg;
try {
System.out.println("myQueueMDBBean的message被调用了" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
新建客户端,在上一篇博客我们已经介绍过客户端的创建,这里我就不在说了,直接上代码
public static void main(String[] args) throws Exception{
InitialContext context = new InitialContext();
//新建队列工厂
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("ConnectionFactory");
//新建连接
QueueConnection connection = factory.createQueueConnection();
//创建队列的session
QueueSession session = (QueueSession) connection.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
//新建队列
Queue queue = (Queue) context.lookup("queue/myqueue");
//创建一个文本消息
TextMessage msg = session.createTextMessage("世界你好");
//创建发送者
QueueSender send = session.createSender((javax.jms.Queue) queue);
send.send(msg);
session.close();
connection.close();
}
sub/pub实现:
EJB项目代码
@MessageDriven(
activationConfig={
@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Topic"),
@ActivationConfigProperty(propertyName="destination",propertyValue="topic/mytopic")
}
)
public class MyTopicMDBBean implements MessageListener {
public void onMessage(Message msg) {
TextMessage textMessage = (TextMessage)msg;
try {
System.out.println("myTopicMDBBean的message被调用了:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
客户端代码
public static void main(String[] args) throws Exception{
InitialContext context = new InitialContext();
//新建主题工厂
TopicConnectionFactory factory = (TopicConnectionFactory)context.lookup("ConnectionFactory");
//新建链接
TopicConnection connection = factory.createTopicConnection();
TopicSession session = (TopicSession) connection.createSession(false, TopicSession.AUTO_ACKNOWLEDGE);
Topic topic = (Topic) context.lookup("topic/mytopic");
//创建一个文本消息
TextMessage msg = session.createTextMessage("世界你好");
//创建发送者
TopicPublisher send = session.createPublisher(topic);
send.send(msg);
session.close();
connection.close();
System.out.println("消息已发送");
}
这样一个发布者的就创建了。
如果你用的是JBOSS5.0以上的版本,可能会出现javax.naming.NameNotFoundException: myqueue not bound或者
javax.naming.NameNotFoundException: mytopic not bound,这是因为上边的代码在jboss4.0还支持,在5.0就不支持了,不过大家找到D:\jboss-5.0.1.GA\server\default\deploy中mail-service.xml的文件,在里边加入如下代码
<mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.org.destination:server=Queue,name=myqueue" >
<attribute name="JNDIName" >queue/myqueue</attribute>
<depends optional-attribute-name = "DestinationManager" >jboss.mq:service=DestinationManager </depends>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Topic" name="jboss.org.destination:server=Topic,name=mytopic" >
<!-- JNDI名称 -->
<attribute name="JNDIName">topic/mytopic</attribute>
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
提示queue的就加上边的代码,提示topic的就加下边的代码。