Browse Source

first commit

lixing 4 years ago
parent
commit
b3a9f973dc
21 changed files with 1627 additions and 0 deletions
  1. 4 0
      README.md
  2. 94 0
      pom.xml
  3. 16 0
      src/main/java/com/persagy/dmp/starter/alarm/AutoConfiguration.java
  4. 38 0
      src/main/java/com/persagy/dmp/starter/alarm/aspect/AlarmClientAspect.java
  5. 78 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmMessage.java
  6. 278 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmMsgBaseHandler.java
  7. 37 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmMsgHandler.java
  8. 111 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmServer.java
  9. 48 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/websocket/AlarmWebSocketCache.java
  10. 98 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/websocket/AlarmWebSocketServer.java
  11. 20 0
      src/main/java/com/persagy/dmp/starter/alarm/communication/websocket/AlarmWebsocketConfiguration.java
  12. 51 0
      src/main/java/com/persagy/dmp/starter/alarm/constant/RequestUrlConstant.java
  13. 44 0
      src/main/java/com/persagy/dmp/starter/alarm/feign/AlarmFeignLogger.java
  14. 75 0
      src/main/java/com/persagy/dmp/starter/alarm/feign/AlarmServerFallbackFactory.java
  15. 45 0
      src/main/java/com/persagy/dmp/starter/alarm/feign/AlarmUrlParam.java
  16. 35 0
      src/main/java/com/persagy/dmp/starter/alarm/feign/DmpResult.java
  17. 162 0
      src/main/java/com/persagy/dmp/starter/alarm/feign/client/AlarmClient.java
  18. 31 0
      src/main/java/com/persagy/dmp/starter/alarm/runner/NettyServerRunner.java
  19. 158 0
      src/main/java/com/persagy/dmp/starter/alarm/service/AlarmService.java
  20. 203 0
      src/main/java/com/persagy/dmp/starter/alarm/service/NettyAlarmService.java
  21. 1 0
      src/main/resources/META-INF/spring.factories

+ 4 - 0
README.md

@@ -0,0 +1,4 @@
+# 报警中心子系统工具包
+
+- feign,rabbitM对接数据中台
+- netty,webSocket对接边缘端

+ 94 - 0
pom.xml

@@ -0,0 +1,94 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.4.0</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.persagy.dmp.starter</groupId>
+    <artifactId>dmp-alarm-starter</artifactId>
+    <version>4.0.0-SNAPSHOT</version>
+    <name>dmp-alarm-starter</name>
+    <description>dmp_alarm_starter</description>
+
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencies>
+        <!-- jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>2.11.3</version>
+        </dependency>
+
+        <!-- lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- starter 标配 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+
+        <!-- feign -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+            <version>2.2.6.RELEASE</version>
+        </dependency>
+
+        <!-- fastjson -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.71</version>
+        </dependency>
+
+        <!-- netty -->
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>4.1.42.Final</version>
+        </dependency>
+
+        <!-- lang -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!-- zkt-brain -->
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>zkt-brain</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+        <!-- websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                    <groupId>org.springframework.boot</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+</project>

+ 16 - 0
src/main/java/com/persagy/dmp/starter/alarm/AutoConfiguration.java

@@ -0,0 +1,16 @@
+package com.persagy.dmp.starter.alarm;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @description: 配置类
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 4:51 下午
+ * @version: V1.0
+ */
+@Configuration
+@ComponentScan(value = "com.persagy.dmp.starter.alarm")
+public class AutoConfiguration {
+}

+ 38 - 0
src/main/java/com/persagy/dmp/starter/alarm/aspect/AlarmClientAspect.java

@@ -0,0 +1,38 @@
+package com.persagy.dmp.starter.alarm.aspect;
+
+import com.persagy.dmp.starter.alarm.feign.DmpResult;
+import feign.Response;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: AlarmClient切面,处理feign调用接口,接口返回值异常的情况
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 3:56 下午
+ * @version: V1.0
+ **/
+@Slf4j
+@Aspect
+@Component
+public class AlarmClientAspect {
+    @Pointcut("execution(public * com.persagy.dmp.starter.alarm.feign.client.*.* (..))")
+    public void feignPointCut() {
+    }
+
+    @Before("feignPointCut()")
+    public void before() {
+        System.out.println("before");
+    }
+
+    @AfterReturning(returning = "res", pointcut = "feignPointCut()")
+    public void after(DmpResult res) throws Exception {
+        if (DmpResult.FAILURE.equals(res.getResult())) {
+            throw new Exception(res.getMessage());
+        }
+    }
+}

+ 78 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmMessage.java

