@@ -20,6 +20,16 @@ | |||||
<artifactId>framework</artifactId> | <artifactId>framework</artifactId> | ||||
<version>1.0-SNAPSHOT</version> | <version>1.0-SNAPSHOT</version> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>net.sf.dozer</groupId> | |||||
<artifactId>dozer</artifactId> | |||||
<version>5.5.1</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.aliyun.openservices</groupId> | |||||
<artifactId>ons-client</artifactId> | |||||
<version>1.8.4.Final</version> | |||||
</dependency> | |||||
<!-- MySql数据库驱动 --> | <!-- MySql数据库驱动 --> | ||||
<dependency> | <dependency> | ||||
<groupId>mysql</groupId> | <groupId>mysql</groupId> | ||||
@@ -0,0 +1,75 @@ | |||||
package com.neusoft.smart.pos.mq; | |||||
import java.util.Properties; | |||||
import javax.annotation.PostConstruct; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.context.annotation.Profile; | |||||
import org.springframework.stereotype.Service; | |||||
import com.alibaba.fastjson.JSON; | |||||
import com.aliyun.openservices.ons.api.Action; | |||||
import com.aliyun.openservices.ons.api.ConsumeContext; | |||||
import com.aliyun.openservices.ons.api.Consumer; | |||||
import com.aliyun.openservices.ons.api.Message; | |||||
import com.aliyun.openservices.ons.api.MessageListener; | |||||
import com.aliyun.openservices.ons.api.ONSFactory; | |||||
import com.aliyun.openservices.ons.api.PropertyKeyConst; | |||||
import com.aliyun.openservices.ons.api.bean.ConsumerBean; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
@Slf4j | |||||
@Service | |||||
@Profile(MQConfig.Impl.ALIYUN_ROCKET_MQ) | |||||
public class AliyunRocketMqConsumer extends MqBaseConsumer { | |||||
@Value("${spring.aliyunRocketmq.accessKeyId}") | |||||
private String accessKeyId; | |||||
@Value("${spring.aliyunRocketmq.accessKeySecret}") | |||||
private String accessKeySecret; | |||||
@Value("${spring.aliyunRocketmq.groupId}") | |||||
private String groupId; | |||||
@Value("${spring.aliyunRocketmq.namesrvAddr}") | |||||
private String namesrvAddr; | |||||
@PostConstruct | |||||
public void init() { | |||||
for (EnumMsgMqTopic topic: EnumMsgMqTopic.values()) { | |||||
Properties properties = new Properties(); | |||||
// 您在控制台创建的 Group ID | |||||
properties.put(PropertyKeyConst.GROUP_ID, topic.getGroupId()); | |||||
// AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||||
properties.put(PropertyKeyConst.AccessKey, accessKeyId); | |||||
// SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||||
properties.put(PropertyKeyConst.SecretKey, accessKeySecret); | |||||
// 设置 TCP 接入域名,到控制台的实例基本信息中查看 | |||||
properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr); | |||||
// 集群订阅方式(默认) | |||||
// properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.CLUSTERING); | |||||
// 广播订阅方式 | |||||
// properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING); | |||||
Consumer consumer = ONSFactory.createConsumer(properties); | |||||
consumer.subscribe(topic.getCode(), "*", new MessageListener() { //订阅多个 Tag | |||||
public Action consume(Message message, ConsumeContext context) { | |||||
try { | |||||
System.out.println("Receive: " + message); | |||||
doMessage(new String(message.getBody())); | |||||
return Action.CommitMessage; | |||||
}catch(Exception e) { | |||||
log.error("AliyunRocketMqConsumer error:",e); | |||||
return Action.ReconsumeLater; | |||||
} | |||||
} | |||||
}); | |||||
consumer.start(); | |||||
log.info(" aliyunrocketMq consumer start success! "+JSON.toJSONString(consumer)); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,118 @@ | |||||
package com.neusoft.smart.pos.mq; | |||||
import java.util.Date; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import java.util.Properties; | |||||
import javax.annotation.PostConstruct; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.context.annotation.Profile; | |||||
import org.springframework.stereotype.Service; | |||||
import com.alibaba.fastjson.JSON; | |||||
import com.aliyun.openservices.ons.api.Message; | |||||
import com.aliyun.openservices.ons.api.ONSFactory; | |||||
import com.aliyun.openservices.ons.api.Producer; | |||||
import com.aliyun.openservices.ons.api.PropertyKeyConst; | |||||
import com.aliyun.openservices.ons.api.SendResult; | |||||
/** | |||||
* @Auther: zfy 阿里云rocketmq | |||||
* @Date: 2019-01-31 | |||||
* @Description: RocketMQ消息生产者 | |||||
*/ | |||||
@Service | |||||
@Profile(MQConfig.Impl.ALIYUN_ROCKET_MQ) | |||||
public class AliyunRocketMqMessageProducer implements MqProducer { | |||||
private final Logger log = LoggerFactory.getLogger(this.getClass()); | |||||
@Value("${spring.aliyunRocketmq.accessKeyId}") | |||||
private String accessKeyId; | |||||
@Value("${spring.aliyunRocketmq.accessKeySecret}") | |||||
private String accessKeySecret; | |||||
@Value("${spring.aliyunRocketmq.groupId}") | |||||
private String groupId; | |||||
@Value("${spring.aliyunRocketmq.namesrvAddr}") | |||||
private String namesrvAddr; | |||||
//@Autowired | |||||
//private WxMsgRecordMapper wxMsgRecordMapper; | |||||
//@Autowired | |||||
//private WxMsgRecordService wxMsgRecordService; | |||||
private static Map<String,Producer> producerMap = null; | |||||
@PostConstruct | |||||
public void init() { | |||||
producerMap = new HashMap<String,Producer>(); | |||||
for (EnumMsgMqTopic topic: EnumMsgMqTopic.values()) { | |||||
Properties properties = new Properties(); | |||||
properties.setProperty(PropertyKeyConst.GROUP_ID, topic.getGroupId()); | |||||
// AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||||
properties.put(PropertyKeyConst.AccessKey,accessKeyId); | |||||
// SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||||
properties.put(PropertyKeyConst.SecretKey, accessKeySecret); | |||||
//设置发送超时时间,单位毫秒 | |||||
properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000"); | |||||
// 设置 TCP 接入域名,到控制台的实例基本信息中查看 | |||||
properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr); | |||||
Producer producer = ONSFactory.createProducer(properties); | |||||
// 在发送消息前,必须调用 start 方法来启动 Producer,只需调用一次即可 | |||||
producer.start(); | |||||
log.info("aliyunrocketmq producer info :"+JSON.toJSONString(producer)); | |||||
producerMap.put(topic.getCode(), producer); | |||||
} | |||||
} | |||||
@Override | |||||
public void sendMessage(Object data, String topic, String tags, String keys) { | |||||
Producer producer = producerMap.get(topic); | |||||
if (null == producer) { | |||||
log.error("topic :"+topic+" has no AliyunRocketMqMessageProducer."); | |||||
return; | |||||
} | |||||
if (producer.isClosed()) { | |||||
producer.start(); | |||||
} | |||||
//循环发送消息 | |||||
Message msg = new Message( // | |||||
// Message 所属的 Topic | |||||
topic, | |||||
// Message Tag 可理解为 Gmail 中的标签,对消息进行再归类,方便 Consumer 指定过滤条件在 MQ 服务器过滤 | |||||
tags, | |||||
// Message Body 可以是任何二进制形式的数据, MQ 不做任何干预, | |||||
// 需要 Producer 与 Consumer 协商好一致的序列化和反序列化方式 | |||||
JsonUtil.obj2Json(data).getBytes()); | |||||
// 设置代表消息的业务关键属性,请尽可能全局唯一。 | |||||
// 以方便您在无法正常收到消息情况下,可通过阿里云服务器管理控制台查询消息并补发 | |||||
// 注意:不设置也不会影响消息正常收发 | |||||
msg.setKey(keys); | |||||
try { | |||||
SendResult sendResult = producer.send(msg); | |||||
// 同步发送消息,只要不抛异常就是成功 | |||||
if (sendResult != null) { | |||||
System.out.println(new Date() + " Send mq message success. Topic is:" + msg.getTopic() + " msgId is: " + sendResult.getMessageId()); | |||||
} | |||||
} | |||||
catch (Exception e) { | |||||
// 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理 | |||||
System.out.println(new Date() + " Send mq message failed. Topic is:" + msg.getTopic()); | |||||
e.printStackTrace(); | |||||
} | |||||
// 在应用退出前,销毁 Producer 对象 | |||||
// 注意:如果不销毁也没有问题 | |||||
//producer.shutdown(); | |||||
} | |||||
} |
@@ -0,0 +1,45 @@ | |||||
package com.neusoft.smart.pos.mq; | |||||
/** | |||||
* Created by luozukai | |||||
*/ | |||||
public enum EnumMsgMqTopic { | |||||
DEFAULT("topic-1","GID_P_1", "默认"), | |||||
STOCK("stock","GID_P_2","库存"), | |||||
; | |||||
public static EnumMsgMqTopic getEnum(String code) { | |||||
for (EnumMsgMqTopic value : values()) { | |||||
if (value.getCode().equals(code)) { | |||||
return value; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
private String code; | |||||
private String message; | |||||
private String groupId; | |||||
EnumMsgMqTopic(String code, String groupId,String message) { | |||||
this.code = code; | |||||
this.message = message; | |||||
this.groupId = groupId; | |||||
} | |||||
public String getCode() { | |||||
return code; | |||||
} | |||||
public String getMessage() { | |||||
return message; | |||||
} | |||||
public String getGroupId() { | |||||
return groupId; | |||||
} | |||||
public void setGroupId(String groupId) { | |||||
this.groupId = groupId; | |||||
} | |||||
} |
@@ -0,0 +1,128 @@ | |||||
package com.neusoft.smart.pos.mq; | |||||
import com.fasterxml.jackson.annotation.JsonInclude; | |||||
import com.fasterxml.jackson.core.JsonGenerator; | |||||
import com.fasterxml.jackson.core.JsonParser; | |||||
import com.fasterxml.jackson.core.JsonProcessingException; | |||||
import com.fasterxml.jackson.databind.DeserializationFeature; | |||||
import com.fasterxml.jackson.databind.JsonSerializer; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | |||||
import com.fasterxml.jackson.databind.SerializerProvider; | |||||
import com.fasterxml.jackson.databind.module.SimpleModule; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.io.IOException; | |||||
import java.text.SimpleDateFormat; | |||||
import java.util.HashMap; | |||||
import java.util.Iterator; | |||||
import java.util.Map; | |||||
public final class JsonUtil { | |||||
private static Logger log = LoggerFactory.getLogger(JsonUtil.class); | |||||
public static final ObjectMapper mapper = new ObjectMapper(); | |||||
private JsonUtil() { | |||||
} | |||||
public static String obj2Json(Object obj) { | |||||
if(obj != null) { | |||||
try { | |||||
return mapper.writeValueAsString(obj); | |||||
} catch (JsonProcessingException var2) { | |||||
throw new RuntimeException(var2); | |||||
} | |||||
} else { | |||||
return null; | |||||
} | |||||
} | |||||
public static byte[] obj2Byte(Object obj) { | |||||
if(obj != null) { | |||||
try { | |||||
return mapper.writeValueAsBytes(obj); | |||||
} catch (JsonProcessingException var2) { | |||||
var2.printStackTrace(); | |||||
} | |||||
} | |||||
return new byte[0]; | |||||
} | |||||
public static Object readValue(String json, Class<?> clazz) { | |||||
Object t = null; | |||||
try { | |||||
return mapper.readValue(json, clazz); | |||||
} catch (Exception var4) { | |||||
log.info("解析对象:{}", json); | |||||
log.error("json解析错误:{}", var4.getMessage(), var4); | |||||
return t; | |||||
} | |||||
} | |||||
// public static <T> T readValue(String json, TypeReference type) { | |||||
// Object object = null; | |||||
// | |||||
// try { | |||||
// object = mapper.readValue(json, type); | |||||
// } catch (Exception var4) { | |||||
// log.info("解析对象:{}", json); | |||||
// log.error("json解析错误:{}", var4.getMessage(), var4); | |||||
// } | |||||
// | |||||
// return object; | |||||
// } | |||||
// | |||||
// public static <T> T readValue(byte[] json, TypeReference type) { | |||||
// Object object = null; | |||||
// | |||||
// try { | |||||
// object = mapper.readValue(json, type); | |||||
// } catch (Exception var4) { | |||||
// log.info("解析对象:{}", json); | |||||
// log.error("json解析错误:{}", var4.getMessage(), var4); | |||||
// } | |||||
// | |||||
// return object; | |||||
// } | |||||
// | |||||
// public static Map<String, Object> readValueAsMap(String json) { | |||||
// return (Map)readValue(json, new TypeReference<HashMap<String, Object>>() { | |||||
// }); | |||||
// } | |||||
static { | |||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | |||||
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); | |||||
mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); | |||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); | |||||
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); | |||||
SimpleModule module = new SimpleModule(); | |||||
module.addSerializer(HashMap.class, new JsonUtil.HashMapSerializer()); | |||||
mapper.registerModule(module); | |||||
} | |||||
public static class HashMapSerializer extends JsonSerializer<HashMap> { | |||||
public HashMapSerializer() { | |||||
} | |||||
public void serialize(HashMap value, JsonGenerator jgen, SerializerProvider provider) throws IOException { | |||||
jgen.writeStartObject(); | |||||
Iterator var4 = value.entrySet().iterator(); | |||||
while(var4.hasNext()) { | |||||
Object entry = var4.next(); | |||||
if(entry instanceof Map.Entry) { | |||||
Map.Entry en = (Map.Entry)entry; | |||||
if(en.getValue() != null && en.getKey() != null) { | |||||
jgen.writeObjectField(en.getKey().toString(), en.getValue()); | |||||
} | |||||
} | |||||
} | |||||
jgen.writeEndObject(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
package com.neusoft.smart.pos.mq; | |||||
public class MQConfig { | |||||
public static class Impl { | |||||
public static final String RABBIT_MQ = "rabbitMQ"; | |||||
public static final String ROCKET_MQ = "rocketMQ"; | |||||
public static final String ALIYUN_ROCKET_MQ = "aliyunRocketMQ"; | |||||
} | |||||
} |
@@ -0,0 +1,7 @@ | |||||
package com.neusoft.smart.pos.mq; | |||||
public interface MqProducer { | |||||
public void sendMessage(Object data, String topic, String tags, String keys); | |||||
} |