Spring集成RabbitMQ消息隊列

準備工作:需要有一個RabbitMQ服務,如果是本地電腦,自行上官網下載並安裝RabbitMQ軟件,在rabbitmq安裝之前,童鞋們需要安裝erlang,因爲rabbitmq是用erlang寫的。

1. maven配置

除了spring常用的基礎包外,我們還需要下面這個包

<!--rabbitmq依賴 -->
<dependency>
	<groupId>org.springframework.amqp</groupId>
	<artifactId>spring-rabbit</artifactId>
	<version>1.3.5.RELEASE</version>
</dependency>
2. 創建幾個生產者和消費者類

jar包加上去下載好之後我們可以進行下一步,創建幾個類

  1. 消息生產者類
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import java.io.IOException;
 
/**
 * 消息生產者
 */
@Service
public class TestRabbitMQProducer {
 
    private Logger logger = LoggerFactory.getLogger(TestRabbitMQProducer.class);
 
    @Resource(name="amqpTemplate")
    private AmqpTemplate amqpTemplate;

 
    public void sendMessage(Object message) throws IOException {
        logger.info("to send message:{}", message);
        //下面這句是發送一條數據到對應隊列,key是配置文件中exchange中配置的對應key
        amqpTemplate.convertAndSend("LeaveQueueKey", message);
        amqpTemplate.convertAndSend("UserinfoQueueKey", message);
    }
}
  1. 消費者一
    消費者一:處理用戶信息
package cn.leave.task;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import cn.leave.weixinentity.UserInfo;
 
/**
 * 消息消費者一
 */
public class UserInfoMessageConsumer implements MessageListener {
 
