在SpringBoot中使用RabbitMQ客戶端詳解

前言

該示例使用的SpringBoot版本是2.2.2

添加依賴

引入amqp的依賴就行,AMQP即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。RabbitMQ就是對該協議的一種實現。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

編寫配置

package com.example.demo.config;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Binding.DestinationType;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.Queue;

@Configuration
public class RabbitMQConfig implements InitializingBean {
	
	/**
	 * RabbitMQ的地址
	 */
	@Value("${rabbit.addresses}")
    private String addresses;

	/**
	 * RabbitMQ的登錄名
	 */
    @Value("${rabbit.username}")
    private String username;

    /**
     * RabbitMQ的登錄密碼
     */
    @Value("${rabbit.password}")
    private String password;

    /**
     * 虛擬消息服務器
     */
    @Value("${rabbit.virtualhost}")
    private String virtualHost;
    
    @Value("${rabbit.queue1.name}")
    private String queue1Name;
    
    @Value("${rabbit.queue2.name}")
    private String queue2Name;
    
    @Value("${rabbit.exchange2.name}")
    private String exchange2Name;
    
    @Value("${rabbit.bindingKey2}")
    private String bindingKey2;
    
    /**
     * 通過這種方式可以申明一個隊列,
     * 該隊列使用跟隊列名相同的bindingKey綁定了RabbitMQ默認的交換器
     * @return 隊列
     */
    @Bean
    public Queue queue1() {
    	return new Queue(queue1Name);
    }
	
    /**
     * 創建連接工廠
     * @return 連接工廠
     */
	@Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
        /*
	     	addresses的格式爲192.168.7.82:5672,192.168.7.81:5672,多個地址之間用","隔開
	    	也可以用host和port來指定RabbitMQ地址
	    	cachingConnectionFactory.setHost("192.168.7.82");
	    	cachingConnectionFactory.setPort(5672);
         */
        cachingConnectionFactory.setAddresses(addresses);
        cachingConnectionFactory.setUsername(username);
        cachingConnectionFactory.setPassword(password);
        cachingConnectionFactory.setVirtualHost(virtualHost);

        return cachingConnectionFactory;
    }
	
	/**
	 * 配置消費者容器工廠
	 * @return 消費者容器工廠
	 */
	@Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory();
        listenerContainerFactory.setConnectionFactory(connectionFactory());
        //手動ack
        listenerContainerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);

        return listenerContainerFactory;
    }
	
	/**
    * RabbitMQ的template,通過該類可以收發消息
    * @return RabbitTemplate
    */
   @Bean
   public RabbitTemplate rabbitTemplate() {
	   return new RabbitTemplate(connectionFactory());
   }
   
   /**
   * 消息中間件的管理控制檯。可以聲明隊列、交換器,以及綁定隊列和交換器
   * @return AmqpAdmin
   */
  @Bean
  public AmqpAdmin amqpAdmin() {
      return new RabbitAdmin(connectionFactory());
  }

  @Override
  public void afterPropertiesSet() throws Exception {
	  AmqpAdmin amqpAdmin = amqpAdmin();
	  //聲明一個隊列
	  amqpAdmin.declareQueue(new Queue(queue2Name));
	  //聲明一個交換器
	  amqpAdmin.declareExchange(new DirectExchange(exchange2Name));
	  //綁定交換器和隊列
	  Binding binding = new Binding(queue2Name, DestinationType.QUEUE, exchange2Name, bindingKey2, null);
	  amqpAdmin.declareBinding(binding);
  }

}

application.yml

server:
  port: 8080
rabbit:
  addresses: 192.168.7.82:5672
  username: admin
  password: 123456
  virtualhost: /
  queue1:
    name: testQueue1
  exchange2:
    name: testExchange2
  queue2: 
    name: testQueue2
  bindingKey2: testBinding2
  queue3:
    name: testQueue3
  exchange3:
    name: testExchange3
  bindingKey3: testBinding3

