开始JMS编程前,我们需要配置消息到达的目标地址Destination,因为只有目标地址存在了,我们才能发送消息到这个地址
。由于每个应用服务器关于目标地址的配置都有所不同,下面以jboss为列。配置一个queue类型的目标地址。
<?xml version="1.0" encoding="UTF-8"?>
<server>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destinatio:service=Queue,name=firstQueue">
<attribute name="JNDIName" >queue/firstQueue</attribute>
<depends optional-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>节点声明这一依赖。
先启动jboss 然后把这个文件发布到jboss-5.0.1.GA/server/default/deploy 下面
控制台下面就可以看到
15:53:51,937 INFO [QueueService] Queue[queue/firstQueue] started, fullSize=200000, pageSize=2000, downCacheSize=2000
说明发布成功了
一般发送消息有以下步骤:
(1) 得到一个JNDI初始化上下文(Context)
InitialContext ctx=new InitialContext();
(2)根据上下文查找一个连接工厂 QueueConnectionFactory .该连接工厂是由JMS提供得,不需要我们自己创建,
每个厂商都为他绑定了一个全局JNDI,我们通过它的全局JNDI便可获取它:
QueueConnectionFactory factory=(QueueConnectionFactory)ctx.lookup("QueueConnectionFactory");
注:如果此处 ctx.lookup("QueueConnectionFactory") 里面的QueueConnectionFactory 找不到 换成ConnectionFactory
(3) 从连接工厂得到一个连接QueueConnection
conn=factory.createQueueConnection();
(4)通过连接来建立一个会话(Session)
session=conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);
这句代码意思是:建立不需要事物的并且能自动确认消息已接受的会话。
(5)查找目标地址
例子对应代码
Destination destination=(Destination)ctx.lookup("queue/firstQueue");
(6)根据会话以及目标地址来建立消息生产者MessageProducer(QueueSender 和TopicPublisher都扩展自MessageProducer接口)
例子对应代码:
MessageProducer producer=session.createProducer(destination);
TextMessage msg=session.createTextMessage("hello ,this is the first message driver bean");
producer.send(msg);
采用消息驱动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部署时,容器将读取其中的配置信息。
下面这个是发送消息
package com;
import java.util.Properties;
import javax.jms.BytesMessage;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.foshanshop.ejb3.bean.Man;
/**
* 发送Queue消息
* @
*
*/
public class QueueSender {
public static void main(String[] args) {
QueueConnection conn = null;
QueueSession session = null;
try {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.setProperty(Context.PROVIDER_URL, "localhost:1099");
props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
InitialContext ctx = new InitialContext(props);
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
conn = factory.createQueueConnection();
session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
Destination destination = (Queue) ctx.lookup("queue/firstQueue");
MessageProducer producer = session.createProducer(destination);
//发送文本
TextMessage msg = session.createTextMessage("您好,这是我的第一个消息驱动Bean");
producer.send(msg);
//发送Ojbect(对象必须实现序列化,否则等着出错吧)
// producer.send(session.createObjectMessage(new Man("劉德華", "北京朝阳区和平里一号")));
//发送MapMessage
MapMessage mapmsg = session.createMapMessage();
mapmsg.setObject("no1", "北京和平里一号");
producer.send(mapmsg);
//发送BytesMessage
BytesMessage bmsg = session.createBytesMessage();
bmsg.writeBytes("我是一个兵,来自老百姓".getBytes());
producer.send(bmsg);
//发送StreamMessage
StreamMessage smsg = session.createStreamMessage();
smsg.writeString("巴巴运动网,http://www.babasport.com");
producer.send(smsg);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
session.close ();
conn.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
然后需要编写消息驱动bean
package com;
import java.io.ByteArrayOutputStream;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.BytesMessage;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
@MessageDriven(activationConfig =
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="queue/firstQueue"),
@ActivationConfigProperty(propertyName="acknowledgeMode",
propertyValue="Auto-acknowledge")
})
public class PrintBean implements MessageListener {
public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
TextMessage tmsg = (TextMessage) msg;
String content = tmsg.getText();
System.out.println(content);
}else if(msg instanceof MapMessage){
MapMessage map = (MapMessage) msg;
String content = map.getString("no1");
System.out.println(content);
}else if(msg instanceof BytesMessage){
BytesMessage bmsg = (BytesMessage) msg;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buffer = new byte[256];
int length = 0;
while ((length = bmsg.readBytes(buffer)) != -1) {
byteStream.write(buffer, 0, length);
}
String content = new String(byteStream.toByteArray());
byteStream.close();
System.out.println(content);
}else if(msg instanceof StreamMessage){
StreamMessage smsg = (StreamMessage) msg;
String content = smsg.readString();
System.out.println(content);
}
} catch (Exception e){
e.printStackTrace();
}
}
}
打成jar 包 发布到 jboss-5.0.1.GA/server/default/deploy 就可以看到刚才发送的消息 已经接收到了