【无标题】

无交换机只有路由(routerKey)

解释下:该消费模型(Hello World模型)只有路由(routerKey)属于点对点消费不属于广播模式,即生产的消息每次只有一个消费者消费,并且是按顺序进行消费
下面开始创建SpringBoot工程引入RabbitMq POM文件

org.springframework.boot spring-boot-starter-amqp 在yml配置RabbitMq的配置文件 spring: application: name: springboot-rabbitmq rabbitmq: host: 127.0.0.1 port: 5672 username: renke password: 123456 publisher-confirms: true virtual-host: /renk 创建SpringBootApplication启动程序入口 @SpringBootApplication public class RabbitmqSpringbootApplication {

public static void main(String[] args) {
SpringApplication.run(RabbitmqSpringbootApplication.class, args);
}

}
创建RabbitMq的配置文件加入到IOC,此配置文件主要是获得RabbitMq
package org.cly.rabbitmq.config;

import org.cly.rabbitmq.hello.UserConsumer;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitmqConfiguration {

@Value("${spring.rabbitmq.host}")
private String addresses;

@Value("${spring.rabbitmq.port}")
private String port;

@Value("${spring.rabbitmq.username}")
private String username;

@Value("${spring.rabbitmq.password}")
private String password;

@Value("${spring.rabbitmq.virtual-host}")
private String virtualHost;

@Value("${spring.rabbitmq.publisher-confirms}")
private boolean publisherConfirms;



/**
 * 连接工厂
 * @return
 */
@Bean
public ConnectionFactory connectionFactory(){
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
    connectionFactory.setAddresses(addresses);
    connectionFactory.setUsername(username);
    connectionFactory.setPassword(password);
    connectionFactory.setVirtualHost(virtualHost);
    //todo 消息发送确认
    connectionFactory.setPublisherConfirms(publisherConfirms);
    return connectionFactory;
}

@Bean
public RabbitTemplate newRabbitTemplate(){
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
    //失败通知
    rabbitTemplate.setMandatory(true);
    //发送方确认
    rabbitTemplate.setConfirmCallback(confirmCallback());
    //失败回调
    rabbitTemplate.setReturnCallback(returnCallback());
    return rabbitTemplate;
}

//=====消费者手动应答
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container
= new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(userQueue());
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(userConsumer);
return container;
}

//=============生产者 发送方确认回调==========
@Bean
public RabbitTemplate.ConfirmCallback confirmCallback(){
    return new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            if(ack){
                System.out.println("发送者确认发送给mq成功");
            }else {
                //处理失败的消息
                System.out.println("发送者发送给mq失败,考虑重发:"+cause);
            }

        }
    };
}

//=============生产者 失败通知回调==========
@Bean
public RabbitTemplate.ReturnCallback returnCallback(){
    return new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(Message message,
                                    int replyCode,
                                    String replyText,
                                    String exchange,
                                    String routingKey) {
            System.out.println("无法路由的消息,需要考虑另外处理。");
            System.out.println("Returned replyText:"+replyText);
            System.out.println("Returned exchange:"+exchange);
            System.out.println("Returned routingKey:"+routingKey);
            String msgJson  = new String(message.getBody());
            System.out.println("Returned Message:"+msgJson);
        }
    };

}

}

下面开始创建没有交换机的生产者和消费者,只有队列,先创建自动消费的例子,说明下该模式下的消息默认是轮训消费的,即一个生产者两个消费者,生产者生产一条消息会被其中一个消费者消费,再次生产一条会被另一个消费者消费

1.新建生产者
@RestController
@RequestMapping(“rabbit-mq/test”)
public class RenkeSpringBootRabbitMq {

@Autowired
RabbitTemplate rabbitTemplate;

@GetMapping(value = "routerHello")
public void HelloWorld(){
    //第一个参数是key即路由,第二个参数是发送的内容,
   //这种属于点对点消费,不是广播模式
    //因此当有多个消费者时会有顺序的消费该消息,
   // 但每次只能有一个消费者消费
    rabbitTemplate.convertAndSend("renke.hello","这是renke.hello");
}

}
2.新建消费者
package org.cly.rabbitmq.controller;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
//Queue该注解是重点可以点进去查看源码:第一个参数:routingKey(路由)
//第二个参数无消费时是否持久化磁盘,也就是当消息还在队列时,如果重启RabbitMqdurable
// 为true是会序列化到磁盘,重启加载到RabbitMq,为false则重启消失
//第三个参数,消费后是否自动删除autoDelete为true
@RabbitListener(queuesToDeclare = @Queue(value = “renke.hello”, durable = “false”, autoDelete = “false”))
public class RouterConsumer {
@RabbitHandler
public void getMessage(String message) {
System.out.println(“RouterConsume开始消费:” + message);

}

}
3.第二个消费者
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queuesToDeclare =@Queue(value = “renke.hello”))
public class RouterConsumer2 {
@RabbitHandler
public void getMessage(String message){
System.out.println(“RouterConsume2开始消费:”+message);
}
}
下面开始新建另一种模式即需要手动确认的ACK,消费者接收到消息后不手动确认ACKRabbitMQ的消息会一直存在
代码搞起来之前在说下流程线:
在配置文件注入Queu以及在配置文件将该Queue设置为收到没回确认即可
配置文件指定配置queue的名称
public final static String QUEUE_USER = “sb.user”;
配置文件创建Queue
@Bean
public Queue userQueue() {
return new Queue(QUEUE_USER);
}

将userQueue设置为ACK为手动确认
//=====消费者手动应答
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container
= new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(userQueue());
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(userConsumer);
return container;
}
生产者
@Component
public class DefaultProducer {

@Autowired
private RabbitTemplate rabbitTemplate;

public void sendDefaultMessage(){
    String helloMessage = "default hello";
    String userMessage = "default user";
    //该队列是普通消费者消费(自动确认)

// rabbitTemplate.convertAndSend(RabbitmqConfiguration.QUEUE_HELLO,helloMessage);
//该队列是消费者手动确认

    rabbitTemplate.convertAndSend(RabbitmqConfiguration.QUEUE_USER,userMessage);
}

}

消费者
import com.rabbitmq.client.Channel;
import org.cly.rabbitmq.config.RabbitmqConfiguration;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = RabbitmqConfiguration.QUEUE_USER)
public class UserConsumer implements ChannelAwareMessageListener {

/**
 * 这些注解没有了,在配置文件里配置
 * @param message
 */

// @RabbitHandler

@Override
public void onMessage(Message message, Channel channel) throws Exception {
    try {
        String msg = new String(message.getBody());
        System.out.println("UserReceiver>>>>>>>接收到消息:"+msg);
        try {
	    //手动确认消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),
                    true);
            System.out.println("UserReceiver>>>>>>消息已应答");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                    false,true);
            System.out.println("UserReceiver>>>>>>拒绝消息,要求Mq重新派发");
            throw e;
        }

    }catch (Exception e){
        System.out.println(e.getMessage());
    }
}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值