@@ -0,0 +1,78 @@
+package com.persagy.dmp.starter.alarm.communication.netty;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @description: netty报警消息格式定义
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 10:52 上午
+ * @version: V1.0
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+public class NettyAlarmMessage<T> {
+    /**
+     * 唯一标识
+     */
+    @JSONField()
+    private long streamId;
+    @JSONField()
+    private int version = 1;
+
+    /**
+     * 操作类型:
+     * 200-建立连接,200的source是projectId
+     * 1-请求、2 -响应、3-通知、
+     * 4-边缘端获取报警定义、
+     * 5-边缘端主动推送报警记录、
+     * 6-边缘端主动更新报警记录状态、
+     * 7-云端推送修改的报警定义给边缘端(增量新增修改报警定义)、
+     * 8-云端把报警记录的id推送到边缘端
+     * 9-边缘端取报警定义,云端推送给边缘端的标记(全量报警定义)
+     * 10-云端推送删除的报警定义给边缘端(增量删除报警定义)、
+     */
+    @JSONField()
+    private int opCode;
+
+    /**
+     * 请求来源
+     */
+    @JSONField()
+    private String source = "group";
+
+    /**
+     * 用于项目控制程序清除之前的时间和命令
+     */
+    @JSONField()
+    private String clearBeforeTimeFlag;
+
+    /**
+     * 传输内容
+     */
+    @JSONField(jsonDirect = true)
+    private List<T> content;
+
+    /**
+     * 成功标识
+     */
+    @JSONField()
+    private Boolean success;
+
+    @Override
+    public String toString() {
+        return JSONObject.toJSONString(this);
+    }
+
+    public NettyAlarmMessage(int opCode, List<T> content) {
+        this.opCode = opCode;
+        this.content = content;
+    }
+}

+ 278 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmMsgBaseHandler.java

