在发布/订阅(pub /分)的产品或应用软件,客户端的地址为主题的消息。 Publishers and subscribers are generally anonymous and may dynamically publish or subscribe to the content hierarchy. 发布服务器和订阅,一般不记名,可以动态地发布或订阅内容的层次结构。 The system takes care of distributing the messages arriving from a topic's multiple publishers to its multiple subscribers. 该系统以照顾用户分配多个消息的多个出版商其到达一个主题。 Topics retain messages only as long as it takes to distribute them to current subscribers. 消息只保留主题,只要他们需要分发到当前用户。
Pub/sub messaging has the following characteristics. 发布/订阅消息有以下几个特点。
The JMS API relaxes this timing dependency to some extent by allowing clients to create durable subscriptions . JMS API的放松这个时间依赖性在一定程度上允许客户创建持久订阅 。 Durable subscriptions can receive messages sent while the subscribers are not active. Durable subscriptions provide the flexibility and reliability of queues but still allow clients to send messages to many recipients. 长期订阅可以接收用户发送的消息,而不是积极的。持久订阅队列提供灵活性和可靠性,但仍允许客户端发送邮件给多个收件人。
在JBOSS中发布订阅模式的开发:
在JBOSS_HOME 的server\default\deploy
<?xml version="1.0" encoding="UTF-8"?> <!-- $Id: mail-service.xml 62350 2007-04-15 16:50:12Z [email protected] $ --> <server> <!-- ==================================================================== --> <!-- Mail Connection Factory --> <!-- ==================================================================== --> <mbean code="org.jboss.mq.server.jmx.Topic" name="jboss.mq.destination:service=Topic,name=chatTopic"> <attribute name="JNDIName">topic/chatTopic</attribute> <depends optional-attribute-name="DestinationManager" >jboss.mq:service=DestinationManager</depends> </mbean> </server>
发布订阅模式的中服务端的信息:
package com.easyway.jboss.jms.ptp.service; import java.util.Properties; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.TextMessage; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; import javax.jms.TopicSession; import javax.naming.Context; import javax.naming.InitialContext; /** * 队列消息的发送者 * 采用JMS点对点的模式 * @author longgangbai * */ public class TopicSender { /** * * @param args */ public static void main(String[] args) { TopicConnection conn=null; TopicSession session=null; try { //得到一个JNDI初始化上下文 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); //根据上下文查找一个连接工厂TopicConnectionFactory/QueueConnectionFactory (有了两种连接工厂, //根绝topic、queue来是哟偶那个相应的类型),该连接工厂是有JMS提供的,不需要我们自己创建,每一个 //厂商为他绑定一个全局的JNDI,我们功过JNDI便可获取它。 TopicConnectionFactory factory=(TopicConnectionFactory)ctx.lookup("ConnectionFactory"); //从连接工厂 中得到一个连接(Connect 的类型有两种,TopicConnection、QueueConnection) conn=factory.createTopicConnection(); //通过连接来建立一个会话(Session) //建立一个不需要事物的并且能自动确认消息已接收的会话 session=conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE); //查找目的地(目的地的类型有两种:Topic、Queue) Destination destination =(Topic)ctx.lookup("topic/chatTopic"); //根绝会话以及目的地建立消息生产者MessageProducter(QueueSender 和TopicPublisher都扩展自MessageProducer接口) MessageProducer producer=session.createProducer(destination); TextMessage msg=session.createTextMessage("hi ,longgangbai ,this is jboss jms MDB message"); producer.send(msg); System.out.println("发送消息成功!"); } catch (Exception e) { e.printStackTrace(); }finally{ try { session.close(); conn.close(); } catch (JMSException e2) { e2.printStackTrace(); } } } }
接受消息的代码如下:
package com.easyway.jboss.jms.ptp.service; import java.util.Properties; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.TextMessage; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; import javax.jms.TopicSession; import javax.naming.Context; import javax.naming.InitialContext; /** * 队列消息的发送者 * 采用JMS点对点的模式 * @author longgangbai * */ public class TopicReceive { /** * * @param args */ public static void main(String[] args) { TopicConnection conn=null; TopicSession session=null; try { //得到一个JNDI初始化上下文 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); //根据上下文查找一个连接工厂TopicConnectionFactory/QueueConnectionFactory (有了两种连接工厂, //根绝topic、queue来是哟偶那个相应的类型),该连接工厂是有JMS提供的,不需要我们自己创建,每一个 //厂商为他绑定一个全局的JNDI,我们功过JNDI便可获取它。 TopicConnectionFactory factory=(TopicConnectionFactory)ctx.lookup("ConnectionFactory"); //从连接工厂 中得到一个连接(Connect 的类型有两种,TopicConnection、QueueConnection) conn=factory.createTopicConnection(); //通过连接来建立一个会话(Session) //建立一个不需要事物的并且能自动确认消息已接收的会话 session=conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE); //查找目的地(目的地的类型有两种:Topic、Queue) Destination destination =(Topic)ctx.lookup("topic/chatTopic"); //根绝会话以及目的地建立消息生产者MessageProducter(QueueSender 和TopicPublisher都扩展自MessageProducer接口) MessageConsumer consumer=session.createConsumer(destination); //DisplayMessage ml = new DisplayMessage(); //consumer.setMessageListener(ml); System.out.println("开始接受消息"); conn.start();//备注如果没有对象将一直处于wait()的状态,直到接受到对象 TextMessage msg = (TextMessage) consumer.receive(); String message = msg.getText(); System.out.println("message="+message); System.out.println("接送消息成功!"); } catch (Exception e) { e.printStackTrace(); }finally{ try { session.close(); conn.close(); } catch (JMSException e2) { e2.printStackTrace(); } } } }