編寫生產者

package com.example.demo.mq;

import java.io.UnsupportedEncodingException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * RabbitMQ生產者
 * @author LiHao
 */
@Component
public class RabbitMQProducer {
	
	@Autowired
	private RabbitTemplate rabbitTemplate;
	
	/**
	 * 發送字符串消息到默認的交換器
	 * @param routingKey 路由鍵(這裏爲了測試方便將路由鍵當做參數)
	 * @param msg 消息
	 */
	public void send(String routingKey, String msg) {
        this.rabbitTemplate.convertAndSend(routingKey, msg);
    }
	
	/**
	 * 發送字符串消息到指定的交換器
	 * @param exchange 交換器名稱
	 * @param routingKey 路由鍵
	 * @param msg 消息
	 */
	public void send1(String exchange, String routingKey, String msg) {
        this.rabbitTemplate.convertAndSend(exchange, routingKey, msg);
    }

	/**
	 * 發送字節數組消息到指定交換器
	 * @param exchange 交換器名稱
	 * @param routingKey 路由鍵
	 * @param msg 消息
	 * @throws UnsupportedEncodingException
	 */
    public void sendByte(String exchange, String routingKey, String msg) throws UnsupportedEncodingException {
        this.rabbitTemplate.convertAndSend(exchange, routingKey, msg.getBytes("utf-8"));
    }
}

編寫消費者

package com.example.demo.mq;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;

/**
 * RabbitMQ消費者
 * @author LiHao
 *
 */
@Component
public class RabbitMQConsumer {
	
	/**
	 * 自動ack可以這樣接收消息
	 * @param msg
	 */
	@RabbitListener(queues = "${rabbit.queue1.name}")
	@RabbitHandler
	public void receive1(String msg) {
		System.out.println("消費者從隊列1接收到的消息:" + msg);
	}
	
	@RabbitListener(queues = "${rabbit.queue2.name}")
	@RabbitHandler
	public void receive2(String msg, Channel channel, Message message) {
		System.out.println("消費者從隊列2接收到的消息:" + msg);
		long deliveryTag = message.getMessageProperties().getDeliveryTag();
		try {
			//確認收到消息,RabbitMQ將刪除該消息
			channel.basicAck(deliveryTag, false);
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * 使用@QueueBinding組合註解可以聲明隊列、交換器,並綁定隊列和交換器
	 * @param msg
	 * @param channel
	 * @param message
	 */
	@RabbitListener(bindings = {
            @QueueBinding(value = @Queue(value = "${rabbit.queue3.name}"),
                    exchange = @Exchange(value = "${rabbit.exchange3.name}"),
                    key = "${rabbit.bindingKey3}")
        })
    @RabbitHandler
	public void receive3(byte[] msg, Channel channel, Message message) {
		try {
			String str = new String(msg, "utf-8");
			System.out.println("消費者從隊列3接收到的消息:" + str);
		} catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		
		long deliveryTag = message.getMessageProperties().getDeliveryTag();
		try {
			channel.basicAck(deliveryTag, false);
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
}

編寫測試類

package com.example.demo.controller;

import java.io.UnsupportedEncodingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.mq.RabbitMQProducer;

@RestController
@RequestMapping("/test")
public class TestController {
	
	@Autowired
	private RabbitMQProducer rabbitMQProducer;
	
	@GetMapping("/mq/str")
	public String test(String exchange, String routingKey, String msg) {
		if (exchange != null) {
			rabbitMQProducer.send1(exchange, routingKey, msg);
		} else {
			rabbitMQProducer.send(routingKey, msg);
		}
		
		return "ok";
	}
	
	@GetMapping("/mq/byte")
	public String test1(String exchange, String msg, String routingKey) {
		try {
			rabbitMQProducer.sendByte(exchange, routingKey, msg);
		} catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		return "ok";
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章