@@ -0,0 +1,278 @@
+package com.persagy.dmp.starter.alarm.communication.netty;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.dmp.starter.alarm.service.NettyAlarmService;
+import com.persagy.zkt.utils.StringUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @description: Netty报警息处理中心
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 10:31 上午
+ * @version: V1.0
+ */
+@Slf4j
+public class NettyAlarmMsgBaseHandler extends ChannelInboundHandlerAdapter {
+
+    /**
+     * 装每个客户端的地址及对应的管道
+     */
+    public Map<String, Channel> socketChannelMap = new ConcurrentHashMap<>();
+
+    private NettyAlarmService nettyAlarmService;
+
+    /**
+     * 保留所有与服务器建立连接的channel对象
+     */
+    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
+
+    public NettyAlarmMsgBaseHandler(NettyAlarmService alarmService) {
+        this.nettyAlarmService = alarmService;
+    }
+
+    @Override
+    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+        SocketAddress socketAddress = ctx.channel().remoteAddress();
+        String remoteAddress = socketAddress.toString();
+        System.out.println("--某个客户端绑定地址:" + remoteAddress + "--");
+    }
+
+    /**
+     * @description: 边缘端请求连接
+     * @param: nettyMessage
+     * @param: channelHandlerContext
+     * @return: void
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 11:06 上午
+     * @version: V1.0
+     */
+    private void connected(NettyAlarmMessage nettyMessage, ChannelHandlerContext channelHandlerContext) {
+        String source = nettyMessage.getSource();
+        socketChannelMap.put(source, channelHandlerContext.channel());
+    }
+
+    /**
+     * @description: 发送全部报警定义到边缘端
+     * @param: nettyMessage
+     * @return: void
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:26 下午
+     * @version: V1.0
+     */
+    private void sendAllAlarmConfigs(NettyAlarmMessage nettyMessage) throws Exception {
+        List<JSONObject> dataList = nettyMessage.getContent();
+        JSONObject data = dataList.get(0);
+        data.put("userId", "system");
+
+        JSONArray alarmConfigs = nettyAlarmService.queryAlarmConfig(data);
+        if (alarmConfigs == null || alarmConfigs.size() <= 0) {
+            return;
+        }
+        String projectId = data.getString("projectId");
+        sendMessage(projectId, new NettyAlarmMessage(9, alarmConfigs).toString());
+    }
+
+    /**
+     * @description: 创建报警记录,并发送报警记录id至边缘端
+     * @param: nettyMessage
+     * @return: void
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:33 下午
+     * @version: V1.0
+     */
+    private void createAlarmRecordAndSendRecordId(NettyAlarmMessage nettyMessage) throws Exception {
+        List<JSONObject> dataList = nettyMessage.getContent();
+        JSONObject data = dataList.get(0);
+        data.put("userId", "system");
+        String alarmRecordId = nettyAlarmService.createAlarm(data);
+
+        JSONObject record = new JSONObject();
+        record.put("id", alarmRecordId);
+        record.put("objId", data.getString("objId"));
+        record.put("itemCode", data.getString("itemCode"));
+        List<JSONObject> records = new ArrayList<>();
+        records.add(record);
+        String projectId = data.getString("projectId");
+        sendMessage(projectId, new NettyAlarmMessage(8, records).toString());
+    }
+
+    /**
+     * @description: 更新报警记录
+     * @param: message
+     * @return: void
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 4:13 下午
+     * @version: V1.0
+     */
+    private void updateAlarmRecord(NettyAlarmMessage message) throws Exception {
+        List<JSONObject> dataList = message.getContent();
+        JSONObject data = dataList.get(0);
+        data.put("userId", "system");
+        nettyAlarmService.updateAlarmRecord(data);
+    }
+
+    /**
+     * @param channelHandlerContext
+     * @param msg
+     * @description: 接受客户端收到的数据
+     * @return: void
+     * @exception:
+     * @author: shiliqiang
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/10/21 10:20
+     * @version: V1.0
+     */
+    @Override
+    public void channelRead(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
+        log.info("收到[" + channelHandlerContext.channel().remoteAddress() + "]消息:" + msg);
+        try {
+            NettyAlarmMessage nettyMessage = StringUtil.tranferItemToDTO(msg.toString(), NettyAlarmMessage.class);
+            /* 操作类型:1-请求、2 -响应、3-通知、
+             * 4-边缘端获取报警定义、
+             * 5-边缘端主动推送报警记录、
+             * 6-边缘端主动更新报警记录状态、
+             * 7-云端推送修改的报警定义给边缘端、
+             * 9-边缘端取报警定义,云端推送给边缘端的标记
+             */
+            int opCode = nettyMessage.getOpCode();
+            List<JSONObject> dataList = nettyMessage.getContent();
+            switch (opCode) {
+                case 200:
+                    /* 接收到边缘端创建连接请求,存储连接请求的projectId和channel映射关系,
+                     * 以后向边缘端发送请求时,通过projectId获取到对应的channel
+                     */
+                    connected(nettyMessage, channelHandlerContext);
+                    break;
+                case 4:
+                    // 向边缘端全量发送报警定义
+                    sendAllAlarmConfigs(nettyMessage);
+                    break;
+                case 5:
+                    // 创建报警记录并发送报警记录id到边缘端
+                    createAlarmRecordAndSendRecordId(nettyMessage);
+                    break;
+                case 6:
+                    // 更新报警记录状态
+                    updateAlarmRecord(nettyMessage);
+                    break;
+                default:
+                    log.info("边缘端发来的参数无效,参数值为:" + opCode);
+                    break;
+            }
+
+        } catch (Exception e) {
+            log.error("channelRead error", e);
+        }
+    }
+
+    @Override
+    public void channelReadComplete(ChannelHandlerContext ctx) {
+        ctx.flush();
+    }
+
+
+    /**
+     * 在读取操作期间,有异常抛出时会调用。
+     *
+     * @param ctx
+     * @param cause
+     * @throws Exception
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        cause.printStackTrace();
+        ctx.close();
+    }
+
+    /**
+     * 新增连接
+     */
+    @Override
+    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+        // TODO Auto-generated method stub
+        //NettyServer.socketChannelMap.put(ctx.channel().remoteAddress().toString(), ctx.channel());
+        channelGroup.add(ctx.channel());
+        log.info("当前连接数:[{}],新建立连接为[{}]...", channelGroup.size(), ctx.channel().remoteAddress().toString());
+        super.handlerAdded(ctx);
+    }
+
+    /**
+     * 断开连接
+     */
+    @Override
+    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+        //chanel可以理解成Connection
+        Channel channel = ctx.channel();
+        Set<Map.Entry<String, Channel>> channelList = socketChannelMap.entrySet();
+        for (Map.Entry<String, Channel> channelEntry : channelList) {
+            if (channelEntry.getValue() == channel) {
+                socketChannelMap.remove(channelEntry.getKey());
+                log.warn("----项目ID[{}],地址[{}] ----离开---", channelEntry.getKey(), channel.remoteAddress().toString());
+            }
+        }
+        log.warn("----客户端[{}] ----离开", channel.remoteAddress().toString());
+    }
+
+    /**
+     * 该方法只会在通道建立时调用一次,连接生效
+     */
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        Channel channel = ctx.channel();
+
+    }
+
+    /**
+     * 连接是否有效
+     */
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+
+    }
+
+    /**
+     * @param msg
+     * @Title: sendMessage
+     * @Description: 服务端给所有客户端发送消息
+     */
+    public void sendMessageToAll(Object msg) {
+        channelGroup.writeAndFlush(msg.toString());
+    }
+
+    /**
+     * @param msg
+     * @Title: sendMessage
+     * @Description: 服务端给某个客户端发送消息
+     */
+    public void sendMessage(String projectId, String msg) {
+        if (socketChannelMap.containsKey(projectId)) {
+            socketChannelMap.get(projectId).writeAndFlush(msg);
+        } else {
+            log.info("...projectId[{}]未建立连接,无法发送!", projectId);
+        }
+
+    }
+}

+ 37 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmMsgHandler.java

@@ -0,0 +1,37 @@
+package com.persagy.dmp.starter.alarm.communication.netty;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.dmp.starter.alarm.service.NettyAlarmService;
+import com.persagy.zkt.utils.StringUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @description: Netty报警息处理中心
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 10:31 上午
+ * @version: V1.0
+ */
+@Slf4j
+public class NettyAlarmMsgHandler extends NettyAlarmMsgBaseHandler {
+    private NettyAlarmService nettyAlarmService;
+
+    public NettyAlarmMsgHandler(NettyAlarmService nettyAlarmService) {
+        super(nettyAlarmService);
+//        this.nettyAlarmService = nettyAlarmService;
+    }
+}

+ 111 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/netty/NettyAlarmServer.java

