关于jms
JMS 是接口,相当于jdbc ,要真正使用它需要某些厂商进行实现 ,即jms provider
常见的jms provider 有
ActiveMQ
JBoss 社区所研发的 HornetQ (在jboss6 中默认即可以使用它)
jbossmq 等
在jboss 5 之前好像一直在用jbossmq ,而从6 开始使用HornetQ ,hornetq 也可以脱离jboss 单独使用
hornetq 的配置在jboss-6.0.0.20100429-M3/server/default/deploy/hornetq/目录进行配置
hornetq-jms.xml 为配置文件 ,只要read一下就可以看明白如何添加一个topic queue 等
</configuration>
...
<queue name="ExpiryQueue">
<entry name="/queue/ExpiryQueue"/>
</queue>
<topic name="testTopic">
<entry name="/queue/testTopic"/>
</topic>
</configuration>
但此处用的jms provider 是activemq ,可以单独运行,而无需j2ee server
下载apache-activemq-5.3.2-bin.tar.gz 解压缩
运 行bin/activemq 启动消息服务器
然后运行ChatServer , 及 一个多个ChatClient
然后在ChatServer 命令行窗口中输入内容就会显示在客户端的窗口上,多人聊天
package org.jixiuf.chat; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import org.jixiuf.util.JNDIUtil; public class Chat implements MessageListener { TopicConnection conn; TopicSession pubSession; TopicPublisher publisher; Topic topic; MessageConsumer subConsumer; String name; public Chat(String name) { this.name = name; conn = JNDIUtil.getTopicConnection(); topic = JNDIUtil.lookupTopic("testTopic"); } public void startServer() throws JMSException { pubSession = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); publisher = pubSession.createPublisher(topic); } public void publishMsg(String msgStr) { TextMessage msg; try { msg = pubSession.createTextMessage(); msg.setText(msgStr); publisher.publish(msg); } catch (JMSException e) { e.printStackTrace(); } } public void startClient() throws JMSException { TopicSession subSession = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); //subConsumer = subSession.createConsumer(topic); subConsumer = subSession.createConsumer(topic,null,false);//true表示不接收自已发布的消息 subConsumer.setMessageListener(this); conn.start();// 注意这个是 } @Override public void onMessage(Message message) { if (message instanceof TextMessage) { TextMessage tmsg = (TextMessage) message; try { System.out.println("定阅的消息:"+tmsg.getText()); } catch (JMSException e) { e.printStackTrace(); } } } } package org.jixiuf.chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import javax.jms.JMSException; /* * 开台两个控制台进行会话 */ public class ChatServer { public static void main(String[] args) throws JMSException { Chat c = new Chat("server"); System.out.println("i am : " + c.name); c.startServer(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; try { line = br.readLine(); while (!line.equals("exit")) { c.publishMsg(c.name + ":" + line); line = br.readLine(); } br.close(); System.exit(0); } catch (IOException e) { e.printStackTrace(); } } } package org.jixiuf.chat; import javax.jms.JMSException; public class ChatClient { public static void main(String[] args) throws JMSException { Chat c = new Chat("client"); System.out.println("i am : " + c.name); c.startClient(); } } package org.jixiuf.util; import javax.jms.JMSException; import javax.jms.Session; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public class JNDIUtil { static InitialContext ctx = null; static TopicConnection conn1 = null; static { try { ctx = new InitialContext(); } catch (NamingException e) { e.printStackTrace(); } } public static TopicConnectionFactory lookupTopicConnectionFactory() { TopicConnectionFactory connf = null; try { connf = (TopicConnectionFactory) ctx.lookup("ConnectionFactory"); } catch (NamingException e) { e.printStackTrace(); } return connf; } // 此类维护两个Connection ,一个供server 一个供client ,其实这两个connection 没什么区别, public static TopicConnection getTopicConnection() { if (conn1 == null) { try { conn1 = lookupTopicConnectionFactory().createTopicConnection(); } catch (JMSException e) { e.printStackTrace(); } } return conn1; } public static Topic lookupTopic(String topicName) { Topic topic = null; try { topic = (Topic) ctx .lookup( topicName); } catch (NamingException e) { e.printStackTrace(); } return topic; } public static void closeSession(Session session) { try { session.close(); session = null; } catch (JMSException e) { e.printStackTrace(); } } }
jndi.properties
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory topic.testTopic=jms.topic23
jndi.proerties 是示例 讲解
# START SNIPPET: jndi(来源 www.iocblog.net) #创建InitialContext的工厂类。(必须要) java.naming.factory.initial = org.activemq.jndi.ActiveMQInitialContextFactory #使用ActiveMQ的Broker url(必须要),这是默认的,不填就是这样 java.naming.provider.url = tcp://localhost:61616 #是否使用内嵌Broker(可选) #useEmbeddedBroker = true #内嵌Broker使用的xml配置文件url。这个url可以是在classpath中, #或在文件路径中。在文件路径中需要采用file:filepath的格式(可选) #brokerXmlConfig = file:src/conf/sample-conf/default.xml #指定connectionFactory的jndi名字,多个名字之间可以逗号分隔。(必须要) #以下为例: #对于topic,使用(TopicConnectionFactory)context.lookup("connectionFactry") #对于queue,(QueueConnectionFactory)context.lookup("connectionFactory") #,(QueueConnectionFactory)context.lookup("connF") connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry ,connF #注册queue,格式:(必须要) #queue.[jndiName] = [physicalName] #使用时:(Queue)context.lookup("jndiName"),此处是MyQueue queue.MyQueue = example.MyQueue #注册topic,格式:(必须要) # topic.[jndiName] = [physicalName] #使用时:(Topic)context.lookup("jndiName"),此处是MyTopic topic.MyTopic = example.MyTopic # END SNIPPET: jndi