Java訊息中介軟體---基礎篇__Java

來源:互聯網
上載者:User

學習慕課網java訊息中介軟體記些筆記 1.概述

中介軟體
非底層作業系統軟體,非業務應用軟體,不是直接給終端使用者使用的,不能直接給客戶帶來價值的軟體統稱為中介軟體。
訊息中介軟體
管制關注於資料的發送和接收,利用高效可靠的非同步訊息傳遞機制整合分布式系統。
優點
① 解耦 ② 非同步 ③ 橫向擴充 ④ 安全可靠 ⑤ 順序保證(比如kafka)
jms
javaMessage Service(Java Message Service)即JMS,是一個Java平台中關於面向訊息中介軟體的api,用於在兩個應用程式之間,或分布式系統中發送訊息,進行非同步通訊
什麼是AMQP
AMQP(advanced message queuing protocol)是一個提供整合通訊服務的應用程式層標準協議,基於此協議的用戶端與訊息中介軟體可傳遞訊息,並不受用戶端/中介軟體不同產品,不同開發語言等條件的限制
常見訊息中介軟體
activeMQ(支援多語言,實現jms1.1,j2ee1.4規範),RabbitMQ(支援更多語言,基於AMQP規範),kafka(高輸送量,分布式,分區,O(1)磁碟順序提供訊息持久化)

JMS訊息模式
隊列模式
用戶端包括生產者和消費者
隊列中的訊息只能被一個消費者消費
消費者可以隨時消費隊列中的訊息
主題模式
用戶端包括髮布者和訂閱者
主題中的訊息被所有訂閱者消費
消費者不能消費訂閱之前就發送到主題中的訊息
JMS編碼介面
ConnectionFactory 用於建立串連到訊息中介軟體的串連工廠
Connection 代表了應用程式和Message Service器之間的通訊鏈路
Destination 指訊息發布和接收的地點,包括隊列或主題
Session 表示一個單線程的上下文,用於發送和接收訊息
MessageConsumer 由會話建立,用於接收發送到目標的訊息
MessageProducer 由會話建立,用於發送訊息到目標
Message 是在消費者和生產者之間傳送的對象,訊息頭,一組訊息屬性,一個訊息體
流程
2.安裝activeMQ

官網 : http://activemq.apache.org/
第一種啟動
進入bin ,activemq.bat 啟動
進入瀏覽器 http://127.0.0.1:8161
使用者名稱密碼預設為admin
第二種以服務啟動
InstallService.bat以管理員身份運行
服務中有ActiveMQ
linux
解壓壓縮包
進入bin 輸入 activemq start,啟動完成 3.jms 示範

建立maven項目
添加依賴

   <dependency>      <groupId>org.apache.activemq</groupId>      <artifactId>activemq-all</artifactId>      <version>5.9.0</version>    </dependency>

建立隊列模式的生產者AppProducer

package com.jms.queue;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnectionFactory;public class AppProducer {    public static final String url = "tcp://localhost:61616";    public static final String queueName = "queue-test ";    public static void main(String[] args) throws JMSException {        //1.建立串連工廠        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);        //2.建立Connection        Connection connection = connectionFactory.createConnection();        //3.啟動串連        connection.start();        //4.建立會話 第一個參數:是否在事務中去處理, 第二個參數.接聽模式        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        //5.建立一個目標        Destination destination = session.createQueue(queueName);        //6建立一個生產者        MessageProducer producer = session.createProducer(destination);        for (int i = 0; i < 100; i++) {            //7.創基建訊息            TextMessage textMessage = session.createTextMessage("test:"+i);            producer.send(textMessage);            System.out.println("發送訊息:"+textMessage.getText());        }        //9關閉串連        connection.close();    }}

運行項目,開啟activeMQ管理工具

100個訊息,沒有消費者消費,串連已關閉
消費者 AppConsumer

package com.jms.queue;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;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 org.apache.activemq.ActiveMQConnectionFactory;public class AppConsumer {    public static final String url = "tcp://localhost:61616";    public static final String queueName = "queue-test ";    public static void main(String[] args) throws JMSException {        //1.建立串連工廠        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);        //2.建立Connection        Connection connection = connectionFactory.createConnection();        //3.啟動串連        connection.start();        //4.建立會話 第一個參數:是否在事務中去處理, 第二個參數.接聽模式        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        //5.建立一個目標        Destination destination = session.createQueue(queueName);        //6建立一個消費者        MessageConsumer consumber = session.createConsumer(destination);        //7建立一個監聽器        consumber.setMessageListener(new MessageListener() {            public void onMessage(Message message) {                TextMessage textMessage = (TextMessage) message;                try {                    System.out.println("接收訊息:"+textMessage.getText());                } catch (JMSException e) {                    e.printStackTrace();                }            }        });        //8關閉串連  訊息是非同步 ,在程式退出是關閉,在這裡不可以關閉        //connection.close();    }}

當啟動2個消費者,再啟動生產者,結果是2個消費者平均消費

建立主題模式發行者AppProducer

package com.jms.topic;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnectionFactory;public class AppProducer {    public static final String url = "tcp://localhost:61616";    public static final String topicName = "topic-test ";    public static void main(String[] args) throws JMSException {        //1.建立串連工廠        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);        //2.建立Connection        Connection connection = connectionFactory.createConnection();        //3.啟動串連        connection.start();        //4.建立會話 第一個參數:是否在事務中去處理, 第二個參數.接聽模式        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        //5.建立一個目標        Destination destination = session.createTopic(topicName);        //6建立一個生產者        MessageProducer producer = session.createProducer(destination);        for (int i = 0; i < 100; i++) {            //7.創基建訊息            TextMessage textMessage = session.createTextMessage("test:"+i);            producer.send(textMessage);            System.out.println("發送訊息:"+textMessage.getText());        }        //9關閉串連        connection.close();    }}


這時直接運行訂閱者接收不到訊息,因為發行者先運行了

訂閱者AppConsumer

package com.jms.topic;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;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 org.apache.activemq.ActiveMQConnectionFactory;public class AppConsumer {    public static final String url = "tcp://localhost:61616";    public static final String topicName = "topic-test ";    public static void main(String[] args) throws JMSException {        //1.建立串連工廠        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);        //2.建立Connection        Connection connection = connectionFactory.createConnection();        //3.啟動串連        connection.start();        //4.建立會話 第一個參數:是否在事務中去處理, 第二個參數.接聽模式        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        //5.建立一個目標        Destination destination = session.createTopic(topicName);        //6建立一個消費者        MessageConsumer consumber = session.createConsumer(destination);        //7建立一個監聽器        consumber.setMessageListener(new MessageListener() {            public void onMessage(Message message) {                TextMessage textMessage = (TextMessage) message;                try {                    System.out.println("接收訊息:"+textMessage.getText());                } catch (JMSException e) {                    e.printStackTrace();                }            }        });        //8關閉串連  訊息是非同步 ,在程式退出是關閉        //connection.close();    }}

啟動兩個訂閱者,再啟動發行者,兩個訂閱者均可收到發行者的訊息 4.使用spring整合jms連結activeMQ

ConnectionFactory 用於管理串連的工廠
JmsTemplate 用於發送和接收訊息的模板類
MessageListerner 訊息監聽器

ConnectionFactory 是spring 為我們提供的串連池
兩種串連池SingleConnectionFactory 和 CachingConnectionFactory
SingleConnectionFactory 是對於jms建立請求,只會返回一個串連
CachingConnectionFactory 實現了SingleConnectionFactory 的所有功能,還提供了緩衝

JmsTemplate spring提供,安全執行緒,可以使用JmsTemplate 操作jms

MessageListerner 實現onMessage方法,接收Message參數

添加依賴

    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-jms</artifactId>        <version>${spring.version}</version>    </dependency>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-core</artifactId>        <version>${spring.version}</version>    </dependency>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>        <version>${spring.version}</version>    </dependency>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-web</artifactId>        <version>${spring.version}</version>    </dependency>     <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-test</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.apache.activemq</groupId>      <artifactId>activemq-core</artifactId>      <version>5.7.0</version>      <exclusions>        <exclusion>            <artifactId>spring-context</artifactId>            <groupId>org.springframework</groupId>        </exclusion>      </exclusions>    </dependency>

這裡注意org.apache.activemq也依賴了spring-context 所以這裡要把他排除掉

生產者 建立介面ProducerService

package com.spring.producer;public interface ProducerService {    void sendMessage(String message);}

實作類別

package com.spring.producer.impl;import javax.annotation.Resource;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.Session;import javax.jms.TextMessage;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;import org.springframework.stereotype.Service;import com.spring.producer.ProducerService;@Servicepublic class ProducerServiceImpl implements ProducerService {    @Autowired    private JmsTemplate jmsTemplate;    @Resource(name= "queueDestination")//因為可能配置多個目的地,所以使用resource name進行區分    Destination destination;    public void sendMessage(final String message) {        //使用JmsTemplate發送訊息        jmsTemplate.send(destination,new MessageCreator() {            //建立訊息            public Message createMessage(Session session) throws JMSException {                TextMessage textMessage = session.createTextMessage(message);                return textMessage;            }        });        System.out.println("發送訊息:"+message);    }}

配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="        http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://www.springframework.org/schema/context         http://www.springframework.org/schema/context/spring-context-4.3.xsd        http://www.springframework.org/schema/mvc        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">        <context:annotation-config></context:annotation-config>            <context:component-scan base-package="com.spring.*" />        <!-- ActiveMQ提供 ConnectionFactory-->    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">    <property name="brokerURL" value="tcp://localhost:61616"></property>    </bean>    <!-- spring-jms提供的串連池 -->    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">    <property name="targetConnectionFactory" ref="targetConnectionFactory"></property>    </bean>      <!-- 一個隊列目的地,點對點 -->    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">    <!-- 指定隊列名字 -->    <constructor-arg value="springQueue"></constructor-arg>    </bean>      <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">    <property name="connectionFactory" ref="connectionFactory"></property>    </bean>   <!-- <bean id="ProducerServiceImpl" class="com.spring.producer.impl.ProducerServiceImpl"></bean> --></beans>

啟動類

package com.spring.producer;import org.springframework.context.ApplicationContext;import org.springframework.context.support.AbstractApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AppProducer {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("producer.xml");        ProducerService service = context.getBean(ProducerService.class);        for(int i=0;i<100;i++){            service.sendMessage("test"+i);        }        //會自動清理資源        ((AbstractApplicationContext) context).close();    }}

可以把公用地方提取出來

<import resource="common.xml"/>

建立消費者
配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="        http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-4.3.xsd

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.