Browse Source

first commit

songwenbin 2 years ago
commit
598f5832cf
39 changed files with 2656 additions and 0 deletions
  1. 45 0
      .gitignore
  2. 22 0
      README.md
  3. 10 0
      bridge/build.gradle
  4. 28 0
      build.gradle
  5. 10 0
      common/utils/build.gradle
  6. 311 0
      common/utils/src/main/java/com/gyee/edge/common/utils/ByteUtil.java
  7. 621 0
      common/utils/src/main/java/com/gyee/edge/common/utils/DateUtil.java
  8. 129 0
      common/utils/src/main/java/com/gyee/edge/common/utils/EncryptUtil.java
  9. 164 0
      common/utils/src/main/java/com/gyee/edge/common/utils/Hex.java
  10. 22 0
      common/utils/src/main/java/com/gyee/edge/common/utils/RequestMapToJsonUtil.java
  11. 46 0
      common/utils/src/main/java/com/gyee/edge/common/utils/StringUtil.java
  12. 32 0
      gateway/Readme.md
  13. 15 0
      gateway/build.gradle
  14. 19 0
      gateway/src/main/java/com/gyee/edge/gateway/HttpServerApplication.java
  15. 85 0
      gateway/src/main/java/com/gyee/edge/gateway/config/NettyHttpServer.java
  16. 57 0
      gateway/src/main/java/com/gyee/edge/gateway/dto/Response.java
  17. 27 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/annotation/NettyHttpHandler.java
  18. 8 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/exception/IllegalMethodNotAllowedException.java
  19. 5 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/exception/IllegalPathDuplicatedException.java
  20. 8 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/exception/IllegalPathNotFoundException.java
  21. 16 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/handler/HelloWorldHandler.java
  22. 10 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/handler/IFunctionHandler.java
  23. 34 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/handler/PathVariableHandler.java
  24. 19 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/handler/RequestBodyHandler.java
  25. 179 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/http/NettyHttpRequest.java
  26. 78 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/http/NettyHttpResponse.java
  27. 93 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/iohandler/FilterLogginglHandler.java
  28. 142 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/iohandler/HttpServerHandler.java
  29. 40 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/iohandler/InterceptorHandler.java
  30. 60 0
      gateway/src/main/java/com/gyee/edge/gateway/restful/path/Path.java
  31. 2 0
      gateway/src/main/resources/application.properties
  32. 39 0
      gradle.properties
  33. BIN
      gradle/wrapper/gradle-wrapper.jar
  34. 7 0
      gradle/wrapper/gradle-wrapper.properties
  35. 172 0
      gradlew
  36. 84 0
      gradlew.bat
  37. 10 0
      loader/build.gradle
  38. 2 0
      lombok.config
  39. 5 0
      settings.gradle

+ 45 - 0
.gitignore

