wayne

JMS (1)

开发任何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
 2public 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
 2public 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消息没找到");
            }

%>

posted on 2008-09-14 05:31 waynemao 阅读(307) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

My Links

Blog Stats

常用链接

留言簿(1)

随笔分类

随笔档案

default

搜索

最新评论

阅读排行榜

评论排行榜