spring:
rabbitmq:
host: 192.168.70.167
port: 5672
username: admin
password: public
# virtual-host: GHost
virtual-host: /
# 确认消息已发送到交换机
publisher-confirms: true
# 消息发送失败后返回
publisher-returns: true
listener:
# 默认配置是simple
type: simple
simple:
# 手动ack Acknowledge mode of container. auto none
acknowledge-mode: manual
# Maximum number of unacknowledged messages that can be outstanding at each consumer.
prefetch: 3
@Configuration
public class RabbitTemplateConfig {
@Bean
public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory){
RabbitTemplate rabbitTemplate=new RabbitTemplate();
rabbitTemplate.setConnectionFactory(connectionFactory);
rabbitTemplate.setMandatory(true);
//推送到server回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) ->
log.info("ConfirmCallback correlationData:{},ack:{},cause:{}",correlationData,ack,cause));
//消息返回给生产者, 路由不到队列时返回给发送者 先returnCallback,再 confirmCallback
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
log.info("ReturnCallback message:{},replyCode:{},replyText:{},exchange:{},routingKey:{}",
message,replyCode,replyText,exchange,routingKey);
});
return rabbitTemplate;
}
}
将rabbitTemplate注入相应的类中即可发送消息
@RestController
@RequestMapping("mqTest1")
public class MqTest1Controller {
@Autowired
RabbitTemplate rabbitTemplate;
@GetMapping("streamPush")
public String streamPush(){
rabbitTemplate.convertAndSend(HeadersRabbitConfig.HEADERS_EXCHANGE_NAME,"","I am a msg".getBytes(),message -> {
Map<String,Object> headers=message.getMessageProperties().getHeaders();
headers.put("format","pdf");
//headers.put("type","report");
headers.put("han","shaohua");
return message;
});
return "hehe";
}
}
listener负责监听队列
@Component
@RabbitListener(queues = {TopicRabbitConfig.TOPIC_QUEUE_NAME})
public class TopicHandler2 {
@RabbitHandler
public void processByteMsg(@Headers MessageHeaders headers, byte[] msgPayload) {
String msg = new String(msgPayload);
log.info("TopicHandler2收到消息:{},exchange:{},routingKey:{},queue:{}",
msg, headers.get("amqp_receivedExchange"),
headers.get("amqp_receivedRoutingKey"),
headers.get("amqp_consumerQueue"));
}
@RabbitHandler
public void processStringMsg(@Headers MessageHeaders headers, Channel channel, String msg,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.CONSUMER_TAG) String consumerTag) throws Exception {
log.info("TopicHandler2收到消息:{},exchange:{},routingKey:{},queue:{}",
msg, headers.get("amqp_receivedExchange"),
headers.get("amqp_receivedRoutingKey"),
headers.get("amqp_consumerQueue"));
channel.basicAck(deliveryTag, false);
//拒绝消息, requeue为true会重入队列, 消息就会一直接受
//channel.basicNack(deliveryTag,false,false);
//channel.basicCancel(consumerTag);
}
}
Fanout类型的exchange会忽略routingKey,所以配置中无法设置routingKey
@Configuration
public class FanoutRabbitConfig {
public static final String FANOUT_QUEUE_NAME="htFanoutQueue";
public static final String FANOUT_EXCHANGE_NAME="htFanoutExchange";
//发送消息时只需要创建exchange即可
@Bean
FanoutExchange fanoutExchange(){
return new FanoutExchange(FANOUT_EXCHANGE_NAME);
}
@Bean
public Queue fanoutQueue(){
//durable:true mq服务器重启后仍然存在 false重启后队列自动删除
return new Queue(FANOUT_QUEUE_NAME,false);
}
/**
* 队列绑定fanout类型的exchange是无法设置routingKey
* @return
*/
@Bean
Binding bindingFanout(){
return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());
}
}
/**
* direct类型exchange routingKey匹配
*/
@Configuration
public class DirectRabbitConfig {
static final String DIRECT_QUEUE_NAME="htDirectQueue";
public static final String DIRECT_EXCHANGE_NAME="htDirectExchange";
public static final String ROUTING_KEY="htDirectRouting";
//发送消息是只需要创建exchange即可
@Bean
DirectExchange directExchange(){
return new DirectExchange(DIRECT_EXCHANGE_NAME);
}
//接收消息是需要声明队列,然后通过routingKey将队列与exchange绑定
@Bean
public Queue directQueue(){
return new Queue(DIRECT_QUEUE_NAME,false);
}
@Bean
Binding bindingDirect(){
return BindingBuilder.bind(directQueue()).to(directExchange()).with(ROUTING_KEY);
}
}
@Configuration
public class TopicRabbitConfig {
static final String TOPIC_QUEUE_NAME="htTopicQueue";
static final String TOPIC_QUEUE1_NAME="htTopicQueue1";
public static final String TOPIC_EXCHANGE_NAME="htTopicExchange";
/**
* #匹配0个或多个单词,*匹配一个单词,即使一个的多个routingKey都匹配上了,但该队列只收到一次消息
*/
public static final String TOPIC="htTopicRouting.*";
public static final String TOPIC1="htTopicRouting.topic1";
//发送消息是只需要创建exchange即可
@Bean
TopicExchange topicExchange(){
return new TopicExchange(TOPIC_EXCHANGE_NAME);
}
//接收消息是需要声明队列,然后通过routingKey将队列与exchange绑定
//带通配符的topic
@Bean
public Queue topicQueue(){
//durable:true mq服务器重启后让然存在 false重启后队列自动删除
return new Queue(TOPIC_QUEUE_NAME,false);
}
@Bean
Binding bindingTopic(){
return BindingBuilder.bind(topicQueue()).to(topicExchange()).with(TOPIC);
}
//topic1
@Bean
public Queue topicQueue1(){
return new Queue(TOPIC_QUEUE1_NAME,false);
}
@Bean
Binding bindingTopic1(){
return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with(TOPIC1);
}
}
@Configuration
public class HeadersRabbitConfig {
static final String HEADERS_QUEUE_NAME="htHeadersQueue";
public static final String HEADERS_EXCHANGE_NAME="htHeadersExchange";
//发送消息是只需要创建exchange即可
@Bean
HeadersExchange headersExchange(){
return new HeadersExchange(HEADERS_EXCHANGE_NAME);
}
@Bean
public Queue headersQueue(){
return new Queue(HEADERS_QUEUE_NAME,false);
}
@Bean
Binding bindingDirect(){
Map<String, Object> arguments = new HashMap<>();
arguments.put("format", "pdf");
arguments.put("type", "report");
//x-match为any
return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAny(arguments).match();
}
@Bean
Binding bindingAllDirect(){
Map<String, Object> arguments = new HashMap<>();
arguments.put("format", "pdf");
arguments.put("type", "report");
//x-match为all
return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAll(arguments).match();
}
}