@@ -0,0 +1,111 @@
+package com.persagy.dmp.starter.alarm.communication.netty;
+
+import com.persagy.dmp.starter.alarm.service.NettyAlarmService;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioChannelOption;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import io.netty.handler.codec.LengthFieldPrepender;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.concurrent.DefaultThreadFactory;
+import io.netty.util.concurrent.UnorderedThreadPoolEventExecutor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @description: netty报警服务端
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 10:54 上午
+ * @version: V1.0
+ */
+@Component
+@Slf4j
+public class NettyAlarmServer {
+    @Autowired
+    private NettyAlarmService nettyAlarmService;
+
+    @Value("${group.alarm.port}")
+    public int port;
+
+    /**
+     * 用于接收客户端的TCP连接
+     */
+    EventLoopGroup bossGroup = null;
+    /**
+     * 处理I/O相关的读写操作,或者执行系统Task、定时任务Task等。
+     */
+    EventLoopGroup workGroup = null;
+    ChannelFuture channelFuture = null;
+
+    /**
+     * @Title: start
+     * @Description: 启动netty服务端
+     */
+    public void start() {
+        bossGroup = new NioEventLoopGroup();
+        workGroup = new NioEventLoopGroup();
+        UnorderedThreadPoolEventExecutor businessGroup = new UnorderedThreadPoolEventExecutor(10, new DefaultThreadFactory("business"));
+
+        try {
+            // (服务端启动类)ServerBootstrap负责初始化netty服务器,并且开始监听端口的socket请求
+            ServerBootstrap startNetty = new ServerBootstrap();
+            startNetty.group(bossGroup, workGroup)
+                    .channel(NioServerSocketChannel.class)
+                    .option(NioChannelOption.SO_BACKLOG, 1024)
+                    .childOption(NioChannelOption.TCP_NODELAY, true)
+                    .handler(new LoggingHandler(LogLevel.INFO))
+                    .childHandler(new ChannelInitializer<SocketChannel>() {
+                        @Override
+                        protected void initChannel(SocketChannel ch) throws Exception {
+                            // 解决粘包和拆包问题,增加的编码和解码器
+                            ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
+                            ch.pipeline().addLast(new LengthFieldPrepender(4));
+                            // the encoder and decoder are static as these are sharable
+                            ch.pipeline().addLast(new StringDecoder());
+                            ch.pipeline().addLast(new StringEncoder());
+                            // 为监听客户端read/write事件的Channel添加用户自定义的ChannelHandler
+                            ch.pipeline().addLast(businessGroup, new NettyAlarmMsgHandler(nettyAlarmService));
+
+                            // 增加超时检查
+                            ch.pipeline().addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS));
+                        }
+                    });
+            channelFuture = startNetty.bind(new InetSocketAddress(port)).sync();
+
+            System.out.println("------服务端启动closeFuture前------------");
+            channelFuture.channel().closeFuture().sync();
+            System.out.println("------服务端启动closeFuture后------------");
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // if (channelFuture != null && channelFuture.isSuccess()) {
+            // System.out.println("------netty启动成功------------");
+            // } else {
+            // System.out.println("------netty启动失败------------");
+            // }
+            // 关闭主线程组
+            bossGroup.shutdownGracefully();
+            // 关闭工作线程组
+            workGroup.shutdownGracefully();
+            businessGroup.shutdownGracefully();
+
+        }
+    }
+
+
+}

+ 48 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/websocket/AlarmWebSocketCache.java

@@ -0,0 +1,48 @@
+package com.persagy.dmp.starter.alarm.communication.websocket;
+
+import javax.websocket.Session;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @description: webSocket缓存,存储通信session
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 7:07 下午
+ * @version: V1.0
+ */
+public class AlarmWebSocketCache {
+    /**
+     * 所有在线的客户端
+     */
+    private static Map<String, Session> clients = new ConcurrentHashMap<>();
+
+    /**
+     * 获取连接中的所有客户端
+     *
+     * @return
+     */
+    public static Set<Session> getClients() {
+    	return new HashSet<>(clients.values());
+    }
+
+    /**
+     * 增加客户端
+     *
+     * @param session
+     */
+    public static void addClient(Session session) {
+        clients.put(session.getId(), session);
+    }
+
+    /**
+     * 删除客户端
+     * @param sessionId 客户端标识
+     */
+    public static void removeClient(String sessionId) {
+        clients.remove(sessionId);
+    }
+
+}

+ 98 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/websocket/AlarmWebSocketServer.java

