开发任何JMS应用之前,首先要做的事是在应用服务器中配置JMS被管对象:连接工厂和目的地。它们最好不要以编程的方式实现,因为其背后的技术有多种不同的API实现,可能无法移植。以下是glassfish中的配置:
在配置--java消息服务里创建两个物理目的地
名称:myQueue
类型:javax.jms.Queue
名称:myTopic
类型:javax.jms.Topic
在资源--jms资源里创建连接工厂
JNIDI名:jms/ConnectionFactory
资源类型:javax.jms.ConnectionFactory
在资源--jms资源里创建两个目的地资源
JNIDI名:jms/Queue
资源类型:javax.jms.Queue
JNIDI名:jms/Topic
资源类型:javax.jms.Topic
这一次创建一个最简单的同步队列消息应用,创建一个EJB模块,我们先创建发送消息的会话bean,首先定义远程接口:
@Remote
public
interface
JMSSendRemote
{
void sendMessage(Object messageData);
}
远程接口向远程客户端公开了一个发送消息的方法,然后是一个无状态会话bean实现远程接口:
1
@Stateless
2
public
class
JMSSendBean
implements
JMSSendRemote
{
3 @Resource(name = "jms/Queue")
4 private Queue queue;
5 @Resource(name = "jms/ConnectionFactory")
6 private ConnectionFactory connectionFactory;
7
8 private Message createJMSMessageForjmsQueue(Session session, Object messageData) throws JMSException {
9 TextMessage message = session.createTextMessage();
10 message.setText(messageData.toString());
11 return message;
12 }
13
14 private void sendJMSMessageToQueue(Object messageData) throws JMSException {
15 Connection connection = null;
16 Session session = null;
17 try {
18 connection = connectionFactory.createConnection();
19 session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
20 MessageProducer messageProducer = session.createProducer(queue);
21 messageProducer.send(createJMSMessageForjmsQueue(session, messageData));
22 } finally {
23 if (session != null) {
24 session.close();
25 }
26 if (connection != null) {
27 connection.close();
28 }
29 }
30 }
31
32 public void sendMessage(Object messageData) {
33 try {
34 sendJMSMessageToQueue(messageData);
35 } catch (JMSException ex) {
36 Logger.getLogger(JMSSendBean.class.getName()).log(Level.SEVERE, null, ex);
37 }
38 }
39
40}
前6行声明了连接工厂和队列,并将被管对象注入其中。SessionFactory用来在消息客户端和消息服务器之间创建一个连接;Queue是一个目的地,另一个是Topic,都是Destination(目的地)的子类,消息生成者将消息发送到目的地而消息使用者在目的地上获取消息。15-16行声明了Connection和Session两个对象,Connection在消息客户端和消息服务器相关端口上建立TCP/IP套接字,用来创建一个或多个Session;Session是一个单线程的上下文,用来生成和使用消息。18行创建一个Connection对象,19行创建一个一个Session对象,第一个参数表明Session未被事务化,第二个参数表明会话能够在成功接收到消息时自动进行确认。MessageProducer是消息生成者,需要指定一个目的地。9行的TextMessage代表消息本身,Message有6个子类,TextMessage只是其中一种。10行设置了消息的正文,21行消息生成者将消息发送到目的地,最后在23-28行将Connection关闭,关闭连接会自动关闭会话和消息生成者,至此整个发送流程结束。
接下来创建接收消息的会话bean,还是先创建远程接口:
@Remote
public
interface
JMSReceiveRemote
{
String receiveMessage();
}
向远程客户端公开了一个接收方法,我们看会话bean如何实现:
1
@Stateless
2
public
class
JMSReceiveBean
implements
JMSReceiveRemote
{
3 @Resource(name = "jms/Queue")
4 private Queue queue;
5 @Resource(name = "jms/ConnectionFactory")
6 private ConnectionFactory queueFactory;
7
8 private String receiveJMSMessageFromQueue() throws JMSException {
9 Connection connection = null;
10 Session session = null;
11 try {
12 connection = queueFactory.createConnection();
13 session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
14 MessageConsumer consumer = session.createConsumer(queue);
15 connection.start();
16 TextMessage msg = (TextMessage)consumer.receive();
17 return msg.getText();
18 } finally {
19 if (session != null) {
20 session.close();
21 }
22 if (connection != null) {
23 connection.close();
24 }
25 }
26 }
27
28 public String receiveMessage() {
29 try {
30 return receiveJMSMessageFromQueue();
31 } catch (JMSException ex) {
32 Logger.getLogger(JMSReceiveBean.class.getName()).log(Level.SEVERE, null, ex);
33 }
34 return null;
35 }
36
37}
很多重复的地方不解释了,14行创建了一个MessageConsumer对象,代表一个消息使用者。在接收消息前始终要打开一个连接,15行正是这个意思。16行consumer.receive()方法从目的地接收消息,receive方法用于执行一个同步接收过程,若不指定参数或参数为0,则在某个消息到来之前方法会一直阻塞,大于0的值代表设定阻塞时长毫秒数。17行从消息中获取正文,19-23行关闭连接,关闭Connection对象将自动关闭会话和消息使用者,至此整个接收流程结束,打包部署EJB模块。
最后创建远程客户端来进行测试:
<%
InitialContext ctx
=
new
InitialContext();
JMSSendRemote sendBean
=
(JMSSendRemote)ctx.lookup(JMSSendRemote.
class
.getName());
sendBean.sendMessage(
"
Hi Tom
"
);
out.println(
"
JMS消息发送成功
"
);
%>
<%
InitialContext ctx
=
new
InitialContext();
JMSReceiveRemote receiveBean
=
(JMSReceiveRemote)ctx.lookup(JMSReceiveRemote.
class
.getName());
String msg
=
receiveBean.receiveMessage();
if
(msg
!=
null
)
{
out.println(msg);
}
else
{
out.println("JMS消息没找到");
}
%>