JMS系列(三)-java操作JMS Topic实例

上一篇介绍如何通过java往jms消息队列里面写消息和读取消息,本文介绍如何通过java往jms主题里写消息和读取消息。

消息发布

同样将消息发布到主题中,需要经过以下步骤

  • 连接jms服务器
  • 获取连接工厂(Connection Factory)
  • 通过连接工厂创建主题连接(TopicConnection)
  • 通过主题连接创建主题会话(TopicSession)
  • 通过主题会话创建主题发布者(Publisher)
  • 创建消息(Message)
  • 通过发布者将消息发送到主题中

代码实现:

package asan.demo.jms;

import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class JMSTopicSender {
    private TopicPublisher sender = null;
    private TopicSession session = null;
    private static final String JMS_FACTORY_JNDI = "jms/jms_test_connection_factory1";
    private static final String JMS_TOPIC_JNDI = "jms/jms_test_topic";

    public JMSTopicSender() {
        super();
    }

    public void sendMessage(String msg) {
        TextMessage textMsg;
        try {
            if (this.sender == null) {
                this.init();
            }
            textMsg = session.createTextMessage();
            textMsg.setText(msg);
            sender.send(textMsg);
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    //    1. 连接jms服务器
    //    2. 获取连接工厂(Connection Factory)
    //    3. 通过连接工厂创建主题连接(TopicConnection)
    //    4. 通过主题连接创建主题会话(TopicSession)
    //    5. 通过主题会话创建主题发布者(Publisher)
    //    6. 创建消息(Message)
    //    7. 通过发布者将消息发送到主题中
    private void init() throws NamingException, JMSException {
        Hashtable properties = new Hashtable();
        properties.put(Context.INITIAL_CONTEXT_FACTORY,
                       "weblogic.jndi.WLInitialContextFactory");
        properties.put(Context.PROVIDER_URL, "t3://127.0.0.1:7101");
        properties.put(Context.SECURITY_PRINCIPAL, "weblogic");
        properties.put(Context.SECURITY_CREDENTIALS, "weblogic1");
        InitialContext ctx = new InitialContext(properties);
        TopicConnectionFactory jmsFactory =
            (TopicConnectionFactory)ctx.lookup(JMS_FACTORY_JNDI);
        TopicConnection jmsConn = jmsFactory.createTopicConnection();
        session = jmsConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = (Topic)ctx.lookup(JMS_TOPIC_JNDI);
        sender = session.createPublisher(topic);
    }
    
    public static void main(String[]cmd){
        JMSTopicSender sender=new JMSTopicSender();
        sender.sendMessage("hello jms topic");
    }
}

与队列不同的是,此时主题没有订阅者,那么该消息就不存储在主题中,即使后面有订阅者订阅了该主题,也无法接收订阅前的消息。

消息订阅

从主题中订阅消息,需要经过以下步骤:

  • 连接jms服务器
  • 获取连接工厂(Connection Factory)
  • 通过连接工厂创建主题连接(TopicConnection)
  • 通过主题连接创建主题会话(TopicSession)
  • 通过主题会话创建订阅者(Subscriber)
  • 接收消息(Message)

代码实现:

package asan.demo.jms;

import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class JMSTopicReciver {
    private TopicSubscriber reciver = null;
    private static final String JMS_FACTORY_JNDI = "jms/jms_test_connection_factory1";
    private static final String JMS_TOPIC_JNDI = "jms/jms_test_topic";
    public JMSTopicReciver() {
        super();
    }
    public void reciveMessage() {
        try {
            if (this.reciver == null) {
                this.init();
            }
            System.out.println("waiting to recive message from jms topic "+JMS_TOPIC_JNDI);
            while(true){
                Message msg=reciver.receive();
                if(msg instanceof TextMessage){
                    TextMessage textMsg=(TextMessage)msg;
                    System.out.println("recive jms message:"+textMsg.getText());
                }
            }
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    //    1. 连接jms服务器
    //    2. 获取连接工厂(Connection Factory)
    //    3. 通过连接工厂创建主题连接(TopicConnection)
    //    4. 通过主题连接创建主题会话(TopicSession)
    //    5. 通过主题会话创建订阅者(Subscriber)
    //    6. 接收消息(Message)
    private void init() throws NamingException, JMSException {
        Hashtable properties = new Hashtable();
        properties.put(Context.INITIAL_CONTEXT_FACTORY,
                       "weblogic.jndi.WLInitialContextFactory");
        properties.put(Context.PROVIDER_URL, "t3://127.0.0.1:7101");
        properties.put(Context.SECURITY_PRINCIPAL, "weblogic");
        properties.put(Context.SECURITY_CREDENTIALS, "weblogic1");
        InitialContext ctx = new InitialContext(properties);
        TopicConnectionFactory jmsFactory =
            (TopicConnectionFactory)ctx.lookup(JMS_FACTORY_JNDI);
        TopicConnection jmsConn = jmsFactory.createTopicConnection();
        TopicSession session = jmsConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = (Topic)ctx.lookup(JMS_TOPIC_JNDI);
        reciver = session.createSubscriber(topic);
        jmsConn.start();
    }
    
    public static void main(String[]cmd){
        JMSTopicReciver consumer=new JMSTopicReciver();
        consumer.reciveMessage();
    }
}

运行代码,此时运行之前消息发布的代码,可以在控制台看到发送的消息

同样,稍微修改下上一篇文章的客户端程序,使整个过程看起来更清晰,修改后的客户端代码如下:

package asan.demo.jms;

import java.util.Scanner;

public class JMSClient {
    public JMSClient() {
        super();
    }

    public static void help() {
        System.out.println("Usage:java -jar JMSClient.jar sender/reciver/topicSender/topicReciver");
        System.out.println("sender:向jms队列发送消息");
        System.out.println("reciver:从队列中取出消息");
        System.out.println("topicSender:向jms主题发送消息");
        System.out.println("topicReciver:从主题中取出消息");
    }

    public static void main(String[] cmd) {
        if (cmd.length == 0) {
            help();
            return;
        }
        String mode = cmd[0];
        if ("sender".equalsIgnoreCase(mode)) {
            JMSSender sender = new JMSSender();
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("input you message(input end to exist):");
                String msg = sc.nextLine();
                if ("end".equalsIgnoreCase(msg)) {
                    return;
                }
                sender.sendMessage(msg);
                System.out.println("message send success");
            }
        } else if ("reciver".equalsIgnoreCase(mode)) {
            JMSReciver consumer = new JMSReciver();
            consumer.reciveMessage();
        } else if ("topicSender".equalsIgnoreCase(mode)) {
            JMSTopicSender sender = new JMSTopicSender();
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("input you message(input end to exist):");
                String msg = sc.nextLine();
                if ("end".equalsIgnoreCase(msg)) {
                    return;
                }
                sender.sendMessage(msg);
                System.out.println("message send success");
            }
        } else if ("topicReciver".equalsIgnoreCase(mode)) {
            JMSTopicReciver consumer = new JMSTopicReciver();
            consumer.reciveMessage();
        }
    }
}

打包运行,执行以下命令将客户端作为主题发布者

java -jar JMSDemo.jar topicSender

新建窗口,执行以下命令将客户端作为主题订阅者

java -jar JMSDemo.jar topicReciver

在发布者上发送消息,在订阅者上看到收到的消息


可以再多开一个窗口,再运行一个订阅者

登录weblogic控制台,进入domain->Services->Messaging->JMS Modules->jms_test_module->jms_test_topic可以查看当前主题订阅统计信息

ActiveMQ安装 : 1.下载:http://activemq.apache.org/download.html 最新Windows版本 2.配置jdk环境,解压ActiveMQ到本地 3.启动ActiveMQ服务器: 32位机 : 直接运行\bin\win32\activemq.bat 64位机 : 直接运行\bin\win64\activemq.bat 4.打开ActiveMQ消息管理后台系统 http://localhost:8161/admin/ 参考文章为 : HelloWorld : http://blog.csdn.net/baggio7095586/article/details/5708519 进阶 :http://haohaoxuexi.iteye.com/blog/1893038 helloworld阶段 : 一个发送消息的程序,一个接收消息的程序..实现最简单的JMS交流... 监听器阶段 : ⑴MessageListener,最简单的监听器..只是拿来监听接收信息的 ⑵SessionAwareMessageListener,有个session的参数..可以拿来对接收到的信息再做响应.. ⑶MessageListenerAdapter,将消息委托交给一个普通的java类来处理.. 转化器阶段 : 实现MessageConverter接口来转换JMS对象与java对象.. 其实在使用MessageListenerAdapter时,Spring默认为我们提供了SimpleMessageConverter转换器.. 事务(无代码): 在Spring整合JMS的应用中,如果我们要进行本地的事务管理的话非常简单,只需要在定义对应的消息监听容器时指定其sessionTransacted属性为true,如: <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="queueDestination" /> <property name="messageListener" ref="consumerMessageListener" /> <property name="sessionTransacted" value="true"/> </bean> 该属性值默认为false,这样JMS在进行消息监听的时候就会进行事务控制,当在接收消息时监听器执行失败时JMS就会对接收到的消息进行回滚, 对于SessionAwareMessageListener在接收到消息后发送一个返回消息时也处于同一事务下,但是对于其他操作如数据库访问等将不属于该事务控制。 数据库跟JMS挂钩的事务先别理..
Classes contained in javax.jms.jar: javax.transaction.xa.XAResource.class javax.jms.BytesMessage.class javax.jms.Message.class javax.jms.JMSException.class javax.jms.Destination.class javax.jms.DeliveryMode.class javax.jms.Connection.class javax.jms.Session.class javax.jms.ConnectionMetaData.class javax.jms.ExceptionListener.class javax.jms.ServerSessionPool.class javax.jms.ConnectionConsumer.class javax.jms.Topic.class javax.jms.MapMessage.class javax.jms.ObjectMessage.class javax.jms.StreamMessage.class javax.jms.TextMessage.class javax.jms.MessageListener.class javax.jms.MessageProducer.class javax.jms.MessageConsumer.class javax.jms.Queue.class javax.jms.TopicSubscriber.class javax.jms.QueueBrowser.class javax.jms.TemporaryQueue.class javax.jms.TemporaryTopic.class javax.jms.ServerSession.class javax.jms.ConnectionFactory.class javax.jms.MessageNotReadableException.class javax.jms.MessageNotWriteableException.class javax.jms.QueueConnection.class javax.jms.QueueSession.class javax.jms.QueueReceiver.class javax.jms.QueueSender.class javax.jms.QueueConnectionFactory.class javax.jms.QueueRequestor.class javax.jms.TopicConnection.class javax.jms.TopicSession.class javax.jms.TopicPublisher.class javax.jms.TopicConnectionFactory.class javax.jms.TopicRequestor.class javax.jms.XAConnection.class javax.jms.XASession.class javax.jms.XAConnectionFactory.class javax.jms.XAQueueConnection.class javax.jms.XAQueueSession.class javax.jms.XAQueueConnectionFactory.class javax.jms.XATopicConnection.class javax.jms.XATopicSession.class javax.jms.XATopicConnectionFactory.class javax.jms.MessageEOFException.class javax.jms.TransactionRolledBackException.class javax.jms.MessageFormatException.class javax.jms.IllegalStateException.class javax.jms.JMSSecurityException.class javax.jms.ResourceAllocationException.class javax.jms.TransactionInProgressException.class javax.jms.InvalidDestinationException.class javax.jms.InvalidClientIDException.class javax.jms.InvalidSelectorException.class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值