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)
點對點
發佈/訂閱模式
準備
- 下載activemq程序包,解壓,啓動。
- 打開activemq的web管理員控制檯 http://localhost:8161/admin/index.jsp
- 添加activemq的jar包到程序中。
- 編寫代碼,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,之一觀察控制檯的變化。