Springboot使用RabbitMQ代码示例

我只是一个虾纸丫 提交于 2020-04-06 08:36:39

Springboot使用RabbitMQ代码示例

示例说明

  • 本示例使用slf4j-log4j12管理日志,需要排除spring-boot-start-amqp的logback-classic依赖以防止冲突。
  • 消息队列几个要点
    • 生产者:发送消息的程序
    • 消费者:监听接收消费消息的程序
    • 消息:一串二进制数据流
    • 队列:消息的暂存区/存储区
    • 转换器:消息的中转站,用于接收分发消息。其中有 fanout、direct、topic、headers 四种
    • 路由:与转换器绑定即可路由消息到指定的队列!

依赖导入

	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
            <!--排除日志冲突-->
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>

配置文件

spring:
  rabbitmq:
    host: 192.168.1.117
    port: 5672
    username: admin
    password: admin
    publisher-confirm-type: correlated #必须配置这个才会确认回调
    publisher-returns: true
    listener:
      type: simple
      simple:
        acknowledge-mode: manual #手动确认
        prefetch: 1 #限制每次发送一条数据。
        concurrency: 3 #同一个队列启动几个消费者
        max-concurrency: 3 #启动消费者最大数量
        #重试策略相关配置
        retry:
          enabled: true #是否支持重试
          max-attempts: 5
          stateless: false
          #时间策略乘数因子
          multiplier: 1.0
          initial-interval: 1000ms
          max-interval: 10000ms
        default-requeue-rejected: true

Bean配置类

@Configuration
public class RabbitMQConfig {
    private static Logger log = LoggerFactory.getLogger(RabbitMQConfig.class);
    @Autowired
    private CachingConnectionFactory connectionFactory;

    //目标转换器,需要哪种类型的转换器就创建哪种类型的转换器
    @Bean
    public DirectExchange exchangeHello(){
        Map<String, Object> eArguments = new HashMap<>();
        //备份交换器参数
        eArguments.put("alternate-exchange", "exchange.ae");
        return new DirectExchange("exchange.hello",true,false,eArguments);
    }
    //备份转换器
    @Bean
    public FanoutExchange exchangeAE(){
        return new FanoutExchange("exchange.ae",true,false,null);
    }
    //死信转换器
    @Bean
    public TopicExchange exchangeDLX(){
        return new TopicExchange("exchange.dlx",true,false,null);
    }

    //目标对列
    @Bean
    public Queue queueHello() {
        Map<String, Object> args = new HashMap<>();
        //声明死信交换器
        args.put("x-dead-letter-exchange", "exchange.dlx");
        //声明死信路由键
        args.put("x-dead-letter-routing-key", "dlx.test" );
        //声明队列消息过期时间 5000ms
        args.put("x-message-ttl", 5000);
        return new Queue("queue.hello",true,false,false,args);
    }

    //备份对列
    @Bean
    public Queue queueAE() {
        return new Queue("queue.ae",true,false,false,null);
    }

    //死信对列
    @Bean
    public Queue queueDLX() {
        return new Queue("queue.dlx",true,false,false,null);
    }

    //绑定目标对列
    @Bean
    public Binding bindingExchangeDirect(@Qualifier("queueHello")Queue queueHello, @Qualifier("exchangeHello") DirectExchange exchangeHello){
        return  BindingBuilder.bind(queueHello).to(exchangeHello).with("helloKey");
    }
    //绑定备份对列
    @Bean
    public Binding bindingExchangeAE(@Qualifier("queueAE")Queue queueAE, @Qualifier("exchangeAE") FanoutExchange exchangeAE){
        return  BindingBuilder.bind(queueAE).to(exchangeAE);
    }

    //绑定死信对列
    @Bean
    public Binding bindingExchangeDLX(@Qualifier("queueDLX")Queue queueAE, @Qualifier("exchangeDLX") TopicExchange exchangeDLX){
        return  BindingBuilder.bind(queueAE).to(exchangeDLX).with("dlx.*");
    }

    /**
     * 如果需要在生产者需要消息发送后的回调,
     * 需要对rabbitTemplate设置ConfirmCallback对象,
     * 由于不同的生产者需要对应不同的ConfirmCallback,
     * 如果rabbitTemplate设置为单例bean,
     * 则所有的rabbitTemplate实际的ConfirmCallback为最后一次申明的ConfirmCallback。
     * @return
     */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        return template;
    }

}

队列生产者

@Controller
public class HelloSender implements  RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback{
    private static Logger log = LoggerFactory.getLogger(HelloSender.class);
    private RabbitTemplate rabbitTemplate;

    //构造方法注入
    @Autowired
    public HelloSender(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        //这是是设置回调能收到发送到响应
        rabbitTemplate.setConfirmCallback(this);
        //如果设置备份队列则不起作用
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback(this);
    }

    @RequestMapping("/send")
    @ResponseBody
    public void send() {
        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
        String sendMsg = "hello1 " + new Date();
        System.out.println("Sender : " + sendMsg);
        //convertAndSend(exchange:交换机名称,routingKey:路由关键字,object:发送的消息内容,correlationData:消息ID)
        rabbitTemplate.convertAndSend("exchange.hello","helloKey", sendMsg,correlationId);
    }


    //回调确认
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
        }else{
            log.info("消息发送失败:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
        }
    }

    //消息发送到转换器的时候没有对列,配置了备份对列该回调则不生效
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
    }
    
}

队列消费者

@Component
public class HelloConsumer {
    private static Logger log = LoggerFactory.getLogger(HelloConsumer.class);

    @RabbitHandler
    @RabbitListener(queues = "queue.hello")
    public void process(Message message, Channel channel) throws IOException {
        log.info("receive: " + new String(message.getBody())+"《线程名:》"+Thread.currentThread().getName()+"《线程id:》"+Thread.currentThread().getId());
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
    }

}

启动类开启RabbitMQ

@EnableRabbit
@SpringBootApplication
public class RabbitmqApplication {
    public static void main(String[] args) {
        SpringApplication.run(RabbitmqApplication.class,args);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!