【RabbitMQ消息中間件】10.Spring-Rabbit項目剖析


版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/u013517797/article/details/79601121
之前我們詳細介紹了RabbitMQ並且講解了其5中隊列模式,在期間編寫了許多小例子。但是在真實的開發階段,我們很少使用之前編寫Demo時的編寫方式,一個是不方便,一個是難以維護。所以,在企業級的開發中,一般是結合框架來進行開發的。

一、spring-rabbit項目介紹
在Java開發中,RabbitMQ的開發自然少不了與Spring框架的結合。本篇我們就來了解一下,Spring為我們提供的與RabbitMQ向結合的開源樣例工程“Spring-Rabbit”,通過了解該開源工程,我們可以更加了解在實際開發中如何結合Spring來進行RabbitMQ業務的開發。

在Spring的官方網站“spring.io”中,我們可以看到spring團隊發布的與spring相關的歷屆以及最新的框架產品:

 

 

而本此我們要了解的,就是spring框架對AMQP協議的支持,即是“spring AMQP”的相關產品:

 

 

 

點擊進去之后,可以看到該開源項目的詳細介紹:

 

 

 

 

 

 

可以在介紹中看到,該產品包含了兩個部分,其中“spring-amqp”是一個基本的抽象實現,而“spring-rabbit”是一個基於RabbitMQ的一個具體實現。

其實就是說,“spring-amqp”是所有符合消息隊列協議產品的基礎實現,而實現該基礎的產品有很多,“spring-rabbit”就是其中一種。

二、spring-rabbit使用
首先我們在Eclipse中創建一個maven項目:

 

 

然后編輯POM文件,添加spring核心依賴、日志相關依賴:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.test.spring.rabbit</groupId>
<artifactId>spring_rabbit_test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>

<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.4.0.RELEASE</version>
</dependency> 

<!-- spring核心依賴 -->
<dependency> 
<groupId>org.springframework</groupId> 
<artifactId>spring-core</artifactId> 
<version>4.2.5.RELEASE</version> 
</dependency>

<dependency> 
<groupId>org.springframework</groupId> 
<artifactId>spring-context</artifactId> 
<version>4.2.5.RELEASE</version> 
</dependency> 
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<version>3.0</version>
</configuration>
</plugin>
</plugins>
</build>
</project>

  


其中,spring-rabbit就是本次結合RabbitMQ的核心依賴jar,而amqp-client是rabbit通信的基礎協議依賴。

然后我們在maven工程的“src/main/resources”下創建日志配置文件“logj4.properties”:

log4j.rootLogger=DEBUG,A1
log4j.logger.com.jack = DEBUG
log4j.logger.org.mybatis = DEBUG

log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

  

下面是重點,在maven工程的“src/main/resources”下創建“rabbitmq-context,xml”來注入RabbitMQ需要的相關工廠類:
  
在該配置

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

<!-- 定義RabbitMQ的連接工廠 -->
<rabbit:connection-factory id="connectionFactory"
host="127.0.0.1" port="5672" username="jack" password="jack"
virtual-host="/jack" />

<!-- 定義Rabbit模板,指定連接工廠以及定義exchange -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" exchange="fanoutExchange" />
<!-- 如果需要定義路由key,則需要添加routing-key參數指定路由key,如:routing-key="foo.bar" -->

<!-- MQ的管理,包括隊列、交換器等 -->
<rabbit:admin connection-factory="connectionFactory" />

<!-- 定義隊列,自動聲明 -->
<rabbit:queue name="myQueue" auto-declare="true"/>

<!-- 定義交換器,自動聲明 -->
<rabbit:fanout-exchange name="fanoutExchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="myQueue"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
<!-- 如果交換機為通配符類型,則需要在隊列中定義通配符的key(pattern),如:pattern="foo.*" -->

<!-- 隊列監聽 -->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="foo" method="listen" queue-names="myQueue" />
</rabbit:listener-container>

<bean id="foo" class="cn.jack.rabbitmq.spring.Foo" />

</beans>

  

文件中,首先定義了RabbitMQ的連接工廠:

