JMS 初步

JMS 初步

簡介

百度百科上對JMS的簡介:

JMS即Java消息服務(Java Message Service)應用程序接口,
是一個Java平臺中關於面向消息中間件(MOM)的API,
用於在兩個應用程序之間,或分佈式系統中發送消息,
進行異步通信。
Java消息服務是一個與具體平臺無關的API,
絕大多數MOM提供商都對JMS提供支持。

百度百科上對ActiveMQ的簡介:

ActiveMQ 是Apache出品,最流行的,能力強勁的開源消息總線。
ActiveMQ 是一個完全支持JMS1.1和J2EE 1.4規範的 JMS Provider實現,
儘管JMS規範出臺已經是很久的事情了,
但是JMS在當今的J2EE應用中間仍然扮演着特殊的地位。

JMS具有兩種通信模式:

Point-to-Point Messaging Domain (點對點)
Publish/Subscribe Messaging Domain (發佈/訂閱模式)

比如:

你要和某個服務器通信,你得寫套接字,連接後雙方各send和recv消息。
而你用JMS,就是向消息服務器(暫且稱爲服務器)發送一個消息,
而接收方,只要從這個服務器取下消息即可,不用去寫套接字啦。
JMS是一套規範,各個廠商有不同的實現。比如ActiveMQ,WebsphereMQ等。
這裏稱之爲消息中間件。
用了消息中間件,通信的雙方都是通過這個中間件來收取消息。
(這樣中間件就通用了,不用再去爲某兩個程序專門寫套接字,有了新程序還得再寫一遍)。
這裏的發送的消息可以是字符串,可以是對象。

模型圖

(圖片來自https://www.cnblogs.com/jaycekon/p/6220200.html

點對點

發佈/訂閱模式

準備

  1. 下載activemq程序包,解壓,啓動。
  2. 打開activemq的web管理員控制檯 http://localhost:8161/admin/index.jsp
  3. 添加activemq的jar包到程序中。
  4. 編寫代碼,JavaWeb項目

點對點

Servlet容器的context.xml文件添加JNDI配置

<!-- activemq JMS 配置 -->
<Resource name="queue/connectionFactory" auth="Container"
	type="org.apache.activemq.ActiveMQConnectionFactory"
	description="JMS Connection Factory"
	factory="org.apache.activemq.jndi.JNDIReferenceFactory"
	brokerURL="tcp://localhost:61616" brokerName="LocalActiveMQBroker" />

<!-- activemq JMS 配置 -->
<Resource name="queue/queue0" auth="Container"
	type="org.apache.activemq.command.ActiveMQQueue"
	description="My Queue"
	factory="org.apache.activemq.jndi.JNDIReferenceFactory"
	physicalName="TomcatQueue" />


@WebServlet("/send")
public class QueueSend extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Writer writer = response.getWriter();

		try {
			InitialContext context = new InitialContext();
			QueueConnectionFactory conFactory = (QueueConnectionFactory) context
					.lookup("java:comp/env/queue/connectionFactory");

			QueueConnection queConn = conFactory.createQueueConnection();
			queConn.start();

			QueueSession queSession = queConn.createQueueSession(false, Session.DUPS_OK_ACKNOWLEDGE);
			QueueSender queSender = queSession.createSender((Queue) context.lookup("java:comp/env/queue/queue0"));
			queSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

			TextMessage message = queSession.createTextMessage("Hello World");
			queSender.send(message);

			queSender.close();
			queSession.close();
			queConn.close();

			writer.write("Message Sent: " + message.getText());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

@WebServlet("/receive")
public class QueueReceive extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Writer writer = response.getWriter();

		try {
			InitialContext context = new InitialContext();
			QueueConnectionFactory conFactory = (QueueConnectionFactory) context
					.lookup("java:comp/env/queue/connectionFactory");

			QueueConnection queConn = conFactory.createQueueConnection();
			queConn.start();

			QueueSession queSession = queConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
			QueueReceiver queReceiver = queSession.createReceiver((Queue) context.lookup("java:comp/env/queue/queue0"));

			TextMessage message = (TextMessage) queReceiver.receive();
			String msg = message.getText();

			queReceiver.close();
			queSession.close();
			queConn.close();

			writer.write("Message Received: " + msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

先訪問send,在訪問receive,注意觀察控制檯變化。

發佈/訂閱模式

import java.io.IOException;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.activemq.ActiveMQConnectionFactory;

	@WebServlet("/topic_send")
	public class TopicSend extends HttpServlet {
		private static final long serialVersionUID = 1L;
	
		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			try {
				ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
				Connection connection = connectionFactory.createConnection();
				connection.start();
	
				Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
				// 也可以在JNDI中配置
				Topic topic = session.createTopic("test-topic");
				MessageProducer producer = session.createProducer(topic);
				TextMessage textMessage = session.createTextMessage("hello!test-topic");
				producer.send(textMessage);
	
				producer.close();
				session.close();
				connection.close();
	
				resp.getWriter().write("Send message : " + textMessage.getText());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	
	}

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
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 org.apache.activemq.ActiveMQConnectionFactory;

public class TopicReceive {
	public static void main(String[] args) {
		try {
			ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
			Connection connection = connectionFactory.createConnection();
			connection.start();

			Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			Topic topic = session.createTopic("test-topic");

			MessageConsumer consumer = session.createConsumer(topic);

			consumer.setMessageListener(new MessageListener() {
				@Override
				public void onMessage(Message message) {
					if (message instanceof TextMessage) {
						TextMessage textMessage = (TextMessage) message;
						try {
							System.out.println("Message received : " + textMessage.getText());
						} catch (JMSException e) {
							e.printStackTrace();
						}
					}
				}
			});

			// 程序等待接收用戶消息
			System.in.read();

			consumer.close();
			session.close();
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

先啓動receive,爲了啓動監聽器,再訪問send,之一觀察控制檯的變化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章