版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接和本聲明。
本文連接:https://blog.csdn.net/u013517797/article/details/79601121
以前咱們詳細介紹了RabbitMQ而且講解了其5中隊列模式,在期間編寫了許多小例子。可是在真實的開發階段,咱們不多使用以前編寫Demo時的編寫方式,一個是不方便,一個是難以維護。因此,在企業級的開發中,通常是結合框架來進行開發的。java
1、spring-rabbit項目介紹
在Java開發中,RabbitMQ的開發天然少不了與Spring框架的結合。本篇咱們就來了解一下,Spring爲咱們提供的與RabbitMQ向結合的開源樣例工程「Spring-Rabbit」,經過了解該開源工程,咱們能夠更加了解在實際開發中如何結合Spring來進行RabbitMQ業務的開發。web
在Spring的官方網站「spring.io」中,咱們能夠看到spring團隊發佈的與spring相關的歷屆以及最新的框架產品:spring
而本此咱們要了解的,就是spring框架對AMQP協議的支持,便是「spring AMQP」的相關產品:apache
點擊進去以後,能夠看到該開源項目的詳細介紹:mybatis
能夠在介紹中看到,該產品包含了兩個部分,其中「spring-amqp」是一個基本的抽象實現,而「spring-rabbit」是一個基於RabbitMQ的一個具體實現。併發
其實就是說,「spring-amqp」是全部符合消息隊列協議產品的基礎實現,而實現該基礎的產品有不少,「spring-rabbit」就是其中一種。mvc
2、spring-rabbit使用
首先咱們在Eclipse中建立一個maven項目:app
而後編輯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
而後咱們在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