@@ -0,0 +1,98 @@
+package com.persagy.dmp.starter.alarm.communication.websocket;
+
+import cn.hutool.core.collection.CollectionUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.ServerEndpoint;
+import java.util.Set;
+
+/**
+ * @description: websocket服务端
+ * 由于是websocket 所以原本是@RestController的http形式直接替换成@ServerEndpoint即可,作用是一样的 就是指定一个地址表示定义一个websocket的Server端
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 6:47 下午
+ * @version: V1.0
+ */
+@ServerEndpoint(value = "/webSocketServer")
+@Component
+@Slf4j
+public class AlarmWebSocketServer {
+
+    @OnOpen
+    public void onOpen(Session session) {
+        log.info("有新的客户端建立连接,编号: " + session.getId());
+        //将新用户存入在线的组
+        AlarmWebSocketCache.addClient(session);
+    }
+
+    /**
+     * 客户端关闭
+     *
+     * @param session session
+     */
+    @OnClose
+    public void onClose(Session session) {
+        String clientId = session.getId();
+        log.info("客户端断开连接,编号:" + clientId);
+        //将掉线的用户移除在线的组里
+        AlarmWebSocketCache.removeClient(clientId);
+    }
+
+    /**
+     * 发生错误
+     *
+     * @param throwable e
+     */
+    @OnError
+    public void onError(Session session, Throwable throwable) {
+        String id = "";
+        if (null != session) {
+            id = session.getId();
+            AlarmWebSocketCache.removeClient(id);
+        }
+        log.info("客户端{}出错 ", id);
+    }
+
+    /**
+     * 收到客户端发来消息
+     *
+     * @param message 消息对象,格式:point,org,1101010001,10001-101,10001-102,10001-103,10001-104
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        String clientId = session.getId();
+        log.info("收到客户端{}的数据请求消息:{}", clientId, message);
+        if ("closeSession".equals(message)) {
+            onClose(session);
+            return;
+        }
+    }
+
+
+    /**
+     * @param msg 消息
+     * @description: 发送消息
+     * @return: void
+     * @exception:
+     * @author: shiliqiang
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/10/21 22:30
+     * @version: V1.0
+     */
+    public static void sendMsgToClients(String msg) throws Exception {
+        Set<Session> clients = AlarmWebSocketCache.getClients();
+        synchronized (clients) {
+            if (CollectionUtil.isNotEmpty(clients)) {
+                for (Session session : clients) {
+                    if (null != session && session.isOpen()) {
+                        //同步发送
+                        session.getBasicRemote().sendText(msg);
+                    }
+                }
+            }
+        }
+    }
+}

+ 20 - 0
src/main/java/com/persagy/dmp/starter/alarm/communication/websocket/AlarmWebsocketConfiguration.java

@@ -0,0 +1,20 @@
+package com.persagy.dmp.starter.alarm.communication.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * @description: websocket配置类
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 6:49 下午
+ * @version: V1.0
+ */
+@Configuration
+public class AlarmWebsocketConfiguration {
+	@Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }	
+}

+ 51 - 0
src/main/java/com/persagy/dmp/starter/alarm/constant/RequestUrlConstant.java

@@ -0,0 +1,51 @@
+package com.persagy.dmp.starter.alarm.constant;
+
+/**
+ * @description: 报警中心url
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 10:16 上午
+ * @version: V1.0
+ */
+public class RequestUrlConstant {
+
+    private static final String QUERY = "query";
+    private static final String CREATE = "create";
+    private static final String UPDATE = "update";
+    private static final String DELETE = "delete";
+
+    /**
+     * 报警定义
+     */
+    private static final String ALARM_CONFIG = "/alarm/config/";
+    public static final String ALARM_CONFIG_QUERY = ALARM_CONFIG + QUERY;
+    public static final String ALARM_CONFIG_CREATE = ALARM_CONFIG + CREATE;
+    public static final String ALARM_CONFIG_UPDATE = ALARM_CONFIG + UPDATE;
+
+    /**
+     * 报警记录
+     */
+    private static final String ALARM_RECORD = "/alarm/record/";
+    public static final String ALARM_RECORD_QUERY = ALARM_RECORD + QUERY;
+    public static final String ALARM_RECORD_CREATE = ALARM_RECORD + CREATE;
+    public static final String ALARM_RECORD_UPDATE = ALARM_RECORD + UPDATE;
+
+    /**
+     * 报警条目
+     */
+    private static final String ALARM_ITEM = "/alarm/item/";
+    public static final String ALARM_ITEM_QUERY = ALARM_ITEM + QUERY;
+
+    /**
+     * 报警批注
+     */
+    private static final String ALARM_COMMENT = "/alarm/comment/";
+    public static final String ALARM_COMMENT_QUERY = ALARM_COMMENT + QUERY;
+    public static final String ALARM_COMMENT_CREATE = ALARM_COMMENT + CREATE;
+
+    /**
+     * 报警字典
+     */
+    private static final String ALARM_DIC = "/dic/dt/data/";
+    public static final String ALARM_DIC_QUERY = ALARM_DIC + QUERY;
+}

+ 44 - 0
src/main/java/com/persagy/dmp/starter/alarm/feign/AlarmFeignLogger.java

@@ -0,0 +1,44 @@
+package com.persagy.dmp.starter.alarm.feign;
+
+
+import feign.Request;
+import feign.Response;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+/**
+ * @description: 日志记录feign调用
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 10:40 上午
+ * @version: V1.0
+ */
+@Slf4j
+public class AlarmFeignLogger extends feign.Logger {
+
+    @Override
+    protected void logRequest(String configKey, Level logLevel, Request request) {
+        if (log.isInfoEnabled()) {
+            super.logRequest(configKey, logLevel, request);
+        }
+    }
+
+    @Override
+    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime)
+            throws IOException {
+        if (log.isInfoEnabled()) {
+            return super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
+        }
+        return response;
+    }
+
+    @Override
+    protected void log(String configKey, String format, Object... args) {
+        if (log.isInfoEnabled()) {
+            log.info(String.format(methodTag(configKey) + format, args));
+        }
+    }
+}

