RabbitMq学习——Springboot整合rabbitmq之direct直连配置(二)

被刻印的时光 ゝ 提交于 2019-12-24 15:09:55

一、简介

direct 直连方式,也称为精确匹配。根据一个限定的routingkey,转发器向指定的消息队列推送消息。
在这里插入图片描述

二、配置

2.1、springboot整合rabbitmq的配置概述

1、springboot整合rabbitmq,基本上都是声明队列的名称各项属性等。
2、如果有交换机,则需要将队列和交换机按照指定的routingkey进行绑定操作。
所以我们接下来的配置项,需要先声明相关参数:

#自定义配置mq相关参数信息
exchange:
  directExchange:
    name: directExchange
    durable: true
    autoDelete: false
    routingKey: direct_queue_routingKey

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: xiangjiao
    password: bunana
    virtual-host: /xiangjiao
    publisher-confirms: true   #开启发送确认
    publisher-returns: true  #开启发送失败回退
    #开启ack
    listener:
      simple:
        acknowledge-mode: manual #采取手动应答
        concurrency: 1 # 指定最小的消费者数量
        max-concurrency: 1 #指定最大的消费者数量
        retry:
          enabled: true # 是否支持重试

再来写配置项:

2.1.1、配置项一:完成队列信息属性、转发器信息属性的注入和绑定。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;



/**
 * rabbitmq 配置项
 * @author 7651
 *
 */
@SpringBootConfiguration
public class DirectRabbitMqConfig {
	
	private static Logger log = LoggerFactory.getLogger(DirectRabbitMqConfig.class);
	
	public static final String directQueueName = "direct_queue";
	
	
	/**
	 * directExchange  properties
	 */
	@Value("${exchange.directExchange.name}")
	private String directExchangeName;
	
	@Value("${exchange.directExchange.durable}")
	private boolean directExchangeDurable;
	
	@Value("${exchange.directExchange.autoDelete}")
	private boolean directExchangeAutoDelete;
	
	@Value("${exchange.directExchange.routingKey}")
	private String directExchangeRoutingKey;
	
	/**
	 * 申明directExchange(直连交换机,根据路由键完全匹配进行路由消息队列)
	 * @return
	 */
	@Bean(name="getDirectExchange")
	public DirectExchange getDirectExchange(){
		//申明并创建直连交换机
		return new DirectExchange(directExchangeName, 
				directExchangeDurable, 
				directExchangeAutoDelete);
	}
	/**
	 * 申明direct交换器使用的队列
	 * @return
	 */
	@Bean(name="getDirectQueue")
	public Queue getDirectQueue(){
		//Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
		return new Queue(directQueueName,true,false,false);
	}
	
	@Bean
	public Binding bindExchangeAndQueue(@Qualifier(value="getDirectExchange") DirectExchange getDirectExchange,
			@Qualifier(value="getDirectQueue") Queue getDirectQueue){
		return BindingBuilder.bind(getDirectQueue).to(getDirectExchange).with(directExchangeRoutingKey);
	}
}

2.1.2、配置消息发送服务

我们按照正常的开发,需要写服务接口和服务子类

public interface IMessageServcie {
	public void sendMessage(String exchange,String routingKey,String msg);
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.linkpower.service.IMessageServcie;

@Component
public class MessageServiceImpl implements IMessageServcie,ConfirmCallback,ReturnCallback {
	
	private static Logger log = LoggerFactory.getLogger(MessageServiceImpl.class);
	
	@Autowired
	private RabbitTemplate rabbitTemplate;
	
	@Override
	public void sendMessage(String exchange,String routingKey,String msg) {
		//消息发送失败返回到队列中, yml需要配置 publisher-returns: true
		rabbitTemplate.setMandatory(true);
		//消息消费者确认收到消息后,手动ack回执
		rabbitTemplate.setConfirmCallback(this);
		rabbitTemplate.setReturnCallback(this);
		
		//发送消息
		rabbitTemplate.convertAndSend(exchange,routingKey,msg);
	}

	@Override
	public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
		log.info("---- returnedMessage ----replyCode="+replyCode+" replyText="+replyText+" ");
	}
	
	@Override
	public void confirm(CorrelationData correlationData, boolean ack, String cause) {
		log.info("---- confirm ----");
		if(ack){
			log.info("---- confirm ----ack==true  cause="+cause);
		}else{
			log.info("---- confirm ----ack==false  cause="+cause);
		}
	}
}

2.1.3、写一个消息接收的代码

springboot整合的rabbitmq,不需要我们在写消费者后还要开启监听什么的。我们只需要采取指定的注解,去监听指定的队列名即可,当队列推送来消息时,即可能够消费。

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.Channel;

import cn.linkpower.config.DirectRabbitMqConfig;

@Component
//监听指定的队列名称
@RabbitListener(queues=DirectRabbitMqConfig.directQueueName)
public class MessageConsumer {
	
	@RabbitHandler
	public void process(String msg,Channel channel, Message message) throws IOException {
		//拿到消息延迟消费
		try {
			Thread.sleep(1000*8);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		
		try {
			//正确执行  手动ack
			//假设收到消息失败呢?  假定收到消息是 message 表示失败
			if("message".equalsIgnoreCase(msg)){
				/*channel.basicNack(message.getMessageProperties().getDeliveryTag(),
						false, false);*/
				//channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
				System.err.println("get msg failed msg = "+msg);
			}else{
				channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
				System.out.println("get msg success msg = "+msg);
			}
			
		} catch (Exception e) {
			//消费者处理出了问题,需要告诉队列信息消费失败
			channel.basicNack(message.getMessageProperties().getDeliveryTag(),
					false, false);
			System.err.println("get msg failed msg = "+msg);
		}
	}
}

2.1.4、编写生产者

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.linkpower.service.IMessageServcie;

@Controller
public class SendController {
	
	@Value("${exchange.directExchange.name}")
	private String directExchangeName;
	
	@Value("${exchange.directExchange.routingKey}")
	private String directExchangeRoutingKey;
	
	@Autowired
	private IMessageServcie messageServiceImpl;
	
	
	@RequestMapping("/sendDirect")
	@ResponseBody
	public String sendDirectMsg(HttpServletRequest request){
		String msg = request.getParameter("msg");
		messageServiceImpl.sendMessage(directExchangeName, directExchangeRoutingKey, msg);
		return "sendDirectMsg";
	}
}

2.2、测试

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!