| @@ -20,6 +20,16 @@ | |||
| <artifactId>framework</artifactId> | |||
| <version>1.0-SNAPSHOT</version> | |||
| </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数据库驱动 --> | |||
| <dependency> | |||
| <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); | |||
| } | |||