springBoot整合RabbitMQ+延迟消息发送

pom依赖
			<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
                <version>2.2.5.RELEASE</version>
            </dependency>
yml
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    virtual-host: /api/mall #mq设置的路由
    username: root
    password: password
    publisher-confirms: true #消息发送到交换器确认
    publisher-returns: true #消息发送到队列确认
    listener:
      simple:
        #消费失败消息干掉
        default-requeue-rejected: true
        retry:
          #5秒
          initial-interval: 5000
          enabled: true
          #最大重试5次
          max-attempts: 5
config配置
RabbitMQ.java

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.dandandog.framework.common.utils.SpringContextUtil;
import com.dandandog.framework.mq.model.ImqBinding;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Stephen
 */
@Configuration
public class RabbitMqConfig implements InitializingBean {

    private final List<ImqBinding> bindings;

    @Autowired
    public RabbitMqConfig(List<ImqBinding> bindings) {
        this.bindings = bindings;
    }

    @Override
    public void afterPropertiesSet() {
        if (CollUtil.isNotEmpty(bindings)) {
            Multimap<String, ImqBinding> bindingMap = ArrayListMultimap.create();
            bindings.forEach(binding -> {
                bindingMap.put(binding.getExchange(), binding);
            });

            bindingMap.keySet().forEach(exchangeName -> {
                CustomExchange customExchange = buildCustomExchange(exchangeName);
                bindingMap.get(exchangeName).forEach(binding -> {
                    Queue queue = buildPluginQueue(binding.getQueue());
                    buildPluginBinding(customExchange, queue, binding.getRouteKey());
                });
            });
        }
    }

    private CustomExchange buildCustomExchange(String exchangeName) {
        Map<String, Object> args = new HashMap<>(1);
        args.put("x-delayed-type", "direct");
        String beanName = createBeanName(exchangeName, "Exchange");
        return SpringContextUtil.registerBean(beanName, CustomExchange.class,
                () -> new CustomExchange(exchangeName, "x-delayed-message", true, false, args));
    }

    private Queue buildPluginQueue(String queueName) {
        String beanName = createBeanName(queueName, "Queue");
        return SpringContextUtil.registerBean(beanName, Queue.class,
                () -> new Queue(queueName, true));
    }

    private Binding buildPluginBinding(CustomExchange exchange, Queue queue, String routeKey) {
        String beanName = createBeanName(routeKey, "Binding");
        return SpringContextUtil.registerBean(beanName, Binding.class,
                () -> BindingBuilder.bind(queue).to(exchange).with(routeKey).noargs());
    }

    private String createBeanName(String name, String suffix) {
        String repName = StrUtil.replace(name, ".", "_");
        String suffixName = StrUtil.addSuffixIfNot(repName, suffix);
        return StrUtil.toCamelCase(suffixName);
    }
}

交换机绑定接口
/**
 * @author Stephen
 */

public interface ImqBinding {


    /**
     * 获取交换机名称
     *
     * @return 交换机名称
     */
    String getExchange();

    /**
     * 获取队列名称
     *
     * @return 队列名称
     */
    String getQueue();

    /**
     * 获取路由键
     *
     * @return 路由键
     */
    String getRouteKey();

}

消息发送抽象类

import com.dandandog.framework.mq.model.ImqBinding;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;

/**
 * @author Stephen
 */
@Component
public abstract class BaseDelaySender<T extends ImqBinding> {


    private final AmqpTemplate amqpTemplate;

    private final T binding;

    @Autowired
    public BaseDelaySender(AmqpTemplate amqpTemplate, T binding) {
        this.amqpTemplate = amqpTemplate;
        this.binding = binding;
    }

    public void sendDelayMessage(Object data, long delayTimes) {
        amqpTemplate.convertAndSend(binding.getExchange(), binding.getRouteKey(), data, message -> {
            message.getMessageProperties().setHeader("x-delay", delayTimes);
            return message;
        });
    }

    public void sendDelayMessage(Object data, LocalDateTime delayDataTime) {
        Duration delayTimes = Duration.between(LocalDateTime.now(), delayDataTime);
        this.sendDelayMessage(data, delayTimes.toMillis());
    }
}

业务使用,例如订单付款失败30分钟后取消订单
设置交换机与队列名称

import com.dandandog.framework.mq.model.ImqBinding;
import org.springframework.stereotype.Service;

/**
 * @author StephenZhang
 */
@Service
public class OrderCancelMessageBinding implements ImqBinding {
    @Override
    public String getExchange() {
        return "message.direct.plugin";
    }

    @Override
    public String getQueue() {
        return "mall.order.cancel.plugin";
    }

    @Override
    public String getRouteKey() {
        return "mall.order.cancel.plugin";
    }
}

消息发送实现类

import com.dandandog.framework.mq.sender.BaseDelaySender;
import com.myelephant.projects.rabbit.config.OrderCancelMessageBinding;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author Stephen
 */
@Component
public class MallCancelOrderSender extends BaseDelaySender<OrderCancelMessageBinding> {

    @Autowired
    public MallCancelOrderSender(AmqpTemplate amqpTemplate, OrderCancelMessageBinding binding) {
        super(amqpTemplate, binding);
    }
}

消息接收实现类

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.myelephant.module.integral.entity.enums.UserLogType;
import com.myelephant.module.integral.service.IntegralUserLogService;
import com.myelephant.module.mall.entity.MallOrder;
import com.myelephant.module.mall.entity.enums.OrderState;
import com.myelephant.module.mall.service.MallOrderService;
import com.myelephant.projects.integral.facet.IntegralTaskFacet;
import com.myelephant.projects.mall.give.facet.GiveProductOrderFacet;
import com.myelephant.projects.mall.give.vo.OrderCancelMqVo;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author StephenZhang
 */
@Component
@RabbitListener(queues = "mall.order.cancel.plugin")
public class MallCancelOrderReceiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(MallCancelOrderReceiver.class);

    @Resource
    private MallOrderService mallOrderService;
    @Resource
    private IntegralUserLogService integralUserLogService;
    @Resource
    private IntegralTaskFacet integralTaskFacet;
    @Resource
    private GiveProductOrderFacet giveProductOrderFacet;
    @Resource
    private RedisTemplate<String, List<MallOrder>> redisTemplate;
    @Value("${spring.redis.key.prefix.mallOrderSpellGift}")
    private String orderSpellGiftKey;

    @RabbitHandler
    public synchronized void handle(String params) {
        //具体业务实现
        LOGGER.info("receive delay message params:{}", params);
    }
}

方法调用
	@Resource
    private MallCancelOrderSender mallcancelOrderSender;
可指定毫秒或者指定时间
    mallcancelOrderSender.sendDelayMessage(params, (30 * 60 * 1000));
Linux下安装MQ+延迟插件

https://blog.csdn.net/Dong_Zi8/article/details/116021223?spm=1001.2014.3001.5501

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值