<!-- 定義RabbitMQ的連接工廠 -->
<rabbit:connection-factory id="connectionFactory"
host="127.0.0.1" port="5672" username="jack" password="jack"
virtual-host="/jack" />
而該連接工廠做的事情,和之前我們自己編寫的連接工廠做的事情是一樣的:
package cn.jack.rabbitmq.connection;
import java.io.IOException;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class ConnectionUtil {
public static Connection getConnection() throws IOException{
//定義連接工廠
ConnectionFactory factory = new ConnectionFactory();
//定義連接地址
factory.setHost("localHost");
//定義端口
factory.setPort(5672);
//設置賬號信息,用戶名、密碼、vhost
factory.setVirtualHost("/jack");
factory.setUsername("jack");
factory.setPassword("jack");
// 通過工廠獲取連接
Connection connection = factory.newConnection();
return connection;
}
}

  


都是定義一些列連接信息后,通過工廠獲取RabbitMQ的連接對象。

然后下面的配置是定義Rabbit模板,指定連接工廠以及定義exchange(交換機):

<!-- 定義Rabbit模板,指定連接工廠以及定義exchange -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" exchange="fanoutExchange" />

  


該處做的事情,就是定義一個模板,指定其獲取連接的連接工廠,和其綁定的交換機。
如果是路由或通配符那種需要定義發送消息的路由key的交換機,則需要再添加一個“routing-key”參數來指定路由key:

<!-- 如果需要定義路由key,則需要添加routing-key參數指定路由key -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
exchange="fanoutExchange" routing-key="foo.bar" />

  


對於上面綁定的交換機,在下面有定義其詳細配置:

<!-- 定義交換器,自動聲明 -->
<rabbit:fanout-exchange name="fanoutExchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="myQueue"/>
</rabbit:bindings>
</rabbit:fanout-exchange>

  


其中auto-declare是指,是否進行自動聲明,即是如果交換機不存在時,spring會幫助創建該交換機,如果交換機存在則忽略。在里面的“rabbit:bindings”中配置的即是與該交換機綁定的隊列。
有三種交換機類型“fanout-exchange”、“direct-exchange”以及“topic-exchange”,分別是“非路由交換機”、“路由交換機”以及“通配符交換機”,具體區別在之前的總結中已經介紹,這里不再贅述。
上面的配置是“fanout-exchange”類型的交換機,如果需要其他類型的,按照不同的前綴進行指定。下面是通配符交換機的配置方式:

<!-- 如果交換機為通配符類型,則需要在隊列中定義通配符的key(pattern) -->
<rabbit:topic-exchange name="myExchange">
<rabbit:bindings>
<rabbit:binding queue="myQueue" pattern="foo.*" />
</rabbit:bindings>
</rabbit:topic-exchange>

  


首先將配置標簽定義為“topic-exchange”,然后里面的隊列要指定相關的key鍵,用以接收符合該key的消息。

對於名為“myQueue”隊列也在上面定義了,並且也配置了自動聲明:

<!-- 定義隊列,自動聲明 -->
<rabbit:queue name="myQueue" auto-declare="true"/>

  


在上面還有一個配置,是RabbitMQ的管理中心:

<!-- MQ的管理,包括隊列、交換器等 -->
<rabbit:admin connection-factory="connectionFactory" />

  


它的作用就是管理交換機和隊列的,對於交換機和路由器上面設置的“auto-declare”自動聲明,是由上面的MQ管理中心來做自動聲明的工作的。

上面所講解的配置,其實已經完成了一個生產者所做的事情。那么最后就是配置消費者的相關設置,即是“隊列監聽”:

<!-- 隊列監聽 -->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="foo" method="listen" queue-names="myQueue" />
</rabbit:listener-container>

<bean id="foo" class="cn.jack.rabbitmq.spring.Foo" />

  


首先為隊列監聽配置一個連接工廠,然后在其中配置消費者的依賴id、執行監聽的方法名以及接受消息的隊列名稱。

對於rabbit:listener中的ref中的對象id,在下面有一個bean的配置,會將foo對象加載到spring的bean容器中。

