一、简介
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、测试
来源:CSDN
作者:专注写bug
链接:https://blog.csdn.net/qq_38322527/article/details/103680186