05_Java通信_JMS_demo

上節簡單描述了一下JMS的概念,這節來寫個小demo。這樣可以比較直觀的看到JMS通信的過程。

前期回顧:04_Java通信_JMS概念

在開發這個demo前,首先要下載ActiveMQ來作爲消息服務器。

Demo實現功能



 這是我們要實現的一個發佈/訂閱模型的demo

A發送消息到消息服務器ActiveMQ,然後ActiveMQ將消息發給訂閱這個Topic的客戶端:A和B

開發流程:

1.要開發一個jms demo首先要下載某廠商的JMS的實現
2.下載ActiveMQ,這是Apache的一個開源MQ系統

下載地址:http://activemq.apache.org/download.html

 

下載歷史版本:http://activemq.apache.org/download-archives.html



 3.下載後直接解壓

我們開發一個demo直接可以使用這個activemq-all-5.2.0.jar這個jar包

4.還需要jms的jar包:
如果使用Maven,可以使用下面的依賴:

<dependency>
	<groupId>javax.jms</groupId>
	<artifactId>jms</artifactId>
	<version>1.1</version>
</dependency>

 

5.開發一個簡單的聊天demo,就想上面那張聊天圖一樣

package com.jms.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

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.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;

public class Chat implements javax.jms.MessageListener {
	private TopicSession pubSession;
	private TopicPublisher publisher;
	private TopicConnection conntection;
	private String username;
	
	public Chat(String topicFactory,String topicName,String username) throws Exception{
//		System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
//		System.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");
//		
		//使用JNDI獲得ConnectionFactory
		InitialContext ctx = new InitialContext();
		TopicConnectionFactory conFactory = (TopicConnectionFactory)ctx.lookup(topicFactory);
		
		//通過ConnectionFactory得到Connection
		TopicConnection connection = conFactory.createTopicConnection();
		
		//得到session
		TopicSession pubSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
		TopicSession subSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
		
		//使用JNDI查找主題Topic
		Topic chatTopic = (Topic)ctx.lookup(topicName);
		
		//通過session和主題Topic獲得發佈者,訂閱者
		TopicPublisher publisher = pubSession.createPublisher(chatTopic);
		TopicSubscriber subscriber = subSession.createSubscriber(chatTopic);
		
		subscriber.setMessageListener(this);
		this.conntection = connection;
		this.pubSession = pubSession;
		this.publisher = publisher;
		this.username = username;
		
		conntection.start();
	}
	@Override
public void onMessage(Message m) {
	try {
//		m.set
		TextMessage tm = (TextMessage)m;
		System.out.println(tm.getText());
	} catch (JMSException e) {
		e.printStackTrace();
	}
	
}
	
	protected void writeMessage(String text) throws Exception{
		TextMessage message = pubSession.createTextMessage();
		message.setText(username+": "+text);
		//消息發送者,發送消息
		publisher.publish(message);
	}
	
	public void close() throws Exception{
		conntection.close();
	}
	
	public static void main(String[] args) throws Exception {
		
		Chat chat = new Chat("TopicCF","topic1","hh");
		
		BufferedReader commandLine = new BufferedReader(new InputStreamReader(System.in));
		
		while(true){
			String s = commandLine.readLine();
			if(s.equalsIgnoreCase("exit")){
				chat.close();
				System.exit(0);
			}else{
				chat.writeMessage(s);
			}
		}
		
	}
}

 

6.配置文件:

java.naming.factory.initial =org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url =tcp://localhost:61616
java.naming.security.principal =system
java.naming.security.credentials =manager
connectionFactoryNames =TopicCF
topic.topic1 =jms.topic1

 7.客戶端B:

package com.jms.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class ChatA {
	public static void main(String[] args) throws Exception {

		Chat chat = new Chat("TopicCF","topic1","cc");
		
		BufferedReader commandLine = new BufferedReader(new InputStreamReader(System.in));
		
		while(true){
			String s = commandLine.readLine();
			if(s.equalsIgnoreCase("exit")){
				chat.close();
				System.exit(0);
			}else{
				chat.writeMessage(s);
			}
		}
		
	}
}

 

8.如何運行代碼:

啓動消息服務器ActiveMQ

進入ActiveMQ的bin目錄


雙擊運行:activemq.bat
查看是否啓動成功:cmd-->netstat -na|find "61616"
出現:


則啓動成功。還可以登陸

admin:http://127.0.0.1:8161/admin/

demo:http://127.0.0.1:8161/demo/

查看。
將配置文件jndi.properties放在classes的根目錄。

項目目錄結構:



 

代碼難點分析:

1.在前面已經介紹過JNDI。我們可以通過JNDI來獲取通信對象。
JMS客戶端使用一個目錄服務(JNDI)來訪問ConnectionFactory和Destination(主題和隊列)對象。也就是說這兩個對象JMS API無法獲得。在這一點上,它和連接,會話,生產者,消費者及消息不同。連接,會話,生產者,消費者及消息都是JMS API內部使用工廠模式生產的JNDI爲了獲得ConnectionFactory和Destination對象提供了一種方便、位置透明、可配置並且可移植的機制,這些對象也稱爲JMS受管對象,因爲它是由系統管理員建立和配置的

2.線程和會話
在程序中創建了兩個topicSession:pubSession,subSession。
爲什麼要創建兩個呢,因爲JMS規定一個session不能同時在一個以上的線程中運行。
這個例子中有兩個線程:
運行writeMessage的主線程(線程所有者:chat應用程序)
運行onMessage的處理線程(線程所有者是JMS提供者所有,即:ActionMQ)

  • 1691286c-8255-350a-b50f-2abf28bf8914-thumb.jpg
  • 大小: 111.6 KB
  • f51e5f51-ec50-3d3d-ba7e-fb5165b9fe6e-thumb.jpg
  • 大小: 41.6 KB
  • c85fbde4-1e46-3027-be91-8f4f2ecfd4de-thumb.jpg
  • 大小: 5.6 KB
  • 2ff93035-9849-38b1-b75f-7c9c326c6360-thumb.jpg
  • 大小: 31.9 KB
  • 9ebb72e0-349b-3c57-9d51-f6de2593fdc2-thumb.jpg
  • 大小: 15.7 KB
  • af2ea032-f138-3753-815a-a237a337fd13-thumb.jpg
  • 大小: 25.5 KB
  • a600d65e-9e06-362a-8a4d-437d7ebb1893-thumb.jpg
  • 大小: 44.5 KB
  • 33ab84d7-1987-35ef-a1ec-57889f79b72a-thumb.jpg
  • 大小: 40.8 KB
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章