Browse Source

feat: mq模块

shc 3 years ago
parent
commit
d115cd2434
18 changed files with 843 additions and 0 deletions
  1. 5 0
      hnqz-common/hnqz-common-bom/pom.xml
  2. 6 0
      hnqz-common/hnqz-common-core/pom.xml
  3. 133 0
      hnqz-common/hnqz-common-core/src/main/java/com/qunzhixinxi/hnqz/common/core/entity/BaseMap.java
  4. 27 0
      hnqz-common/hnqz-common-core/src/main/java/com/qunzhixinxi/hnqz/common/core/util/SpringContextHolder.java
  5. 27 0
      hnqz-common/hnqz-common-mq/pom.xml
  6. 29 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/annotation/RabbitMqComponent.java
  7. 363 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/client/RabbitMqClient.java
  8. 54 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/config/RabbitMqConfig.java
  9. 31 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/core/BaseRabbiMqHandler.java
  10. 39 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/core/MapMessageConverter.java
  11. 27 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/BaseApplicationEvent.java
  12. 8 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/BusEventHandler.java
  13. 21 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/EventObj.java
  14. 29 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/HnqzRemoteApplicationEvent.java
  15. 30 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/exchange/DelayExchangeBuilder.java
  16. 10 0
      hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/listenter/MqListener.java
  17. 3 0
      hnqz-common/hnqz-common-mq/src/main/resources/META-INF/spring.factories
  18. 1 0
      hnqz-common/pom.xml

+ 5 - 0
hnqz-common/hnqz-common-bom/pom.xml

@@ -113,6 +113,11 @@
 				<artifactId>hnqz-common-taxhelper</artifactId>
 				<version>${hnqz.version}</version>
 			</dependency>
+			<dependency>
+				<groupId>com.qunzhixinxi</groupId>
+				<artifactId>hnqz-common-mq</artifactId>
+				<version>${hnqz.version}</version>
+			</dependency>
 			<!--<dependency>-->
 			<!--	<groupId>com.qunzhixinxi</groupId>-->
 			<!--	<artifactId>hnqz-common-transaction</artifactId>-->

+ 6 - 0
hnqz-common/hnqz-common-core/pom.xml

@@ -66,5 +66,11 @@
 			<groupId>io.swagger</groupId>
 			<artifactId>swagger-annotations</artifactId>
 		</dependency>
+		<!-- commons-beanutils -->
+		<dependency>
+			<groupId>commons-beanutils</groupId>
+			<artifactId>commons-beanutils</artifactId>
+			<version>1.9.4</version>
+		</dependency>
 	</dependencies>
 </project>

+ 133 - 0
hnqz-common/hnqz-common-core/src/main/java/com/qunzhixinxi/hnqz/common/core/entity/BaseMap.java