    private Logger logger = LoggerFactory.getLogger(UserInfoMessageConsumer.class);
    /**
     * 實現MessageListener的消息接收接口
     */
    @Override
    public void onMessage(Message message, Channel channel) {
        logger.info("消費者接受消息 message------->:{}", message);
        try {
        	//消息轉換爲對象
	        UserInfo userInfo=(UserInfo) getObjectFromBytes(message.getBody());
	        //TODO 使用對象,加入業務邏輯
			......
			//完成任務 反饋給RabbitMQ,從隊列刪除
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        catch (Exception e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
    }
    /**
     * //字節碼轉化爲對象(反序列化)
     * @param objBytes
     * @return
     * @throws Exception
     */
    
    public  Object getObjectFromBytes(byte[] objBytes) throws Exception {
        if (objBytes == null || objBytes.length == 0) {
            return null;
        }
        ByteArrayInputStream bi = new ByteArrayInputStream(objBytes);
        ObjectInputStream oi = new ObjectInputStream(bi);
        return oi.readObject();
    }
}
  1. 消費者二
    消費者二:處理假單信息
package cn.leave.task;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

import cn.leave.entity.Leave;
 
/**
 * 消息消費者一
 */
public class LeaveMessageConsumer implements MessageListener {
 
    private Logger logger = LoggerFactory.getLogger(LeaveMessageConsumer.class);
    /**
     * 實現MessageListener的消息接收接口
     */
    @Override
    public void onMessage(Message message, Channel channel) {
        logger.info("消費者接受消息 message------->:{}", message);
        try {
        	//消息轉換爲對象
	        Leave leave=(Leave) getObjectFromBytes(message.getBody());
	        //TODO 使用對象,此處加入業務邏輯....
			......
			//完成任務 反饋給RabbitMQ,從隊列刪除
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        catch (Exception e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
    }
    /**
     * //字節碼轉化爲對象(反序列化)
     * @param objBytes
     * @return
     * @throws Exception
     */
    
    public  Object getObjectFromBytes(byte[] objBytes) throws Exception {
        if (objBytes == null || objBytes.length == 0) {
            return null;
        }
        ByteArrayInputStream bi = new ByteArrayInputStream(objBytes);
        ObjectInputStream oi = new ObjectInputStream(bi);
        return oi.readObject();
    }
}
3.創建配置文件

下面就是spring中配置RabbitMQ,我這單獨寫在了一個配置文件中

<?xml version="1.0" encoding="UTF-8"?>
<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/beans 
		  http://www.springframework.org/schema/beans/spring-beans.xsd
		  http://www.springframework.org/schema/context 
		  http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/rabbit
          http://www.springframework.org/schema/rabbit/spring-rabbit-1.3.xsd">
	<!--1、創建工廠連接 -->
	<rabbit:connection-factory id="rabbitConnectionFactory" 
	   username="guest" password="guest" host="127.0.0.1" port="5672" />
	<!--定義rabbit template用於數據的接收和發送 -->
	<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory" exchange="exchangeConfirmLeave" />
	<!--通過指定下面的admin信息,當前producer中的exchange和queue會在rabbitmq服務器上自動生成 -->
	<rabbit:admin connection-factory="rabbitConnectionFactory" />
	<!--定義queue  這裏的name會在RabbitMQ服務那邊創建對應名字的隊列 -->
	<rabbit:queue name="LeaveQueue" durable="true" auto-delete="false" exclusive="false" />
	<rabbit:queue name="UserinfoQueue" durable="true" auto-delete="false" exclusive="false" />

	<!-- 定義direct exchange,綁定queueTest -->
	<rabbit:direct-exchange name="exchangeConfirmLeave" durable="true" auto-delete="false">
		<rabbit:bindings>
			<!--這裏可以放多個dinding-->
			<!-- queue 是上面"定義queue"  key是發送消息時使用的key-->
			<rabbit:binding queue="LeaveQueue" key="LeaveQueueKey">
			</rabbit:binding>
			<rabbit:binding queue="UserinfoQueue" key="UserinfoQueueKey">
			</rabbit:binding>

		</rabbit:bindings>

	</rabbit:direct-exchange>

	<!-- 加載消息接收者 前面聲明的監聽器類-->
	<bean id="leaveMessageConsumer" class="cn.leave.task.LeaveMessageConsumer"></bean>
	<bean id="userInfoMessageConsumer" class="cn.leave.task.UserInfoMessageConsumer"></bean>

	<!-- queue litener 觀察 監聽模式 當有消息到達時會通知監聽在對應的隊列上的監聽對象 -->
	<!-- acknowledge="manual" 爲了保證數據不被丟失,RabbitMQ支持消息確認機制,即ack。爲了保證數據能被正確處理而不僅僅是被Consumer收到, -->
	<rabbit:listener-container
		connection-factory="rabbitConnectionFactory" acknowledge="manual"
		prefetch="10">
		<!--定義監聽器 這裏可以放多個監聽器
		 queues:監聽的隊列 多個可以","隔開;ref:監聽器在spring中的引用 -->
		<rabbit:listener queues="LeaveQueue" ref="leaveMessageConsumer" />
		<rabbit:listener queues="UserinfoQueue" ref="userInfoMessageConsumer" />
	</rabbit:listener-container>
</beans>

下面一段一段解釋一下

  1. connect-factory 管理 rabbitmq服務 的連接,這個參數不再解釋
	<!--1、創建工廠連接 -->
	<rabbit:connection-factory id="rabbitConnectionFactory" 
	   username="guest" password="guest" host="127.0.0.1" port="5672" />
  1. rabbit:template 類似於mysql中的template ,對隊列進行一些操作,如加入消息到隊列
    connection-factory:使用的連接工廠
    exchange:使用的交換機
<!--定義rabbit template用於數據的接收和發送 -->
	<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory" exchange="exchangeConfirmLeave" />
  1. exchange 交換機,用來控制消息發送到哪個隊列
    direct-exchange:直連交換機,全名匹配
    durable:是否持久化
    auto_delete: 當所有消費客戶端連接斷開後,是否自動刪除隊列
    rabbit:binding:設置消息queue匹配的key,綁定其關係
<!-- 定義direct exchange,綁定queueTest -->
	<rabbit:direct-exchange name="exchangeConfirmLeave" durable="true" auto-delete="false">
		<rabbit:bindings>
			<!--這裏可以放多個dinding-->
			<!-- queue 是上面"定義queue"  key是發送消息時使用的key-->
			<rabbit:binding queue="LeaveQueue" key="LeaveQueueKey"> </rabbit:binding>
			<rabbit:binding queue="UserinfoQueue" key="UserinfoQueueKey"> </rabbit:binding>
		</rabbit:bindings>
	</rabbit:direct-exchange>
  1. rabbit:queue 定義隊列
    durable:是否持久化
    exclusive: 僅創建者可以使用的私有隊列,斷開後自動刪除
    auto_delete: 當所有消費客戶端連接斷開後,是否自動刪除隊列
<!--定義queue  這裏的name會在RabbitMQ服務那邊創建對應名字的隊列 -->
	<rabbit:queue name="LeaveQueue" durable="true" auto-delete="false" exclusive="false" />
	<rabbit:queue name="UserinfoQueue" durable="true" auto-delete="false" exclusive="false" />
  1. rabbit:admin通過指定下面的admin信息,當前producer中的exchange和queue會在rabbitmq服務器上自動生成
	<!--通過指定下面的admin信息,當前producer中的exchange和queue會在rabbitmq服務器上自動生成 -->
	<rabbit:admin connection-factory="rabbitConnectionFactory" />
  1. 配置監聽器
	<!-- queue litener 觀察 監聽模式 當有消息到達時會通知監聽在對應的隊列上的監聽對象 -->
	<!-- acknowledge="manual" 爲了保證數據不被丟失,RabbitMQ支持消息確認機制,即ack。爲了保證數據能被正確處理而不僅僅是被Consumer收到, -->
	<rabbit:listener-container
		connection-factory="rabbitConnectionFactory" acknowledge="manual"
		prefetch="10">
		<!--定義監聽器 這裏可以放多個監聽器
		 queues:監聽的隊列 多個可以","隔開;ref:監聽器在spring中的引用 -->
		<rabbit:listener queues="LeaveQueue" ref="leaveMessageConsumer" />
		<rabbit:listener queues="UserinfoQueue" ref="userInfoMessageConsumer" />
	</rabbit:listener-container>

剩下的spring基礎配置就不放到這了,下面是一些名詞的解釋
connect-factory進行連接rabbitmq服務.

template用於連接factory並指定exchange, 這上面還能直接指定rout-key.

admin相當於一個管理員的角色…可以將exchange和queue進行管理,

queue和topic-exchange分別定義隊列和路由器, 這裏需要用declared-by指定管理員,從而連接到相應的factory.

listener-container用於消費者的監聽,rabbit配置中是可以指定某個類的某個方法的,如下

<rabbit:listener-container message-converter="jackson2JsonMessageConverter">
     <rabbit:listener queue-names="RESPONSE_QUEUE1, RESPONSE_QUEUE2, RESPONSE_QUEUE3, RESPONSE_QUEUE4, RESPONSE_QUEUE5"
                      ref="responseMapConsumer" method="listenResponseMap"/>
 </rabbit:listener-container>

到此配置完成,啓動項目,執行一下生產者的sendMessage()方法就可以把消息發送給RabbitMQ,然後監聽器監聽到消息就可以執行onMessage方法接受消息了

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