配置文件講解完畢,我們基於該配置來創建一個生產者和消費者。
在“src/mian/java”下創建一個SpringMain類,在其中創建一個mian方法,編寫生產者的邏輯:

package cn.jack.rabbitmq.spring;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringMain {
public static void main(String[] args) throws Exception {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:rabbitmq-context.xml");
//Rabbit模板
RabbitTemplate template = ctx.getBean(RabbitTemplate.class);
//發送消息
template.convertAndSend("Hello,world!");
Thread.sleep(1000);//休眠1秒
ctx.close();//關閉容器
}
}

  


在該類中,首先使用ClassPathXmlApplicationContext獲取xml配置的對象ctx,然后通過getBean獲取“RabbitTemplate”類型的Rabbit模板,之后執行convertAndSend方法將消息發送至交換機或隊列,最后執行ctx的close關閉容器。

其實上面我們業務層需要關注的就是獲取RabbitTemplate並發送消息,之前的ClassPathXmlApplicationContext獲取xml配置對象的操作在一般的企業工程中是不會這樣寫的,一般會進行包掃描和自動注解注入的方式獲取相關的bean,無需直接操作ClassPathXmlApplicationContext獲取xml配置對象:
消息發送類:

package com.training.rabbitmq.sender; 
import org.springframework.amqp.core.AmqpTemplate; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

@Component 
public class DemoRabbitMqSender { 

@Autowired 
private AmqpTemplate rabbitTemplate; 

public void send(String content) { 
System.out.println("Sender : " + content); 
this.rabbitTemplate.convertAndSend("hello", content); 
} 

} 

  


消息接收類

package com.training.rabbitmq.controller; 
import io.swagger.annotations.ApiOperation; 
import javax.servlet.http.HttpSession; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.training.core.dto.ResultDataDto; 
import com.training.rabbitmq.sender.DemoRabbitMqSender; 

@RestController 
@RequestMapping(value="/rabbitmq") 
public class DemoRabbitMqController { 

@Autowired 
private DemoRabbitMqSender demoRabbitMqSender; 

/** 
* 發送測試消息隊列 
*/ 
@ApiOperation(value="發送測試消息隊列", notes="addEntity") 
@RequestMapping(value = "/addRabbitMq", method = RequestMethod.GET) 
public @ResponseBody ResultDataDto addEntity(HttpSession httpSession) { 
demoRabbitMqSender.send("Hello,World!"); 
return ResultDataDto.addAddSuccess(); 
} 
} 

  


上面的代碼僅供參考,不使用於本篇創建的樣例工程,因為這里沒有集成Spring的其它環境(核心/web/mvc等),僅僅為了方便演示rabbit的整合,所以直接使用了ClassPathXmlApplicationContext。

對於消費者,它的編寫就十分的簡單。之前配置文件中配置了一個foo的bean:

<bean id="foo" class="cn.jack.rabbitmq.spring.Foo" />

  


所以我們下面在“src/mian/java”下創建cn.jack.rabbitmq.spring包下的Foo類:

package cn.jack.rabbitmq.spring;
public class Foo {
//具體執行業務的方法
public void listen(String foo){
System.out.println("消費者:"+foo);
}
}

  


代碼十分簡單,復雜的傳輸過程已經由spring通過配置文件的規則進行了處理。上面的listen方法即是在隊列監聽中配置的“method”參數:

<!-- 隊列監聽 -->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="foo" method="listen" queue-names="myQueue" />
</rabbit:listener-container>

  


下面我們運行SpringMain類的main方法,可以在控制台看到如下信息:

 

 

然后到RabbitMQ的管理工具中查看隊列:

 

 

可以看到創建了一個新的名為“MyQueue”的隊列。
至此,Spring與RabbitMQ結合的小樣例工程編寫完畢。

后期將會編寫一個結合Web工程的RabbitMQ與Spring結合的實例,到時將使用包掃描和注解的方式注入Rabbit模板的實現。

轉載請注明出處:http://blog.csdn.net/acmman/article/details/79601121
————————————————
版權聲明:本文為CSDN博主「光仔December」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/acmman/article/details/79601121


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM