SpringBoot整合RabbitMQ案例

 

这里还是采用用户注册后发送邮件和短信为例来说明:

 

SpringBoot整合RabbitMQ案例_第1张图片

生产者代码

package com.infosys.china.producer;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class FanoutConfig
{

    // 邮件队列
    private String FANOUT_EMAIL_QUEUE = "fanout_email_queue";

    // 短信队列
    private String FANOUT_SMS_QUEUE = "fanout_sms_queue";

    // 定义交换机
    private String EXCHANGE_NAME = "fanoutExchange";

    // 1.定义邮件队列
    @Bean
    public Queue fanOutEmailQueue()
    {
        return new Queue(FANOUT_EMAIL_QUEUE);
    }

    // 1.定义短信队列
    @Bean
    public Queue fanOutSmsQueue()
    {
        return new Queue(FANOUT_SMS_QUEUE);
    }

    // 2.定义交换机
    @Bean
    public FanoutExchange fanoutExchange()
    {
        return new FanoutExchange(EXCHANGE_NAME);
    }

    // 3.队列与交换机绑定邮件队列
    @Bean
    Binding bindingExchangeEamil(Queue fanOutEmailQueue, FanoutExchange fanoutExchange)
    {
        return BindingBuilder.bind(fanOutEmailQueue).to(fanoutExchange);
    }

    // 4.队列与交换机绑定短信队列
    @Bean
    Binding bindingExchangeSms(Queue fanOutSmsQueue, FanoutExchange fanoutExchange)
    {
        return BindingBuilder.bind(fanOutSmsQueue).to(fanoutExchange);
    }
}
package com.infosys.china.producer;

import java.util.Date;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 
 * 生产者发送消息
 * 
 * @author Jiayoubing
 * @version [版本号,2020年5月7日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Component
public class FanoutProducer
{
    @Autowired
    private AmqpTemplate amqpTemplate;

    public void send(String queueName)
    {
        String msg = "my_fanout_msg:" + new Date();
        System.out.println("msg is :" + msg);
        amqpTemplate.convertAndSend(queueName, msg);
    }
}
package com.infosys.china.producer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProducerController
{
    @Autowired
    private FanoutProducer fanoutProducer;

    @RequestMapping("/sendFanout")
    public String sendFanout(String queueName)
    {
        fanoutProducer.send(queueName);
        return "success";
    }

}

POM文件


		org.springframework.boot
		spring-boot-starter-parent
		2.1.7.RELEASE
		 
	

	

		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
		
			org.springframework.boot
			spring-boot-starter-amqp
		
		
			org.apache.commons
			commons-lang3
		
		
		
			com.alibaba
			fastjson
			1.2.49
		

	

	
		3.1.1
	
/**
 * 文件名:AppProducer.java 版权:Company Technologies Co.,Ltd.Copyright YYYY-YYYY,All
 * rights reserved 版权:Copyright (c) 2020, [email protected] All Rights
 * Reserved. 描述:<描述> 修改人:Administrator 修改时间:2020年5月7日 修改内容:<修改内容>
 */
package com.infosys.china.producer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

/**
 * <一句话功能简述> <功能详细描述>
 * 
 * @author Jiayoubing
 * @version [版本号,2020年5月7日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class AppProducer
{
    public static void main(String[] args) throws Exception
    {
        SpringApplication.run(AppProducer.class, args);
    }

}

消费者代码

/**
 * 文件名:AppConsumer.java 版权:Company Technologies Co.,Ltd.Copyright YYYY-YYYY,All
 * rights reserved 版权:Copyright (c) 2020, [email protected] All Rights
 * Reserved. 描述:<描述> 修改人:Administrator 修改时间:2020年5月7日 修改内容:<修改内容>
 */
package com.infosys.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

/**
 * <一句话功能简述> <功能详细描述>
 * 
 * @author Jiayoubing
 * @version [版本号,2020年5月7日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class AppConsumer
{
    public static void main(String[] args) throws Exception
    {
        SpringApplication.run(AppConsumer.class, args);
    }

}
package com.infosys.consumer;

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

@Component
@RabbitListener(queues = "fanout_email_queue")
public class FanoutEamilConsumer {
	@RabbitHandler
	public void process(String msg) throws Exception {
		System.out.println("邮件消费者获取生产者消息msg:" + msg);
	}
}
package com.infosys.consumer;

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

@Component
@RabbitListener(queues = "fanout_sms_queue")
public class FanoutSmsConsumer {
	@RabbitHandler
	public void process(String msg) {
		System.out.println("短信消费者获取生产者消息msg:" + msg);
	}
}

在启动生产者和消费者之前,需要先创建交货机和队列

SpringBoot整合RabbitMQ案例_第2张图片

 

SpringBoot整合RabbitMQ案例_第3张图片

执行结果:

SpringBoot整合RabbitMQ案例_第4张图片

SpringBoot整合RabbitMQ案例_第5张图片

开启消息重试机制和手动应答机制

 

spring:
  rabbitmq:
  ####连接地址
    host: 192.168.234.103
   ####端口号   
    port: 5672
   ####账号 
    username: guest
   ####密码  
    password: guest
   ### 地址
    virtual-host: /
    listener:
      simple:
        retry:
          ###开启消费者重试
          enabled: true
          ###重试次数
          max-attempts: 5
          ###重试间隔时间
          initial-interval: 3000
        ###手动开启ack应答模式
        acknowledge-mode: manual
            

代码加上手动应答机制:

package com.infosys.consumer;

import java.util.Map;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.Channel;

@Component
@RabbitListener(queues = "fanout_email_queue")
public class FanoutEamilConsumer
{
    @RabbitHandler
    public void process(String msg, @Headers Map headers, Channel channel) throws Exception
    {
        System.out.println("邮件消费者获取生产者消息msg:" + msg);

        // 手动ack
        Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
        // 手动签收
        channel.basicAck(deliveryTag, false);

    }
}

 

如何解决消费者重复消费的问题?

解决办法:在生产者里面传一个唯一的消息id或者业务id(这个id必须为唯一性的),在消费者里面判断这个id是否已执行,如果没有执行,就处理,如果执行直接返回成功。

Message message = MessageBuilder.withBody(msg.getBytes()).setContentType(MessageProperties.CONTENT_TYPE_JSON)
                .setContentEncoding("utf-8").setMessageId(UUID.randomUUID() + "").build();

 

你可能感兴趣的:(SpringBoot整合RabbitMQ案例)