+ 75 - 0
src/main/java/com/persagy/dmp/starter/alarm/feign/AlarmServerFallbackFactory.java

@@ -0,0 +1,75 @@
+package com.persagy.dmp.starter.alarm.feign;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.dmp.starter.alarm.feign.client.AlarmClient;
+import feign.hystrix.FallbackFactory;
+import lombok.extern.slf4j.Slf4j;
+
+
+/**
+ * @description: 降级处理
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 2:05 下午
+ * @version: V1.0
+ */
+@Slf4j
+public class AlarmServerFallbackFactory implements FallbackFactory<AlarmClient> {
+    @Override
+    public AlarmClient create(Throwable throwable) {
+       return new AlarmClient() {
+           private String errorMsg = "feign调用报警中心接口异常,接口名称:[{}], 请求体:[{}]";
+
+           @Override
+           public DmpResult<JSONArray> queryAlarmConfig(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+               throw new Exception(String.format(errorMsg, "queryAlarmConfig", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONObject> createAlarmConfig(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "createAlarmConfig", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONObject> updateAlarmConfig(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "updateAlarmConfig", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONArray> queryAlarmRecord(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "queryAlarmRecord", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONObject> createAlarmRecord(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "createAlarmRecord", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONObject> updateAlarmRecord(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "updateAlarmRecord", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONArray> queryAlarmItem(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "queryAlarmItem", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONObject> createAlarmComment(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "createAlarmComment", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONArray> queryAlarmComment(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception{
+               throw new Exception(String.format(errorMsg, "queryAlarmComment", jsonObject.toString()));
+           }
+
+           @Override
+           public DmpResult<JSONArray> queryAlarmDic(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+               throw new Exception(String.format(errorMsg, "queryAlarmDic", jsonObject.toString()));
+           }
+       };
+    }
+}

+ 45 - 0
src/main/java/com/persagy/dmp/starter/alarm/feign/AlarmUrlParam.java

@@ -0,0 +1,45 @@
+package com.persagy.dmp.starter.alarm.feign;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @description: 报警请求 url 通用参数
+ * @author: xingmaojun
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/10/28 11:50
+ * @version: V1.0
+ **/
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AlarmUrlParam implements Serializable {
+
+    /**
+     * 用户id
+     */
+    private String userId;
+
+    /**
+     * 集团编码
+     */
+    private String groupCode;
+
+    /**
+     * 项目Id
+     */
+    private String projectId;
+
+    /**
+     * 应用id
+     */
+    private String appId;
+
+}

+ 35 - 0
src/main/java/com/persagy/dmp/starter/alarm/feign/DmpResult.java

@@ -0,0 +1,35 @@
+package com.persagy.dmp.starter.alarm.feign;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @description: 数据中台返回值通用类
+ * @author: xingmaojun
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/10/28 15:40
+ * @version: V1.0
+ */
+@Data
+public class DmpResult<T> implements Serializable {
+
+    /**
+     * 成功
+     */
+    public final static String SUCCESS = "success";
+
+    /**
+     * 失败
+     */
+    public final static String FAILURE = "fail";
+
+    private String result;
+
+    private T data;
+
+    private Integer count;
+
+    private String message;
+
+}

+ 162 - 0
src/main/java/com/persagy/dmp/starter/alarm/feign/client/AlarmClient.java

@@ -0,0 +1,162 @@
+package com.persagy.dmp.starter.alarm.feign.client;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.dmp.starter.alarm.constant.RequestUrlConstant;
+import com.persagy.dmp.starter.alarm.feign.AlarmServerFallbackFactory;
+import com.persagy.dmp.starter.alarm.feign.AlarmUrlParam;
+import com.persagy.dmp.starter.alarm.feign.DmpResult;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.cloud.openfeign.SpringQueryMap;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * @description: feign调用数据中台报警接口
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 10:43 上午
+ * @version: V1.0
+ */
+@FeignClient(name = "dmp-alarm", fallbackFactory = AlarmServerFallbackFactory.class)
+public interface AlarmClient {
+    /**
+     * @description: 查询报警定义
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_CONFIG_QUERY)
+    DmpResult<JSONArray> queryAlarmConfig(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 创建报警定义
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_CONFIG_CREATE)
+    DmpResult<JSONObject> createAlarmConfig(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 更新报警定义
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_CONFIG_UPDATE)
+    DmpResult<JSONObject> updateAlarmConfig(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 查询报警记录
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_RECORD_QUERY)
+    DmpResult<JSONArray> queryAlarmRecord(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 创建报警记录
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_RECORD_CREATE)
+    DmpResult<JSONObject> createAlarmRecord(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 更新报警记录
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_RECORD_UPDATE)
+    DmpResult<JSONObject> updateAlarmRecord(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 查询报警条目
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_ITEM_QUERY)
+    DmpResult<JSONArray> queryAlarmItem(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 创建报警批注
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:42 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_COMMENT_CREATE)
+    DmpResult<JSONObject> createAlarmComment(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+
+    /**
+     * @description: 查询报警批注
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:42 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_COMMENT_QUERY)
+    DmpResult<JSONArray> queryAlarmComment(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+    
+    /**
+     * @description: 查询报警字典
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<com.alibaba.fastjson.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 7:10 下午
+     * @version: V1.0
+     */
+    @PostMapping(RequestUrlConstant.ALARM_DIC_QUERY)
+    DmpResult<JSONArray> queryAlarmDic(@SpringQueryMap AlarmUrlParam alarmUrlParam, @RequestBody JSONObject jsonObject) throws Exception;
+}

+ 31 - 0
src/main/java/com/persagy/dmp/starter/alarm/runner/NettyServerRunner.java

@@ -0,0 +1,31 @@
+package com.persagy.dmp.starter.alarm.runner;
+
+import com.persagy.dmp.starter.alarm.communication.netty.NettyAlarmServer;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * @description: 初始化项目
+ * @author: shiliqiang
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/10/20 15:37
+ * @version: V1.0
+ */
+@Component
+@Slf4j
+@Order(1)
+public class NettyServerRunner implements CommandLineRunner {
+	@Autowired
+	private NettyAlarmServer nettyServer;
+
+	@Override
+	public void run(String... args) throws Exception {
+		// 项目加载完成后启动netty
+		nettyServer.start();
+		log.info("-------NettyAlarmServer启动成功--------");
+	}
+}

+ 158 - 0
src/main/java/com/persagy/dmp/starter/alarm/service/AlarmService.java

@@ -0,0 +1,158 @@
+package com.persagy.dmp.starter.alarm.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.dmp.starter.alarm.feign.AlarmUrlParam;
+import com.persagy.dmp.starter.alarm.feign.DmpResult;
+import com.persagy.dmp.starter.alarm.feign.client.AlarmClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @description:
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/27 6:57 下午
+ * @version: V1.0
+ **/
+@Service
+public class AlarmService {
+    @Autowired
+    private AlarmClient alarmClient;
+
+    /**
+     * @description: 查询报警定义
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONArray> queryAlarmConfig(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.queryAlarmConfig(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 创建报警定义
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONObject> createAlarmConfig(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.createAlarmConfig(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 更新报警定义
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONObject> updateAlarmConfig(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.updateAlarmConfig(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 查询报警记录
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONArray> queryAlarmRecord(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.queryAlarmRecord(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 创建报警记录
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONObject> createAlarmRecord(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.createAlarmRecord(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 更新报警记录
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONObject> updateAlarmRecord(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.updateAlarmRecord(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 查询报警条目
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:41 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONArray> queryAlarmItem(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.queryAlarmItem(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 创建报警批注
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONObject>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:42 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONObject> createAlarmComment(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.createAlarmComment(alarmUrlParam, jsonObject);
+    }
+
+    /**
+     * @description: 查询报警批注
+     * @param: alarmUrlParam
+     * @param: jsonObject
+     * @return: com.persagy.dmp.starter.alarm.feign.DmpResult<org.springframework.boot.configurationprocessor.json.JSONArray>
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/27 3:42 下午
+     * @version: V1.0
+     */
+    public DmpResult<JSONArray> queryAlarmComment(AlarmUrlParam alarmUrlParam, JSONObject jsonObject) throws Exception {
+        return alarmClient.queryAlarmComment(alarmUrlParam, jsonObject);
+    }
+
+}

+ 203 - 0
src/main/java/com/persagy/dmp/starter/alarm/service/NettyAlarmService.java

@@ -0,0 +1,203 @@
+package com.persagy.dmp.starter.alarm.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.dmp.starter.alarm.feign.AlarmUrlParam;
+import com.persagy.dmp.starter.alarm.feign.DmpResult;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * @description: 处理netty消息中调用数据中台的逻辑
+ * @author: lixing
+ * @company: Persagy Technology Co.,Ltd
+ * @since: 2020/11/30 2:38 下午
+ * @version: V1.0
+ **/
+public abstract class NettyAlarmService {
+    @Autowired
+    AlarmService alarmService;
+
+    /**
+     * @description: 参数校验
+     * @param: obj
+     * @return: void
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:14 下午
+     * @version: V1.0
+     */
+    private void checkRequestParam(JSONObject obj) throws Exception {
+        String projectId = obj.getString("projectId");
+        String userId = obj.getString("userId");
+        String groupCode = obj.getString("groupCode");
+        if (StringUtils.isBlank(projectId)) {
+            throw new Exception("projectId不能为空");
+        } else if (StringUtils.isBlank(userId)) {
+            throw new Exception("userId不能为空");
+        } else if (StringUtils.isBlank(groupCode)) {
+            throw new Exception("groupCode不能为空");
+        }
+    }
+
+    /**
+     * @description: 获取request中的param
+     * @param: obj
+     * @return: com.persagy.dmp.starter.alarm.feign.AlarmUrlParam
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:14 下午
+     * @version: V1.0
+     */
+    private AlarmUrlParam getAlarmUrlParam(JSONObject obj) throws Exception {
+        this.checkRequestParam(obj);
+
+        return new AlarmUrlParam(
+                obj.getString("userId"),
+                obj.getString("groupCode"),
+                obj.getString("projectId"),
+                obj.getString("appId")
+        );
+    }
+
+    /**
+     * @description: 获取request中的body
+     * @param: obj
+     * @return: com.alibaba.fastjson.JSONObject
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:14 下午
+     * @version: V1.0
+     */
+    private JSONObject getRequestBody(JSONObject obj) throws Exception {
+        JSONObject requestBody = new JSONObject();
+        JSONObject criteria = (JSONObject) obj.clone();
+        criteria.remove("appId");
+        criteria.remove("userId");
+        if (!CollectionUtils.isEmpty(criteria.getJSONArray("orders"))) {
+            requestBody.put("orders", criteria.getJSONArray("orders"));
+            criteria.remove("orders");
+        }
+
+        if (!CollectionUtils.isEmpty(criteria.getJSONArray("withColumns"))) {
+            requestBody.put("withColumns", criteria.getJSONArray("withColumns"));
+            criteria.remove("withColumns");
+        }
+
+        if (criteria.containsKey("onlyCount")) {
+            requestBody.put("onlyCount", criteria.getBooleanValue("onlyCount"));
+            criteria.remove("onlyCount");
+        }
+
+        Integer page = criteria.getInteger("page");
+        Integer size = criteria.getInteger("size");
+        requestBody.put("page", page);
+        requestBody.put("size", size);
+        criteria.remove("page");
+        criteria.remove("size");
+
+        requestBody.put("criteria", criteria);
+        return requestBody;
+    }
+
+    /**
+     * @description: 查询报警定义
+     * @param: data
+     * @return: com.alibaba.fastjson.JSONArray
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:25 下午
+     * @version: V1.0
+     */
+    public JSONArray queryAlarmConfig(JSONObject data) throws Exception {
+        DmpResult<JSONArray> queryResult = alarmService.queryAlarmConfig(getAlarmUrlParam(data), getRequestBody(data));
+        JSONArray alarmConfigs = queryResult.getData();
+        // 报警定义中的信息点转换为表号、功能号
+        for (Object alarmConfig : alarmConfigs) {
+            JSONObject config = (JSONObject)alarmConfig;
+            JSONObject condition = config.getJSONObject("condition");
+            JSONArray infoCodeArray = condition.getJSONArray("infoCode");
+
+            JSONArray infoCodes = new JSONArray();
+            JSONObject infoCode = new JSONObject();
+            for (Object infoCodeObj : infoCodeArray) {
+                String infoCodeStr = (String)infoCodeObj;
+                String[] tmp = infoCodeStr.split("_");
+                infoCode.put("infoCode", infoCodeStr);
+                infoCode.put("meterId", tmp[0]);
+                infoCode.put("funcId", tmp[1]);
+                infoCodes.add(infoCode);
+            }
+            config.put("infoCodes", infoCodes);
+        }
+        return alarmConfigs;
+    }
+
+
+    /**
+     * @description: 获取报警名称
+     * @param: objId
+     * @return: java.lang.String
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 4:00 下午
+     * @version: V1.0
+     */
+    public abstract String getAlarmName(String objId);
+
+    /**
+     * @description: 获取报警备注
+     * @param: objId
+     * @return: java.lang.String
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 4:00 下午
+     * @version: V1.0
+     */
+    public abstract String getAlarmRemark(String objId);
+
+    /**
+     * @description: 创建报警id
+     * @param: data
+     * @return: java.lang.String
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 3:45 下午
+     * @version: V1.0
+     */
+    public String createAlarm(JSONObject data) throws Exception {
+        //报警分类(设备、空间、系统 Eq,Sp,Sy)
+        String category = data.getString("category");
+        String objId = data.getString("objId");
+        String classCode = data.getString("classCode");
+        String projectId = data.getString("projectId");
+
+        data.put("name", getAlarmName(objId));
+        data.put("remark", getAlarmRemark(objId));
+
+        DmpResult<JSONObject> alarmRecord = alarmService.createAlarmRecord(getAlarmUrlParam(data), data);
+        return alarmRecord.getData().getString("id");
+    }
+
+    /**
+     * @description: 更新报警记录
+     * @param: data
+     * @return: void
+     * @exception:
+     * @author: lixing
+     * @company: Persagy Technology Co.,Ltd
+     * @since: 2020/11/30 4:13 下午
+     * @version: V1.0
+     */
+    public void updateAlarmRecord(JSONObject data) throws Exception {
+        alarmService.updateAlarmRecord(getAlarmUrlParam(data), data);
+    }
+}

+ 1 - 0
src/main/resources/META-INF/spring.factories

@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.persagy.dmp.starter.alarm.AutoConfiguration