@@ -0,0 +1,45 @@
+/.idea
+/.gradle
+/admin/out
+/alarm/custom/out
+/alarm/qswindnew/out
+/alarm/scadafault/out
+/alarm/scadasnew/out
+/alarm/sharding/out
+/alarm/sharding-mysql/out
+/alarm/windturbinenew/out
+/calculate/feature/out
+/calculate/status8/out
+/control-calc/out
+/controlnetwork/out
+/data-adapter/out
+/data-adapter-client-demo/out
+/external-interface/out
+/dao/*/out
+/alarm/*/out
+/alarm/*/build
+/common/data/build
+/common/utils/build
+/admin/build
+/alarm/custom/build
+/alarm/qswindnew/build
+/alarm/scadafault/build
+/alarm/scadasnew/build
+/alarm/sharding/build
+/alarm/alarmstatistic/build
+/alarm/sharding-mysql/build
+/alarm/windturbinenew/build
+/calculate/feature/build
+/calculate/status8/build
+/control-calc/build
+/controlnetwork/build
+/data-adapter/build
+/data-adapter-client-demo/build
+/external-interface/build
+/dao/*/build
+/common/data/build
+/common/utils/build
+/warning-web/build
+/logs
+/*.class
+.DS_Store

+ 22 - 0
README.md

@@ -0,0 +1,22 @@
+# edge
+
+
+##模块:
+### common -- 公共类型和方法
+* data -- 公共数据类型
+* utils -- 公共方法
+
+
+### gateway -- 设备数据采集网关
+
+### bridge -- 数据转发服务
+
+### loader -- 数据入库服务
+
+
+
+
+
+
+
+

+ 10 - 0
bridge/build.gradle

@@ -0,0 +1,10 @@
+buildscript {
+}
+
+dependencies {
+    api("commons-codec:commons-codec:$commonsCodecVersion")
+    api("org.apache.commons:commons-lang3:$commonsLang3Version")
+    api("com.google.guava:guava:$guavaVersion")
+    api("com.alibaba:fastjson:$fastjsonVersion")
+    api("commons-beanutils:commons-beanutils:$commonsBeanUtilsVersion")
+}

+ 28 - 0
build.gradle

@@ -0,0 +1,28 @@
+subprojects {
+    apply plugin: "java-library"
+    apply plugin: "idea"
+    apply plugin: "eclipse"
+    apply plugin: "maven-publish"
+
+    [compileJava, compileTestJava, javadoc]*.options*.encoding = "UTF-8"
+
+    configurations {
+        all*.exclude module: "spring-boot-starter-tomcat"
+        all*.exclude module: "spring-boot-starter-logging"
+    }
+
+    dependencies {
+        compileOnly("org.projectlombok:lombok:$lombokVersion")
+        annotationProcessor("org.projectlombok:lombok:$lombokVersion")
+    }
+
+    repositories {
+        mavenLocal()
+        maven {
+            allowInsecureProtocol = true
+            url "http://maven.aliyun.com/nexus/content/groups/public/"
+        }
+        mavenCentral()
+    }
+}
+

+ 10 - 0
common/utils/build.gradle

@@ -0,0 +1,10 @@
+buildscript {
+}
+
+dependencies {
+    api("commons-codec:commons-codec:$commonsCodecVersion")
+    api("org.apache.commons:commons-lang3:$commonsLang3Version")
+    api("com.google.guava:guava:$guavaVersion")
+    api("com.alibaba:fastjson:$fastjsonVersion")
+    api("commons-beanutils:commons-beanutils:$commonsBeanUtilsVersion")
+}

+ 311 - 0
common/utils/src/main/java/com/gyee/edge/common/utils/ByteUtil.java

@@ -0,0 +1,311 @@
+package com.gyee.edge.common.utils;
+
+public class ByteUtil {
+    /**
+     * 转换short为byte
+     *
+     * @param b
+     * @param s
+     *            需要转换的short
+     * @param index
+     */
+    public static void putShort(byte b[], short s, int index) {
+        b[index + 1] = (byte) (s >> 8);
+        b[index + 0] = (byte) (s >> 0);
+    }
+
+    /**
+     * 通过byte数组取到short
+     *
+     * @param b
+     * @param index
+     *            第几位开始取
+     * @return
+     */
+    public static short getShort(byte[] b, int index) {
+        return (short) (((b[index + 1] << 8) | b[index + 0] & 0xff));
+    }
+
+    /**
+     * 转换int为byte数组
+     *
+     * @param bb
+     * @param x
+     * @param index
+     */
+    public static void putInt(byte[] bb, int x, int index) {
+        bb[index + 3] = (byte) (x >> 24);
+        bb[index + 2] = (byte) (x >> 16);
+        bb[index + 1] = (byte) (x >> 8);
+        bb[index + 0] = (byte) (x >> 0);
+    }
+
+    /**
+     * 通过byte数组取到int
+     *
+     * @param bb
+     * @param index
+     *            第几位开始
+     * @return
+     */
+    public static int getInt(byte[] bb, int index) {
+        return (int) ((((bb[index + 3] & 0xff) << 24)
+                | ((bb[index + 2] & 0xff) << 16)
+                | ((bb[index + 1] & 0xff) << 8) | ((bb[index + 0] & 0xff) << 0)));
+    }
+
+    /**
+     * 转换long型为byte数组
+     *
+     * @param b
+     * @param x
+     * @param index
+     */
+    public static byte[] putLong(byte[] b, long x, int index) {
+        byte[] bb = new byte[8];
+        for (int i = 0; i < 8; i++) {
+            int offset = 64 - (i + 1) * 8;
+            bb[i] = (byte) ((x >> offset) & 0xff);
+        }
+        return bb;
+    }
+
+    /**
+     * 通过byte数组取到long
+     *
+     * @param bb
+     * @param index
+     * @return
+     */
+    public static long getLong(byte[] bb, int index) {
+        return ((((long) bb[index + 7] & 0xff) << 56)
+                | (((long) bb[index + 6] & 0xff) << 48)
+                | (((long) bb[index + 5] & 0xff) << 40)
+                | (((long) bb[index + 4] & 0xff) << 32)
+                | (((long) bb[index + 3] & 0xff) << 24)
+                | (((long) bb[index + 2] & 0xff) << 16)
+                | (((long) bb[index + 1] & 0xff) << 8) | (((long) bb[index + 0] & 0xff) << 0));
+    }
+
+    /**
+     * 通过byte数组取到long
+     *
+     * @param bb
+     * @param index
+     * @return
+     */
+    public static long getLong2(byte[] bb, int index) {
+        return ((((long) bb[index + 0] & 0xff) << 56)
+                | (((long) bb[index + 1] & 0xff) << 48)
+                | (((long) bb[index + 2] & 0xff) << 40)
+                | (((long) bb[index + 3] & 0xff) << 32)
+                | (((long) bb[index + 4] & 0xff) << 24)
+                | (((long) bb[index + 5] & 0xff) << 16)
+                | (((long) bb[index + 6] & 0xff) << 8)
+                | (((long) bb[index + 7] & 0xff) << 0) );
+    }
+
+    /**
+     * 字符到字节转换
+     *
+     * @param ch
+     * @return
+     */
+    public static void putChar(byte[] bb, char ch, int index) {
+        int temp = (int) ch;
+        // byte[] b = new byte[2];
+        for (int i = 0; i < 2; i ++ ) {
+            bb[index + i] = new Integer(temp & 0xff).byteValue(); // 将最高位保存在最低位
+            temp = temp >> 8; // 向右移8位
+        }
+    }
+
+    /**
+     * 字节到字符转换
+     *
+     * @param b
+     * @return
+     */
+    public static char getChar(byte[] b, int index) {
+        int s = 0;
+        if (b[index + 1] > 0)
+            s += b[index + 1];
+        else
+            s += 256 + b[index + 0];
+        s *= 256;
+        if (b[index + 0] > 0)
+            s += b[index + 1];
+        else
+            s += 256 + b[index + 0];
+        char ch = (char) s;
+        return ch;
+    }
+
+    /**
+     * float转换byte
+     *
+     * @param bb
+     * @param x
+     * @param index
+     */
+    public static void putFloat(byte[] bb, float x, int index) {
+        // byte[] b = new byte[4];
+        int l = Float.floatToIntBits(x);
+        for (int i = 0; i < 4; i++) {
+            bb[index + i] = new Integer(l).byteValue();
+            l = l >> 8;
+        }
+    }
+
+    /**
+     * 通过byte数组取得float
+     *
+     * @param b
+     * @param index
+     * @return
+     */
+    public static float getFloat(byte[] b, int index) {
+        int l;
+        l = b[index + 0];
+        l &= 0xff;
+        l |= ((long) b[index + 1] << 8);
+        l &= 0xffff;
+        l |= ((long) b[index + 2] << 16);
+        l &= 0xffffff;
+        l |= ((long) b[index + 3] << 24);
+        return Float.intBitsToFloat(l);
+    }
+
+    /**
+     * double转换byte
+     *
+     * @param bb
+     * @param x
+     * @param index
+     */
+    public static byte[] putDouble(byte[] bb, double x, int index) {
+        byte[] b = new byte[8];
+        long l = Double.doubleToLongBits(x);
+        for (int i = 0; i < 8; i++) {
+            b[index + i] = new Long(l).byteValue();
+            l = l >> 8;
+        }
+        return b;
+    }
+
+    /**
+     * 通过byte数组取得double
+     *
+     * @param b
+     * @param index
+     * @return
+     */
+    public static double getDouble(byte[] b, int index) {
+        long l;
+        l = b[0];
+        l &= 0xff;
+        l |= ((long) b[1] << 8);
+        l &= 0xffff;
+        l |= ((long) b[2] << 16);
+        l &= 0xffffff;
+        l |= ((long) b[3] << 24);
+        l &= 0xffffffffl;
+        l |= ((long) b[4] << 32);
+        l &= 0xffffffffffl;
+        l |= ((long) b[5] << 40);
+        l &= 0xffffffffffffl;
+        l |= ((long) b[6] << 48);
+        l &= 0xffffffffffffffl;
+        l |= ((long) b[7] << 56);
+        return Double.longBitsToDouble(l);
+    }
+
+    public static void putHexString(byte[] bb, String s, int index){
+        for (int i = 0; i < s.length(); i+=2) {
+            byte c= (byte)( charToByte(s.charAt(i))<<4 | charToByte(s.charAt(i+1)));
+            bb[index+(i>>1)] = c;
+        }
+    }
+
+    private static byte charToByte(char c) {
+        return (byte) "0123456789ABCDEF".indexOf(c);
+    }
+
+    public static String getHexString(byte[] b, int index, int count){
+        StringBuilder stringBuilder = new StringBuilder("");
+        if (b == null || index < 0 || b.length < index + count ) {
+            return null;
+        }
+        for (int i = index; i < count + index; i++) {
+            int v = b[i] & 0xFF;
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    public static String getBinaryString(int d,int length){
+        StringBuilder stringBuilder = new StringBuilder("");
+        String hv = Integer.toBinaryString(d);
+        for (int j = 0; j < length - hv.length(); j++) {
+            stringBuilder.append(0);
+        }
+        stringBuilder.append(hv);
+        return stringBuilder.toString();
+    }
+
+    public static String getBinaryReverseString(int d,int length){
+        StringBuilder stringBuilder = new StringBuilder("");
+        String hv = Integer.toBinaryString(d);
+        for (int j = 0; j < length - hv.length(); j++) {
+            stringBuilder.append(0);
+        }
+        stringBuilder.append(hv);
+        stringBuilder.reverse();
+
+        return stringBuilder.toString();
+    }
+
+
+    //网络字节逆序
+    public static byte[] ReversEndian(byte b[],int count, boolean big)
+    {
+        byte by;
+        byte data[] = new byte[count];
+        for(int i=0;i<count;i++)
+        {
+            data[i] = b[i];
+        }
+        if(big==false)
+        {
+            for(int i=0;i<count;i++)
+            {
+                by = b[i];
+                data[count-i-1] = by;
+            }
+        }
+        return data;
+    }
+
+    public static short htons(short s){
+        short rslt = 0;
+        byte [] bs1 = new byte[2];
+        ByteUtil.putShort(bs1, s, 0);
+        byte[] bs2 = ReversEndian(bs1, 2, false);
+        rslt = ByteUtil.getShort(bs2, 0);
+        return rslt;
+    }
+
+    public static int htonl(int d){
+        int rslt = 0;
+        byte [] bs1 = new byte[4];
+        ByteUtil.putInt(bs1, d, 0);
+        byte[] bs2 = ReversEndian(bs1, 4, false);
+        rslt = ByteUtil.getInt(bs2, 0);
+        return rslt;
+    }
+
+}

+ 621 - 0
common/utils/src/main/java/com/gyee/edge/common/utils/DateUtil.java

@@ -0,0 +1,621 @@
+package com.gyee.edge.common.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+public class DateUtil {
+
+    private static final String format = "yyyy-MM-dd";
+    private static final String format1 = "yyyy-MM-dd HH:mm:ss";
+    private static final String format2 = "MM/dd/yyyy HH:mm:ss";
+    private static final String formatGMT = "yyyy-MM-dd'T'HH:mm:ss.SSS"; //2017-06-28T13:49:15.000+0800
+
+    // 第一次调用get将返回null
+    private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
+
+    // 获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中
+    public static SimpleDateFormat getFormat() {
+
+        SimpleDateFormat df = (SimpleDateFormat) threadLocal.get();
+
+        if (df == null) {
+            df = new SimpleDateFormat(format);
+            threadLocal.set(df);
+        }
+
+        return df;
+
+    }
+
+    public static SimpleDateFormat getFormat1() {
+
+        SimpleDateFormat df1 = (SimpleDateFormat) threadLocal.get();
+
+        if (df1 == null) {
+            df1 = new SimpleDateFormat(format1);
+            threadLocal.set(df1);
+        }
+
+        return df1;
+
+    }
+
+    public static SimpleDateFormat getFormat2() {
+
+        SimpleDateFormat df2 = (SimpleDateFormat) threadLocal.get();
+
+        if (df2 == null) {
+            df2 = new SimpleDateFormat(format2);
+            threadLocal.set(df2);
+        }
+
+        return df2;
+
+    }
+    
+    public static SimpleDateFormat getFormatGMT() {
+
+        SimpleDateFormat df2 = (SimpleDateFormat) threadLocal.get();
+        if (df2 == null) {
+            df2 = new SimpleDateFormat(formatGMT);
+            threadLocal.set(df2);
+        }
+
+        return df2;
+    }
+
+    /**
+     * 字符串时间转换成 时间戳  毫秒
+     * 2021-05-02 00:00:00     ===    168089860000
+     * @param time
+     * @return
+     */
+    public static long coverTimeMillis(String time){
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date = null;
+        try {
+            date = format.parse(time);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return date.getTime();
+    }
+
+    /**
+     * 获取系统日期(无时分秒毫秒)
+     * 
+     * @return
+     */
+    public static Date today() {
+        return truncate(now());
+    }
+
+    /**
+     * 获取系统时间
+     * 
+     * @return
+     */
+    public static Date now() {
+        return new Date();
+    }
+
+    /**
+     * 根据年月日生成日期对象
+     * 
+     * @param y
+     * @param m
+     * @param d
+     * @return
+     */
+    public static Date cons(int y, int m, int d) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(y, m, d, 0, 0, 0);
+        return cal.getTime();
+    }
+
+    public static String toDate(Date date) {
+        return getFormat1().format(date);
+    }
+
+    public static String toDate2(Date date) {
+        return getFormat2().format(date);
+    }
+
+    public static String toDate1(Date date) {
+        return getFormat().format(date);
+    }
+    
+    public static String toDateGMT(Date date) {
+        return getFormatGMT().format(date);
+    }
+
+    /**
+     * 根据年月日时分秒生成日期对象
+     * 
+     * @param y
+     * @param m
+     * @param d
+     * @param h
+     * @param mi
+     * @param s
+     * @return
+     */
+    public static Date cons(int y, int m, int d, int h, int mi, int s) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(y, m, d, h, mi, s);
+        return cal.getTime();
+    }
+
+    /**
+     * 将指定时间转化为 Calendar
+     * 
+     * @param date
+     * @return
+     */
+    public static Calendar getCal(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        return cal;
+    }
+
+    /**
+     * 将时间的时分秒毫秒字段去掉
+     * 
+     * @param date
+     * @return
+     */
+    public static Date truncate(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * 去掉日期中日及下级字段
+     * 
+     * @param date
+     * @return
+     */
+    public static Date truncDay(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * 去掉日期中的月及下级字段
+     * 
+     * @param date
+     * @return
+     */
+    public static Date truncMonth(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.MONTH, 0);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * 在指定时间上加指定的天数
+     * 
+     * @param date
+     * @param day
+     * @return
+     */
+    public static Date addDays(Date date, int day) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.DAY_OF_MONTH, day);
+        return cal.getTime();
+    }
+
+    /**
+     * 在指定的时间上加指定的月数
+     * 
+     * @param date
+     * @param month
+     * @return
+     */
+    public static Date addMonths(Date date, int month) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.MONTH, month);
+        return cal.getTime();
+    }
+
+
+    public static Date addYears(Date date, int year) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.YEAR, year);
+        return cal.getTime();
+    }
+
+
+    public static Date addHours(Date date, int hour) {
+        return new Date(date.getTime() + hour * 3600 * 1000);
+    }
+
+
+    public static Date addMinutes(Date date, int m) {
+        return new Date(date.getTime() + m * 60 * 1000);
+    }
+
+
+    public static Date addSeconds(Date date, int s) {
+        return new Date(date.getTime() + s * 1000);
+    }
+
+    /**
+     * 计算两个时间之间差的天数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int daysDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 60 * 24 * 1000));
+    }
+
+    /**
+     * 计算两个时间之间差的小时数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int hoursDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 60 * 1000));
+    }
+
+    public static double hoursDiff1(Date d1, Date d2) {
+        return Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (double) (60 * 60 * 1000));
+    }
+
+    public static double hoursDiff2(Date d1, Date d2) {
+        return Math.abs((d1.getTime() - d2.getTime())) / (double) (60 * 60 * 1000);
+    }
+
+    /**
+     * 计算两个时间之间差的分钟数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int minutesDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 1000));
+    }
+
+    /**
+     * 计算两个时间之间差的分钟数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static double minutesDiff2(Date d1, Date d2) {
+        return Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 1000));
+    }
+
+    /**
+     * 计算两个时间之间差的毫秒数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static long millisecondDiff(Date d1, Date d2) {
+        return Math.abs(d1.getTime() - d2.getTime());
+    }
+
+    /**
+     * 计算两个时间之间差的秒数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int secondsDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (1000));
+    }
+
+    /**
+     * 计算两个时间之间的月差
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int monthsDiff(Date d1, Date d2) {
+        Calendar cal1 = Calendar.getInstance();
+        Calendar cal2 = Calendar.getInstance();
+        cal1.setTime(d1);
+        cal2.setTime(d2);
+
+        return (int) Math.abs((cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR)) * 12 + cal1.get(Calendar.MONTH) - cal2.get(Calendar.MONTH));
+
+    }
+
+    /**
+     * 计算两个时间之间的月差
+     *
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int monthsDiff2(Date d1, Date d2) {
+        Calendar cal1 = Calendar.getInstance();
+        Calendar cal2 = Calendar.getInstance();
+        cal1.setTime(d1);
+        cal2.setTime(d2);
+
+        return (cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR)) * 12 + cal1.get(Calendar.MONTH) - cal2.get(Calendar.MONTH);
+
+    }
+
+    /**
+     * 获得指定时间的月数
+     * 
+     * @param date
+     * @return
+     */
+    public static int getMonth(Date date) {
+        Calendar cd = Calendar.getInstance();
+        cd.setTime(date);
+        return cd.get(Calendar.MONTH);
+    }
+
+    /**
+     * 获得指定时间的年数
+     * 
+     * @param date
+     * @return
+     */
+    public static int getYear(Date date) {
+        Calendar cd = Calendar.getInstance();
+        cd.setTime(date);
+        return cd.get(Calendar.YEAR);
+    }
+
+    /**
+     * 获取指定时间的天数
+     * 
+     * @param date
+     * @return
+     */
+    public static int getDay(Date date) {
+        Calendar cd = Calendar.getInstance();
+        cd.setTime(date);
+        return cd.get(Calendar.DAY_OF_MONTH);
+    }
+
+    public static int getCurrentMonthLastDay() {
+        Calendar a = Calendar.getInstance();
+        a.set(Calendar.DATE, 1);
+        a.roll(Calendar.DATE, -1);
+        int maxDate = a.get(Calendar.DATE);
+        return maxDate;
+    }
+
+    public static int getMonthDays(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(DateUtil.getYear(date), DateUtil.getMonth(date), DateUtil.getDay(date));
+        int dayst = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+        return dayst;
+    }
+
+    /**
+     * 获取当前月的第一天
+     * 
+     * @return
+     */
+    public static String getCurrtenFirstDay() {
+
+        Calendar c = Calendar.getInstance();
+        // c.add(Calendar.MONTH, 0);
+        c.set(Calendar.DAY_OF_MONTH, 1);
+        return getFormat().format(c.getTime());
+    }
+
+    /**
+     * 获取当前月的最后一天
+     * 
+     * @return
+     */
+    public static String getCurrtenLastDay() {
+
+        Calendar ca = Calendar.getInstance();
+        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
+        return getFormat().format(ca.getTime());
+    }
+
+    /**
+     * 获取当前月的第一天
+     * 
+     * @return
+     */
+    public static Date getCurrtenFirstDate() {
+
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 1);
+        return c.getTime();
+    }
+
+    /**
+     * 获取当前月的最后一天
+     * 
+     * @return
+     */
+    public static Date getCurrtenLastDate() {
+
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
+        c.set(Calendar.HOUR_OF_DAY, 23);
+        c.set(Calendar.MINUTE, 59);
+        c.set(Calendar.SECOND, 59);
+        return c.getTime();
+    }
+
+    public static Date parseDate(String date) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(format);
+            return sdf.parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date parseDate1(String date) {
+        try {
+            return getFormat1().parse(date);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date parseDate2(String date) {
+        try {
+            return getFormat2().parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    
+    public static Date parseDateGMT(String date) {
+        try {
+            return getFormatGMT().parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date parseLongToDate(long time) {
+        return new Date(time);
+    }
+
+    /**
+     * 转换Edna时间格式为标准格式
+     * 
+     * @param pointTime
+     * @return
+     */
+    public static String convertEdnaTime2(String pointTime, Boolean isNoSec) {
+        StringBuffer sb = new StringBuffer();
+        String[] dt = pointTime.split(" ");
+        String[] ymd = dt[0].split("-");
+        String[] hms = dt[1].split(":");
+        sb.append(ymd[0]).append("-");
+        if (ymd[1].length() == 1) {
+            sb.append("0").append(ymd[1]);
+        } else {
+            sb.append(ymd[1]);
+        }
+        if (ymd[2].length() == 1) {
+            sb.append("-").append("0").append(ymd[2]);
+        } else {
+            sb.append("-").append(ymd[2]);
+        }
+        if (hms[0].length() == 1) {
+            sb.append(" ").append("0").append(hms[0]);
+        } else {
+            sb.append(" ").append(hms[0]);
+        }
+        if (hms[1].length() == 1) {
+            sb.append(":").append("0").append(hms[1]);
+        } else {
+            sb.append(":").append(hms[1]);
+        }
+
+        if (isNoSec) {
+            sb.append(":").append("00");
+        } else {
+            if (hms[2].length() == 1) {
+                sb.append(":").append("0").append(hms[2]);
+            } else {
+                sb.append(":").append(hms[2]);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 转换Edna时间格式为标准格式
+     * 
+     * @param pointTime
+     * @return
+     */
+    public static String convertEdnaTime(String pointTime, Boolean isNoSec) {
+        String date = getFormat().format(new Date());
+        StringBuffer sb = new StringBuffer();
+        String[] dt = pointTime.split(" ");
+        String[] ymd = dt[0].split("/");
+        String[] hms = dt[1].split(":");
+        if (ymd[2].length() == 2) {
+            sb.append(date.substring(0, 2)).append(ymd[2]).append("-");
+        }
+        if (ymd[0].length() == 1) {
+            sb.append("0").append(ymd[0]);
+        } else {
+            sb.append(ymd[0]);
+        }
+        if (ymd[1].length() == 1) {
+            sb.append("-").append("0").append(ymd[1]);
+        } else {
+            sb.append("-").append(ymd[1]);
+        }
+        if (hms[0].length() == 1) {
+            sb.append(" ").append("0").append(hms[0]);
+        } else {
+            sb.append(" ").append(hms[0]);
+        }
+        if (hms[1].length() == 1) {
+            sb.append(":").append("0").append(hms[1]);
+        } else {
+            sb.append(":").append(hms[1]);
+        }
+
+        if (isNoSec) {
+            sb.append(":").append("00");
+        } else {
+            if (hms[2].length() == 1) {
+                sb.append(":").append("0").append(hms[2]);
+            } else {
+                sb.append(":").append(hms[2]);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    public static String convertEdnaTime(String pointTime) {
+        return convertEdnaTime2(pointTime, false);
+    }
+
+
+
+}

+ 129 - 0
common/utils/src/main/java/com/gyee/edge/common/utils/EncryptUtil.java

@@ -0,0 +1,129 @@
+package com.gyee.edge.common.utils;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class EncryptUtil {
+    public static final String KEY_SHA = "SHA";
+    public static final String KEY_MD5 = "MD5";
+    public static final String KEY_MAC = "HmacMD5";
+
+
+// sun不推荐使用它们自己的base64,用apache的挺好
+
+    /**
+     * BASE64解密
+     */
+    public static byte[] decryptBASE64(byte[] dest) {
+        if (dest == null) {
+            return null;
+        }
+        return Base64.decodeBase64(dest);
+    }
+
+    /**
+     * BASE64加密
+     */
+    public static byte[] encryptBASE64(byte[] origin) {
+        if (origin == null) {
+            return null;
+        }
+        return Base64.encodeBase64(origin);
+    }
+
+    /**
+     * MD5加密
+     *
+     * @throws NoSuchAlgorithmException
+     */
+    public static byte[] encryptMD5(byte[] data)
+            throws NoSuchAlgorithmException {
+        if (data == null) {
+            return null;
+        }
+        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
+        md5.update(data);
+        return md5.digest();
+    }
+
+    /**
+     * SHA加密
+     *
+     * @throws NoSuchAlgorithmException
+     */
+    public static byte[] encryptSHA(byte[] data)
+            throws NoSuchAlgorithmException {
+        if (data == null) {
+            return null;
+        }
+        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
+        sha.update(data);
+        return sha.digest();
+    }
+
+    /**
+     * 初始化HMAC密钥
+     *
+     * @throws NoSuchAlgorithmException
+     */
+    public static String initMacKey() throws NoSuchAlgorithmException {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
+        SecretKey secretKey = keyGenerator.generateKey();
+        return new String(encryptBASE64(secretKey.getEncoded()));
+    }
+
+    /**
+     * HMAC加密
+     *
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeyException
+     */
+    public static byte[] encryptHMAC(byte[] data, String key)
+            throws NoSuchAlgorithmException, InvalidKeyException {
+        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key.getBytes()),
+                KEY_MAC);
+        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
+        mac.init(secretKey);
+        return mac.doFinal(data);
+
+    }
+
+    /***
+     * 系统加密算法
+     * @param plainPassword 原始密码
+     * @return
+     */
+    public static String encryptPwd(String plainPassword) {
+        try {
+            return encryptMD5(plainPassword.getBytes()).toString();
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static void main(String[] args) throws Exception {
+// TODO Auto-generated method stub
+        String data = "简单加密";
+//        System.out.println(new BigInteger(encryptBASE64(data.getBytes())).toString(16));
+//        System.out.println(new BigInteger(encryptBASE64(data.getBytes())).toString(32));
+//        System.out.println(new String(decryptBASE64(encryptBASE64(data.getBytes()))));
+//
+//        System.out.println(new BigInteger(encryptMD5(data.getBytes())).toString());
+//        System.out.println(encryptSHA(data.getBytes()).toString());
+        System.out.println(EncryptUtil.encryptPwd(encryptMD5("123456".getBytes()).toString()));
+        System.out.println(EncryptUtil.encryptPwd("123456"));
+        System.out.println(EncryptUtil.encryptPwd("e10adc3949ba59abbe56e057f20f883e"));
+        System.out.println(EncryptUtil.encryptPwd("e10adc3949ba59abbe56e057f20f883e"));
+//
+//        System.out.println(new BigInteger(encryptHMAC(data.getBytes(), initMacKey())).toString());
+    }
+
+}

+ 164 - 0
common/utils/src/main/java/com/gyee/edge/common/utils/Hex.java

@@ -0,0 +1,164 @@
+package com.gyee.edge.common.utils;
+
+/**
+ * @see byte数组与十六进制字符串互转
+ * @author Herman.Xiong
+ * @date 2014年5月5日 17:00:01
+ */
+public class Hex {
+
+    /**
+     * 用于建立十六进制字符的输出的小写字符数组
+     */
+    private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
+            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+    /**
+     * 用于建立十六进制字符的输出的大写字符数组
+     */
+    private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
+            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+    /**
+     * @see 将字节数组转换为十六进制字符数组
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:06:52
+     * @param data byte[]
+     * @return 十六进制char[]
+     */
+    public static char[] encodeHex(byte[] data) {
+        return encodeHex(data, true);
+    }
+
+    /**
+     * @see 将字节数组转换为十六进制字符数组
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:07:14
+     * @param data byte[]
+     * @param toLowerCase true传换成小写格式 ,false传换成大写格式
+     * @return 十六进制char[]
+     */
+    public static char[] encodeHex(byte[] data, boolean toLowerCase) {
+        return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+    }
+
+    /**
+     * @see 将字节数组转换为十六进制字符数组
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:07:31
+     * @param data byte[]
+     * @param toDigits 用于控制输出的char[]
+     * @return 十六进制char[]
+     */
+    protected static char[] encodeHex(byte[] data, char[] toDigits) {
+        int l = data.length;
+        char[] out = new char[l << 1];
+        for (int i = 0, j = 0; i < l; i++) {
+            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
+            out[j++] = toDigits[0x0F & data[i]];
+        }
+        return out;
+    }
+
+    /**
+     * @see 将字节数组转换为十六进制字符串
+     * @date 2014年5月5日 17:07:43
+     * @author Herman.Xiong
+     * @param data byte[]
+     * @return 十六进制String
+     */
+    public static String encodeHexStr(byte[] data) {
+        return encodeHexStr(data, true);
+    }
+
+    /**
+     * @see 将字节数组转换为十六进制字符串
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:08:01
+     * @param data byte[]
+     * @param toLowerCase true 传换成小写格式 , false 传换成大写格式
+     * @return 十六进制String
+     */
+    public static String encodeHexStr(byte[] data, boolean toLowerCase) {
+        return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+    }
+
+    /**
+     * @see 将字节数组转换为十六进制字符串
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:08:15
+     * @param data byte[]
+     * @param toDigits 用于控制输出的char[]
+     * @return 十六进制String
+     */
+    protected static String encodeHexStr(byte[] data, char[] toDigits) {
+        return new String(encodeHex(data, toDigits));
+    }
+
+    /**
+     * @see 将十六进制字符数组转换为字节数组
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:08:28
+     * @param data 十六进制char[]
+     * @return byte[]
+     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
+     */
+    public static byte[] decodeHex(char[] data) {
+        int len = data.length;
+        if ((len & 0x01) != 0) {
+            throw new RuntimeException("未知的字符");
+        }
+        byte[] out = new byte[len >> 1];
+        for (int i = 0, j = 0; j < len; i++) {
+            int f = toDigit(data[j], j) << 4;
+            j++;
+            f = f | toDigit(data[j], j);
+            j++;
+            out[i] = (byte) (f & 0xFF);
+        }
+        return out;
+    }
+
+    /**
+     * @see 将十六进制字符转换成一个整数
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:08:46
+     * @param ch  十六进制char
+     * @param index 十六进制字符在字符数组中的位置
+     * @return 一个整数
+     * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
+     */
+    protected static int toDigit(char ch, int index) {
+        int digit = Character.digit(ch, 16);
+        if (digit == -1) {
+            throw new RuntimeException("非法16进制字符 " + ch
+                    + " 在索引 " + index);
+        }
+        return digit;
+    }
+
+    /**
+     * @see 将byte[]数组转换为String字符串
+     * @author Herman.Xiong
+     * @date 2014年5月5日 17:15:42
+     * @param data byte数组
+     * @return String 转换后的字符串
+     */
+    public static String byteToArray(byte[]data){
+        String result="";
+        for (int i = 0; i < data.length; i++) {
+            result+=Integer.toHexString((data[i] & 0xFF) | 0x100).toUpperCase().substring(1, 3);
+        }
+        return result;
+    }
+
+    public static void main(String[] args) {
+        String srcStr = "待转换字符串";
+        String encodeStr = encodeHexStr(srcStr.getBytes());
+        String decodeStr = new String(decodeHex(encodeStr.toCharArray()));
+        System.out.println("转换前:" + srcStr);
+        System.out.println("转换后:" + encodeStr);
+        System.out.println("还原后:" + decodeStr);
+    }
+
+}

+ 22 - 0
common/utils/src/main/java/com/gyee/edge/common/utils/RequestMapToJsonUtil.java

@@ -0,0 +1,22 @@
+package com.gyee.edge.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.collections.map.HashedMap;
+
+import java.util.Map;
+
+
+public class RequestMapToJsonUtil {
+
+    public static String toJson(Map<String, String[]> params) {
+        Map<String,String> dataMap=new HashedMap(params.size()-1);
+        for(String key : params.keySet()) {
+            if (key.equals("_csrf")) {
+                continue;
+            }
+            dataMap.put(key,params.get(key)[0]);
+        }
+        return JSON.toJSONString(dataMap);
+    }
+
+}

+ 46 - 0
common/utils/src/main/java/com/gyee/edge/common/utils/StringUtil.java

@@ -0,0 +1,46 @@
+package com.gyee.edge.common.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.UUID;
+
+/**
+ * String辅助类
+ * 
+ */
+public class StringUtil extends StringUtils {
+	
+	/**
+	 * 非空判断
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static boolean isNotBlank(Object obj) {
+		return !isBlank(obj);
+	}
+
+	/**
+	 * 为空判断
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static boolean isBlank(Object obj) {
+		if (obj == null || StringUtils.isBlank(obj.toString())) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 获得一个UUID
+	 * @return String UUID
+	 */
+	public static String getUUID(){
+		String uuid = UUID.randomUUID().toString();
+		//去掉“-”符号
+		return uuid.replaceAll("-", "");
+	}
+
+}

+ 32 - 0
gateway/Readme.md

@@ -0,0 +1,32 @@
+# gateway
+
+
+##目录:
+### bridge -- 与数据中转服务的通信
+
+### cdt -- cdt数据采集
+
+### config -- 基础配置
+
+### dto -- dto数据传输对象
+
+### iec102 -- iec102数据采集
+
+### iec104 -- iec104数据采集
+
+### message -- 消息定义
+
+### modbus -- modbus数据采集
+
+### prediction -- 功率预测数据采集
+
+### restful -- restful管理服务
+
+
+
+
+
+
+
+
+

+ 15 - 0
gateway/build.gradle

@@ -0,0 +1,15 @@
+buildscript {
+}
+
+dependencies {
+    implementation project(":common:utils")
+    implementation("io.restful:restful-all:$nettyVersion")
+    implementation("$bootGroup:spring-boot-starter:$springBootVersion")
+    implementation("com.google.code.gson:gson:$gsonVersion")
+    implementation("com.google.code.gson:gson:$gsonVersion")
+    implementation("org.apache.logging.log4j:log4j-core:$log4jVersion")
+    implementation("org.apache.logging.log4j:log4j-jul:$log4jVersion")
+    implementation("org.apache.logging.log4j:log4j-api:$log4jVersion")
+    implementation("org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion")
+
+}

+ 19 - 0
gateway/src/main/java/com/gyee/edge/gateway/HttpServerApplication.java

@@ -0,0 +1,19 @@
+
+package com.gyee.edge.gateway;
+
+import com.gyee.edge.gateway.restful.annotation.NettyHttpHandler;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication()
+@ComponentScan(includeFilters = @ComponentScan.Filter(NettyHttpHandler.class))
+
+public class HttpServerApplication {
+
+    public static void main(String[] args) {
+        new SpringApplicationBuilder(HttpServerApplication.class).web(WebApplicationType.NONE).run(args);
+    }
+
+}

+ 85 - 0
gateway/src/main/java/com/gyee/edge/gateway/config/NettyHttpServer.java

@@ -0,0 +1,85 @@
+package com.gyee.edge.gateway.config;
+
+
+import com.gyee.edge.gateway.restful.iohandler.FilterLogginglHandler;
+import com.gyee.edge.gateway.restful.iohandler.HttpServerHandler;
+import com.gyee.edge.gateway.restful.iohandler.InterceptorHandler;
+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.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpServerCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.lang.NonNull;
+
+import javax.annotation.Resource;
+
+
+@Configuration
+public class NettyHttpServer implements ApplicationListener<ApplicationStartedEvent> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(NettyHttpServer.class);
+
+    @Value("${server.port}")
+    private int port;
+
+    @Resource
+    private InterceptorHandler interceptorHandler;
+
+    @Resource
+    private HttpServerHandler httpServerHandler;
+
+    @Override
+    public void onApplicationEvent(@NonNull ApplicationStartedEvent event) {
+
+        ServerBootstrap bootstrap = new ServerBootstrap();
+        EventLoopGroup bossGroup = new NioEventLoopGroup();
+        EventLoopGroup workerGroup = new NioEventLoopGroup();
+
+        bootstrap.group(bossGroup, workerGroup);
+        bootstrap.channel(NioServerSocketChannel.class);
+        bootstrap.childOption(NioChannelOption.TCP_NODELAY, true);
+        bootstrap.childOption(NioChannelOption.SO_REUSEADDR,true);
+        bootstrap.childOption(NioChannelOption.SO_KEEPALIVE,false);
+        bootstrap.childOption(NioChannelOption.SO_RCVBUF, 2048);
+        bootstrap.childOption(NioChannelOption.SO_SNDBUF, 2048);
+        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
+            @Override
+            public void initChannel(SocketChannel ch) {
+                ch.pipeline().addLast("codec", new HttpServerCodec());
+                ch.pipeline().addLast("aggregator", new HttpObjectAggregator(512 * 1024));
+                ch.pipeline().addLast("logging", new FilterLogginglHandler());
+                ch.pipeline().addLast("interceptor", interceptorHandler);
+                ch.pipeline().addLast("bizHandler", httpServerHandler);
+            }
+        })
+        ;
+        ChannelFuture channelFuture = bootstrap.bind(port).syncUninterruptibly().addListener(future -> {
+            String logBanner = "\n\n" +
+                    "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" +
+                    "*                                                                                   *\n" +
+                    "*                                                                                   *\n" +
+                    "*                   Netty Http Server started on port {}.                         *\n" +
+                    "*                                                                                   *\n" +
+                    "*                                                                                   *\n" +
+                    "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n";
+            LOGGER.info(logBanner, port);
+        });
+        channelFuture.channel().closeFuture().addListener(future -> {
+            LOGGER.info("Netty Http Server Start Shutdown ............");
+            bossGroup.shutdownGracefully();
+            workerGroup.shutdownGracefully();
+        });
+    }
+
+}

+ 57 - 0
gateway/src/main/java/com/gyee/edge/gateway/dto/Response.java

@@ -0,0 +1,57 @@
+
+package com.gyee.edge.gateway.dto;
+
+import com.google.gson.GsonBuilder;
+
+public final class Response<T> {
+    private int code;
+    private String message;
+    private T data;
+
+
+    public Response(int code, String message, T data) {
+        this.code = code;
+        this.message = message;
+        this.data = data;
+    }
+
+    @Override
+    public String toString() {
+        return "Response{" +
+                "code=" + code +
+                ", message='" + message + '\'' +
+                ", data=" + data +
+                '}';
+    }
+
+    public String toJSONString(){
+        return new GsonBuilder().create().toJson(this);
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public static <T> Response<T> ok(T data) {
+        return new Response<>(200, "ok", data);
+    }
+    public static  Response<Void> ok() {
+        return new Response(200, "ok", null);
+    }
+
+    public static <T> Response<T> ok(String msg, T data) {
+        return new Response<>(200, msg, data);
+    }
+
+    public static Response fail(String msg) {
+        return new Response<String>(500, msg, null);
+    }
+}

+ 27 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/annotation/NettyHttpHandler.java

@@ -0,0 +1,27 @@
+
+package com.gyee.edge.gateway.restful.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface NettyHttpHandler {
+    /**
+     * 请求路径
+     * @return
+     */
+    String path() default "";
+
+    /**
+     * 支持的提交方式
+     * @return
+     */
+    String method() default "GET";
+
+    /**
+     * path和请求路径是否需要完全匹配。 如果是PathVariable传参数,设置为false
+     * @return
+     */
+    boolean equal() default true;
+}

+ 8 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/exception/IllegalMethodNotAllowedException.java

@@ -0,0 +1,8 @@
+
+package com.gyee.edge.gateway.restful.exception;
+
+public class IllegalMethodNotAllowedException extends Exception {
+    public IllegalMethodNotAllowedException() {
+        super("METHOD NOT ALLOWED");
+    }
+}

+ 5 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/exception/IllegalPathDuplicatedException.java

@@ -0,0 +1,5 @@
+
+package com.gyee.edge.gateway.restful.exception;
+
+public class IllegalPathDuplicatedException extends Exception {
+}

+ 8 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/exception/IllegalPathNotFoundException.java

@@ -0,0 +1,8 @@
+
+package com.gyee.edge.gateway.restful.exception;
+
+public class IllegalPathNotFoundException extends Exception {
+    public IllegalPathNotFoundException() {
+        super("PATH NOT FOUND");
+    }
+}

+ 16 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/handler/HelloWorldHandler.java

@@ -0,0 +1,16 @@
+
+package com.gyee.edge.gateway.restful.handler;
+
+
+import com.gyee.edge.gateway.dto.Response;
+import com.gyee.edge.gateway.restful.annotation.NettyHttpHandler;
+import com.gyee.edge.gateway.restful.http.NettyHttpRequest;
+
+@NettyHttpHandler(path = "/hello/world")
+public class HelloWorldHandler implements IFunctionHandler<String> {
+
+    @Override
+    public Response<String> execute(NettyHttpRequest request) {
+         return Response.ok("Hello World");
+    }
+}

+ 10 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/handler/IFunctionHandler.java

@@ -0,0 +1,10 @@
+
+package com.gyee.edge.gateway.restful.handler;
+
+
+import com.gyee.edge.gateway.dto.Response;
+import com.gyee.edge.gateway.restful.http.NettyHttpRequest;
+
+public interface IFunctionHandler<T> {
+    Response<T> execute(NettyHttpRequest request);
+}

+ 34 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/handler/PathVariableHandler.java

@@ -0,0 +1,34 @@
+
+package com.gyee.edge.gateway.restful.handler;
+
+
+
+import com.gyee.edge.gateway.dto.Response;
+import com.gyee.edge.gateway.restful.annotation.NettyHttpHandler;
+import com.gyee.edge.gateway.restful.http.NettyHttpRequest;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+
+@NettyHttpHandler(path = "/moment/list/",equal = false)
+public class PathVariableHandler implements IFunctionHandler<List<HashMap<String,String>>> {
+    @Override
+    public Response<List<HashMap<String,String>>> execute(NettyHttpRequest request) {
+
+        /**
+         * 通过请求uri获取到path参数
+         */
+        String id = request.getStringPathValue(3);
+
+        List<HashMap<String,String>> list = new LinkedList<>();
+        HashMap<String,String> data = new HashMap<>();
+        data.put("id","1");
+        data.put("name","Bluesky");
+        data.put("text","hello sea!");
+        data.put("time","2018-08-08 08:08:08");
+        list.add(data);
+        return Response.ok(list);
+    }
+}

+ 19 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/handler/RequestBodyHandler.java

@@ -0,0 +1,19 @@
+
+package com.gyee.edge.gateway.restful.handler;
+
+
+import com.gyee.edge.gateway.dto.Response;
+import com.gyee.edge.gateway.restful.annotation.NettyHttpHandler;
+import com.gyee.edge.gateway.restful.http.NettyHttpRequest;
+
+@NettyHttpHandler(path = "/request/body",method = "POST")
+public class RequestBodyHandler implements IFunctionHandler<String> {
+    @Override
+    public Response<String> execute(NettyHttpRequest request) {
+        /**
+         * 可以在此拿到json转成业务需要的对象
+         */
+        String json = request.contentText();
+        return Response.ok(json);
+    }
+}

+ 179 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/http/NettyHttpRequest.java

@@ -0,0 +1,179 @@
+
+package com.gyee.edge.gateway.restful.http;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.DecoderResult;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpVersion;
+
+import java.nio.charset.Charset;
+import java.util.Objects;
+
+public class NettyHttpRequest implements FullHttpRequest {
+
+    private FullHttpRequest realRequest;
+
+    public NettyHttpRequest(FullHttpRequest request){
+        this.realRequest = request;
+    }
+
+    public String contentText(){
+        return content().toString(Charset.forName("UTF-8"));
+    }
+
+    public long getLongPathValue(int index){
+        String[] paths = uri().split("/");
+        return Long.parseLong(paths[index]);
+    }
+
+    public String getStringPathValue(int index){
+        String[] paths = uri().split("/");
+        return paths[index];
+    }
+
+    public int getIntPathValue(int index){
+        String[] paths = uri().split("/");
+        return Integer.parseInt(paths[index]);
+    }
+
+    public boolean isAllowed(String method){
+        return getMethod().name().equalsIgnoreCase(method);
+    }
+
+    public boolean matched(String path,boolean equal){
+        String uri = uri().toLowerCase();
+        return equal ? Objects.equals(path,uri) : uri.startsWith(path);
+    }
+
+    @Override
+    public ByteBuf content() {
+        return realRequest.content();
+    }
+
+    @Override
+    public HttpHeaders trailingHeaders() {
+        return realRequest.trailingHeaders();
+    }
+
+    @Override
+    public FullHttpRequest copy() {
+        return realRequest.copy();
+    }
+
+    @Override
+    public FullHttpRequest duplicate() {
+        return realRequest.duplicate();
+    }
+
+    @Override
+    public FullHttpRequest retainedDuplicate() {
+        return realRequest.retainedDuplicate();
+    }
+
+    @Override
+    public FullHttpRequest replace(ByteBuf byteBuf) {
+        return realRequest.replace(byteBuf);
+    }
+
+    @Override
+    public FullHttpRequest retain(int i) {
+        return realRequest.retain(i);
+    }
+
+    @Override
+    public int refCnt() {
+        return realRequest.refCnt();
+    }
+
+    @Override
+    public FullHttpRequest retain() {
+        return realRequest.retain();
+    }
+
+    @Override
+    public FullHttpRequest touch() {
+        return realRequest.touch();
+    }
+
+    @Override
+    public FullHttpRequest touch(Object o) {
+        return realRequest.touch(o);
+    }
+
+    @Override
+    public boolean release() {
+        return realRequest.release();
+    }
+
+    @Override
+    public boolean release(int i) {
+        return realRequest.release(i);
+    }
+
+    @Override
+    public HttpVersion getProtocolVersion() {
+        return realRequest.protocolVersion();
+    }
+
+    @Override
+    public HttpVersion protocolVersion() {
+        return realRequest.protocolVersion();
+    }
+
+    @Override
+    public FullHttpRequest setProtocolVersion(HttpVersion httpVersion) {
+        return realRequest.setProtocolVersion(httpVersion);
+    }
+
+    @Override
+    public HttpHeaders headers() {
+        return realRequest.headers();
+    }
+
+    @Override
+    public HttpMethod getMethod() {
+        return realRequest.getMethod();
+    }
+
+    @Override
+    public HttpMethod method() {
+        return realRequest.method();
+    }
+
+    @Override
+    public FullHttpRequest setMethod(HttpMethod httpMethod) {
+        return realRequest.setMethod(httpMethod);
+    }
+
+    @Override
+    public String getUri() {
+        return realRequest.getUri();
+    }
+
+    @Override
+    public String uri() {
+        return realRequest.uri();
+    }
+
+    @Override
+    public FullHttpRequest setUri(String s) {
+        return realRequest.setUri(s);
+    }
+
+    @Override
+    public DecoderResult getDecoderResult() {
+        return realRequest.getDecoderResult();
+    }
+
+    @Override
+    public DecoderResult decoderResult() {
+        return realRequest.decoderResult();
+    }
+
+    @Override
+    public void setDecoderResult(DecoderResult decoderResult) {
+        realRequest.setDecoderResult(decoderResult);
+    }
+}

+ 78 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/http/NettyHttpResponse.java

@@ -0,0 +1,78 @@
+
+package com.gyee.edge.gateway.restful.http;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+
+import static io.netty.handler.codec.http.HttpHeaderNames.*;
+
+public class NettyHttpResponse extends DefaultFullHttpResponse {
+
+    private static final PooledByteBufAllocator BYTE_BUF_ALLOCATOR = new PooledByteBufAllocator(false);
+
+    private static final String CONTENT_NORMAL_200 = "{\"code\":200,\"message\":\"OK\"}";
+    private static final String CONTENT_ERROR_401 = "{\"code\":401,\"message\":\"UNAUTHORIZED\"}";
+    private static final String CONTENT_ERROR_404 = "{\"code\":404,\"message\":\"REQUEST PATH NOT FOUND\"}";
+    private static final String CONTENT_ERROR_405 = "{\"code\":405,\"message\":\"METHOD NOT ALLOWED\"}";
+    private static final String CONTENT_ERROR_500 = "{\"code\":500,\"message\":\"%s\"}";
+
+    private String content;
+
+    private NettyHttpResponse(HttpResponseStatus status, ByteBuf buffer ) {
+        super(HttpVersion.HTTP_1_1, status,buffer);
+        headers().set(CONTENT_TYPE, "application/json");
+        headers().setInt(CONTENT_LENGTH, content().readableBytes());
+
+        /**
+         * 支持CORS 跨域访问
+         */
+        headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
+        headers().set(ACCESS_CONTROL_ALLOW_HEADERS, "Origin, X-Requested-With, Content-Type, Accept, RCS-ACCESS-TOKEN");
+        headers().set(ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,DELETE");
+    }
+
+    public static FullHttpResponse make(HttpResponseStatus status) {
+        if (HttpResponseStatus.UNAUTHORIZED == status) {
+            return NettyHttpResponse.make(HttpResponseStatus.UNAUTHORIZED, CONTENT_ERROR_401);
+        }
+        if (HttpResponseStatus.NOT_FOUND == status) {
+            return NettyHttpResponse.make(HttpResponseStatus.NOT_FOUND, CONTENT_ERROR_404);
+        }
+        if (HttpResponseStatus.METHOD_NOT_ALLOWED == status) {
+            return NettyHttpResponse.make(HttpResponseStatus.METHOD_NOT_ALLOWED, CONTENT_ERROR_405);
+        }
+        return NettyHttpResponse.make(HttpResponseStatus.OK,CONTENT_NORMAL_200);
+    }
+
+    public static FullHttpResponse makeError(Exception exception) {
+        String message = exception.getClass().getName() + ":" + exception.getMessage();
+        return NettyHttpResponse.make(HttpResponseStatus.INTERNAL_SERVER_ERROR, String.format(CONTENT_ERROR_500,message));
+    }
+
+    public static FullHttpResponse ok(String content) {
+        return make(HttpResponseStatus.OK,content);
+    }
+
+    private static FullHttpResponse make(HttpResponseStatus status,String content) {
+        byte[] body = content.getBytes();
+        ByteBuf buffer = BYTE_BUF_ALLOCATOR.buffer(body.length);
+        buffer.writeBytes(body);
+        NettyHttpResponse response = new NettyHttpResponse(status,buffer);
+        response.content = content;
+        return response;
+    }
+
+    @Override
+    public String toString(){
+        StringBuilder builder = new StringBuilder();
+        builder.append(protocolVersion().toString()).append(" ").append(status().toString()).append("\n");
+        builder.append(CONTENT_TYPE).append(": ").append(headers().get(CONTENT_TYPE)).append("\n");
+        builder.append(CONTENT_LENGTH).append(": ").append(headers().get(CONTENT_LENGTH)).append("\n");
+        builder.append("content-body").append(": ").append(content).append("\n");
+        return builder.toString();
+    }
+}

+ 93 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/iohandler/FilterLogginglHandler.java

@@ -0,0 +1,93 @@
+
+package com.gyee.edge.gateway.restful.iohandler;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+
+import java.net.SocketAddress;
+
+import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
+import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
+
+public class FilterLogginglHandler extends LoggingHandler {
+    public FilterLogginglHandler() {
+        super(LogLevel.INFO);
+    }
+
+    public void channelRegistered(ChannelHandlerContext ctx) {
+        ctx.fireChannelRegistered();
+    }
+
+    public void channelUnregistered(ChannelHandlerContext ctx) {
+        ctx.fireChannelUnregistered();
+    }
+
+    public void channelActive(ChannelHandlerContext ctx) {
+        ctx.fireChannelActive();
+    }
+
+    public void channelInactive(ChannelHandlerContext ctx) {
+        ctx.fireChannelInactive();
+    }
+
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
+        ctx.fireUserEventTriggered(evt);
+    }
+
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise){
+        if (this.logger.isEnabled(this.internalLevel)) {
+            this.logger.log(this.internalLevel,ctx.channel().toString() + " WRITE \n" + msg.toString());
+        }
+
+        ctx.write(msg, promise);
+    }
+
+    public void channelRead(ChannelHandlerContext ctx, Object msg)   {
+        if (this.logger.isEnabled(this.internalLevel)) {
+            HttpRequest request = (HttpRequest) msg;
+            String log = request.method() + " " + request.uri() + " " + request.protocolVersion() + "\n" +
+                    CONTENT_TYPE + ": " + request.headers().get(CONTENT_TYPE) + "\n" +
+                    CONTENT_LENGTH + ": " + request.headers().get(CONTENT_LENGTH) + "\n";
+            this.logger.log(this.internalLevel,ctx.channel().toString() + " READ \n" + log);
+        }
+        ctx.fireChannelRead(msg);
+    }
+
+
+
+
+    public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) {
+        ctx.bind(localAddress, promise);
+    }
+
+    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
+        ctx.connect(remoteAddress, localAddress, promise);
+    }
+
+    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
+        ctx.disconnect(promise);
+    }
+
+    public void close(ChannelHandlerContext ctx, ChannelPromise promise) {
+        ctx.close(promise);
+    }
+
+    public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) {
+        ctx.deregister(promise);
+    }
+
+    public void channelReadComplete(ChannelHandlerContext ctx) {
+        ctx.fireChannelReadComplete();
+    }
+
+    public void channelWritabilityChanged(ChannelHandlerContext ctx) {
+        ctx.fireChannelWritabilityChanged();
+    }
+
+    public void flush(ChannelHandlerContext ctx) {
+        ctx.flush();
+    }
+}

+ 142 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/iohandler/HttpServerHandler.java

@@ -0,0 +1,142 @@
+
+package com.gyee.edge.gateway.restful.iohandler;
+
+
+
+import com.gyee.edge.gateway.dto.Response;
+import com.gyee.edge.gateway.restful.annotation.NettyHttpHandler;
+import com.gyee.edge.gateway.restful.exception.IllegalMethodNotAllowedException;
+import com.gyee.edge.gateway.restful.exception.IllegalPathDuplicatedException;
+import com.gyee.edge.gateway.restful.exception.IllegalPathNotFoundException;
+import com.gyee.edge.gateway.restful.handler.IFunctionHandler;
+import com.gyee.edge.gateway.restful.http.NettyHttpRequest;
+import com.gyee.edge.gateway.restful.http.NettyHttpResponse;
+import com.gyee.edge.gateway.restful.path.Path;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.util.ReferenceCountUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+@ChannelHandler.Sharable
+@Component
+public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> implements ApplicationContextAware {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(HttpServerHandler.class);
+
+    private HashMap<Path, IFunctionHandler> functionHandlerMap = new HashMap<>();
+
+    private ExecutorService executor = Executors.newCachedThreadPool(runnable -> {
+        Thread thread = Executors.defaultThreadFactory().newThread(runnable);
+        thread.setName("NettyHttpHandler-" + thread.getName());
+        return thread;
+    });
+
+    @Override
+    public void channelReadComplete(ChannelHandlerContext ctx) {
+        ctx.flush();
+    }
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
+        FullHttpRequest copyRequest = request.copy();
+        executor.execute(() -> onReceivedRequest(ctx,new NettyHttpRequest(copyRequest)));
+    }
+
+
+    private void onReceivedRequest(ChannelHandlerContext context, NettyHttpRequest request){
+        FullHttpResponse response = handleHttpRequest(request);
+        context.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
+        ReferenceCountUtil.release(request);
+    }
+
+    private FullHttpResponse handleHttpRequest(NettyHttpRequest request) {
+
+        IFunctionHandler functionHandler = null;
+
+        try {
+            functionHandler = matchFunctionHandler(request);
+            Response response =  functionHandler.execute(request);
+            return NettyHttpResponse.ok(response.toJSONString());
+        }
+        catch (IllegalMethodNotAllowedException error){
+            return NettyHttpResponse.make(HttpResponseStatus.METHOD_NOT_ALLOWED);
+        }
+        catch (IllegalPathNotFoundException error){
+            return NettyHttpResponse.make(HttpResponseStatus.NOT_FOUND);
+        }
+        catch (Exception error){
+            LOGGER.error(functionHandler.getClass().getSimpleName() + " Error",error);
+            return NettyHttpResponse.makeError(error);
+        }
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        Map<String, Object> handlers =  applicationContext.getBeansWithAnnotation(NettyHttpHandler.class);
+        for (Map.Entry<String, Object> entry : handlers.entrySet()) {
+            Object handler = entry.getValue();
+            Path path = Path.make(handler.getClass().getAnnotation(NettyHttpHandler.class));
+            if (functionHandlerMap.containsKey(path)){
+                LOGGER.error("IFunctionHandler has duplicated :" + path.toString(),new IllegalPathDuplicatedException());
+                System.exit(0);
+            }
+            functionHandlerMap.put(path, (IFunctionHandler) handler);
+        }
+    }
+
+    private IFunctionHandler matchFunctionHandler(NettyHttpRequest request) throws IllegalPathNotFoundException, IllegalMethodNotAllowedException {
+
+        AtomicBoolean matched = new AtomicBoolean(false);
+
+        Stream<Path> stream = functionHandlerMap.keySet().stream()
+                .filter(((Predicate<Path>) path -> {
+                    /**
+                     *过滤 Path URI 不匹配的
+                     */
+                    if (request.matched(path.getUri(), path.isEqual())) {
+                        matched.set(true);
+                        return matched.get();
+                    }
+                    return false;
+
+                }).and(path -> {
+                    /**
+                     * 过滤 Method 匹配的
+                     */
+                    return request.isAllowed(path.getMethod());
+                }));
+
+        Optional<Path> optional = stream.findFirst();
+
+        stream.close();
+
+        if (!optional.isPresent() && !matched.get()){
+            throw  new IllegalPathNotFoundException();
+        }
+
+        if (!optional.isPresent() && matched.get()){
+            throw  new IllegalMethodNotAllowedException();
+        }
+
+        return functionHandlerMap.get(optional.get());
+    }
+
+}

+ 40 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/iohandler/InterceptorHandler.java

@@ -0,0 +1,40 @@
+
+package com.gyee.edge.gateway.restful.iohandler;
+
+import com.gyee.edge.gateway.restful.http.NettyHttpResponse;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.util.ReferenceCountUtil;
+import org.springframework.stereotype.Component;
+
+
+@ChannelHandler.Sharable
+@Component
+/**
+ * 在这里可以做拦截器,验证一些请求的合法性
+ */
+public class InterceptorHandler extends ChannelInboundHandlerAdapter {
+    @Override
+    public void channelRead(ChannelHandlerContext context, Object msg)   {
+        if (isPassed((FullHttpRequest) msg)){
+            context.fireChannelRead(msg);
+            return;
+        }
+
+        ReferenceCountUtil.release(msg);
+        context.writeAndFlush(NettyHttpResponse.make(HttpResponseStatus.UNAUTHORIZED)).addListener(ChannelFutureListener.CLOSE);
+    }
+
+    /**
+     * 修改实现来验证合法性
+     * @param request
+     * @return
+     */
+    private boolean isPassed(FullHttpRequest request){
+        return true;
+    }
+}

+ 60 - 0
gateway/src/main/java/com/gyee/edge/gateway/restful/path/Path.java

@@ -0,0 +1,60 @@
+
+package com.gyee.edge.gateway.restful.path;
+
+
+import com.gyee.edge.gateway.restful.annotation.NettyHttpHandler;
+
+public class Path {
+    private String method;
+    private String uri;
+    private boolean equal;
+
+    public static Path make(NettyHttpHandler annotation){
+        return new Path(annotation);
+    }
+    public Path(NettyHttpHandler annotation){
+        method = annotation.method();
+        uri = annotation.path();
+        equal = annotation.equal();
+    }
+    public String getMethod() {
+        return method;
+    }
+
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public boolean isEqual() {
+        return equal;
+    }
+
+    public void setEqual(boolean equal) {
+        this.equal = equal;
+    }
+
+    @Override
+    public String toString(){
+        return  method.toUpperCase() + " " + uri.toUpperCase();
+    }
+    @Override
+    public int hashCode(){
+        return  ("HTTP " + method.toUpperCase() + " " + uri.toUpperCase()).hashCode();
+    }
+    @Override
+    public boolean equals(Object object){
+        if (object instanceof  Path){
+            Path path = (Path) object;
+            return method.equalsIgnoreCase(path.method) && uri.equalsIgnoreCase(path.uri);
+        }
+        return false;
+    }
+}

+ 2 - 0
gateway/src/main/resources/application.properties

@@ -0,0 +1,2 @@
+server.port=8080
+spring.application.name=netty-http-server

+ 39 - 0
gradle.properties

@@ -0,0 +1,39 @@
+ group=com.gyee.edge
+version=1.0
+description=Gyee edge platform
+
+sourceCompatibility=1.8
+targetCompatibility=1.8
+
+# Abbr
+bootGroup=org.springframework.boot
+cloudGroup=org.springframework.cloud
+kotlinGroup=org.jetbrains.kotlin
+# Lib
+kotlinVersion=1.1.3
+aspectjVersion=1.8.10
+junitVersion=4.12
+mockitoVersion=2.8.47
+objenesisVersion=2.6
+findbugsContribVersion=7.0.2
+findbugsSecVersion=1.6.0
+#log4jVersion=2.8.2
+jsr305Version=3.0.1
+lombokVersion=1.18.20
+guavaVersion=30.1.1-jre
+checkstyleVersion=8.0
+springBootVersion=2.7.0
+springCloudDependenciesVersion=Hoxton.SR9
+commonsLang3Version=3.12.0
+commonsCodecVersion=1.15
+jodaTimeVersion=2.9.9
+nettyVersion=4.1.79.Final
+cassandraVersion=3.0.0
+hbaseVersion=1.2.0-cdh5.16.2
+hadoopVersion=2.6.0-cdh5.16.2
+mysqlConnectorVersion=8.0.28
+log4jVersion=2.17.1
+fastjsonVersion=1.2.58
+commonsBeanUtilsVersion=1.9.4
+alibabaDruidVersion=1.2.9
+gsonVersion=2.8.5

BIN
gradle/wrapper/gradle-wrapper.jar


+ 7 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,7 @@
+#Tue Sep 17 14:57:12 CST 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+#distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip

+ 172 - 0
gradlew

@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"

+ 84 - 0
gradlew.bat

@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 10 - 0
loader/build.gradle

@@ -0,0 +1,10 @@
+buildscript {
+}
+
+dependencies {
+    api("commons-codec:commons-codec:$commonsCodecVersion")
+    api("org.apache.commons:commons-lang3:$commonsLang3Version")
+    api("com.google.guava:guava:$guavaVersion")
+    api("com.alibaba:fastjson:$fastjsonVersion")
+    api("commons-beanutils:commons-beanutils:$commonsBeanUtilsVersion")
+}

+ 2 - 0
lombok.config

@@ -0,0 +1,2 @@
+config.stopBubbling=true
+lombok.equalsAndHashCode.callSuper=call

+ 5 - 0
settings.gradle

@@ -0,0 +1,5 @@
+rootProject.name = "edge"
+include "common:utils"
+include "gateway"
+include "gateway"
+include "gateway"