@@ -0,0 +1,133 @@
+package com.qunzhixinxi.hnqz.common.core.entity;
+
+import cn.hutool.core.util.ObjectUtil;
+import lombok.NoArgsConstructor;
+import org.apache.commons.beanutils.ConvertUtils;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 自定义Map
+ */
+@NoArgsConstructor
+public class BaseMap extends HashMap<String, Object> {
+
+	public BaseMap(Map<String, Object> map) {
+        this.putAll(map);
+    }
+
+    @Override
+    public BaseMap put(String key, Object value) {
+        super.put(key, Optional.ofNullable(value).orElse(""));
+        return this;
+    }
+
+    public BaseMap add(String key, Object value) {
+        super.put(key, Optional.ofNullable(value).orElse(""));
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(String key) {
+        Object obj = super.get(key);
+        if (ObjectUtil.isNotEmpty(obj)) {
+            return (T) obj;
+        } else {
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Boolean getBoolean(String key) {
+        Object obj = super.get(key);
+        if (ObjectUtil.isNotEmpty(obj)) {
+            return Boolean.valueOf(obj.toString());
+        } else {
+            return false;
+        }
+    }
+
+    public Long getLong(String key) {
+        Object v = get(key);
+        if (ObjectUtil.isNotEmpty(v)) {
+            return new Long(v.toString());
+        }
+        return null;
+    }
+
+    public Long[] getLongs(String key) {
+        Object v = get(key);
+        if (ObjectUtil.isNotEmpty(v)) {
+            return (Long[]) v;
+        }
+        return null;
+    }
+
+    public List<Long> getListLong(String key) {
+        List<String> list = get(key);
+        if (ObjectUtil.isNotEmpty(list)) {
+            return list.stream().map(e -> new Long(e)).collect(Collectors.toList());
+        } else {
+            return null;
+        }
+    }
+
+    public Long[] getLongIds(String key) {
+        Object ids = get(key);
+        if (ObjectUtil.isNotEmpty(ids)) {
+            return (Long[]) ConvertUtils.convert(ids.toString().split(","), Long.class);
+        } else {
+            return null;
+        }
+    }
+
+
+    public Integer getInt(String key, Integer def) {
+        Object v = get(key);
+        if (ObjectUtil.isNotEmpty(v)) {
+            return Integer.parseInt(v.toString());
+        } else {
+            return def;
+        }
+    }
+
+    public Integer getInt(String key) {
+        Object v = get(key);
+        if (ObjectUtil.isNotEmpty(v)) {
+            return Integer.parseInt(v.toString());
+        } else {
+            return 0;
+        }
+    }
+
+    public BigDecimal getBigDecimal(String key) {
+        Object v = get(key);
+        if (ObjectUtil.isNotEmpty(v)) {
+            return new BigDecimal(v.toString());
+        }
+        return new BigDecimal("0");
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(String key, T def) {
+        Object obj = super.get(key);
+        if (ObjectUtil.isEmpty(obj)) {
+            return def;
+        }
+        return (T) obj;
+    }
+
+    public static BaseMap toBaseMap(Map<String, Object> obj) {
+        BaseMap map = new BaseMap();
+        map.putAll(obj);
+        return map;
+    }
+
+
+}

+ 27 - 0
hnqz-common/hnqz-common-core/src/main/java/com/qunzhixinxi/hnqz/common/core/util/SpringContextHolder.java

@@ -19,6 +19,7 @@
 
 package com.qunzhixinxi.hnqz.common.core.util;
 
+import cn.hutool.core.util.StrUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.context.ApplicationContext;
@@ -97,4 +98,30 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
 		SpringContextHolder.clearHolder();
 	}
 
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	public static <T> T getHandler(String name, Class<T> cls) {
+		T t = null;
+		if (StrUtil.isNotBlank(name)) {
+			checkApplicationContext();
+			try {
+				t = applicationContext.getBean(name, cls);
+			} catch (Exception e) {
+				log.error("####################" + name + "未定义");
+			}
+		}
+		return t;
+	}
+
+	/**
+	 * 检查
+	 */
+	private static void checkApplicationContext() {
+		if (applicationContext == null) {
+			throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
+		}
+	}
+
+
 }

+ 27 - 0
hnqz-common/hnqz-common-mq/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<parent>
+		<artifactId>hnqz-common</artifactId>
+		<groupId>com.qunzhixinxi</groupId>
+		<version>3.9.0</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>hnqz-common-mq</artifactId>
+	<description>消息队列</description>
+
+	<dependencies>
+		<!-- 核心模块 -->
+		<dependency>
+			<groupId>com.qunzhixinxi</groupId>
+			<artifactId>hnqz-common-core</artifactId>
+		</dependency>
+		<!-- 消息总线 rabbitmq -->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
+		</dependency>
+	</dependencies>
+</project>

+ 29 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/annotation/RabbitMqComponent.java

@@ -0,0 +1,29 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.annotation;
+
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.stereotype.Component;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 消息队列初始化注解
+ * @author Hengchen.Sun
+ * @date 2021/08/23 16:25:23
+ * @version 1.0.0
+ */
+@Documented
+@Inherited
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Component
+public @interface RabbitMqComponent {
+    @AliasFor(
+            annotation = Component.class
+    )
+    String value();
+}

+ 363 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/client/RabbitMqClient.java

@@ -0,0 +1,363 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.client;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.qunzhixinxi.hnqz.common.core.entity.BaseMap;
+import com.qunzhixinxi.hnqz.common.rabbitmq.annotation.RabbitMqComponent;
+import com.qunzhixinxi.hnqz.common.rabbitmq.event.EventObj;
+import com.qunzhixinxi.hnqz.common.rabbitmq.event.HnqzRemoteApplicationEvent;
+import com.qunzhixinxi.hnqz.common.rabbitmq.exchange.DelayExchangeBuilder;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.bus.BusProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Method;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * rabbitmq消息队列客户端
+ *
+ * @author Hengchen.sun
+ * @version 1.0.0
+ * @date 2021/08/23 16:27:18
+ */
+@Slf4j
+@Configuration
+public class RabbitMqClient {
+
+	private final RabbitAdmin rabbitAdmin;
+
+	private final RabbitTemplate rabbitTemplate;
+
+	private final Map<String, Object> sentObj = new HashMap<>();
+
+	@Autowired
+	public RabbitMqClient(RabbitAdmin rabbitAdmin, RabbitTemplate rabbitTemplate) {
+		this.rabbitAdmin = rabbitAdmin;
+		this.rabbitTemplate = rabbitTemplate;
+	}
+
+	@Resource
+	private SimpleMessageListenerContainer messageListenerContainer;
+
+	@Resource
+	BusProperties busProperties;
+
+	@Resource
+	private ApplicationEventPublisher publisher;
+
+	@Resource
+	private ApplicationContext applicationContext;
+
+
+	/**
+	 * 初始化队列
+	 */
+	@Bean
+	public void initQueue() {
+		Map<String, Object> beansWithRabbitComponentMap = this.applicationContext.getBeansWithAnnotation(RabbitMqComponent.class);
+		Class<?> clazz;
+		log.info(">>>>>>>>>>>> 初始化队列开始 <<<<<<<<<<<<");
+		for (Map.Entry<String, Object> entry : beansWithRabbitComponentMap.entrySet()) {
+			//获取到实例对象的class信息
+			clazz = entry.getValue().getClass();
+			Method[] methods = clazz.getMethods();
+			RabbitListener rabbitListener = clazz.getAnnotation(RabbitListener.class);
+			if (ObjectUtil.isNotEmpty(rabbitListener)) {
+				createQueue(rabbitListener);
+			}
+			for (Method method : methods) {
+				RabbitListener methodRabbitListener = method.getAnnotation(RabbitListener.class);
+				if (ObjectUtil.isNotEmpty(methodRabbitListener)) {
+					createQueue(methodRabbitListener);
+				}
+			}
+		}
+		log.info(">>>>>>>>>>>> 初始化队列结束 <<<<<<<<<<<<");
+
+	}
+
+	/**
+	 * 创建队列
+	 *
+	 * @param rabbitListener 监听
+	 */
+	private void createQueue(RabbitListener rabbitListener) {
+		String[] queues = rabbitListener.queues();
+		DirectExchange directExchange = createExchange(DelayExchangeBuilder.DEFAULT_DIRECT_EXCHANGE);
+		//创建交换机
+		rabbitAdmin.declareExchange(directExchange);
+		if (ObjectUtil.isNotEmpty(queues)) {
+			for (String queueName : queues) {
+				Queue queue = new Queue(queueName);
+				addQueue(queue);
+				Binding binding = BindingBuilder.bind(queue).to(directExchange).with(queueName);
+				rabbitAdmin.declareBinding(binding);
+				log.info("## 队列创建成功:【{}】 ##", queueName);
+			}
+		}
+	}
+
+
+	/**
+	 * 发送远程事件
+	 *
+	 * @param handlerName 绑定名称
+	 * @param baseMap     事件
+	 */
+	public void publishEvent(String handlerName, BaseMap baseMap) {
+		EventObj eventObj = new EventObj();
+		eventObj.setHandlerName(handlerName);
+		eventObj.setBaseMap(baseMap);
+		publisher.publishEvent(new HnqzRemoteApplicationEvent(eventObj, busProperties.getId()));
+	}
+
+	/**
+	 * 转换Message对象
+	 *
+	 * @param messageType 返回消息类型 MessageProperties类中常量
+	 * @param msg
+	 * @return 信息对象
+	 */
+	public Message getMessage(String messageType, Object msg) {
+		MessageProperties messageProperties = new MessageProperties();
+		messageProperties.setContentType(messageType);
+		return new Message(msg.toString().getBytes(), messageProperties);
+	}
+
+	/**
+	 * 有绑定Key的Exchange发送
+	 *
+	 * @param routingKey 路由key
+	 * @param msg        信息
+	 */
+	public void sendMessageToExchange(TopicExchange topicExchange, String routingKey, Object msg) {
+		Message message = getMessage(MessageProperties.CONTENT_TYPE_JSON, msg);
+		rabbitTemplate.send(topicExchange.getName(), routingKey, message);
+	}
+
+	/**
+	 * 没有绑定KEY的Exchange发送
+	 *
+	 * @param exchange 交换机
+	 * @param msg      信息
+	 */
+	public void sendMessageToExchange(TopicExchange topicExchange, AbstractExchange exchange, String msg) {
+		addExchange(exchange);
+		log.info("RabbitMQ 发送信息{} -> {}", exchange.getName(), msg);
+		rabbitTemplate.convertAndSend(topicExchange.getName(), msg);
+	}
+
+
+	/**
+	 * 发送消息
+	 *
+	 * @param queueName 队列名称
+	 * @param params    消息内容map
+	 */
+	public void sendMessage(String queueName, Object params) {
+		log.info("发送消息到mq:{}", params);
+		try {
+			rabbitTemplate.convertAndSend(DelayExchangeBuilder.DEFAULT_DIRECT_EXCHANGE, queueName, params, message -> message);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * 发送消息
+	 *
+	 * @param queueName 队列名称
+	 */
+	public void sendMessage(String queueName) {
+		this.send(queueName, this.sentObj, 0);
+		this.sentObj.clear();
+	}
+
+
+	/**
+	 * 添加发送信息
+	 *
+	 * @param key   信息key
+	 * @param value 信息值
+	 * @return 客户端
+	 */
+	public RabbitMqClient put(String key, Object value) {
+		this.sentObj.put(key, value);
+		return this;
+	}
+
+	/**
+	 * 延迟发送消息
+	 *
+	 * @param queueName  队列名称
+	 * @param params     消息内容params
+	 * @param expiration 延迟时间 单位毫秒
+	 */
+	public void sendMessage(String queueName, Object params, Integer expiration) {
+		this.send(queueName, params, expiration);
+	}
+
+	/**
+	 * 发送消息
+	 *
+	 * @param queueName  队列名
+	 * @param params     参数
+	 * @param expiration 过期时间
+	 */
+	private void send(String queueName, Object params, Integer expiration) {
+		Queue queue = new Queue(queueName);
+		addQueue(queue);
+		CustomExchange customExchange = DelayExchangeBuilder.buildExchange();
+		rabbitAdmin.declareExchange(customExchange);
+		Binding binding = BindingBuilder.bind(queue).to(customExchange).with(queueName).noargs();
+		rabbitAdmin.declareBinding(binding);
+		log.debug("发送时间:{}", LocalDateTime.now());
+		messageListenerContainer.setQueueNames(queueName);
+		rabbitTemplate.convertAndSend(DelayExchangeBuilder.DEFAULT_DELAY_EXCHANGE, queueName, params, message -> {
+			if (expiration != null && expiration > 0) {
+				message.getMessageProperties().setHeader("x-delay", expiration);
+			}
+			return message;
+		});
+	}
+
+
+	/**
+	 * 给queue发送消息
+	 *
+	 * @param queueName 队列名
+	 */
+	public String receiveFromQueue(String queueName) {
+		return receiveFromQueue(DirectExchange.DEFAULT, queueName);
+	}
+
+	/**
+	 * 给direct交换机指定queue发送消息
+	 *
+	 * @param directExchange 直接模式交换机
+	 * @param queueName      队列名
+	 */
+	public String receiveFromQueue(DirectExchange directExchange, String queueName) {
+		Queue queue = new Queue(queueName);
+		addQueue(queue);
+		Binding binding = BindingBuilder.bind(queue).to(directExchange).withQueueName();
+		rabbitAdmin.declareBinding(binding);
+		String messages = (String) rabbitTemplate.receiveAndConvert(queueName);
+		log.info("接收到的信息:{}", messages);
+		return messages;
+	}
+
+	/**
+	 * 创建Exchange
+	 *
+	 * @param exchange 交换机
+	 */
+	public void addExchange(AbstractExchange exchange) {
+		rabbitAdmin.declareExchange(exchange);
+	}
+
+	/**
+	 * 删除一个Exchange
+	 *
+	 * @param exchangeName 交换机名称
+	 */
+	public boolean deleteExchange(String exchangeName) {
+		return rabbitAdmin.deleteExchange(exchangeName);
+	}
+
+
+	/**
+	 * 声明其名称自动命名的队列。它是用exclusive=true、autoDelete=true和 durable = false
+	 *
+	 * @return Queue
+	 */
+	public Queue addQueue() {
+		return rabbitAdmin.declareQueue();
+	}
+
+	/**
+	 * 创建一个指定的Queue
+	 *
+	 * @param queue 队列
+	 * @return queueName
+	 */
+	public String addQueue(Queue queue) {
+		return rabbitAdmin.declareQueue(queue);
+	}
+
+	/**
+	 * 删除一个队列
+	 *
+	 * @param queueName the name of the queue.
+	 * @param unused    true if the queue should be deleted only if not in use.
+	 * @param empty     true if the queue should be deleted only if empty.
+	 */
+	public void deleteQueue(String queueName, boolean unused, boolean empty) {
+		rabbitAdmin.deleteQueue(queueName, unused, empty);
+	}
+
+	/**
+	 * 删除一个队列
+	 *
+	 * @param queueName 队列名
+	 * @return true if the queue existed and was deleted.
+	 */
+	public boolean deleteQueue(String queueName) {
+		return rabbitAdmin.deleteQueue(queueName);
+	}
+
+	/**
+	 * 绑定一个队列到一个匹配型交换器使用一个routingKey
+	 *
+	 * @param queue      队列
+	 * @param exchange   交换机
+	 * @param routingKey 路由key
+	 */
+	public void addBinding(Queue queue, TopicExchange exchange, String routingKey) {
+		Binding binding = BindingBuilder.bind(queue).to(exchange).with(routingKey);
+		rabbitAdmin.declareBinding(binding);
+	}
+
+	/**
+	 * 绑定一个Exchange到一个匹配型Exchange 使用一个routingKey
+	 *
+	 * @param exchange      交换机
+	 * @param topicExchange topic交换机
+	 * @param routingKey    路由key
+	 */
+	public void addBinding(Exchange exchange, TopicExchange topicExchange, String routingKey) {
+		Binding binding = BindingBuilder.bind(exchange).to(topicExchange).with(routingKey);
+		rabbitAdmin.declareBinding(binding);
+	}
+
+	/**
+	 * 去掉一个binding
+	 *
+	 * @param binding 绑定
+	 */
+	public void removeBinding(Binding binding) {
+		rabbitAdmin.removeBinding(binding);
+	}
+
+	/**
+	 * 创建交换器
+	 *
+	 * @param exchangeName 交换机名称
+	 * @return 直接模式交换机
+	 */
+	public DirectExchange createExchange(String exchangeName) {
+		return new DirectExchange(exchangeName, true, false);
+	}
+}

+ 54 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/config/RabbitMqConfig.java

@@ -0,0 +1,54 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.config;
+
+import com.qunzhixinxi.hnqz.common.rabbitmq.event.HnqzRemoteApplicationEvent;
+import org.springframework.amqp.core.AcknowledgeMode;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.support.ConsumerTagStrategy;
+import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.UUID;
+
+/**
+ * 消息队列配置类
+ *
+ * @author zyf
+ */
+@Configuration
+@RemoteApplicationEventScan(basePackageClasses = HnqzRemoteApplicationEvent.class)
+public class RabbitMqConfig {
+
+    @Bean
+    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
+        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
+        //设置忽略声明异常
+        rabbitAdmin.setIgnoreDeclarationExceptions(true);
+        return rabbitAdmin;
+    }
+
+    @Bean
+    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) {
+        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
+        container.setConnectionFactory(connectionFactory);
+        //手动确认
+        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
+        //当前的消费者数量
+        container.setConcurrentConsumers(1);
+        //最大的消费者数量
+        container.setMaxConcurrentConsumers(1);
+        //是否重回队列
+        container.setDefaultRequeueRejected(true);
+        //消费端的标签策略
+        container.setConsumerTagStrategy(new ConsumerTagStrategy() {
+            @Override
+            public String createConsumerTag(String queue) {
+                return queue + "_" + UUID.randomUUID().toString();
+            }
+        });
+        return container;
+    }
+
+}

+ 31 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/core/BaseRabbiMqHandler.java

@@ -0,0 +1,31 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.core;
+
+import com.qunzhixinxi.hnqz.common.rabbitmq.listenter.MqListener;
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+
+@Slf4j
+public class BaseRabbiMqHandler<T> {
+
+    public void onMessage(T t, Long deliveryTag, Channel channel, MqListener mqListener) {
+        try {
+            mqListener.handler(t, channel);
+            channel.basicAck(deliveryTag, false);
+        } catch (Exception e) {
+            log.info("接收消息失败,重新放回队列");
+            try {
+                /**
+                 * deliveryTag:该消息的index
+                 * multiple:是否批量.true:将一次性拒绝所有小于deliveryTag的消息。
+                 * requeue:被拒绝的是否重新入队列
+                 */
+                channel.basicNack(deliveryTag, false, true);
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+
+    }
+}

+ 39 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/core/MapMessageConverter.java

@@ -0,0 +1,39 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.core;
+
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.support.converter.MessageConversionException;
+import org.springframework.amqp.support.converter.MessageConverter;
+
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MapMessageConverter implements MessageConverter {
+    @Override
+    public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
+        return new Message(object.toString().getBytes(), messageProperties);
+    }
+
+    @Override
+    public Object fromMessage(Message message) throws MessageConversionException {
+        String contentType = message.getMessageProperties().getContentType();
+        if (null != contentType && contentType.contains("text")) {
+            return new String(message.getBody());
+        } else {
+            ObjectInputStream objInt = null;
+            try {
+                ByteArrayInputStream byteInt = new ByteArrayInputStream(message.getBody());
+                objInt = new ObjectInputStream(byteInt);
+                //byte[]转map
+                Map map = (HashMap) objInt.readObject();
+                return map;
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+
+    }
+}

+ 27 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/BaseApplicationEvent.java

@@ -0,0 +1,27 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.event;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.qunzhixinxi.hnqz.common.core.util.SpringContextHolder;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * 监听远程事件,并分发消息到业务模块消息处理器
+ */
+@Component
+public class BaseApplicationEvent implements ApplicationListener<HnqzRemoteApplicationEvent> {
+
+    @Override
+    public void onApplicationEvent(HnqzRemoteApplicationEvent hnqzRemoteApplicationEvent) {
+        EventObj eventObj = hnqzRemoteApplicationEvent.getEventObj();
+        if (ObjectUtil.isNotEmpty(eventObj)) {
+            //获取业务模块消息处理器
+            BusEventHandler busEventHandler = SpringContextHolder.getHandler(eventObj.getHandlerName(), BusEventHandler.class);
+            if (ObjectUtil.isNotEmpty(busEventHandler)) {
+                //通知业务模块
+                busEventHandler.onMessage(eventObj);
+            }
+        }
+    }
+
+}

+ 8 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/BusEventHandler.java

@@ -0,0 +1,8 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.event;
+
+/**
+ * 业务模块消息处理器接口
+ */
+public interface BusEventHandler {
+    void onMessage(EventObj map);
+}

+ 21 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/EventObj.java

@@ -0,0 +1,21 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.event;
+
+import com.qunzhixinxi.hnqz.common.core.entity.BaseMap;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 远程事件数据对象
+ */
+@Data
+public class EventObj implements Serializable {
+    /**
+     * 数据对象
+     */
+    private BaseMap baseMap;
+    /**
+     * 自定义业务模块消息处理器beanName
+     */
+    private String handlerName;
+}

+ 29 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/event/HnqzRemoteApplicationEvent.java

@@ -0,0 +1,29 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.event;
+
+import lombok.Data;
+import org.springframework.cloud.bus.event.RemoteApplicationEvent;
+
+/**
+ * 自定义网关刷新远程事件
+ *
+ * @author : zyf
+ * @date :2020-11-10
+ */
+@Data
+public class HnqzRemoteApplicationEvent extends RemoteApplicationEvent {
+
+    private EventObj eventObj;
+
+    private HnqzRemoteApplicationEvent() {
+    }
+
+    public HnqzRemoteApplicationEvent(EventObj source, String originService, String destinationService) {
+        super(source, originService, destinationService);
+        this.eventObj = source;
+    }
+
+    public HnqzRemoteApplicationEvent(EventObj source, String originService) {
+        super(source, originService, null);
+        this.eventObj = source;
+    }
+}

+ 30 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/exchange/DelayExchangeBuilder.java

@@ -0,0 +1,30 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.exchange;
+
+import org.springframework.amqp.core.CustomExchange;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 延迟交换器构造器
+ */
+public class DelayExchangeBuilder {
+    /**
+     * 默认延迟消息交换器
+     */
+    public final static  String DEFAULT_DELAY_EXCHANGE = "default.delayed.exchange";
+    /**
+     * 普通交换器
+     */
+    public final static  String DEFAULT_DIRECT_EXCHANGE = "default.direct.exchange";
+
+    /**
+     * 构建延迟消息交换器
+     * @return
+     */
+    public static CustomExchange buildExchange() {
+        Map<String, Object> args = new HashMap<String, Object>();
+        args.put("x-delayed-type", "direct");
+        return new CustomExchange(DEFAULT_DELAY_EXCHANGE, "x-delayed-message", true, false, args);
+    }
+}

+ 10 - 0
hnqz-common/hnqz-common-mq/src/main/java/com/qunzhixinxi/hnqz/common/rabbitmq/listenter/MqListener.java

@@ -0,0 +1,10 @@
+package com.qunzhixinxi.hnqz.common.rabbitmq.listenter;
+
+import com.rabbitmq.client.Channel;
+
+public interface MqListener<T> {
+
+    default void handler(T map, Channel channel) {
+    }
+
+}

+ 3 - 0
hnqz-common/hnqz-common-mq/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.qunzhixinxi.hnqz.common.rabbitmq.config.RabbitMqConfig,\
+  com.qunzhixinxi.hnqz.common.rabbitmq.client.RabbitMqClient

+ 1 - 0
hnqz-common/pom.xml

@@ -51,5 +51,6 @@
 		<module>hnqz-common-ding</module>
 		<module>hnqz-common-taxhelper</module>
 		<module>hnqz-common-qcc</module>
+		<module>hnqz-common-mq</module>
 	</modules>
 </project>