mengshibin 4 роки тому
батько
коміт
f618fbd593
100 змінених файлів з 31917 додано та 0 видалено
  1. 138 0
      4dkankan-application/pom.xml
  2. 37 0
      4dkankan-application/src/main/java/com/fdkankan/App.java
  3. 95 0
      4dkankan-application/src/main/resources/application-dev.properties
  4. 95 0
      4dkankan-application/src/main/resources/application-pro.properties
  5. 95 0
      4dkankan-application/src/main/resources/application-test.properties
  6. 36 0
      4dkankan-application/src/main/resources/application.properties
  7. 16 0
      4dkankan-application/src/main/resources/key/private_pkcs8.pem
  8. 6 0
      4dkankan-application/src/main/resources/key/public.pem
  9. 156 0
      4dkankan-application/src/main/resources/logback-spring.xml
  10. 1 0
      4dkankan-application/src/main/resources/static/MP_verify_i9CLaVAyYoDvylKB.txt
  11. 9 0
      4dkankan-application/src/main/resources/static/apppro.html
  12. BIN
      4dkankan-application/src/main/resources/static/img/logo.jpg
  13. BIN
      4dkankan-application/src/main/resources/static/img/logo.png
  14. 12 0
      4dkankan-application/src/main/resources/static/refreshToken.json
  15. 1125 0
      4dkankan-application/src/main/resources/static/txt/SensitiveWord.txt
  16. 39 0
      4dkankan-application/src/test/java/com/fdkankan/ModelingTest.java
  17. 217 0
      4dkankan-base/pom.xml
  18. 24 0
      4dkankan-base/src/main/java/com/fdkankan/base/config/DataSourceConfig.java
  19. 98 0
      4dkankan-base/src/main/java/com/fdkankan/base/config/FileRouteConfig.java
  20. 31 0
      4dkankan-base/src/main/java/com/fdkankan/base/config/MyNacosLifecycle.java
  21. 46 0
      4dkankan-base/src/main/java/com/fdkankan/base/config/PrimaryConfig.java
  22. 91 0
      4dkankan-base/src/main/java/com/fdkankan/base/config/Swagger2.java
  23. 107 0
      4dkankan-base/src/main/java/com/fdkankan/base/config/WebMvcConfig.java
  24. 11 0
      4dkankan-base/src/main/java/com/fdkankan/base/constant/AgentConstant.java
  25. 69 0
      4dkankan-base/src/main/java/com/fdkankan/base/constant/AppConstant.java
  26. 33 0
      4dkankan-base/src/main/java/com/fdkankan/base/constant/CameraConstant.java
  27. 68 0
      4dkankan-base/src/main/java/com/fdkankan/base/constant/LoginConstant.java
  28. 90 0
      4dkankan-base/src/main/java/com/fdkankan/base/constant/SceneConstant.java
  29. 71 0
      4dkankan-base/src/main/java/com/fdkankan/base/entity/BaseEntity.java
  30. 99 0
      4dkankan-base/src/main/java/com/fdkankan/base/entity/LogEntity.java
  31. 57 0
      4dkankan-base/src/main/java/com/fdkankan/base/interceptor/BodyReaderHttpServletRequestWrapper.java
  32. 47 0
      4dkankan-base/src/main/java/com/fdkankan/base/interceptor/CommonInterceptor.java
  33. 9 0
      4dkankan-base/src/main/java/com/fdkankan/base/mapper/ILogMapper.java
  34. 15 0
      4dkankan-base/src/main/java/com/fdkankan/base/mapper/base/IBaseMapper.java
  35. 64 0
      4dkankan-base/src/main/java/com/fdkankan/base/mq/ModelingMsgProducer.java
  36. 112 0
      4dkankan-base/src/main/java/com/fdkankan/base/mq/RabbitConfig.java
  37. 7340 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/BigSceneProto.java
  38. 4654 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/Common.java
  39. 4345 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/Visionmodeldata.java
  40. 156 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/format/CouchDBFormat.java
  41. 703 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/format/HtmlFormat.java
  42. 1338 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/format/JavaPropsFormat.java
  43. 1603 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/format/JsonFormat.java
  44. 602 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/format/SmileFormat.java
  45. 1333 0
      4dkankan-base/src/main/java/com/fdkankan/base/proto/format/XmlFormat.java
  46. 47 0
      4dkankan-base/src/main/java/com/fdkankan/base/service/IBaseService.java
  47. 6 0
      4dkankan-base/src/main/java/com/fdkankan/base/service/ILogService.java
  48. 156 0
      4dkankan-base/src/main/java/com/fdkankan/base/service/impl/BaseServiceImpl.java
  49. 123 0
      4dkankan-base/src/main/java/com/fdkankan/base/service/impl/FileService.java
  50. 22 0
      4dkankan-base/src/main/java/com/fdkankan/base/service/impl/LogServiceImpl.java
  51. 95 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/AesUtil.java
  52. 220 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/ConvertCommonUtils.java
  53. 220 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/ConvertUtils.java
  54. 98 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/CookieUtil.java
  55. 133 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/FileMd5Util.java
  56. 141 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/FileSizeUtil.java
  57. 134 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/FileUpload.java
  58. 263 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/FileUtil.java
  59. 115 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/HttpHelper.java
  60. 90 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/MD5.java
  61. 465 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/RSAEncrypt.java
  62. 215 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/SnowFlakeUUidUtils.java
  63. 135 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/SnowflakeIdGenerator.java
  64. 230 0
      4dkankan-base/src/main/java/com/fdkankan/base/util/ZipUtil.java
  65. 283 0
      4dkankan-common/pom.xml
  66. 143 0
      4dkankan-common/src/main/java/com/fdkankan/common/api/BaseController.java
  67. 41 0
      4dkankan-common/src/main/java/com/fdkankan/common/api/ModifyHttpServletRequestWrapper.java
  68. 14 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/Constant.java
  69. 28 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantCmd.java
  70. 94 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantExcel.java
  71. 20 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantFileName.java
  72. 17 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantFilePath.java
  73. 11 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantRegex.java
  74. 9 0
      4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantUrl.java
  75. 35 0
      4dkankan-common/src/main/java/com/fdkankan/common/exception/BaseRuntimeException.java
  76. 46 0
      4dkankan-common/src/main/java/com/fdkankan/common/exception/GlobalExceptionHandler.java
  77. 101 0
      4dkankan-common/src/main/java/com/fdkankan/common/model/Result.java
  78. 23 0
      4dkankan-common/src/main/java/com/fdkankan/common/model/SSOUser.java
  79. 199 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/AndroidNotification.java
  80. 6 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/App.java
  81. 304 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/Demo.java
  82. 95 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/IOSNotification.java
  83. 103 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/PushClient.java
  84. 86 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/UmengNotification.java
  85. 11 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidBroadcast.java
  86. 22 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidCustomizedcast.java
  87. 15 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidFilecast.java
  88. 16 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidGroupcast.java
  89. 16 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidUnicast.java
  90. 12 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSBroadcast.java
  91. 23 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSCustomizedcast.java
  92. 15 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSFilecast.java
  93. 16 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSGroupcast.java
  94. 15 0
      4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSUnicast.java
  95. 83 0
      4dkankan-common/src/main/java/com/fdkankan/common/util/Base64Converter.java
  96. 47 0
      4dkankan-common/src/main/java/com/fdkankan/common/util/DateEditor.java
  97. 404 0
      4dkankan-common/src/main/java/com/fdkankan/common/util/DateUtil.java
  98. 958 0
      4dkankan-common/src/main/java/com/fdkankan/common/util/FileUtils.java
  99. 405 0
      4dkankan-common/src/main/java/com/fdkankan/common/util/HttpRequestorUtil.java
  100. 0 0
      4dkankan-common/src/main/java/com/fdkankan/common/util/JwtUtil.java

+ 138 - 0
4dkankan-application/pom.xml

@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-application</artifactId>
+    <version>1.0.0</version>
+    <packaging>war</packaging>
+    <repositories>
+        <repository>
+            <id>nexus-aliyun</id>
+            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
+        </repository>
+    </repositories>
+
+    <name>4dkankan-application</name>
+    <description>程序入口</description>
+
+    <parent>
+        <groupId>com.fdkankan</groupId>
+        <artifactId>4dkankan_hd</artifactId>
+        <version>1.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.fdkankan</groupId>
+            <artifactId>4dkankan-base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fdkankan</groupId>
+            <artifactId>4dkankan-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fdkankan</groupId>
+            <artifactId>4dkankan-web</artifactId>
+        </dependency>
+
+        <!--<dependency>-->
+            <!--<groupId>com.fdkankan</groupId>-->
+            <!--<artifactId>4dkankan-modeling</artifactId>-->
+        <!--</dependency>-->
+
+
+        <dependency>
+            <groupId>com.fdkankan</groupId>
+            <artifactId>4dkankan-scene</artifactId>
+        </dependency>
+
+        <!-- spring boot -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <!--<exclusions>-->
+                <!--<exclusion>-->
+                    <!--<groupId>org.springframework.boot</groupId>-->
+                    <!--<artifactId>spring-boot-starter-tomcat</artifactId>-->
+                <!--</exclusion>-->
+            <!--</exclusions>-->
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <!-- mysql -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>tk.mybatis</groupId>
+            <artifactId>mapper-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>4dkankan_hd</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <!-- 指定该Main Class为全局的唯一入口 -->
+                    <mainClass>com.fdkankan.App</mainClass>
+                    <fork>true</fork>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 37 - 0
4dkankan-application/src/main/java/com/fdkankan/App.java

@@ -0,0 +1,37 @@
+package com.fdkankan;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@EnableFeignClients
+@EnableDiscoveryClient
+@SpringBootApplication
+@EnableCaching
+@EnableScheduling
+@EnableAsync
+//@RestController
+@ComponentScan(basePackages = {"com.oxing.mall","com.oxing.blog"})
+public class App extends SpringBootServletInitializer {
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        return application.sources(App.class);
+    }
+
+    public static void main(String[] args) {
+        SpringApplication.run(App.class, args);
+    }
+}

+ 95 - 0
4dkankan-application/src/main/resources/application-dev.properties

@@ -0,0 +1,95 @@
+#应用名
+spring.application.name=4dkankan-scene
+#注册中心
+spring.cloud.nacos.discovery.server-addr=192.168.0.98:8848
+
+#DB (new)
+spring.datasource.primary.url=jdbc:mysql://localhost:3306/4dkankan_hd?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.primary.username=root
+spring.datasource.primary.password=123456
+spring.datasource.primary.driverClassName=com.mysql.jdbc.Driver
+
+spring.servlet.multipart.max-file-size=500MB
+spring.servlet.multipart.max-request-size=1000MB
+spring.servlet.multipart.enabled=true
+spring.servlet.multipart.location=/mnt/data/
+#redis
+spring.redis.cluster.nodes=10.1.152.54:6379
+spring.redis.database=0
+spring.redis.password=
+spring.redis.timeout=3000ms
+spring.redis.jedis.pool.max-idle=8
+spring.redis.jedis.pool.min-idle=0
+spring.redis.jedis.pool.max-active=8
+spring.redis.jedis.pool.max-wait=-1ms
+# file route
+file.route.hardDisk=/mnt/data/
+file.route.imageFolder=IMAGE
+file.route.documentFolder=VIDEO
+file.route.videoFolder=DOCUMENT
+file.route.musicFolder=MUSIC
+file.route.imageType=[".bmp", ".jpg", ".jpeg", ".png", ".tiff", ".gif", ".pcx", ".tga", ".exif", ".fpx", ".svg", ".psd",".cdr", ".pcd", ".dxf", ".ufo", ".eps", ".ai", ".raw", ".wmf"]
+file.route.documentType=[".txt", ".doc", ".docx", ".xls", ".htm", ".html", ".jsp", ".rtf", ".wpd", ".pdf", ".ppt",".js"]
+file.route.videoType=[".mp4", ".avi", ".mov", ".wmv", ".asf", ".navi", ".3gp", ".mkv", ".f4v", ".rmvb", ".webm"]
+file.route.musicType=[".mp3", ".wma", ".wav", ".mod", ".ra", ".cd", ".md", ".asf", ".aac", ".vqf", ".ape", ".mid", ".ogg",".m4a", ".vqf"]
+file.route.IPs=["0:0:0:0:0:0:0:1","192.168.0.100"]
+#swagger
+swagger.basePackage=com.fdkankan.web.controller
+swagger.title=四维看看2.0单机版
+swagger.description=api文档
+swagger.serviceUrl=http://39.108.220.65:8080
+swagger.version=2.0
+#rabbitmq
+#spring.rabbitmq.host=8.135.98.231
+#spring.rabbitmq.port=30672
+spring.rabbitmq.address=8.135.98.231:30672
+spring.rabbitmq.username=root
+spring.rabbitmq.password=root
+spring.rabbitmq.virtual-host=/
+spring.rabbitmq.connection-timeout=15000
+#confirm模式
+spring.rabbitmq.publisher-confirms=true
+#return机制
+spring.rabbitmq.publisher-returns=true
+#与return机制结合配置次属性
+spring.rabbitmq.template.mandatory=true
+
+spring.mvc.static-path-pattern=/**
+spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/, classpath:/web/, file:${server.file.location}
+
+oss.point=http://oss-cn-shenzhen-internal.aliyuncs.com
+oss.key=LTAIUrvuHqj8pvry
+oss.secrey=JLOVl0k8Ke0aaM8nLMMiUAZ3EiiqI4
+oss.bucket=oss-xiaoan
+oss.type=oss
+
+main.url=https://test.4dkankan.com/
+main.intranet.url=https://test.4dkankan.com/
+scene.url=show.html?m=
+scene.pro.url=showProMobile.html?m=
+scene.pro.new.url=smobile.html?m=
+
+prefix.ali=https://4dkk.4dage.com/
+
+#服务器环境,dev为测试环境,formal为正式环境
+environment=dev
+
+#mq的任务key
+rabbitmq.queue=QUEUE_MODELING_A
+#mq当排队任务超过这个数量时启用弹性升缩
+mq.base.num=300
+#弹性伸缩组id
+scaling.group.id=asg-wz92989gdhgek3ktdlsw
+#弹性伸缩规则id
+scaling.rule.ari=ari:acs:ess:cn-shenzhen:1899912233141089:scalingrule/asr-wz97gv4s2nod1cxznynx
+
+#服务器类型,aliyun或hqyun
+ecs.type=aliyun
+
+knife4j.basic.enable=true
+knife4j.basic.username=apiadmin
+knife4j.basic.password=fdkankancui
+
+
+
+

+ 95 - 0
4dkankan-application/src/main/resources/application-pro.properties

@@ -0,0 +1,95 @@
+#应用名
+spring.application.name=4dkankan-scene
+#注册中心
+spring.cloud.nacos.discovery.server-addr=10.71.9.205:80
+
+#DB (new)
+spring.datasource.primary.url=jdbc:mysql://10.71.188.241:3306/db_4dkankan?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.primary.username=user_4dkankan_rw
+spring.datasource.primary.password=AE1ksBti1goH8f4zVbPj
+spring.datasource.primary.driverClassName=com.mysql.jdbc.Driver
+
+spring.servlet.multipart.max-file-size=500MB
+spring.servlet.multipart.max-request-size=1000MB
+spring.servlet.multipart.enabled=true
+spring.servlet.multipart.location=/mnt/data/
+#redis
+spring.redis.cluster.nodes=10.71.188.181:7000,10.71.188.108:7000,10.71.188.113:7000,10.71.188.206:7000,10.71.188.238:7000,10.71.188.148:7000
+spring.redis.database=0
+spring.redis.password=m8P6JugfYevMBi8bUnlu
+spring.redis.timeout=3000ms
+spring.redis.jedis.pool.max-idle=8
+spring.redis.jedis.pool.min-idle=0
+spring.redis.jedis.pool.max-active=8
+spring.redis.jedis.pool.max-wait=-1ms
+# file route
+file.route.hardDisk=/mnt/data/
+file.route.imageFolder=IMAGE
+file.route.documentFolder=VIDEO
+file.route.videoFolder=DOCUMENT
+file.route.musicFolder=MUSIC
+file.route.imageType=[".bmp", ".jpg", ".jpeg", ".png", ".tiff", ".gif", ".pcx", ".tga", ".exif", ".fpx", ".svg", ".psd",".cdr", ".pcd", ".dxf", ".ufo", ".eps", ".ai", ".raw", ".wmf"]
+file.route.documentType=[".txt", ".doc", ".docx", ".xls", ".htm", ".html", ".jsp", ".rtf", ".wpd", ".pdf", ".ppt",".js"]
+file.route.videoType=[".mp4", ".avi", ".mov", ".wmv", ".asf", ".navi", ".3gp", ".mkv", ".f4v", ".rmvb", ".webm"]
+file.route.musicType=[".mp3", ".wma", ".wav", ".mod", ".ra", ".cd", ".md", ".asf", ".aac", ".vqf", ".ape", ".mid", ".ogg",".m4a", ".vqf"]
+file.route.IPs=["0:0:0:0:0:0:0:1","192.168.0.100"]
+#swagger
+swagger.basePackage=com.fdkankan.web.controller
+swagger.title=四维看看2.0单机版
+swagger.description=api文档
+swagger.serviceUrl=http://39.108.220.65:8080
+swagger.version=2.0
+#rabbitmq
+#spring.rabbitmq.host=8.135.98.231
+#spring.rabbitmq.port=30672
+spring.rabbitmq.address=10.71.9.204:5672,10.71.9.203:5672
+spring.rabbitmq.username=admin
+spring.rabbitmq.password=fcb@admin_4dage
+spring.rabbitmq.virtual-host=/
+spring.rabbitmq.connection-timeout=15000
+#confirm模式
+spring.rabbitmq.publisher-confirms=true
+#return机制
+spring.rabbitmq.publisher-returns=true
+#与return机制结合配置次属性
+spring.rabbitmq.template.mandatory=true
+
+spring.mvc.static-path-pattern=/**
+spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/, classpath:/web/, file:${server.file.location}
+
+oss.point=http://oss-cn-shenzhen-internal.aliyuncs.com
+oss.key=LTAI4G132z2c589AN39YTvub
+oss.secrey=TokcDacRasG8hqbl6ynfaiNTZ97XhO
+oss.bucket=fcb-vrkanfang-prd
+oss.type=oss
+
+main.url=https://vr-web01.fcb.com.cn/
+main.intranet.url=https://vr-mc01.fcb.com.cn/
+scene.url=show.html?m=
+scene.pro.url=showProMobile.html?m=
+scene.pro.new.url=smobile.html?m=
+
+prefix.ali=https://vr-oss01.fcb.com.cn/
+
+#服务器环境,dev为测试环境,formal为正式环境
+environment=dev
+
+#mq的任务key
+rabbitmq.queue=QUEUE_MODELING_A
+#mq当排队任务超过这个数量时启用弹性升缩
+mq.base.num=0
+#弹性伸缩组id
+scaling.group.id=asg-wz97mug9t0pfgsjiuphr
+#弹性伸缩规则id
+scaling.rule.ari=ari:acs:ess:cn-shenzhen:1899912233141089:scalingrule/asr-wz96ed9xxytsxzmi2x5h
+
+#服务器类型,aliyun或hqyun
+ecs.type=aliyun
+
+knife4j.basic.enable=true
+knife4j.basic.username=apiadmin
+knife4j.basic.password=fdkankancui
+
+
+
+

+ 95 - 0
4dkankan-application/src/main/resources/application-test.properties

@@ -0,0 +1,95 @@
+#应用名
+spring.application.name=4dkankan-scene
+#注册中心
+spring.cloud.nacos.discovery.server-addr=10.71.5.163:80
+
+#DB (new)
+spring.datasource.primary.url=jdbc:mysql://10.71.184.146:3306/db_4dkankan?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.primary.username=user_4dkankan_rw
+spring.datasource.primary.password=y2b9a42wRwGNKkJjCm1o
+spring.datasource.primary.driverClassName=com.mysql.jdbc.Driver
+
+spring.servlet.multipart.max-file-size=500MB
+spring.servlet.multipart.max-request-size=1000MB
+spring.servlet.multipart.enabled=true
+spring.servlet.multipart.location=/mnt/data/
+#redis
+spring.redis.cluster.nodes=10.71.184.237:7000,10.71.184.181:7000,10.71.184.217:7000,10.71.184.188:7000,10.71.184.222:7000,10.71.184.200:7000
+spring.redis.database=0
+spring.redis.password=QBzhHTxfcYLTs0n5J5VQ
+spring.redis.timeout=3000ms
+spring.redis.jedis.pool.max-idle=8
+spring.redis.jedis.pool.min-idle=0
+spring.redis.jedis.pool.max-active=8
+spring.redis.jedis.pool.max-wait=-1ms
+# file route
+file.route.hardDisk=/mnt/data/
+file.route.imageFolder=IMAGE
+file.route.documentFolder=VIDEO
+file.route.videoFolder=DOCUMENT
+file.route.musicFolder=MUSIC
+file.route.imageType=[".bmp", ".jpg", ".jpeg", ".png", ".tiff", ".gif", ".pcx", ".tga", ".exif", ".fpx", ".svg", ".psd",".cdr", ".pcd", ".dxf", ".ufo", ".eps", ".ai", ".raw", ".wmf"]
+file.route.documentType=[".txt", ".doc", ".docx", ".xls", ".htm", ".html", ".jsp", ".rtf", ".wpd", ".pdf", ".ppt",".js"]
+file.route.videoType=[".mp4", ".avi", ".mov", ".wmv", ".asf", ".navi", ".3gp", ".mkv", ".f4v", ".rmvb", ".webm"]
+file.route.musicType=[".mp3", ".wma", ".wav", ".mod", ".ra", ".cd", ".md", ".asf", ".aac", ".vqf", ".ape", ".mid", ".ogg",".m4a", ".vqf"]
+file.route.IPs=["0:0:0:0:0:0:0:1","192.168.0.100"]
+#swagger
+swagger.basePackage=com.fdkankan.web.controller
+swagger.title=四维看看2.0单机版
+swagger.description=api文档
+swagger.serviceUrl=http://39.108.220.65:8080
+swagger.version=2.0
+#rabbitmq
+#spring.rabbitmq.host=8.135.98.231
+#spring.rabbitmq.port=30672
+spring.rabbitmq.address=10.71.5.163:5672,10.71.5.164:5672
+spring.rabbitmq.username=admin
+spring.rabbitmq.password=fcb@admin_4dage
+spring.rabbitmq.virtual-host=/
+spring.rabbitmq.connection-timeout=15000
+#confirm模式
+spring.rabbitmq.publisher-confirms=true
+#return机制
+spring.rabbitmq.publisher-returns=true
+#与return机制结合配置次属性
+spring.rabbitmq.template.mandatory=true
+
+spring.mvc.static-path-pattern=/**
+spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/, classpath:/web/, file:${server.file.location}
+
+oss.point=http://oss-cn-shenzhen-internal.aliyuncs.com
+oss.key=LTAI4FyDDFpGGjTJZEQH4yaK
+oss.secrey=mqVRTWbWcn4sNMoWmnRq6eToWr9BIy
+oss.bucket=fcb-vrkanfang-uat
+oss.type=oss
+
+main.url=https://vr-web01-uat-fcb.com.cn/
+main.intranet.url=https://vr-mc01-uat-fcb.com/
+scene.url=show.html?m=
+scene.pro.url=showProMobile.html?m=
+scene.pro.new.url=smobile.html?m=
+
+prefix.ali=https://fcb-vrkanfang-uat.os-cn-shenzhen.aliyuncs.com/
+
+#服务器环境,dev为测试环境,formal为正式环境
+environment=dev
+
+#mq的任务key
+rabbitmq.queue=QUEUE_MODELING_A
+#mq当排队任务超过这个数量时启用弹性升缩
+mq.base.num=300
+#弹性伸缩组id
+scaling.group.id=asg-wz92989gdhgek3ktdlsw
+#弹性伸缩规则id
+scaling.rule.ari=ari:acs:ess:cn-shenzhen:1899912233141089:scalingrule/asr-wz97gv4s2nod1cxznynx
+
+#服务器类型,aliyun或hqyun
+ecs.type=aliyun
+
+knife4j.basic.enable=true
+knife4j.basic.username=apiadmin
+knife4j.basic.password=fdkankancui
+
+
+
+

+ 36 - 0
4dkankan-application/src/main/resources/application.properties

@@ -0,0 +1,36 @@
+server.port=8010
+server.servlet.context-path=/4dkankan_v2
+server.file.location=/mnt/4Dkankan/
+
+spring.profiles.active=dev
+
+spring.mvc.async.request-timeout=1800000
+
+#log
+logging.path=/4Dkankan/logs/
+logging.config=classpath:logback-spring.xml
+logging.level.com.fdkankan=debug
+#mybatis
+mybatis.mapper-locations=classpath:mapper/*.xml
+mybatis.type-aliases-package=com.fdkankan.*.mapper
+mybatis.configuration.mapUnderscoreToCamelCase=true
+mapper.identity=MYSQL
+mapper.mappers=tk.mybatis.mapper.common.Mapper
+#pager
+pagehelper.helper-dialect=mysql
+pagehelper.params=count=countSql
+pagehelper.reasonable=false
+pagehelper.support-methods-arguments=true
+
+spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+spring.jackson.time-zone=GMT+8
+
+server.tomcat.uri-encoding=UTF-8
+spring.http.encoding.charset=UTF-8
+spring.http.encoding.enabled=true
+spring.http.encoding.force=true
+
+
+
+
+

+ 16 - 0
4dkankan-application/src/main/resources/key/private_pkcs8.pem

@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAOScGE5AR1jixcGo
+HZMd0kySDk4BQarT1rbYTdXFKXmjn5cXnqGFEfCWnD+bSdLi7fyZdrPso8HjMELo
+vPhBdGmcLwSv74/OT8LnXb1nBZV0uvNe8euFLO3VSUJbOi05z4uTBLsiIJRIpMsU
+j43UpEmgVQvTtmDV23ddhbFMJKUxAgMBAAECgYEAjA6R2YcJ7wvn6jAsBlCz4ZNt
+zh5488aa+iRk8z26njo/cNrYpc4X4pTzHwjtXpUHBsWicrLc1NFyZNufwlyfi1eK
+AaoNC2dHghapmahzCdKRbozVA0+1zsGsUPCNXwPM58YHUtax+nSem1gQJME5+XAA
+A3B1HZSswmiYd6KkBm0CQQD+L1TpsIBpGFWAwvznfHymvifYRzSZzY+Jw110vpt2
+rgPCi77emlBqUsZ5q0VLYaqwuNUjcQp4DB2Ur+7+E7+7AkEA5j4CkmYsb4iIgPiQ
+urmpHrYmIfl8/U6pEaENPDyqzkhyD2IfRh1AqFQfTZzCYlzG7QzzNYY2VCeWMbam
+PMbSAwJBAIW7AUGxyt2AH/wOmmBv7mULxorTa6k/rTUdxB2X6tMV2oSQYWtcZNKL
+mkCJC3wNdnBjzj9HSeq+9RE1PtgOK+ECQQDO4v+an1bkbbIC+dfLAZN29kOzmaR3
+VRxUq/vhmb39mFlte0UQ0q5L0zNBoU+F5UoWreFIwi3FVsD+MNqVmC4TAkEArOZg
+qpGu5SgVNcZKQy0KdBQZoYafD9px+UY0KOo9n08l89DiW63YjrZfcOAf68CBV43R
+t+NFRAUK59TFqvNF6w==
+-----END PRIVATE KEY-----

+ 6 - 0
4dkankan-application/src/main/resources/key/public.pem

@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDknBhOQEdY4sXBqB2THdJMkg5O
+AUGq09a22E3VxSl5o5+XF56hhRHwlpw/m0nS4u38mXaz7KPB4zBC6Lz4QXRpnC8E
+r++Pzk/C5129ZwWVdLrzXvHrhSzt1UlCWzotOc+LkwS7IiCUSKTLFI+N1KRJoFUL
+07Zg1dt3XYWxTCSlMQIDAQAB
+-----END PUBLIC KEY-----

+ 156 - 0
4dkankan-application/src/main/resources/logback-spring.xml

@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <property name="LOG_MAX_HISTORY" value="180"/>
+    <springProperty scope="context" name="LOG_PATH" source="logging.path"/>
+
+    <!-- 控制台输出 -->
+    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
+            <pattern>${LOG_PATH}/%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+    <!-- 按照每天生成日志文件:主项目日志 -->
+    <appender name="file.all" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 追加日志到原文件结尾 -->
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 -->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{500} - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+    <!--info日志统一输出到这里-->
+    <appender name="file.info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 每小时生成日志文件 -->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/info/console-info.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!--错误日志统一输出到这里-->
+    <appender name="file.error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/error/console-error.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录error级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!--warn日志统一输出到这里-->
+    <appender name="file.warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 按小时生成日志-->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/warn/console-warn.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>WARN</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!--debug级别日志统一输出到这里-->
+    <appender name="file.debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 按小时生成日志-->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/debug/console-debug.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <!-- 除按日志记录之外,还配置了日志文件不能超过5M,若超过5M,日志文件会以索引0开始,命名日志文件,例如console-debug.2018-08-24-09.1.log -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>DEBUG</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY </onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
+    <appender name="file.async" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <includeCallerData>true</includeCallerData>
+        <appender-ref ref="file.all" />
+    </appender>
+
+    <!--  日志输出级别 -->
+    <!-- TRACE\DEBUG\INFO\WARN\ERROR\FATAL\OFF -->
+    <root level="INFO">
+        <appender-ref ref="console" />
+        <appender-ref ref="file.async"/>
+        <appender-ref ref="file.error" />
+        <appender-ref ref="file.info" />
+        <appender-ref ref="file.debug" />
+        <appender-ref ref="file.warn" />
+    </root>
+
+</configuration>

+ 1 - 0
4dkankan-application/src/main/resources/static/MP_verify_i9CLaVAyYoDvylKB.txt

@@ -0,0 +1 @@
+i9CLaVAyYoDvylKB

+ 9 - 0
4dkankan-application/src/main/resources/static/apppro.html

@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+    <head>
+    <title>1</title>
+    </head>
+    <body >
+        4dage,app部门文件,请勿删除
+    </body>
+</html>

BIN
4dkankan-application/src/main/resources/static/img/logo.jpg


BIN
4dkankan-application/src/main/resources/static/img/logo.png


Різницю між файлами не показано, бо вона завелика
+ 12 - 0
4dkankan-application/src/main/resources/static/refreshToken.json


Різницю між файлами не показано, бо вона завелика
+ 1125 - 0
4dkankan-application/src/main/resources/static/txt/SensitiveWord.txt


+ 39 - 0
4dkankan-application/src/test/java/com/fdkankan/ModelingTest.java

@@ -0,0 +1,39 @@
+package com.fdkankan;
+
+import com.fdkankan.base.mq.ModelingMsgProducer;
+import com.fdkankan.scene.entity.OpenBuildEntity;
+import com.fdkankan.scene.service.IOpenBuildService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = App.class)
+public class ModelingTest {
+
+    @Autowired
+    private IOpenBuildService openBuildService;
+
+    @Autowired
+    private ModelingMsgProducer workSend;
+
+    @Test
+    public void send() throws Exception {
+        for (int i = 0; i < 15; i++){
+            workSend.sendMsg(String.valueOf(i));
+        }
+    }
+
+    /**
+     * 获取对应队列的数量;
+     *
+     * @return
+     */
+    @Test
+    public void getMessageCount() {
+        System.out.println(workSend.getMessageCount());
+    }
+
+}

+ 217 - 0
4dkankan-base/pom.xml

@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.fdkankan</groupId>
+    <artifactId>4dkankan-base</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+    <repositories>
+        <repository>
+            <id>nexus-aliyun</id>
+            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
+        </repository>
+    </repositories>
+
+    <name>4dkankan-base</name>
+    <description>4dkankan base</description>
+
+    <parent>
+        <groupId>com.fdkankan</groupId>
+        <artifactId>4dkankan_hd</artifactId>
+        <version>1.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.fdkankan</groupId>
+            <artifactId>4dkankan-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.penggle</groupId>
+            <artifactId>kaptcha</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+
+        <!--阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <!--<artifactId>druid-spring-boot-starter</artifactId>-->
+            <artifactId>druid</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>tk.mybatis</groupId>
+            <artifactId>mapper-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-orm</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.protobuf-java-format</groupId>
+            <artifactId>protobuf-java-format</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>ant</groupId>
+            <artifactId>ant</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+        </dependency>
+
+        <!-- knife4j aip 包-->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-spring-boot-starter</artifactId>
+            <version>2.0.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+        <!--<dependency>-->
+            <!--<groupId>org.springframework.amqp</groupId>-->
+            <!--<artifactId>spring-amqp</artifactId>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.11</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>2.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-smile</artifactId>
+            <version>1.9.12</version>
+        </dependency>
+
+    </dependencies>
+
+    <distributionManagement>
+        <repository>
+            <!-- 这里的ID要和setting的id一致 -->
+            <id>releases</id>
+            <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/releases/</url>
+        </repository>
+        <!--这是打成快照版本的配置 -->
+        <snapshotRepository>
+            <id>snapshots</id>
+            <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/snapshots/</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+            <resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.xml</include>
+                </includes>
+            </resource>
+        </resources>
+    </build>
+
+</project>

+ 24 - 0
4dkankan-base/src/main/java/com/fdkankan/base/config/DataSourceConfig.java

@@ -0,0 +1,24 @@
+package com.fdkankan.base.config;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import javax.sql.DataSource;
+
+
+@Configuration
+public class DataSourceConfig {
+
+    @Primary
+    @Bean(name = "primaryDataSource")
+    @Qualifier("primaryDataSource")
+    @ConfigurationProperties(prefix="spring.datasource.primary")
+    public DataSource primaryDataSource() {
+        DataSource dataSource = new com.alibaba.druid.pool.DruidDataSource();
+        return dataSource;
+    }
+
+}

+ 98 - 0
4dkankan-base/src/main/java/com/fdkankan/base/config/FileRouteConfig.java

@@ -0,0 +1,98 @@
+package com.fdkankan.base.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+
+@Component
+@ConfigurationProperties(prefix = "file.route")
+public class FileRouteConfig {
+    /**
+     * 路径
+     */
+    //保存硬盘地址
+    private String hardDisk;
+    //默认图片类型文件夹
+    private String imageFolder;
+    //默认文件类型文件夹
+    private String documentFolder;
+    //默认的视频类型文件夹
+    private String videoFolder;
+    //默认的音频类型文件夹
+    private String musicFolder;
+    //允许上传的ip(上传白名单)
+    private String[] IPs;
+    /**
+     * 类型
+     */
+    //图片类型
+    private String[] imageType;
+    //文件类型
+    private String[] documentType;
+    //视频类型
+    private String[] videoType;
+    //音频类型
+    private String[] musicType;
+	public String getHardDisk() {
+		return hardDisk;
+	}
+	public String getImageFolder() {
+		return imageFolder;
+	}
+	public String getDocumentFolder() {
+		return documentFolder;
+	}
+	public String getVideoFolder() {
+		return videoFolder;
+	}
+	public String getMusicFolder() {
+		return musicFolder;
+	}
+	public String[] getIPs() {
+		return IPs;
+	}
+	public String[] getImageType() {
+		return imageType;
+	}
+	public String[] getDocumentType() {
+		return documentType;
+	}
+	public String[] getVideoType() {
+		return videoType;
+	}
+	public String[] getMusicType() {
+		return musicType;
+	}
+	public void setHardDisk(String hardDisk) {
+		this.hardDisk = hardDisk;
+	}
+	public void setImageFolder(String imageFolder) {
+		this.imageFolder = imageFolder;
+	}
+	public void setDocumentFolder(String documentFolder) {
+		this.documentFolder = documentFolder;
+	}
+	public void setVideoFolder(String videoFolder) {
+		this.videoFolder = videoFolder;
+	}
+	public void setMusicFolder(String musicFolder) {
+		this.musicFolder = musicFolder;
+	}
+	public void setIPs(String[] iPs) {
+		IPs = iPs;
+	}
+	public void setImageType(String[] imageType) {
+		this.imageType = imageType;
+	}
+	public void setDocumentType(String[] documentType) {
+		this.documentType = documentType;
+	}
+	public void setVideoType(String[] videoType) {
+		this.videoType = videoType;
+	}
+	public void setMusicType(String[] musicType) {
+		this.musicType = musicType;
+	}
+    
+    
+}

+ 31 - 0
4dkankan-base/src/main/java/com/fdkankan/base/config/MyNacosLifecycle.java

@@ -0,0 +1,31 @@
+package com.fdkankan.base.config;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.registry.NacosAutoServiceRegistration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+/**
+ * Created by Hb_zzZ on 2021/1/11.
+ */
+@Configuration
+public class MyNacosLifecycle implements ApplicationContextAware {
+
+    @Autowired(required = false)
+    private NacosAutoServiceRegistration registration;
+
+    @Autowired
+    private Environment environment;
+
+    @Override
+    public void setApplicationContext(ApplicationContext context) throws BeansException {
+        if (registration != null) {
+            String port = environment.getProperty("server.port");
+            registration.setPort(Integer.parseInt(port));
+            registration.start();
+        }
+    }
+}

+ 46 - 0
4dkankan-base/src/main/java/com/fdkankan/base/config/PrimaryConfig.java

@@ -0,0 +1,46 @@
+package com.fdkankan.base.config;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import tk.mybatis.spring.annotation.MapperScan;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = PrimaryConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
+public class PrimaryConfig {
+
+    static final String PACKAGE = "com.fdkankan.base.mapper,com.fdkankan.scene.mapper";
+    static final String MAPPER_LOCATION = "classpath:mapper/*.xml";
+
+    @Autowired
+    @Qualifier("primaryDataSource")
+    private DataSource primaryDataSource;
+
+
+    @Bean(name = "masterTransactionManager")
+    @Primary
+    public DataSourceTransactionManager masterTransactionManager() {
+        return new DataSourceTransactionManager(primaryDataSource);
+    }
+
+    @Bean(name = "masterSqlSessionFactory")
+    @Primary
+    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource)
+            throws Exception {
+        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+        sessionFactory.setDataSource(primaryDataSource);
+//        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
+//                .getResources(PrimaryConfig.MAPPER_LOCATION));
+        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
+        return sessionFactory.getObject();
+    }
+
+}

+ 91 - 0
4dkankan-base/src/main/java/com/fdkankan/base/config/Swagger2.java

@@ -0,0 +1,91 @@
+package com.fdkankan.base.config;
+
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import com.google.common.collect.Lists;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.ApiKey;
+import springfox.documentation.service.AuthorizationScope;
+import springfox.documentation.service.SecurityReference;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by owen on 2020/2/18
+ *
+ * 集成Swagger有3步:
+ * 1.pom.xml添加依赖
+ * 2.添加Swagger2.class
+ * 3.Application.class 加上注解@EnableSwagger2 表示开启Swagger
+ * 4.http://localhost:8080/doc.html#/
+ *
+ * 2.9.2 不需要字启动类配置注解
+ */
+//@EnableKnife4j 开启动态响应值
+@Configuration
+@EnableSwagger2
+@EnableKnife4j
+public class Swagger2 {
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.fdkankan.web.controller"))
+                .paths(PathSelectors.any())
+                .build()
+                //添加登录认证,可以使用token
+                .securityContexts(securityContexts())
+                .securitySchemes(securitySchemes())
+                ;
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("四维看看")
+                .description("四维看看Api接口文档")
+                .version("1.0")
+                .build();
+    }
+
+    private List<ApiKey> securitySchemes() {
+        //设置请求头信息
+        List<ApiKey> result = new ArrayList<>();
+//        ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
+        ApiKey apiKey = new ApiKey("Authorization", "token", "header");
+        result.add(apiKey);
+        return result;
+
+    }
+
+
+    private List<SecurityContext> securityContexts() {
+
+        SecurityContext context = SecurityContext.builder()
+                .securityReferences(defaultAuth())
+                .build();
+
+        return Lists.newArrayList(context);
+
+    }
+
+    private List<SecurityReference> defaultAuth() {
+        List<SecurityReference> result = new ArrayList<>();
+        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+        authorizationScopes[0] = authorizationScope;
+        result.add(new SecurityReference("Authorization", authorizationScopes));
+        return result;
+    }
+}

+ 107 - 0
4dkankan-base/src/main/java/com/fdkankan/base/config/WebMvcConfig.java

@@ -0,0 +1,107 @@
+package com.fdkankan.base.config;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4;
+import com.fdkankan.base.interceptor.CommonInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Configuration
+public class WebMvcConfig extends WebMvcConfigurerAdapter {
+
+    @Autowired
+    private CommonInterceptor commonInterceptor;
+    /**
+     * fastJson相关设置
+     */
+    private FastJsonConfig getFastJsonConfig() {
+
+        FastJsonConfig fastJsonConfig = new FastJsonConfig();
+        // 在serializerFeatureList中添加转换规则
+        List<SerializerFeature> serializerFeatureList = new ArrayList<SerializerFeature>();
+        serializerFeatureList.add(SerializerFeature.PrettyFormat);
+        serializerFeatureList.add(SerializerFeature.WriteMapNullValue);
+        serializerFeatureList.add(SerializerFeature.WriteNullStringAsEmpty);
+        serializerFeatureList.add(SerializerFeature.WriteNullListAsEmpty);
+        serializerFeatureList.add(SerializerFeature.DisableCircularReferenceDetect);
+        SerializerFeature[] serializerFeatures = serializerFeatureList.toArray(new SerializerFeature[serializerFeatureList.size()]);
+        fastJsonConfig.setSerializerFeatures(serializerFeatures);
+        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
+        return fastJsonConfig;
+    }
+    /**
+     * fastJson相关设置
+     */
+    private FastJsonHttpMessageConverter4 fastJsonHttpMessageConverter() {
+
+        FastJsonHttpMessageConverter4 fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter4();
+
+        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
+        supportedMediaTypes.add(MediaType.parseMediaType("text/html;charset=UTF-8"));
+        supportedMediaTypes.add(MediaType.parseMediaType("application/json"));
+
+        fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
+        fastJsonHttpMessageConverter.setFastJsonConfig(getFastJsonConfig());
+
+        return fastJsonHttpMessageConverter;
+    }
+    /**
+     * 添加fastJsonHttpMessageConverter到converters
+     */
+    @Override
+    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
+        converters.add(fastJsonHttpMessageConverter());
+    }
+    /**
+     * 添加拦截器
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(commonInterceptor).addPathPatterns("/**");
+//        registry.addInterceptor(userPermissionInterceptor).addPathPatterns("/api/user/**", "/api/scene/edit/**", "/api/device/**");
+    }
+
+    /*@Bean
+    public FilterRegistrationBean registFilter() {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new OpenSessionInViewFilter());
+        registration.addUrlPatterns("/*");
+        registration.setOrder(1);
+        return registration;
+    }*/
+
+    @Override
+    public void addViewControllers(ViewControllerRegistry registry ) {
+        registry.addViewController("/" ).setViewName( "forward:/index.html" );
+        registry.setOrder(Ordered.HIGHEST_PRECEDENCE );
+        super.addViewControllers(registry);
+    }
+
+//    @Override
+//    public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
+//        configurer.setDefaultTimeout(300000);
+//        configurer.registerCallableInterceptors(timeoutInterceptor());
+//    }
+//
+//    @Bean
+//    public TimeoutCallableProcessingInterceptor timeoutInterceptor() {
+//        return new TimeoutCallableProcessingInterceptor();
+//    }
+
+    /*@Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("*")
+                .allowCredentials(true)
+                .allowedMethods("GET", "POST", "DELETE", "PUT")
+                .maxAge(3600);
+    }*/
+}

+ 11 - 0
4dkankan-base/src/main/java/com/fdkankan/base/constant/AgentConstant.java

@@ -0,0 +1,11 @@
+package com.fdkankan.base.constant;
+
+public class AgentConstant {
+
+    public static final String CHILD_PASSWORD_VALUE = "4dkankan@4dage";
+
+    public static final String WIFI_PASSWORD_VALUE = "12345678";
+
+
+    public static final String DEFAULT_AGENT = "4dage";
+}

+ 69 - 0
4dkankan-base/src/main/java/com/fdkankan/base/constant/AppConstant.java

@@ -0,0 +1,69 @@
+package com.fdkankan.base.constant;
+
+// 4001-5000 App状态码
+public class AppConstant {
+
+    public static final String APP_USER_NAME = "APP_USER_NAME";
+
+    public static final int SUCCESS_CODE = 0;
+
+    public static final int FAILURE_CODE_4001 = 4001;
+    public static final String FAILURE_MSG_4001 = "验证码超时";
+
+    public static final int FAILURE_CODE_4002 = 4002;
+    public static final String FAILURE_MSG_4002 = "用户已经存在";
+
+    public static final int FAILURE_CODE_4003 = 4003;
+    public static final String FAILURE_MSG_4003 = "手机号已经被注册";
+
+    public static final int FAILURE_CODE_4004 = 4004;
+    public static final String FAILURE_MSG_4004 = "两次输入的密码不正确";
+
+    public static final int FAILURE_CODE_4005 = 4005;
+    public static final String FAILURE_MSG_4005 = "手机号与验证码不匹配";
+
+    public static final int FAILURE_CODE_4006 = 4006;
+    public static final String FAILURE_MSG_4006 = "验证码错误";
+
+    public static final int FAILURE_CODE_4007 = 4007;
+    public static final String FAILURE_MSG_4007 = "用户名不存在";
+
+    public static final int FAILURE_CODE_4008 = 4008;
+    public static final String FAILURE_MSG_4008 = "用户尚未登录";
+
+    public static final int FAILURE_CODE_4009 = 4009;
+    public static final String FAILURE_MSG_4009 = "异常错误";
+
+    public static final int FAILURE_CODE_4010 = 4010;
+    public static final String FAILURE_MSG_4010 = "绑定的相机不存在";
+
+    public static final int FAILURE_CODE_4011 = 4011;
+    public static final String FAILURE_MSG_4011 = "相机已经被绑定";
+
+    public static final int FAILURE_CODE_4012 = 4012;
+    public static final String FAILURE_MSG_4012 = "账号或密码错误";
+
+    public static final int FAILURE_CODE_4013 = 4013;
+    public static final String FAILURE_MSG_4013 = "昵称重复";
+
+    public static final int FAILURE_CODE_4014 = 4014;
+    public static final String FAILURE_MSG_4014 = "余额不足,无法生成模型,请前往网页端充值或上传时去掉生成模型选项";
+
+    public static final int FAILURE_CODE_4015 = 4015;
+    public static final String FAILURE_MSG_4015 = "昵称中包含敏感词";
+
+    public static final int FAILURE_CODE_4016 = 4016;
+    public static final String FAILURE_MSG_4016 = "参数为空";
+
+    public static final int FAILURE_CODE_4017 = 4017;
+    public static final String FAILURE_MSG_4017 = "场景为空";
+
+    public static final int FAILURE_CODE_4018 = 4018;
+    public static final String FAILURE_MSG_4018 = "场景不属于该相机";
+
+    public static final int FAILURE_CODE_4019 = 4019;
+    public static final String FAILURE_MSG_4019 = "场景序号为空";
+
+    public static final int FAILURE_CODE_4020 = 4020;
+    public static final String FAILURE_MSG_4020 = "相机未绑定用户";
+}

+ 33 - 0
4dkankan-base/src/main/java/com/fdkankan/base/constant/CameraConstant.java

@@ -0,0 +1,33 @@
+package com.fdkankan.base.constant;
+
+// 6001-7000 相机状态码
+public class CameraConstant {
+
+    public static final int FAILURE_CODE_6001 = 6001;
+    public static final String FAILURE_MSG_6001 = "物理地址重复";
+
+    public static final int FAILURE_CODE_6002 = 6002;
+    public static final String FAILURE_MSG_6002 = "相机sn重复";
+
+    public static final int FAILURE_CODE_6003 = 6003;
+    public static final String FAILURE_MSG_6003 = "相机不存在";
+
+    public static final int FAILURE_CODE_6004 = 6004;
+    public static final String FAILURE_MSG_6004 = "表示相机的点数超过了10万";
+
+    public static final int FAILURE_CODE_6005 = 6005;
+	public static final String FAILURE_MSG_6005 = "无权操作该相机";
+
+    public static final int FAILURE_CODE_6006 = 6006;
+    public static final String FAILURE_MSG_6006 = "不支持重复绑定";
+
+    public static final int FAILURE_CODE_6007 = 6007;
+    public static final String FAILURE_MSG_6007 = "八目相机不支持解除绑定";
+
+    public static final int FAILURE_CODE_6008 = 6008;
+	public static final String FAILURE_MSG_6008 = "相机容量不足";
+
+    public static final int FAILURE_CODE_6009 = 6009;
+    public static final String FAILURE_MSG_6009 = "data.fdage文件不存在";
+
+}

+ 68 - 0
4dkankan-base/src/main/java/com/fdkankan/base/constant/LoginConstant.java

@@ -0,0 +1,68 @@
+package com.fdkankan.base.constant;
+
+// 3001-4000 登陆注册状态码
+public class LoginConstant {
+
+    public static final String LOCAL_CLINET_USER = "LOCAL_CLINET_USER";
+
+    public static final String SUCCESS_MSG = "操作成功";
+    public static final String ERROR_MSG = "操作失败";
+
+    public static final String FAILURE_MSG_9999 = "系统暂不可用,请稍后再试!";
+
+    public static final int FAILURE_CODE_3001 = 3001;
+    public static final String FAILURE_MSG_3001 = "缺少必要参数";
+
+    public static final int FAILURE_CODE_3002 = 3002;
+    public static final String FAILURE_MSG_3002 = "访问异常!";
+
+    public static final int FAILURE_CODE_3003 = 3003;
+    public static final String FAILURE_MSG_3003 = "非法访问!";
+
+    public static final int FAILURE_CODE_3004 = 3004;
+    public static final String FAILURE_MSG_3004 = "用户未登录";
+
+    public static final int FAILURE_CODE_3005 = 3005;
+    public static final String FAILURE_MSG_3005 = "验证码已过期";
+
+    public static final int FAILURE_CODE_3006 = 3006;
+    public static final String FAILURE_MSG_3006 = "验证码错误";
+
+    public static final int FAILURE_CODE_3007 = 3007;
+    public static final String FAILURE_MSG_3007 = "昵称已存在";
+
+    public static final int FAILURE_CODE_3008 = 3008;
+    public static final String FAILURE_MSG_3008 = "该手机已被注册";
+
+    public static final int FAILURE_CODE_3009 = 3009;
+    public static final String FAILURE_MSG_3009 = "两次输入的密码不一致";
+
+    public static final int FAILURE_CODE_3010 = 3010;
+    public static final String FAILURE_MSG_3010 = "昵称长度错误";
+
+    public static final int FAILURE_CODE_3011 = 3011;
+    public static final String FAILURE_MSG_3011 = "密码需要包含英文大小写、数字,长度8-16字符";
+
+    public static final int FAILURE_CODE_3012 = 3012;
+    public static final String FAILURE_MSG_3012 = "昵称包含敏感词";
+
+    public static final int FAILURE_CODE_3013 = 3013;
+    public static final String FAILURE_MSG_3013 = "手机号码格式错误";
+
+    public static final int FAILURE_CODE_3014 = 3014;
+    public static final String FAILURE_MSG_3014 = "账号或密码不正确";
+
+    public static final int FAILURE_CODE_3015 = 3015;
+    public static final String FAILURE_MSG_3015 = "用户不存在";
+
+    public static final int FAILURE_CODE_3016 = 3016;
+    public static final String FAILURE_MSG_3016 = "登录失败,账号无权访问";
+
+    public static final int FAILURE_CODE_3017 = 3017;
+    public static final String FAILURE_MSG_3017 = "空文件";
+
+    public static final int FAILURE_CODE_3018 = 3018;
+    public static final String FAILURE_MSG_3018 = "需要上传或使用的文件不存在";
+
+
+}

+ 90 - 0
4dkankan-base/src/main/java/com/fdkankan/base/constant/SceneConstant.java

@@ -0,0 +1,90 @@
+
+package com.fdkankan.base.constant;
+
+// 5001-6000 场景状态码
+public class SceneConstant {
+
+    public static final int FAILURE_CODE_5001 = 5001;
+    public static final String FAILURE_MSG_5001 = "modeldata.json为空";
+
+    public static final int FAILURE_CODE_5002 = 5002;
+    public static final String FAILURE_MSG_5002 = "order值为空";
+
+    public static final int FAILURE_CODE_5003 = 5003;
+    public static final String FAILURE_MSG_5003 = "guideSid或order值为空";
+
+    public static final int FAILURE_CODE_5004 = 5004;
+    public static final String FAILURE_MSG_5004 = "guideSid或guideName值为空";
+
+    public static final int FAILURE_CODE_5005 = 5005;
+    public static final String FAILURE_MSG_5005 = "场景为空";
+
+    public static final int FAILURE_CODE_5006 = 5006;
+    public static final String FAILURE_MSG_5006 = "余额不足";
+
+    public static final int FAILURE_CODE_5007 = 5007;
+    public static final String FAILURE_MSG_5007 = "非八目场景";
+
+    public static final int FAILURE_CODE_5008 = 5008;
+    public static final String FAILURE_MSG_5008 = "该场景已经被封存,无法删除";
+
+    public static final int FAILURE_CODE_5009 = 5009;
+    public static final String FAILURE_MSG_5009 = "场景被删除";
+
+	public static final int FAILURE_CODE_5010 = 5010;
+    public static final String FAILURE_MSG_5010 = "场景不属于该相机";
+
+    public static final int FAILURE_CODE_5011 = 5011;
+    public static final String FAILURE_MSG_5011 = "创建";
+
+    public static final int FAILURE_CODE_5012 = 5012;
+    public static final String FAILURE_MSG_5012 = "数据不正常";
+
+    public static final int FAILURE_CODE_5013 = 5013;
+    public static final String FAILURE_MSG_5013 = "场景对应的用户名为空";
+
+    public static final int FAILURE_CODE_5014 = 5014;
+    public static final String FAILURE_MSG_5014 = "该用户无权操作该场景";
+
+    public static final int FAILURE_CODE_5015 = 5015;
+    public static final String FAILURE_MSG_5015 = "该场景不属于当前登录账号";
+
+    public static final int FAILURE_CODE_5016 = 5016;
+    public static final String FAILURE_MSG_5016 = "热点外链场景不对";
+
+    public static final int FAILURE_CODE_5017 = 5017;
+    public static final String FAILURE_MSG_5017 = "*上传模型失败,请参照右侧教程";
+
+    public static final int FAILURE_CODE_5018 = 5018;
+    public static final String FAILURE_MSG_5018 = "zip文件只能有一层目录或无目录";
+
+    public static final int FAILURE_CODE_5019 = 5019;
+    public static final String FAILURE_MSG_5019 = "必须有且仅有一个obj和mtl文件";
+
+    public static final int FAILURE_CODE_5020 = 5020;
+    public static final String FAILURE_MSG_5020 = "贴图需控制在1.5M以内,obj文件需要控制在20M以内。";
+
+    public static final int FAILURE_CODE_5021 = 5021;
+    public static final String FAILURE_MSG_5021 = "场景密钥不正确";
+
+    public static final int FAILURE_CODE_5022 = 5022;
+    public static final String FAILURE_MSG_5022 = "上传文件格式,名称不一致";
+
+    public static final int FAILURE_CODE_5023 = 5023;
+    public static final String FAILURE_MSG_5023 = "上传文件格式不正确,只能是jpg或mp4格式";
+
+    public static final int FAILURE_CODE_5024 = 5024;
+    public static final String FAILURE_MSG_5024 = "有场景打包中,请稍后重试";
+
+    public static final int FAILURE_CODE_5025 = 5025;
+    public static final String FAILURE_MSG_5025 = "场景已上线不可编辑";
+
+    public static final int FAILURE_CODE_5026 = 5026;
+    public static final String FAILURE_MSG_5026 = "场景未审核";
+
+    public static final int FAILURE_CODE_5027 = 5027;
+    public static final String FAILURE_MSG_5027 = "已绑定VR项目,不允许删除";
+
+    public static final int FAILURE_CODE_5028 = 5028;
+    public static final String FAILURE_MSG_5028 = "上传的文件不符合规范,请重新上传";
+}

+ 71 - 0
4dkankan-base/src/main/java/com/fdkankan/base/entity/BaseEntity.java

@@ -0,0 +1,71 @@
+package com.fdkankan.base.entity;
+
+import com.alibaba.fastjson.annotation.JSONField;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@MappedSuperclass
+public abstract class BaseEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private String id;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
+    @Column(name = "create_time")
+    private Date createTime;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
+    @Column(name = "update_time")
+    private Date updateTime;
+
+    @Column(name = "is_delete")
+    private String isDelete;
+
+/*    @Column(name = "update_by")
+    private Long updateBy;*/
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getIsDelete() {
+        return isDelete;
+    }
+
+    public void setIsDelete(String isDelete) {
+        this.isDelete = isDelete;
+    }
+
+/*    public Long getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(Long updateBy) {
+        this.updateBy = updateBy;
+    }*/
+}

+ 99 - 0
4dkankan-base/src/main/java/com/fdkankan/base/entity/LogEntity.java

@@ -0,0 +1,99 @@
+package com.fdkankan.base.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+@Table(name = "t_log")
+public class LogEntity extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = 8970489969272197517L;
+
+    @Column(name = "description")
+    private String description;
+
+    @Column(name = "exception_code")
+    private String exceptionCode;
+
+    @Column(name = "type")
+    private String type;
+
+    @Column(name = "exception_detail")
+    private String exceptionDetail;
+
+    @Column(name = "method")
+    private String method;
+
+    @Column(name = "params")
+    private String params;
+
+    @Column(name = "request_ip")
+    private String requestIp;
+
+    @Column(name = "create_by")
+    private Long createBy;
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getExceptionCode() {
+        return exceptionCode;
+    }
+
+    public void setExceptionCode(String exceptionCode) {
+        this.exceptionCode = exceptionCode;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getExceptionDetail() {
+        return exceptionDetail;
+    }
+
+    public void setExceptionDetail(String exceptionDetail) {
+        this.exceptionDetail = exceptionDetail;
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    public String getParams() {
+        return params;
+    }
+
+    public void setParams(String params) {
+        this.params = params;
+    }
+
+    public String getRequestIp() {
+        return requestIp;
+    }
+
+    public void setRequestIp(String requestIp) {
+        this.requestIp = requestIp;
+    }
+
+    public Long getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(Long createBy) {
+        this.createBy = createBy;
+    }
+}

+ 57 - 0
4dkankan-base/src/main/java/com/fdkankan/base/interceptor/BodyReaderHttpServletRequestWrapper.java

@@ -0,0 +1,57 @@
+package com.fdkankan.base.interceptor;
+
+import com.fdkankan.base.util.HttpHelper;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+
+public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+    private final byte[] body;
+
+    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
+        super(request);
+        body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return new BufferedReader(new InputStreamReader(getInputStream()));
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+
+        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+
+        return new ServletInputStream() {
+
+            @Override
+            public int read() throws IOException {
+                return bais.read();
+            }
+
+            @Override
+            public boolean isFinished() {
+                return false;
+            }
+
+            @Override
+            public boolean isReady() {
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+
+            }
+        };
+    }
+}

+ 47 - 0
4dkankan-base/src/main/java/com/fdkankan/base/interceptor/CommonInterceptor.java

@@ -0,0 +1,47 @@
+package com.fdkankan.base.interceptor;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Slf4j
+@Component
+public class CommonInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request,
+                             HttpServletResponse response, Object handler) throws Exception {
+        if(!request.getRequestURI().contains("/static/") && !request.getRequestURI().contains("/sendUserInfo")
+                && !request.getRequestURI().contains(".json") && !request.getRequestURI().contains(".png")
+                && !request.getRequestURI().contains(".html") && !request.getRequestURI().contains(".mp3")
+                && !request.getRequestURI().contains(".jpg") && !request.getRequestURI().equals("/")){
+            log.info(request.getRequestURI() + ",进入该请求!");
+        }
+        return true;
+    }
+
+    @Override
+    public void postHandle(HttpServletRequest request,
+                           HttpServletResponse response, Object handler,
+                           ModelAndView modelAndView) throws Exception {
+        request.setAttribute("ctx", request.getContextPath());
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request,
+                                HttpServletResponse response, Object handler, Exception ex)
+            throws Exception {
+        if(!request.getRequestURI().contains("/static/") && !request.getRequestURI().contains("/sendUserInfo")
+                && !request.getRequestURI().contains(".json") && !request.getRequestURI().contains(".png")
+                && !request.getRequestURI().contains(".html") && !request.getRequestURI().contains(".mp3")
+                && !request.getRequestURI().contains(".jpg") && !request.getRequestURI().equals("/")){
+            log.info(request.getRequestURI() + ",完成请求!");
+        }
+    }
+
+
+}

+ 9 - 0
4dkankan-base/src/main/java/com/fdkankan/base/mapper/ILogMapper.java

@@ -0,0 +1,9 @@
+package com.fdkankan.base.mapper;
+
+import com.fdkankan.base.entity.LogEntity;
+import com.fdkankan.base.mapper.base.IBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ILogMapper extends IBaseMapper<LogEntity, Long> {
+}

+ 15 - 0
4dkankan-base/src/main/java/com/fdkankan/base/mapper/base/IBaseMapper.java

@@ -0,0 +1,15 @@
+package com.fdkankan.base.mapper.base;
+
+import com.fdkankan.base.entity.BaseEntity;
+import tk.mybatis.mapper.common.BaseMapper;
+import tk.mybatis.mapper.common.ConditionMapper;
+import tk.mybatis.mapper.common.IdsMapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
+
+import java.io.Serializable;
+
+public interface IBaseMapper<T extends BaseEntity, ID extends Serializable> extends BaseMapper<T>,
+        ConditionMapper<T>,
+        IdsMapper<T>,
+        InsertListMapper<T> {
+}

+ 64 - 0
4dkankan-base/src/main/java/com/fdkankan/base/mq/ModelingMsgProducer.java

@@ -0,0 +1,64 @@
+package com.fdkankan.base.mq;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.core.ChannelCallback;
+import org.springframework.amqp.rabbit.support.CorrelationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import com.rabbitmq.client.AMQP;
+import com.rabbitmq.client.Channel;
+
+import java.util.UUID;
+
+@Log4j2
+@Component
+public class ModelingMsgProducer implements RabbitTemplate.ConfirmCallback {
+
+//    @Autowired
+//    private Queue workQueue;
+    private RabbitTemplate rabbitTemplate;
+
+    @Value("${rabbitmq.queue}")
+    private String queue;
+
+    @Autowired
+    public ModelingMsgProducer(RabbitTemplate rabbitTemplate) {
+        this.rabbitTemplate = rabbitTemplate;
+        this.rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果为单例的话,那回调就是最后设置的内容
+    }
+
+    @Override
+    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
+        log.info(" 回调id:" + correlationData);
+        if (ack) {
+            log.info("消息成功消费");
+        } else {
+            log.info("消息消费失败:" + cause);
+        }
+    }
+
+    public void sendMsg(String content) {
+        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
+        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTINGKEY_A, content, correlationId);
+//        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_MODELING, RabbitConfig.ROUTINGKEY_MODELING_A, content, correlationId);
+
+    }
+
+    /**
+     * 获取mq的数量
+     * @return
+     */
+    public int getMessageCount() {
+        AMQP.Queue.DeclareOk declareOk = rabbitTemplate.execute(new ChannelCallback<AMQP.Queue.DeclareOk>() {
+            public AMQP.Queue.DeclareOk doInRabbit(Channel channel) throws Exception {
+                return channel.queueDeclarePassive(queue);
+            }
+        });
+
+        return declareOk.getMessageCount();
+    }
+}

+ 112 - 0
4dkankan-base/src/main/java/com/fdkankan/base/mq/RabbitConfig.java

@@ -0,0 +1,112 @@
+package com.fdkankan.base.mq;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+
+@Log4j2
+@Configuration
+public class RabbitConfig {
+
+//    @Value("${spring.rabbitmq.host}")
+//    private String host;
+//
+//    @Value("${spring.rabbitmq.port}")
+//    private int port;
+
+    @Value("${spring.rabbitmq.address}")
+    private String address;
+
+    @Value("${spring.rabbitmq.username}")
+    private String username;
+
+    @Value("${spring.rabbitmq.password}")
+    private String password;
+
+    @Value("${rabbitmq.queue}")
+    private String queue;
+
+
+    public static final String EXCHANGE_A = "QUEUE_EXCHANGE_A";
+    public static final String ROUTINGKEY_A = "QUEUE_ROUTINGKEY_A";
+
+    @Bean
+    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
+        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+        factory.setConnectionFactory(connectionFactory());
+        factory.setPrefetchCount(1);
+        return factory;
+    }
+
+    @Bean
+    public ConnectionFactory connectionFactory() {
+        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
+        connectionFactory.setAddresses(address);
+        connectionFactory.setUsername(username);
+        connectionFactory.setPassword(password);
+        connectionFactory.setVirtualHost("/");
+        connectionFactory.setPublisherConfirms(true);
+        return connectionFactory;
+    }
+
+    @Bean
+    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+    public RabbitTemplate rabbitTemplate() {
+        return new RabbitTemplate(connectionFactory());
+    }
+
+
+
+    /**
+     * 针对消费者配置
+     * 1. 设置交换机类型
+     * 2. 将队列绑定到交换机
+     FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
+     HeadersExchange :通过添加属性key-value匹配
+     DirectExchange:按照routingkey分发到指定队列
+     TopicExchange:多关键字匹配
+     */
+
+    @Bean
+    public DirectExchange defaultExchange() {
+        return new DirectExchange(EXCHANGE_A);
+    }
+
+    /**
+     * 获取队列A
+     * @return
+     */
+    @Bean
+    public Queue modelingQueueA() {
+        return new Queue(queue, true); //队列持久
+    }
+
+    @Bean
+    public Binding binding() {
+        return BindingBuilder.bind(modelingQueueA()).to(defaultExchange()).with(ROUTINGKEY_A);
+    }
+
+//    @Bean
+//    public Queue workQueue() {
+//        return new Queue(queue);
+//    }
+
+
+//    @Bean
+//    public ModelingMsgProducer modelingMsgProducer() {
+//        return new ModelingMsgProducer(rabbitTemplate());
+//    }
+
+}

Різницю між файлами не показано, бо вона завелика
+ 7340 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/BigSceneProto.java


Різницю між файлами не показано, бо вона завелика
+ 4654 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/Common.java


Різницю між файлами не показано, бо вона завелика
+ 4345 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/Visionmodeldata.java


+ 156 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/format/CouchDBFormat.java

@@ -0,0 +1,156 @@
+package com.fdkankan.base.proto.format;
+
+
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.Message;
+import com.google.protobuf.UnknownFieldSet;
+
+import java.io.IOException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: aantonov
+ * Date: Mar 16, 2010
+ * Time: 4:06:05 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class CouchDBFormat extends JsonFormat {
+
+    /**
+     * Outputs a textual representation of the Protocol Message supplied into the parameter output.
+     * (This representation is the new version of the classic "ProtocolPrinter" output from the
+     * original Protocol Buffer system)
+     */
+    public static void print(Message message, Appendable output) throws IOException {
+        CouchDBGenerator generator = new CouchDBGenerator(output);
+        generator.print("{");
+        print(message, generator);
+        generator.print("}");
+    }
+
+    /**
+     * Outputs a textual representation of {@code fields} to {@code output}.
+     */
+    public static void print(UnknownFieldSet fields, Appendable output) throws IOException {
+        CouchDBGenerator generator = new CouchDBGenerator(output);
+        generator.print("{");
+        printUnknownFields(fields, generator);
+        generator.print("}");
+    }
+
+    /**
+     * Like {@code print()}, but writes directly to a {@code String} and returns it.
+     */
+    public static String printToString(Message message) {
+        try {
+            StringBuilder text = new StringBuilder();
+            print(message, text);
+            return text.toString();
+        } catch (IOException e) {
+            throw new RuntimeException("Writing to a StringBuilder threw an IOException (should never happen).",
+                                       e);
+        }
+    }
+
+    /**
+     * Like {@code print()}, but writes directly to a {@code String} and returns it.
+     */
+    public static String printToString(UnknownFieldSet fields) {
+        try {
+            StringBuilder text = new StringBuilder();
+            print(fields, text);
+            return text.toString();
+        } catch (IOException e) {
+            throw new RuntimeException("Writing to a StringBuilder threw an IOException (should never happen).",
+                                       e);
+        }
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     */
+    public static void merge(Readable input, Message.Builder builder) throws IOException {
+        merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     */
+    public static void merge(CharSequence input, Message.Builder builder) throws ParseException {
+        merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     * Extensions will be recognized if they are registered in {@code extensionRegistry}.
+     */
+    public static void merge(Readable input,
+                             ExtensionRegistry extensionRegistry,
+                             Message.Builder builder) throws IOException {
+        // Read the entire input to a String then parse that.
+
+        // If StreamTokenizer were not quite so crippled, or if there were a kind
+        // of Reader that could read in chunks that match some particular regex,
+        // or if we wanted to write a custom Reader to tokenize our stream, then
+        // we would not have to read to one big String. Alas, none of these is
+        // the case. Oh well.
+
+        merge(JsonFormat.toStringBuilder(input), extensionRegistry, builder);
+    }
+
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     * Extensions will be recognized if they are registered in {@code extensionRegistry}.
+     */
+    public static void merge(CharSequence input,
+                             ExtensionRegistry extensionRegistry,
+                             Message.Builder builder) throws ParseException {
+        Tokenizer tokenizer = new Tokenizer(input);
+
+        // Based on the state machine @ http://json.org/
+
+        tokenizer.consume("{"); // Needs to happen when the object starts.
+        while (!tokenizer.tryConsume("}")) { // Continue till the object is done
+            JsonFormat.mergeField(tokenizer, extensionRegistry, builder);
+        }
+    }
+
+    protected static class Tokenizer extends JsonFormat.Tokenizer {
+
+        /**
+         * Construct a tokenizer that parses tokens from the given text.
+         */
+        public Tokenizer(CharSequence text) {
+            super(text);
+        }
+
+        @Override
+        public String consumeIdentifier() throws ParseException {
+            String id = super.consumeIdentifier();
+            if ("_id".equals(id)) {
+                return "id";
+            } else if ("_rev".equals(id)) {
+                return "rev";
+            }
+            return id;
+        }
+    }
+
+    protected static class CouchDBGenerator extends JsonFormat.JsonGenerator {
+
+        public CouchDBGenerator(Appendable output) {
+            super(output);
+        }
+
+        @Override
+        public void print(CharSequence text) throws IOException {
+            if ("id".equals(text)) {
+                super.print("_id");
+            } else if ("rev".equals(text)) {
+                super.print("_rev");
+            } else {
+                super.print(text);
+            }
+        }
+    }
+}

+ 703 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/format/HtmlFormat.java

@@ -0,0 +1,703 @@
+package com.fdkankan.base.proto.format;
+/* 
+    Copyright (c) 2009, Orbitz World Wide
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification, 
+    are permitted provided that the following conditions are met:
+
+        * Redistributions of source code must retain the above copyright notice, 
+          this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above copyright notice, 
+          this list of conditions and the following disclaimer in the documentation 
+          and/or other materials provided with the distribution.
+        * Neither the name of the Orbitz World Wide nor the names of its contributors 
+          may be used to endorse or promote products derived from this software 
+          without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Message;
+import com.google.protobuf.UnknownFieldSet;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Provide ascii html formatting support for proto2 instances.
+ * <p>
+ * (c) 2009-10 Orbitz World Wide. All Rights Reserved.
+ * 
+ * @author eliran.bivas@gmail.com Eliran Bivas
+ * @version $HtmlFormat.java Mar 12, 2009 4:00:33 PM$
+ */
+public final class HtmlFormat {
+
+    private static final String META_CONTENT = "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\" />";
+    private static final String MAIN_DIV_STYLE = "color: black; font-size: 14px; font-family: sans-serif; font-weight: bolder; margin-bottom: 10px;";
+    private static final String FIELD_NAME_STYLE = "font-weight: bold; color: #669966;font-size: 14px; font-family: sans-serif;";
+    private static final String FIELD_VALUE_STYLE = "color: #3300FF;font-size: 13px; font-family: sans-serif;";
+
+    /**
+     * Outputs a textual representation of the Protocol Message supplied into the parameter output.
+     * (This representation is the new version of the classic "ProtocolPrinter" output from the
+     * original Protocol Buffer system)
+     */
+    public static void print(Message message, Appendable output) throws IOException {
+        HtmlGenerator generator = new HtmlGenerator(output);
+        printTitle(message, generator);
+        print(message, generator);
+        generator.print("</body></html>");
+    }
+
+    private static void printTitle(final Message message, final HtmlGenerator generator) throws IOException {
+        generator.print("<html><head>");
+        generator.print(META_CONTENT);
+        generator.print("<title>");
+        generator.print(message.getDescriptorForType().getFullName());
+        generator.print("</title></head><body>");
+        generator.print("<div style=\"");
+        generator.print(MAIN_DIV_STYLE);
+        generator.print("\">message : ");
+        generator.print(message.getDescriptorForType().getFullName());
+        generator.print("</div>");
+    }
+
+    /**
+     * Outputs a textual representation of {@code fields} to {@code output}.
+     */
+    public static void print(UnknownFieldSet fields, Appendable output) throws IOException {
+        HtmlGenerator generator = new HtmlGenerator(output);
+        generator.print("<html>");
+        generator.print(META_CONTENT);
+        generator.print("</head><body>");
+        printUnknownFields(fields, generator);
+        generator.print("</body></html>");
+    }
+
+    /**
+     * Like {@code print()}, but writes directly to a {@code String} and returns it.
+     */
+    public static String printToString(Message message) {
+        try {
+            StringBuilder text = new StringBuilder();
+            print(message, text);
+            return text.toString();
+        } catch (IOException e) {
+            throw new RuntimeException("Writing to a StringBuilder threw an IOException (should never happen).",
+                                       e);
+        }
+    }
+
+    /**
+     * Like {@code print()}, but writes directly to a {@code String} and returns it.
+     */
+    public static String printToString(UnknownFieldSet fields) {
+        try {
+            StringBuilder text = new StringBuilder();
+            print(fields, text);
+            return text.toString();
+        } catch (IOException e) {
+            throw new RuntimeException("Writing to a StringBuilder threw an IOException (should never happen).",
+                                       e);
+        }
+    }
+
+    private static void print(Message message, HtmlGenerator generator) throws IOException {
+
+        for (Map.Entry<FieldDescriptor, Object> field : message.getAllFields().entrySet()) {
+            printField(field.getKey(), field.getValue(), generator);
+        }
+        printUnknownFields(message.getUnknownFields(), generator);
+    }
+
+    public static void printField(FieldDescriptor field, Object value, HtmlGenerator generator) throws IOException {
+
+        if (field.isRepeated()) {
+            // Repeated field. Print each element.
+            for (Object element : (List<?>) value) {
+                printSingleField(field, element, generator);
+            }
+        } else {
+            printSingleField(field, value, generator);
+        }
+    }
+
+    private static void printSingleField(FieldDescriptor field,
+                                         Object value,
+                                         HtmlGenerator generator) throws IOException {
+        if (field.isExtension()) {
+            generator.print("[<span style=\"");
+            generator.print(FIELD_NAME_STYLE);
+            generator.print("\">");
+            // We special-case MessageSet elements for compatibility with proto1.
+            if (field.getContainingType().getOptions().getMessageSetWireFormat()
+                            && (field.getType() == FieldDescriptor.Type.MESSAGE) && (field.isOptional())
+                            // object equality
+                            && (field.getExtensionScope() == field.getMessageType())) {
+                generator.print(field.getMessageType().getFullName());
+            } else {
+                generator.print(field.getFullName());
+            }
+            generator.print("</span>]");
+        } else {
+            generator.print("<span style=\"");
+            generator.print(FIELD_NAME_STYLE);
+            generator.print("\">");
+            if (field.getType() == FieldDescriptor.Type.GROUP) {
+                // Groups must be serialized with their original capitalization.
+                generator.print(field.getMessageType().getName());
+            } else {
+                generator.print(field.getName());
+            }
+            generator.print("</span>");
+        }
+
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            generator.print(" <span style=\"color: red;\">{</span><br/>");
+            generator.indent();
+        } else {
+            generator.print(": ");
+        }
+
+        printFieldValue(field, value, generator);
+
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            generator.outdent();
+            generator.print("<span style=\"color: red;\">}</span>");
+        }
+        generator.print("<br/>");
+    }
+
+    private static void printFieldValue(FieldDescriptor field, Object value, HtmlGenerator generator) throws IOException {
+        generator.print("<span style=\"");
+        generator.print(FIELD_VALUE_STYLE);
+        generator.print("\">");
+        switch (field.getType()) {
+            case INT32:
+            case INT64:
+            case SINT32:
+            case SINT64:
+            case SFIXED32:
+            case SFIXED64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+                // Good old toString() does what we want for these types.
+                generator.print(value.toString());
+                break;
+
+            case UINT32:
+            case FIXED32:
+                generator.print(unsignedToString((Integer) value));
+                break;
+
+            case UINT64:
+            case FIXED64:
+                generator.print(unsignedToString((Long) value));
+                break;
+
+            case STRING:
+                generator.print("\"");
+                generator.print(value.toString());
+                generator.print("\"");
+                break;
+
+            case BYTES: {
+                generator.print("\"");
+                generator.print(escapeBytes((ByteString) value));
+                generator.print("\"");
+                break;
+            }
+
+            case ENUM: {
+                generator.print(((EnumValueDescriptor) value).getName());
+                break;
+            }
+
+            case MESSAGE:
+            case GROUP:
+                print((Message) value, generator);
+                break;
+        }
+        generator.print("</span>");
+    }
+
+    private static void printUnknownFields(UnknownFieldSet unknownFields, HtmlGenerator generator) throws IOException {
+        for (Map.Entry<Integer, UnknownFieldSet.Field> entry : unknownFields.asMap().entrySet()) {
+            UnknownFieldSet.Field field = entry.getValue();
+
+            for (long value : field.getVarintList()) {
+                generator.print(entry.getKey().toString());
+                generator.print(": ");
+                generator.print(unsignedToString(value));
+                generator.print("<br/>");
+            }
+            for (int value : field.getFixed32List()) {
+                generator.print(entry.getKey().toString());
+                generator.print(": ");
+                generator.print(String.format((Locale) null, "0x%08x", value));
+                generator.print("<br/>");
+            }
+            for (long value : field.getFixed64List()) {
+                generator.print(entry.getKey().toString());
+                generator.print(": ");
+                generator.print(String.format((Locale) null, "0x%016x", value));
+                generator.print("<br/>");
+            }
+            for (ByteString value : field.getLengthDelimitedList()) {
+                generator.print(entry.getKey().toString());
+                generator.print(": \"");
+                generator.print(escapeBytes(value));
+                generator.print("\"<br/>");
+            }
+            for (UnknownFieldSet value : field.getGroupList()) {
+                generator.print(entry.getKey().toString());
+                generator.print(" <span style=\"color: red;\">{</span><br/>");
+                generator.indent();
+                printUnknownFields(value, generator);
+                generator.outdent();
+                generator.print("<span style=\"color: red;\">}</span><br/>");
+            }
+        }
+    }
+
+    /**
+     * Convert an unsigned 32-bit integer to a string.
+     */
+    private static String unsignedToString(int value) {
+        if (value >= 0) {
+            return Integer.toString(value);
+        } else {
+            return Long.toString((value) & 0x00000000FFFFFFFFL);
+        }
+    }
+
+    /**
+     * Convert an unsigned 64-bit integer to a string.
+     */
+    private static String unsignedToString(long value) {
+        if (value >= 0) {
+            return Long.toString(value);
+        } else {
+            // Pull off the most-significant bit so that BigInteger doesn't think
+            // the number is negative, then set it again using setBit().
+            return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL).setBit(63).toString();
+        }
+    }
+
+    /**
+     * An inner class for writing text to the output stream.
+     */
+    static private final class HtmlGenerator {
+
+        Appendable output;
+        boolean atStartOfLine = true;
+
+        public HtmlGenerator(Appendable output) {
+            this.output = output;
+        }
+
+        /**
+         * Indent text by two spaces. After calling Indent(), two spaces will be inserted at the
+         * beginning of each line of text. Indent() may be called multiple times to produce deeper
+         * indents.
+         * 
+         * @throws IOException
+         */
+        public void indent() throws IOException {
+            print("<div style=\"margin-left: 25px\">");
+        }
+
+        /**
+         * Reduces the current indent level by two spaces, or crashes if the indent level is zero.
+         * 
+         * @throws IOException
+         */
+        public void outdent() throws IOException {
+            print("</div>");
+        }
+
+        /**
+         * Print text to the output stream.
+         */
+        public void print(CharSequence text) throws IOException {
+            int size = text.length();
+            int pos = 0;
+
+            for (int i = 0; i < size; i++) {
+                if (text.charAt(i) == '\n') {
+                    write("<br/>", i - pos + 1);
+                    pos = i + 1;
+                    atStartOfLine = true;
+                }
+            }
+            write(text.subSequence(pos, size), size - pos);
+        }
+
+        private void write(CharSequence data, int size) throws IOException {
+            if (size == 0) {
+                return;
+            }
+            if (atStartOfLine) {
+                atStartOfLine = false;
+            }
+            output.append(data);
+        }
+    }
+
+    // =================================================================
+    // Utility functions
+    //
+    // Some of these methods are package-private because Descriptors.java uses
+    // them.
+
+    /**
+     * Escapes bytes in the format used in protocol buffer text format, which is the same as the
+     * format used for C string literals. All bytes that are not printable 7-bit ASCII characters
+     * are escaped, as well as backslash, single-quote, and double-quote characters. Characters for
+     * which no defined short-hand escape sequence is defined will be escaped using 3-digit octal
+     * sequences.
+     */
+    static String escapeBytes(ByteString input) {
+        StringBuilder builder = new StringBuilder(input.size());
+        for (int i = 0; i < input.size(); i++) {
+            byte b = input.byteAt(i);
+            switch (b) {
+                // Java does not recognize \a or \v, apparently.
+                case 0x07:
+                    builder.append("\\a");
+                    break;
+                case '\b':
+                    builder.append("\\b");
+                    break;
+                case '\f':
+                    builder.append("\\f");
+                    break;
+                case '\n':
+                    builder.append("\\n");
+                    break;
+                case '\r':
+                    builder.append("\\r");
+                    break;
+                case '\t':
+                    builder.append("\\t");
+                    break;
+                case 0x0b:
+                    builder.append("\\v");
+                    break;
+                case '\\':
+                    builder.append("\\\\");
+                    break;
+                case '\'':
+                    builder.append("\\\'");
+                    break;
+                case '"':
+                    builder.append("\\\"");
+                    break;
+                default:
+                    if (b >= 0x20) {
+                        builder.append((char) b);
+                    } else {
+                        builder.append('\\');
+                        builder.append((char) ('0' + ((b >>> 6) & 3)));
+                        builder.append((char) ('0' + ((b >>> 3) & 7)));
+                        builder.append((char) ('0' + (b & 7)));
+                    }
+                    break;
+            }
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Un-escape a byte sequence as escaped using
+     * {@link #escapeBytes(com.googlecode.protobuf.format.ByteString)}. Two-digit hex escapes (starting with
+     * "\x") are also recognized.
+     */
+    static ByteString unescapeBytes(CharSequence input) throws InvalidEscapeSequence {
+        byte[] result = new byte[input.length()];
+        int pos = 0;
+        for (int i = 0; i < input.length(); i++) {
+            char c = input.charAt(i);
+            if (c == '\\') {
+                if (i + 1 < input.length()) {
+                    ++i;
+                    c = input.charAt(i);
+                    if (isOctal(c)) {
+                        // Octal escape.
+                        int code = digitValue(c);
+                        if ((i + 1 < input.length()) && isOctal(input.charAt(i + 1))) {
+                            ++i;
+                            code = code * 8 + digitValue(input.charAt(i));
+                        }
+                        if ((i + 1 < input.length()) && isOctal(input.charAt(i + 1))) {
+                            ++i;
+                            code = code * 8 + digitValue(input.charAt(i));
+                        }
+                        result[pos++] = (byte) code;
+                    } else {
+                        switch (c) {
+                            case 'a':
+                                result[pos++] = 0x07;
+                                break;
+                            case 'b':
+                                result[pos++] = '\b';
+                                break;
+                            case 'f':
+                                result[pos++] = '\f';
+                                break;
+                            case 'n':
+                                result[pos++] = '\n';
+                                break;
+                            case 'r':
+                                result[pos++] = '\r';
+                                break;
+                            case 't':
+                                result[pos++] = '\t';
+                                break;
+                            case 'v':
+                                result[pos++] = 0x0b;
+                                break;
+                            case '\\':
+                                result[pos++] = '\\';
+                                break;
+                            case '\'':
+                                result[pos++] = '\'';
+                                break;
+                            case '"':
+                                result[pos++] = '\"';
+                                break;
+
+                            case 'x':
+                                // hex escape
+                                int code = 0;
+                                if ((i + 1 < input.length()) && isHex(input.charAt(i + 1))) {
+                                    ++i;
+                                    code = digitValue(input.charAt(i));
+                                } else {
+                                    throw new InvalidEscapeSequence("Invalid escape sequence: '\\x' with no digits");
+                                }
+                                if ((i + 1 < input.length()) && isHex(input.charAt(i + 1))) {
+                                    ++i;
+                                    code = code * 16 + digitValue(input.charAt(i));
+                                }
+                                result[pos++] = (byte) code;
+                                break;
+
+                            default:
+                                throw new InvalidEscapeSequence("Invalid escape sequence: '\\" + c
+                                                                + "'");
+                        }
+                    }
+                } else {
+                    throw new InvalidEscapeSequence("Invalid escape sequence: '\\' at end of string.");
+                }
+            } else {
+                result[pos++] = (byte) c;
+            }
+        }
+
+        return ByteString.copyFrom(result, 0, pos);
+    }
+
+    /**
+     * Thrown by {@link JsonFormat#unescapeBytes} and {@link JsonFormat#unescapeText} when an
+     * invalid escape sequence is seen.
+     */
+    static class InvalidEscapeSequence extends IOException {
+
+        private static final long serialVersionUID = 1L;
+
+        public InvalidEscapeSequence(String description) {
+            super(description);
+        }
+    }
+
+    /**
+     * Like {@link #escapeBytes(com.googlecode.protobuf.format.ByteString)}, but escapes a text string.
+     * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped individually as a
+     * 3-digit octal escape. Yes, it's weird.
+     */
+    static String escapeText(String input) {
+        return escapeBytes(ByteString.copyFromUtf8(input));
+    }
+
+    /**
+     * Un-escape a text string as escaped using {@link #escapeText(String)}. Two-digit hex escapes
+     * (starting with "\x") are also recognized.
+     */
+    static String unescapeText(String input) throws InvalidEscapeSequence {
+        return unescapeBytes(input).toStringUtf8();
+    }
+
+    /**
+     * Is this an octal digit?
+     */
+    private static boolean isOctal(char c) {
+        return ('0' <= c) && (c <= '7');
+    }
+
+    /**
+     * Is this a hex digit?
+     */
+    private static boolean isHex(char c) {
+        return (('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f'))
+        || (('A' <= c) && (c <= 'F'));
+    }
+
+    /**
+     * Interpret a character as a digit (in any base up to 36) and return the numeric value. This is
+     * like {@code Character.digit()} but we don't accept non-ASCII digits.
+     */
+    private static int digitValue(char c) {
+        if (('0' <= c) && (c <= '9')) {
+            return c - '0';
+        } else if (('a' <= c) && (c <= 'z')) {
+            return c - 'a' + 10;
+        } else {
+            return c - 'A' + 10;
+        }
+    }
+
+    /**
+     * Parse a 32-bit signed integer from the text. Unlike the Java standard {@code
+     * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+     * hexidecimal and octal numbers, respectively.
+     */
+    static int parseInt32(String text) throws NumberFormatException {
+        return (int) parseInteger(text, true, false);
+    }
+
+    /**
+     * Parse a 32-bit unsigned integer from the text. Unlike the Java standard {@code
+     * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+     * hexidecimal and octal numbers, respectively. The result is coerced to a (signed) {@code int}
+     * when returned since Java has no unsigned integer type.
+     */
+    static int parseUInt32(String text) throws NumberFormatException {
+        return (int) parseInteger(text, false, false);
+    }
+
+    /**
+     * Parse a 64-bit signed integer from the text. Unlike the Java standard {@code
+     * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+     * hexidecimal and octal numbers, respectively.
+     */
+    static long parseInt64(String text) throws NumberFormatException {
+        return parseInteger(text, true, true);
+    }
+
+    /**
+     * Parse a 64-bit unsigned integer from the text. Unlike the Java standard {@code
+     * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+     * hexidecimal and octal numbers, respectively. The result is coerced to a (signed) {@code long}
+     * when returned since Java has no unsigned long type.
+     */
+    static long parseUInt64(String text) throws NumberFormatException {
+        return parseInteger(text, false, true);
+    }
+
+    private static long parseInteger(String text, boolean isSigned, boolean isLong) throws NumberFormatException {
+        int pos = 0;
+
+        boolean negative = false;
+        if (text.startsWith("-", pos)) {
+            if (!isSigned) {
+                throw new NumberFormatException("Number must be positive: " + text);
+            }
+            ++pos;
+            negative = true;
+        }
+
+        int radix = 10;
+        if (text.startsWith("0x", pos)) {
+            pos += 2;
+            radix = 16;
+        } else if (text.startsWith("0", pos)) {
+            radix = 8;
+        }
+
+        String numberText = text.substring(pos);
+
+        long result = 0;
+        if (numberText.length() < 16) {
+            // Can safely assume no overflow.
+            result = Long.parseLong(numberText, radix);
+            if (negative) {
+                result = -result;
+            }
+
+            // Check bounds.
+            // No need to check for 64-bit numbers since they'd have to be 16 chars
+            // or longer to overflow.
+            if (!isLong) {
+                if (isSigned) {
+                    if ((result > Integer.MAX_VALUE) || (result < Integer.MIN_VALUE)) {
+                        throw new NumberFormatException("Number out of range for 32-bit signed integer: "
+                                                        + text);
+                    }
+                } else {
+                    if ((result >= (1L << 32)) || (result < 0)) {
+                        throw new NumberFormatException("Number out of range for 32-bit unsigned integer: "
+                                                        + text);
+                    }
+                }
+            }
+        } else {
+            BigInteger bigValue = new BigInteger(numberText, radix);
+            if (negative) {
+                bigValue = bigValue.negate();
+            }
+
+            // Check bounds.
+            if (!isLong) {
+                if (isSigned) {
+                    if (bigValue.bitLength() > 31) {
+                        throw new NumberFormatException("Number out of range for 32-bit signed integer: "
+                                                        + text);
+                    }
+                } else {
+                    if (bigValue.bitLength() > 32) {
+                        throw new NumberFormatException("Number out of range for 32-bit unsigned integer: "
+                                                        + text);
+                    }
+                }
+            } else {
+                if (isSigned) {
+                    if (bigValue.bitLength() > 63) {
+                        throw new NumberFormatException("Number out of range for 64-bit signed integer: "
+                                                        + text);
+                    }
+                } else {
+                    if (bigValue.bitLength() > 64) {
+                        throw new NumberFormatException("Number out of range for 64-bit unsigned integer: "
+                                                        + text);
+                    }
+                }
+            }
+
+            result = bigValue.longValue();
+        }
+
+        return result;
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 1338 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/format/JavaPropsFormat.java


Різницю між файлами не показано, бо вона завелика
+ 1603 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/format/JsonFormat.java


+ 602 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/format/SmileFormat.java

@@ -0,0 +1,602 @@
+package com.fdkankan.base.proto.format;
+/* 
+	Copyright (c) 2009, Orbitz World Wide
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, 
+	are permitted provided that the following conditions are met:
+
+		* Redistributions of source code must retain the above copyright notice, 
+		  this list of conditions and the following disclaimer.
+		* Redistributions in binary form must reproduce the above copyright notice, 
+		  this list of conditions and the following disclaimer in the documentation 
+		  and/or other materials provided with the distribution.
+		* Neither the name of the Orbitz World Wide nor the names of its contributors 
+		  may be used to endorse or promote products derived from this software 
+		  without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+import com.google.protobuf.*;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonToken;
+import org.codehaus.jackson.smile.SmileFactory;
+import org.codehaus.jackson.smile.SmileGenerator;
+import org.codehaus.jackson.smile.SmileParser;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Provide ascii text parsing and formatting support for proto2 instances. The implementation
+ * largely follows google/protobuf/text_format.cc.
+ * <p>
+ * (c) 2011 Neustar, Inc. All Rights Reserved.
+ *
+ * @author jeffrey.damick@neustar.biz Jeffrey Damick
+ *         Based on the original code by:
+ * @author eliran.bivas@gmail.com Eliran Bivas
+ * @author aantonov@orbitz.com Alex Antonov
+ *         <p/>
+ * @author wenboz@google.com Wenbo Zhu
+ * @author kenton@google.com Kenton Varda
+ */
+public class SmileFormat {
+    private static SmileFactory smileFactory = new SmileFactory();
+	
+		
+    /**
+     * Outputs a Smile representation of the Protocol Message supplied into the parameter output.
+     * (This representation is the new version of the classic "ProtocolPrinter" output from the
+     * original Protocol Buffer system)
+     */
+    public static void print(Message message, OutputStream output) throws IOException {
+        JsonGenerator generator = createGenerator(output);
+    	print(message, generator);
+    	generator.close();
+    }
+    
+    /**
+     * Outputs a Smile representation of the Protocol Message supplied into the parameter output.
+     * (This representation is the new version of the classic "ProtocolPrinter" output from the
+     * original Protocol Buffer system)
+     */
+    public static void print(Message message, JsonGenerator generator) throws IOException {
+    	generator.writeStartObject();
+    	printMessage(message, generator);
+        generator.writeEndObject();
+        generator.flush();
+    }
+
+    /**
+     * Outputs a Smile representation of {@code fields} to {@code output}.
+     */
+    public static void print(UnknownFieldSet fields, OutputStream output) throws IOException {
+    	JsonGenerator generator = createGenerator(output);
+    	generator.writeStartObject();
+    	printUnknownFields(fields, generator);
+        generator.writeEndObject();
+        generator.close();
+    }
+    
+    
+    
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     */
+    public static void merge(InputStream input, Message.Builder builder) throws IOException {
+        merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+    }
+
+        
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     * Extensions will be recognized if they are registered in {@code extensionRegistry}.
+     * @throws IOException 
+     */
+    public static void merge(InputStream input,
+                             ExtensionRegistry extensionRegistry,
+                             Message.Builder builder) throws IOException {
+    	
+    	SmileParser parser = smileFactory.createJsonParser(input); 
+    	merge(parser, extensionRegistry, builder);
+    }
+    
+    /**
+     * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+     * Extensions will be recognized if they are registered in {@code extensionRegistry}.
+     * @throws IOException 
+     */
+    public static void merge(JsonParser parser,                 
+    						 ExtensionRegistry extensionRegistry,
+                             Message.Builder builder) throws IOException {
+    	
+        JsonToken token = parser.nextToken();
+        if (token.equals(JsonToken.START_OBJECT)) {
+        	token = parser.nextToken();
+        }
+        while (token != null && !token.equals(JsonToken.END_OBJECT)) {
+        	mergeField(parser, extensionRegistry, builder);
+        	token = parser.nextToken();
+        }
+        
+        // Test to make sure the tokenizer has reached the end of the stream.
+        if (parser.nextToken() != null) {
+            throw new RuntimeException("Expecting the end of the stream, but there seems to be more data!  Check the input for a valid JSON format.");
+        }
+    }
+    
+    
+    
+    protected static JsonGenerator createGenerator(OutputStream output) throws IOException {
+    	SmileGenerator generator = smileFactory.createJsonGenerator(output);
+    	generator.enable(SmileGenerator.Feature.WRITE_HEADER);
+    	generator.enable(SmileGenerator.Feature.WRITE_END_MARKER);
+    	return generator;
+    }
+
+    
+    protected static void printMessage(Message message, JsonGenerator generator) throws IOException {
+
+        for (Iterator<Map.Entry<FieldDescriptor, Object>> iter = message.getAllFields().entrySet().iterator(); iter.hasNext();) {
+            Map.Entry<FieldDescriptor, Object> field = iter.next();
+            printField(field.getKey(), field.getValue(), generator);
+        }
+        printUnknownFields(message.getUnknownFields(), generator);
+    }
+
+    public static void printField(FieldDescriptor field, Object value, JsonGenerator generator) throws IOException {
+
+        printSingleField(field, value, generator);
+    }
+
+    private static void printSingleField(FieldDescriptor field,
+                                         Object value,
+                                         JsonGenerator generator) throws IOException {
+        if (field.isExtension()) {
+            // We special-case MessageSet elements for compatibility with proto1.
+            if (field.getContainingType().getOptions().getMessageSetWireFormat()
+                && (field.getType() == FieldDescriptor.Type.MESSAGE) && (field.isOptional())
+                // object equality
+                && (field.getExtensionScope() == field.getMessageType())) {
+                generator.writeFieldName(field.getMessageType().getFullName());
+            } else {
+            	// extensions will have '.' in them, while normal fields wont..
+            	generator.writeFieldName(field.getFullName());
+            }
+        } else {
+            if (field.getType() == FieldDescriptor.Type.GROUP) {
+                // Groups must be serialized with their original capitalization.
+                generator.writeFieldName(field.getMessageType().getName());
+            } else {
+                generator.writeFieldName(field.getName());
+            }
+        }
+
+        // Done with the name, on to the value
+        if (field.isRepeated()) {
+            // Repeated field. Print each element.
+            generator.writeStartArray();
+            for (Iterator<?> iter = ((List<?>) value).iterator(); iter.hasNext();) {
+                printFieldValue(field, iter.next(), generator);
+            }
+            generator.writeEndArray();
+        } else {
+            printFieldValue(field, value, generator);
+        }
+    }
+
+    private static void printFieldValue(FieldDescriptor field, Object value, JsonGenerator generator) throws IOException {
+    	// TODO: look at using field.getType().getJavaType(), to simplify this..
+    	switch (field.getType()) {
+            case INT32:
+            case SINT32:
+            case SFIXED32:
+            	generator.writeNumber((Integer)value);
+            	break;
+            
+            case INT64:
+            case SINT64:
+            case SFIXED64:
+            	generator.writeNumber((Long)value);
+            	break;
+            	
+            case FLOAT:
+            	generator.writeNumber((Float)value);
+            	break;
+            	
+            case DOUBLE:
+            	generator.writeNumber((Double)value);
+            	break;
+            	
+            case BOOL:
+                // Good old toString() does what we want for these types.
+                generator.writeBoolean((Boolean)value);
+                break;
+
+            case UINT32:
+            case FIXED32:
+                generator.writeNumber(unsignedInt((Integer) value));
+                break;
+
+            case UINT64:
+            case FIXED64:
+                generator.writeNumber(unsignedLong((Long) value));
+                break;
+
+            case STRING:
+            	generator.writeString((String) value);
+                break;
+
+            case BYTES: {
+            	// Here we break with JsonFormat - since there is an issue with non-utf8 bytes..
+            	generator.writeBinary(((ByteString)value).toByteArray());
+                break;
+            }
+
+            case ENUM: {
+            	generator.writeString(((EnumValueDescriptor) value).getName());
+                break;
+            }
+
+            case MESSAGE:
+            case GROUP:
+            	generator.writeStartObject();
+                printMessage((Message) value, generator);
+                generator.writeEndObject();
+                break;
+        }
+    }
+
+    protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGenerator generator) throws IOException {
+        for (Map.Entry<Integer, UnknownFieldSet.Field> entry : unknownFields.asMap().entrySet()) {
+            UnknownFieldSet.Field field = entry.getValue();
+            
+            generator.writeArrayFieldStart(entry.getKey().toString());
+            for (long value : field.getVarintList()) {
+                generator.writeNumber(value);
+            }
+            for (int value : field.getFixed32List()) {
+                generator.writeNumber(value);
+            }
+            for (long value : field.getFixed64List()) {
+                generator.writeNumber(value);
+            }
+            for (ByteString value : field.getLengthDelimitedList()) {
+            	// here we break with the JsonFormat to support non-utf8 bytes
+            	generator.writeBinary(value.toByteArray());
+            }
+            for (UnknownFieldSet value : field.getGroupList()) {
+                generator.writeStartObject();
+                printUnknownFields(value, generator);
+                generator.writeEndObject();
+            }
+            generator.writeEndArray();
+        }
+    }
+
+
+
+    // =================================================================
+    // Parsing
+   
+    private static final Pattern DIGITS = Pattern.compile(
+          "[0-9]",
+          Pattern.CASE_INSENSITIVE);
+
+    /**
+     * Parse a single field from {@code parser} and merge it into {@code builder}. If a ',' is
+     * detected after the field ends, the next field will be parsed automatically
+     * @throws IOException 
+     * @throws JsonParseException 
+     */
+    protected static void mergeField(JsonParser parser,
+                                   ExtensionRegistry extensionRegistry,
+                                   Message.Builder builder) throws JsonParseException, IOException {
+        FieldDescriptor field = null;
+        Descriptor type = builder.getDescriptorForType();
+        boolean unknown = false;
+        ExtensionRegistry.ExtensionInfo extension = null;
+        JsonToken token = parser.getCurrentToken();
+
+        if (token != null) {
+            String name = parser.getCurrentName();
+            
+            if (name.contains(".")) {
+            	// should be an extension
+            	extension = extensionRegistry.findExtensionByName(name);
+                if (extension == null) {
+                    throw new RuntimeException("Extension \""
+                    		+ name + "\" not found in the ExtensionRegistry.");
+                } else if (extension.descriptor.getContainingType() != type) {
+                    throw new RuntimeException("Extension \"" + name
+                    		+ "\" does not extend message type \""
+                    		+ type.getFullName() + "\".");
+                }
+
+            	field = extension.descriptor;
+            } else {
+            	field = type.findFieldByName(name);
+            }
+
+            // Group names are expected to be capitalized as they appear in the
+            // .proto file, which actually matches their type names, not their field
+            // names.
+            if (field == null) {
+                // Explicitly specify US locale so that this code does not break when
+                // executing in Turkey.
+                String lowerName = name.toLowerCase(Locale.US);
+                field = type.findFieldByName(lowerName);
+                // If the case-insensitive match worked but the field is NOT a group,
+                if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
+                    field = null;
+                }
+            }
+            // Again, special-case group names as described above.
+            if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
+                && !field.getMessageType().getName().equals(name)
+                && !field.getMessageType().getFullName().equalsIgnoreCase(name) /* extension */) {
+                field = null;
+            }
+
+            // Last try to lookup by field-index if 'name' is numeric,
+            // which indicates a possible unknown field
+            if (field == null && DIGITS.matcher(name).matches()) {
+                field = type.findFieldByNumber(Integer.parseInt(name));
+                unknown = true;
+            }
+
+            // no throwing exceptions if field not found, since it could be a different version.
+            if (field == null) {
+            	UnknownFieldSet.Builder unknownsBuilder = UnknownFieldSet.newBuilder();
+            	handleMissingField(name, parser, extensionRegistry, unknownsBuilder);
+            	builder.setUnknownFields(unknownsBuilder.build());
+            }
+        }
+
+        if (field != null) {
+        	token = parser.nextToken();
+        	
+            boolean array = token.equals(JsonToken.START_ARRAY);
+
+            if (array) {
+            	token = parser.nextToken();
+                while (!token.equals(JsonToken.END_ARRAY)) {
+                    handleValue(parser, extensionRegistry, builder, field, extension, unknown);
+                    token = parser.nextToken();
+                }
+            } else {
+                handleValue(parser, extensionRegistry, builder, field, extension, unknown);
+            }
+        }
+    }
+
+    private static void handleMissingField(String fieldName, JsonParser parser,
+                                           ExtensionRegistry extensionRegistry,
+                                           UnknownFieldSet.Builder builder) throws IOException {
+    	
+        JsonToken token = parser.nextToken();
+        if (token.equals(JsonToken.START_OBJECT)) {
+            // Message structure
+        	token = parser.nextToken(); // skip name
+        	while (token != null && !token.equals(JsonToken.END_OBJECT)) {
+                handleMissingField(fieldName, parser, extensionRegistry, builder);
+                token = parser.nextToken(); // get } or field name
+            }
+        } else if (token.equals(JsonToken.START_ARRAY)) {
+            // Collection
+            do {
+                handleMissingField(fieldName, parser, extensionRegistry, builder);
+                token = parser.getCurrentToken(); // got value or ]
+            } while (token != null && !token.equals(JsonToken.END_ARRAY));
+        } else {
+            // Primitive value
+        	// NULL, INT, BOOL, STRING
+        	// nothing to do..
+        }
+    }
+
+    private static void handleValue(JsonParser parser,
+                                    ExtensionRegistry extensionRegistry,
+                                    Message.Builder builder,
+                                    FieldDescriptor field,
+                                    ExtensionRegistry.ExtensionInfo extension,
+                                    boolean unknown) throws IOException {
+
+        Object value = null;
+        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+            value = handleObject(parser, extensionRegistry, builder, field, extension, unknown);
+        } else {
+            value = handlePrimitive(parser, field);
+        }
+        if (value != null) {
+            if (field.isRepeated()) {
+                builder.addRepeatedField(field, value);
+            } else {
+                builder.setField(field, value);
+            }
+        }
+    }
+
+    private static Object handlePrimitive(JsonParser parser, FieldDescriptor field) throws IOException {
+        Object value = null;
+        
+        JsonToken token = parser.getCurrentToken();
+        
+        if (token.equals(JsonToken.VALUE_NULL)) {
+            return value;
+        }
+        
+        switch (field.getType()) {
+            case INT32:
+            case SINT32:
+            case SFIXED32:
+            	value = parser.getIntValue();
+                break;
+
+            case INT64:
+            case SINT64:
+            case SFIXED64:
+            	value = parser.getLongValue();
+                break;
+
+            case UINT32:
+            case FIXED32:
+            	int valueInt = parser.getIntValue();
+            	if (valueInt < 0) {
+            		throw new NumberFormatException("Number must be positive: " + valueInt);
+            	}
+            	value = valueInt;
+                break;
+
+            case UINT64:
+            case FIXED64:
+            	long valueLong = parser.getLongValue();
+            	if (valueLong < 0) {
+            		throw new NumberFormatException("Number must be positive: " + valueLong);
+            	}
+            	value = valueLong;
+                break;
+
+            case FLOAT:
+            	value = parser.getFloatValue();
+                break;
+
+            case DOUBLE:
+            	value = parser.getDoubleValue();
+                break;
+
+            case BOOL:
+            	value = parser.getBooleanValue();
+                break;
+
+            case STRING:
+            	value = parser.getText();
+                break;
+
+            case BYTES:
+            	value = ByteString.copyFrom(parser.getBinaryValue());
+                break;
+
+            case ENUM: {
+                EnumDescriptor enumType = field.getEnumType();
+                if (token.equals(JsonToken.VALUE_NUMBER_INT)) {
+                    int number = parser.getIntValue();
+                    value = enumType.findValueByNumber(number);
+                    if (value == null) {
+                        throw new RuntimeException("Enum type \""
+                        		+ enumType.getFullName()
+                        		+ "\" has no value with number "
+                        		+ number + ".");
+                    }
+                } else {
+                    String id = parser.getText();
+                    value = enumType.findValueByName(id);
+                    if (value == null) {
+                    	throw new RuntimeException("Enum type \""
+                    			+ enumType.getFullName()
+                    			+ "\" has no value named \""
+                    			+ id + "\".");
+                    }
+                }
+                break;
+            }
+
+            case MESSAGE:
+            case GROUP:
+                throw new RuntimeException("Can't get here.");
+        }
+        return value;
+    }
+    
+
+    private static Object handleObject(JsonParser parser,
+                                       ExtensionRegistry extensionRegistry,
+                                       Message.Builder builder,
+                                       FieldDescriptor field,
+                                       ExtensionRegistry.ExtensionInfo extension,
+                                       boolean unknown) throws IOException {
+
+        Message.Builder subBuilder;
+        if (extension == null) {
+            subBuilder = builder.newBuilderForField(field);
+        } else {
+            subBuilder = extension.defaultInstance.newBuilderForType();
+        }
+
+        JsonToken token = parser.getCurrentToken();
+
+        if (unknown) {
+        	ByteString data = ByteString.copyFrom(parser.getBinaryValue());
+            try {
+                subBuilder.mergeFrom(data);
+                return subBuilder.build();
+            } catch (InvalidProtocolBufferException e) {
+                throw new RuntimeException("Failed to build " + field.getFullName() + " from " + data);
+            }
+        }
+
+        //token = parser.nextToken();
+        if (token.equals(JsonToken.START_OBJECT)) {
+	        token = parser.nextToken();
+	        while (token != null && !token.equals(JsonToken.END_OBJECT)) {
+	            mergeField(parser, extensionRegistry, subBuilder);
+	            token = parser.nextToken();
+	        }
+        }
+        return subBuilder.build();
+    }
+
+    // =================================================================
+    // Utility functions
+    //
+    // Some of these methods are package-private because Descriptors.java uses
+    // them.
+    
+    /**
+     * Convert an unsigned 32-bit integer to a string.
+     */
+    private static Integer unsignedInt(int value) {
+        if (value < 0) {
+            return (int) ((value) & 0x00000000FFFFFFFFL);
+        }
+        return value;
+    }
+
+    /**
+     * Convert an unsigned 64-bit integer to a string.
+     */
+    private static Long unsignedLong(long value) {
+        if (value < 0) {
+            // Pull off the most-significant bit so that BigInteger doesn't think
+            // the number is negative, then set it again using setBit().
+            return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL).setBit(63).longValue();
+        }
+        return value;
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 1333 - 0
4dkankan-base/src/main/java/com/fdkankan/base/proto/format/XmlFormat.java


+ 47 - 0
4dkankan-base/src/main/java/com/fdkankan/base/service/IBaseService.java

@@ -0,0 +1,47 @@
+package com.fdkankan.base.service;
+
+import com.github.pagehelper.PageInfo;
+import tk.mybatis.mapper.entity.Condition;
+
+import java.io.Serializable;
+import java.util.List;
+
+public interface IBaseService<T, ID extends Serializable> {
+
+    public abstract T findById(ID id);
+
+    public abstract T findOne(T entity);
+
+    public abstract List<T> findByIds(String ids);
+
+    public abstract long count();
+
+    public abstract boolean exists(ID id);
+
+    public abstract int save(T entity);
+
+    public abstract int update(T entity);
+
+    public abstract int updateAll(T entity);
+
+    public abstract int deleteById(ID id);
+
+    public abstract int deleteByIds(String ids);
+
+    public abstract int delete(T entity);
+
+    public abstract List<T> findAll(Condition condition, String orderBy);
+
+    public abstract List<T> findAll(Condition condition);
+
+    public abstract List<T> findAll();
+
+    public abstract PageInfo<T> findAll(int pageNum, int pageSize);
+
+    public abstract PageInfo<T> findAll(int pageNum, int pageSize, String orderBy);
+
+    public abstract PageInfo<T> findAll(Condition condition, int pageNum, int pageSize);
+
+    public abstract PageInfo<T> findAll(Condition condition, int pageNum, int pageSize, String orderBy);
+
+}

+ 6 - 0
4dkankan-base/src/main/java/com/fdkankan/base/service/ILogService.java

@@ -0,0 +1,6 @@
+package com.fdkankan.base.service;
+
+import com.fdkankan.base.entity.LogEntity;
+
+public interface ILogService extends IBaseService<LogEntity, Long>{
+}

+ 156 - 0
4dkankan-base/src/main/java/com/fdkankan/base/service/impl/BaseServiceImpl.java

@@ -0,0 +1,156 @@
+package com.fdkankan.base.service.impl;
+
+import com.fdkankan.base.entity.BaseEntity;
+import com.fdkankan.base.mapper.base.IBaseMapper;
+import com.fdkankan.base.service.IBaseService;
+import com.fdkankan.base.util.SnowFlakeUUidUtils;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.apache.ibatis.annotations.Options;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import tk.mybatis.mapper.entity.Condition;
+
+import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.util.Date;
+import java.util.List;
+
+@Transactional
+public abstract class BaseServiceImpl<T extends BaseEntity, ID extends Serializable> implements IBaseService<T, ID> {
+
+    public abstract IBaseMapper<T, ID> getBaseMapper();
+
+    private Class<T> entityClass;
+
+    public BaseServiceImpl(){
+        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
+        entityClass = (Class<T>) pt.getActualTypeArguments()[0];
+    }
+
+    @Override
+    public T findById(ID id){
+        Condition condition = new Condition(entityClass);
+        condition.createCriteria().andEqualTo("id", id);
+        condition.and().andEqualTo("isDelete", "0");
+        List<T> ts = getBaseMapper().selectByCondition(condition);
+        if (ts != null && ts.size() > 0){
+            return ts.get(0);
+        }else{
+            return null;
+        }
+    }
+
+    @Override
+    public T findOne(T entity){
+        entity.setIsDelete("0");
+        return getBaseMapper().selectOne(entity);
+    }
+
+    @Override
+    public List<T> findAll(){
+        Condition condition = new Condition(entityClass);
+        condition.createCriteria().andEqualTo("isDelete", "0");
+        return getBaseMapper().selectByCondition(condition);
+    }
+
+    /**
+     * 根据主键字符串进行查询,类中只有存在一个带有@Id注解的字段
+     *
+     * @param ids 如 "1,2,3,4"
+     * @return
+     */
+    @Override
+    public List<T> findByIds(String ids){
+        return getBaseMapper().selectByIds(ids);
+    }
+
+    @Override
+    public long count(){
+        List<T> all = this.findAll();
+        if (all != null && all.size() > 0){
+            return all.size();
+        }
+        return 0;
+    }
+
+    @Override
+    public boolean exists(ID id){
+        return getBaseMapper().existsWithPrimaryKey(id);
+    }
+
+    @Override
+    public int save(T entity) {
+        entity.setId(SnowFlakeUUidUtils.generaUUid(null, null, null));
+        entity.setCreateTime(new Date());
+        entity.setUpdateTime(new Date());
+        entity.setIsDelete("0");
+        return getBaseMapper().insertSelective(entity);
+    }
+
+    @Override
+    public int update(T entity) {
+        entity.setUpdateTime(new Date());
+        return getBaseMapper().updateByPrimaryKeySelective(entity);
+    }
+
+    @Override
+    public int updateAll(T entity) {
+        entity.setUpdateTime(new Date());
+        return getBaseMapper().updateByPrimaryKey(entity);
+    }
+
+    @Override
+    public int deleteById(ID id) {
+        return getBaseMapper().deleteByPrimaryKey(id);
+    }
+
+    @Override
+    public int deleteByIds(String ids){
+        return getBaseMapper().deleteByIds(ids);
+    }
+
+    @Override
+    public int delete(T entity){
+        return getBaseMapper().delete(entity);
+    }
+
+    public List<T> findAll(Condition condition){
+        condition.and().andEqualTo("isDelete", "0");
+        return getBaseMapper().selectByCondition(condition);
+    }
+
+    public List<T> findAll(Condition condition, String orderBy){
+        condition.and().andEqualTo("isDelete", "0");
+        if (!StringUtils.isEmpty(orderBy)){
+            PageHelper.orderBy(orderBy);
+        }
+        return getBaseMapper().selectByCondition(condition);
+    }
+
+    public PageInfo<T> findAll(int pageNum, int pageSize){
+        PageHelper.startPage(pageNum, pageSize);
+        return new PageInfo<>(this.findAll());
+    }
+
+    public PageInfo<T> findAll(int pageNum, int pageSize, String orderBy){
+        PageHelper.startPage(pageNum, pageSize);
+        if (!StringUtils.isEmpty(orderBy)){
+            PageHelper.orderBy(orderBy);
+        }
+        return new PageInfo<>(this.findAll());
+    }
+
+    public PageInfo<T> findAll(Condition condition, int pageNum, int pageSize){
+        PageHelper.startPage(pageNum, pageSize);
+        return new PageInfo<>(this.findAll(condition));
+    }
+
+    public PageInfo<T> findAll(Condition condition, int pageNum, int pageSize, String orderBy){
+        PageHelper.startPage(pageNum, pageSize);
+        if (!StringUtils.isEmpty(orderBy)){
+            PageHelper.orderBy(orderBy);
+        }
+        return new PageInfo<>(this.findAll(condition));
+    }
+}

+ 123 - 0
4dkankan-base/src/main/java/com/fdkankan/base/service/impl/FileService.java

@@ -0,0 +1,123 @@
+package com.fdkankan.base.service.impl;
+
+import com.fdkankan.base.config.FileRouteConfig;
+import com.fdkankan.base.util.FileUpload;
+import com.fdkankan.base.util.FileUtil;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.UUID;
+
+@Log4j2
+@Service
+public class FileService {
+
+    @Autowired
+    private FileRouteConfig routeConfig;
+
+    public String saveFile(MultipartFile file, String filePath, String fileId) throws IOException {
+        //扩展名格式
+        String extName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
+        String name;
+        /*
+          指定上传目录
+         */
+        if (filePath != null && !"".equals(filePath.trim())) {
+            name = designatedUp(filePath, fileId, file);
+            return name;
+        }
+        /*
+          默认上传目录
+         */
+        //图片类型文件
+        if (this.inArray(routeConfig.getImageType(), extName)) {
+            filePath = routeConfig.getImageFolder();
+        }
+        //视频类型文件
+        else if (this.inArray(routeConfig.getVideoType(), extName)) {
+            filePath = routeConfig.getVideoFolder();
+        }
+        //文档类型文件
+        else if (this.inArray(routeConfig.getDocumentType(), extName)) {
+            filePath = routeConfig.getDocumentFolder();
+        }
+        //音频类型文件
+        else if (this.inArray(routeConfig.getMusicType(), extName)) {
+            filePath = routeConfig.getMusicFolder();
+        } else {
+            return "This upload type is not supported temporarily";
+        }
+        name = myfileUp(filePath, file);
+        return name;
+    }
+
+    /**
+     * 删除文件
+     *
+     * @param filePath 包含文件路径的文件名
+     * @return
+     */
+    public String dropFile(String filePath) {
+        try {
+            FileUtil.delFile(routeConfig.getHardDisk() + File.separator + filePath);
+            return "successful operation";
+        } catch (Exception e) {
+            return "drop file error";
+        }
+    }
+
+    /**
+     * 判断数组中是否包含某个元素
+     *
+     * @param array   类型的数组
+     * @param element 被检查的类型
+     * @return
+     */
+    private boolean inArray(String[] array, String element) {
+        boolean flag = false;
+        for (String type : array) {
+            if (element.equals(type)) {
+                flag = true;
+                break;
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * 默认上传文件到文件夹
+     *
+     * @param folder 默认文件夹
+     * @param file   上传的文件
+     * @return
+     */
+    private String myfileUp(String folder, MultipartFile file) throws IOException {
+        LocalDate today = LocalDate.now();
+        String saveName = File.separator + today.getYear() + "." + today.getMonthValue() + File.separator;
+        String fileCode = UUID.randomUUID().toString().trim().replaceAll("-", "");
+        String returnName = FileUpload.fileUp(file, routeConfig.getHardDisk() + File.separator + folder + saveName, fileCode);
+        saveName = folder + File.separator + saveName + File.separator + returnName;
+        log.warn("This file has been uploaded: " + saveName);
+        return saveName;
+    }
+
+    /**
+     * 指定目录上传文件
+     *
+     * @param folder 指定文件夹
+     * @param file   上传文件
+     * @return
+     */
+    private String designatedUp(String folder, String fileId, MultipartFile file) throws IOException {
+        StringBuffer sb = new StringBuffer(routeConfig.getHardDisk()).append(File.separator).append(folder);
+        String returnName = FileUpload.fileUp(file, sb.toString(), fileId);
+        String filePathName = sb.toString() + File.separator + File.separator + returnName;
+        log.warn("This file has been uploaded: " + filePathName);
+        return filePathName;
+    }
+}

+ 22 - 0
4dkankan-base/src/main/java/com/fdkankan/base/service/impl/LogServiceImpl.java

@@ -0,0 +1,22 @@
+package com.fdkankan.base.service.impl;
+
+import com.fdkankan.base.entity.LogEntity;
+import com.fdkankan.base.mapper.base.IBaseMapper;
+import com.fdkankan.base.mapper.ILogMapper;
+import com.fdkankan.base.service.ILogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service("logService")
+@Transactional
+public class LogServiceImpl extends BaseServiceImpl<LogEntity, Long> implements ILogService{
+
+    @Autowired
+    private ILogMapper logMapper;
+
+    @Autowired
+    public IBaseMapper<LogEntity, Long> getBaseMapper(){
+        return this.logMapper;
+    }
+}

+ 95 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/AesUtil.java

@@ -0,0 +1,95 @@
+package com.fdkankan.base.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import com.aliyuncs.utils.Base64Helper;
+import org.apache.commons.codec.binary.Base64;
+
+import java.util.UUID;
+
+/**
+ * Created by Hb_zzZ on 2020/4/9.
+ */
+public class AesUtil {
+
+    /**
+     * @author miracle.qu
+     * @see AES算法加密明文
+     * @param data 明文
+     * @param key 密钥,长度16
+     * @param iv 偏移量,长度16
+     * @return 密文
+     */
+    public static String encryptAES(String data,String key,String iv) throws Exception {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+            int blockSize = cipher.getBlockSize();
+            byte[] dataBytes = data.getBytes();
+            int plaintextLength = dataBytes.length;
+
+            if (plaintextLength % blockSize != 0) {
+                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
+            }
+
+            byte[] plaintext = new byte[plaintextLength];
+            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
+
+            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
+
+            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
+            byte[] encrypted = cipher.doFinal(plaintext);
+
+            return Base64Helper.encode(encrypted).trim();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * @author miracle.qu
+     * @see AES算法解密密文
+     * @param data 密文
+     * @param key 密钥,长度16
+     * @param iv 偏移量,长度16
+     * @return 明文
+     */
+//    public static String decryptAES(String data,String key,String iv) throws Exception {
+//        try
+//        {
+//            byte[] encrypted1 = Base64Helper.decode(data);
+//
+//            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+//            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+//            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
+//
+//            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
+//
+//            byte[] original = cipher.doFinal(encrypted1);
+//            String originalString = new String(original);
+//            return originalString.trim();
+//        }
+//        catch (Exception e) {
+//            e.printStackTrace();
+//            return null;
+//        }
+//    }
+
+    public static void main(String[] args) {
+        try{
+            UUID uuid = UUID.randomUUID();
+            String id = uuid.toString().replace("-","");
+
+            String s = "[{\"Devicemac\":\"74ee2ac1dabc#74ee2abff122\"},{\"Devicemac\":\"74ee2ac1c236#74ee2ab96d80\"},{\"Devicemac\":\"74ee2ac1c236#74ee2ab96d80\"},{\"Devicemac\":\"74ee2ac1c236#74ee2ab96d80\"},{\"Devicemac\":\"74ee2ac1c236#74ee2ab96d80\"},{\"Devicemac\":\"74ee2ac1c236#74ee2ab96d80\"},{\"Devicemac\":\"74ee2ac1c236#74ee2ab96d80\"}]";
+            String key = id.substring(0,16);
+            System.out.println("key:" + key);
+            System.out.println(encryptAES(s,key,key));
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+}

+ 220 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/ConvertCommonUtils.java

@@ -0,0 +1,220 @@
+package com.fdkankan.base.util;
+
+//import com.fdkankan.base.proto.Common;
+import com.fdkankan.base.proto.Common;
+import com.fdkankan.base.proto.format.JsonFormat;
+import lombok.extern.log4j.Log4j2;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Log4j2
+public class ConvertCommonUtils {
+
+    public static void convertVisionModelDataToTxt(String srcPath, String desPath) throws Exception {
+
+        BufferedOutputStream bos = null;
+        BufferedInputStream bis = null;
+        try {
+            File file = new File(srcPath);
+            FileInputStream fis = new FileInputStream(file);
+
+            Common.NavigationInfo data_NavigationInfo = Common.NavigationInfo.parseFrom(fis);
+
+            String jsonFormat1 = JsonFormat.printToString(data_NavigationInfo);
+            ByteArrayInputStream stream = new ByteArrayInputStream(jsonFormat1.getBytes());
+            bos = new BufferedOutputStream(new FileOutputStream(desPath));//设置输出路径
+            bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            //out.close();
+            bis.close();
+            bos.close();
+        } catch (Exception e) {
+            StringWriter trace = new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        } finally {
+            if (bos != null) {
+                bos.close();
+            }
+            if (bis != null) {
+                bis.close();
+            }
+        }
+    }
+
+    public static void convertTxtToVisionModelData(String srcPath, String desPath) throws Exception {
+        BufferedOutputStream bos = null;
+        BufferedInputStream bis = null;
+        try {
+            Common.NavigationInfo.Builder builder = Common.NavigationInfo.newBuilder();
+            String jsonFormat = readTxtFileToJson(srcPath);
+            JsonFormat.merge(jsonFormat, builder);
+            byte[] buf = builder.build().toByteArray();
+
+            //把序列化后的数据写入本地磁盘
+            ByteArrayInputStream stream = new ByteArrayInputStream(buf);
+            bos = new BufferedOutputStream(new FileOutputStream(desPath));//设置输出路径
+            bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            bis.close();
+            bos.close();
+        } catch (Exception e) {
+            StringWriter trace = new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        } finally {
+            if (bos != null) {
+                bos.close();
+            }
+            if (bis != null) {
+                bis.close();
+            }
+        }
+    }
+
+    public static String readTxtFileToJson(String filePath) {
+        try {
+            String encoding = "UTF-8";
+            File file = new File(filePath);
+            if (file.isFile() && file.exists()) {
+                InputStreamReader read = new InputStreamReader(
+                        new FileInputStream(file), encoding);
+                BufferedReader bufferedReader = new BufferedReader(read);
+                String lineTxt = null;
+                String result = "";
+                while ((lineTxt = bufferedReader.readLine()) != null) {
+                    result += lineTxt;
+                }
+                read.close();
+                return result;
+            } else {
+                return null;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+
+    public List<List<String>> descartes(List<List<String>> dimValue) {
+        List<List<String>> res = new ArrayList<>();
+        if (dimValue == null || dimValue.size() == 0)
+            return res;
+        backtrace(dimValue, 0, res, new ArrayList<>());
+        return res;
+
+    }
+
+    /**
+     * 递归回溯法求解
+     *
+     * @param dimValue 原始数据集合
+     * @param index 当前执行的集合索引
+     * @param result 结果集合
+     * @param curList 当前的单个结果集
+     */
+    private void backtrace(List<List<String>> dimValue, int index,
+                           List<List<String>> result, List<String> curList) {
+
+        if (curList.size() == dimValue.size())
+            result.add(new ArrayList<>(curList));
+        else
+            for (int j = 0; j < dimValue.get(index).size(); j++) {
+                curList.add(dimValue.get(index).get(j));
+                backtrace(dimValue, index + 1, result, curList);
+                curList.remove(curList.size() - 1);
+            }
+
+    }
+
+    public static void main(String[] args) {
+        List<String> list1 = new ArrayList<String>();
+        list1.add("普通会员");
+        list1.add("专业会员");
+        list1.add("商业会员");
+        List<String> list2 = new ArrayList<String>();
+        list2.add("1G");
+        list2.add("1T");
+        List<List<String>> dimValue = new ArrayList<List<String>>();
+        dimValue.add(list1);
+        dimValue.add(list2);
+
+        // 递归实现笛卡尔积
+        ConvertCommonUtils s = new ConvertCommonUtils();
+        List<List<String>> res = s.descartes(dimValue);
+        System.out.println("递归实现笛卡尔乘积: 共 " + res.size() + " 个结果");
+        for (List<String> list : res) {
+            for (String string : list) {
+                System.out.print(string + " ");
+            }
+            System.out.println();
+        }
+    }
+
+    public static void convertTxtToVisionmodeldata(String srcpath,String despath)throws Exception
+    {
+        try
+        {
+            Common.NavigationInfo.Builder builder = Common.NavigationInfo.newBuilder();
+            String jsonFormat = readTxtFileToJson(srcpath);
+            JsonFormat.merge(jsonFormat, builder);
+            byte[] buf= builder.build().toByteArray();
+
+            //把序列化后的数据写入本地磁盘
+            ByteArrayInputStream stream = new ByteArrayInputStream(buf);
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(despath));//设置输出路径
+            BufferedInputStream bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            bis.close();
+            bos.close();
+        }
+        catch(Exception e)
+        {
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        }
+    }
+
+    public static void convertVisionmodeldataToTxt(String srcpath,String despath)throws Exception
+    {
+        try
+        {
+            File file = new File(srcpath);
+            FileInputStream fis=new FileInputStream(file);
+
+            Common.NavigationInfo data_NavigationInfo = Common.NavigationInfo.parseFrom(fis);
+
+            //PrintStream out = new PrintStream(despath);
+            String jsonFormat1 = JsonFormat.printToString(data_NavigationInfo);
+            ByteArrayInputStream stream = new ByteArrayInputStream(jsonFormat1.getBytes());
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(despath));//设置输出路径
+            BufferedInputStream bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            //out.close();
+            bis.close();
+            bos.close();
+        }
+        catch(Exception e)
+        {
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        }
+    }
+}

+ 220 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/ConvertUtils.java

@@ -0,0 +1,220 @@
+package com.fdkankan.base.util;
+
+//import com.fdkankan.base.proto.Common;
+import com.fdkankan.base.proto.Visionmodeldata;
+import com.fdkankan.base.proto.format.JsonFormat;
+import lombok.extern.log4j.Log4j2;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Log4j2
+public class ConvertUtils {
+
+    public static void convertVisionModelDataToTxt(String srcPath, String desPath) throws Exception {
+
+        BufferedOutputStream bos = null;
+        BufferedInputStream bis = null;
+        try {
+            File file = new File(srcPath);
+            FileInputStream fis = new FileInputStream(file);
+
+            Visionmodeldata.NavigationInfo data_NavigationInfo = Visionmodeldata.NavigationInfo.parseFrom(fis);
+
+            String jsonFormat1 = JsonFormat.printToString(data_NavigationInfo);
+            ByteArrayInputStream stream = new ByteArrayInputStream(jsonFormat1.getBytes());
+            bos = new BufferedOutputStream(new FileOutputStream(desPath));//设置输出路径
+            bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            //out.close();
+            bis.close();
+            bos.close();
+        } catch (Exception e) {
+            StringWriter trace = new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        } finally {
+            if (bos != null) {
+                bos.close();
+            }
+            if (bis != null) {
+                bis.close();
+            }
+        }
+    }
+
+    public static void convertTxtToVisionModelData(String srcPath, String desPath) throws Exception {
+        BufferedOutputStream bos = null;
+        BufferedInputStream bis = null;
+        try {
+            Visionmodeldata.NavigationInfo.Builder builder = Visionmodeldata.NavigationInfo.newBuilder();
+            String jsonFormat = readTxtFileToJson(srcPath);
+            JsonFormat.merge(jsonFormat, builder);
+            byte[] buf = builder.build().toByteArray();
+
+            //把序列化后的数据写入本地磁盘
+            ByteArrayInputStream stream = new ByteArrayInputStream(buf);
+            bos = new BufferedOutputStream(new FileOutputStream(desPath));//设置输出路径
+            bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            bis.close();
+            bos.close();
+        } catch (Exception e) {
+            StringWriter trace = new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        } finally {
+            if (bos != null) {
+                bos.close();
+            }
+            if (bis != null) {
+                bis.close();
+            }
+        }
+    }
+
+    public static String readTxtFileToJson(String filePath) {
+        try {
+            String encoding = "UTF-8";
+            File file = new File(filePath);
+            if (file.isFile() && file.exists()) {
+                InputStreamReader read = new InputStreamReader(
+                        new FileInputStream(file), encoding);
+                BufferedReader bufferedReader = new BufferedReader(read);
+                String lineTxt = null;
+                String result = "";
+                while ((lineTxt = bufferedReader.readLine()) != null) {
+                    result += lineTxt;
+                }
+                read.close();
+                return result;
+            } else {
+                return null;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+
+    public List<List<String>> descartes(List<List<String>> dimValue) {
+        List<List<String>> res = new ArrayList<>();
+        if (dimValue == null || dimValue.size() == 0)
+            return res;
+        backtrace(dimValue, 0, res, new ArrayList<>());
+        return res;
+
+    }
+
+    /**
+     * 递归回溯法求解
+     *
+     * @param dimValue 原始数据集合
+     * @param index 当前执行的集合索引
+     * @param result 结果集合
+     * @param curList 当前的单个结果集
+     */
+    private void backtrace(List<List<String>> dimValue, int index,
+                           List<List<String>> result, List<String> curList) {
+
+        if (curList.size() == dimValue.size())
+            result.add(new ArrayList<>(curList));
+        else
+            for (int j = 0; j < dimValue.get(index).size(); j++) {
+                curList.add(dimValue.get(index).get(j));
+                backtrace(dimValue, index + 1, result, curList);
+                curList.remove(curList.size() - 1);
+            }
+
+    }
+
+    public static void main(String[] args) {
+        List<String> list1 = new ArrayList<String>();
+        list1.add("普通会员");
+        list1.add("专业会员");
+        list1.add("商业会员");
+        List<String> list2 = new ArrayList<String>();
+        list2.add("1G");
+        list2.add("1T");
+        List<List<String>> dimValue = new ArrayList<List<String>>();
+        dimValue.add(list1);
+        dimValue.add(list2);
+
+        // 递归实现笛卡尔积
+        ConvertUtils s = new ConvertUtils();
+        List<List<String>> res = s.descartes(dimValue);
+        System.out.println("递归实现笛卡尔乘积: 共 " + res.size() + " 个结果");
+        for (List<String> list : res) {
+            for (String string : list) {
+                System.out.print(string + " ");
+            }
+            System.out.println();
+        }
+    }
+
+    public static void convertTxtToVisionmodeldata(String srcpath,String despath)throws Exception
+    {
+        try
+        {
+            Visionmodeldata.NavigationInfo.Builder builder = Visionmodeldata.NavigationInfo.newBuilder();
+            String jsonFormat = readTxtFileToJson(srcpath);
+            JsonFormat.merge(jsonFormat, builder);
+            byte[] buf= builder.build().toByteArray();
+
+            //把序列化后的数据写入本地磁盘
+            ByteArrayInputStream stream = new ByteArrayInputStream(buf);
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(despath));//设置输出路径
+            BufferedInputStream bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            bis.close();
+            bos.close();
+        }
+        catch(Exception e)
+        {
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        }
+    }
+
+    public static void convertVisionmodeldataToTxt(String srcpath,String despath)throws Exception
+    {
+        try
+        {
+            File file = new File(srcpath);
+            FileInputStream fis=new FileInputStream(file);
+
+            Visionmodeldata.NavigationInfo data_NavigationInfo = Visionmodeldata.NavigationInfo.parseFrom(fis);
+
+            //PrintStream out = new PrintStream(despath);
+            String jsonFormat1 = JsonFormat.printToString(data_NavigationInfo);
+            ByteArrayInputStream stream = new ByteArrayInputStream(jsonFormat1.getBytes());
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(despath));//设置输出路径
+            BufferedInputStream bis = new BufferedInputStream(stream);
+            int b = -1;
+            while ((b = bis.read()) != -1) {
+                bos.write(b);
+            }
+            //out.close();
+            bis.close();
+            bos.close();
+        }
+        catch(Exception e)
+        {
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        }
+    }
+}

+ 98 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/CookieUtil.java

@@ -0,0 +1,98 @@
+package com.fdkankan.base.util;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Cookie.Util
+ *
+ *  2015-12-12 18:01:06
+ */
+public class CookieUtil {
+
+	// 默认缓存时间,单位/秒, 2H
+	private static final int COOKIE_MAX_AGE = 60 * 60 * 2;
+	// 保存路径,根路径
+	private static final String COOKIE_PATH = "/";
+	
+	/**
+	 * 保存
+	 *
+	 * @param response
+	 * @param key
+	 * @param value
+	 * @param ifRemember 
+	 */
+	public static void set(HttpServletResponse response, String key, String value, boolean ifRemember) {
+		int age = ifRemember?COOKIE_MAX_AGE:-1;
+		set(response, key, value, null, COOKIE_PATH, age, true);
+	}
+
+	/**
+	 * 保存
+	 *
+	 * @param response
+	 * @param key
+	 * @param value
+	 * @param maxAge
+	 */
+	private static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {
+		Cookie cookie = new Cookie(key, value);
+		if (domain != null) {
+			cookie.setDomain(domain);
+		}
+		cookie.setPath(path);
+		cookie.setMaxAge(maxAge);
+		cookie.setHttpOnly(isHttpOnly);
+		response.addCookie(cookie);
+	}
+	
+	/**
+	 * 查询value
+	 *
+	 * @param request
+	 * @param key
+	 * @return
+	 */
+	public static String getValue(HttpServletRequest request, String key) {
+		Cookie cookie = get(request, key);
+		if (cookie != null) {
+			return cookie.getValue();
+		}
+		return null;
+	}
+
+	/**
+	 * 查询Cookie
+	 *
+	 * @param request
+	 * @param key
+	 */
+	private static Cookie get(HttpServletRequest request, String key) {
+		Cookie[] arr_cookie = request.getCookies();
+		if (arr_cookie != null && arr_cookie.length > 0) {
+			for (Cookie cookie : arr_cookie) {
+				if (cookie.getName().equals(key)) {
+					return cookie;
+				}
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * 删除Cookie
+	 *
+	 * @param request
+	 * @param response
+	 * @param key
+	 */
+	public static void remove(HttpServletRequest request, HttpServletResponse response, String key) {
+		Cookie cookie = get(request, key);
+		if (cookie != null) {
+			set(response, key, "", null, COOKIE_PATH, 0, true);
+		}
+	}
+
+}

+ 133 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/FileMd5Util.java

@@ -0,0 +1,133 @@
+package com.fdkankan.base.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+
+public class FileMd5Util {
+
+    public static final String KEY_MD5 = "MD5";
+    public static final String CHARSET_ISO88591 = "ISO-8859-1";
+
+    /**
+     * Get MD5 of one file:hex string,test OK!
+     *
+     * @param file
+     * @return
+     */
+    public static String getFileMD5(File file) {
+        if (!file.exists() || !file.isFile()) {
+            return null;
+        }
+        MessageDigest digest = null;
+        FileInputStream in = null;
+        byte buffer[] = new byte[1024];
+        int len;
+        try {
+            digest = MessageDigest.getInstance("MD5");
+            in = new FileInputStream(file);
+            while ((len = in.read(buffer, 0, 1024)) != -1) {
+                digest.update(buffer, 0, len);
+            }
+            in.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        byte by[] = digest.digest();
+        int i;
+        StringBuffer sbf = new StringBuffer();
+        for (int j = 0; j < by.length; j++) {
+            i = by[j];
+            if (i < 0) {
+                i += 256;
+            } else if (i < 16) {
+                sbf.append("0");    //因为大于16的有两位,因此小于16需要补位,
+            }
+            sbf.append(Integer.toHexString(i));
+
+        }
+
+        return sbf.toString();
+//        BigInteger bigInt = new BigInteger(1, digest.digest());
+//        return bigInt.toString(16);
+    }
+
+    /***
+     * Get MD5 of one file!test ok!
+     *
+     * @param filepath
+     * @return
+     */
+    public static String getFileMD5(String filepath) {
+        File file = new File(filepath);
+        return getFileMD5(file);
+    }
+
+    /**
+     * MD5 encrypt,test ok
+     *
+     * @param data
+     * @return byte[]
+     * @throws Exception
+     */
+    public static byte[] encryptMD5(byte[] data) throws Exception {
+
+        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
+        md5.update(data);
+        return md5.digest();
+    }
+
+    public static byte[] encryptMD5(String data) throws Exception {
+        return encryptMD5(data.getBytes(CHARSET_ISO88591));
+    }
+
+    /***
+     * compare two file by Md5
+     *
+     * @param file1
+     * @param file2
+     * @return
+     */
+    public static boolean isSameMd5(File file1, File file2) {
+        String md5_1 = FileMd5Util.getFileMD5(file1);
+        String md5_2 = FileMd5Util.getFileMD5(file2);
+        return md5_1.equals(md5_2);
+    }
+
+    /***
+     * compare two file by Md5
+     *
+     * @param filepath1
+     * @param filepath2
+     * @return
+     */
+    public static boolean isSameMd5(String filepath1, String filepath2) {
+        File file1 = new File(filepath1);
+        File file2 = new File(filepath2);
+        return isSameMd5(file1, file2);
+    }
+
+    public static void main(String[] args){
+//        String path = "F:\\桌面\\";
+//
+//        StringBuffer sb = new StringBuffer(path + "20190925151119.h264");
+//        File dbFile = new File(sb.toString());
+//
+//        String fileMD5 = FileMd5Util.getFileMD5(dbFile);
+//        System.out.println(fileMD5);
+
+//        String path1 = "F:\\文档\\WeChat Files\\Iove-bing\\FileStorage\\File\\2020-05\\1.3.4-update.zip";
+//        File dbFile1 = new File(path1);
+//
+//        String fileMD51 = FileMd5Util.getFileMD5(dbFile1);
+//        System.out.println(fileMD51);
+
+        BigInteger usedSpace = new BigInteger("0");
+        BigInteger space = new BigInteger("560800515");
+        usedSpace.add(space);
+        System.out.println(usedSpace.intValue());
+
+    }
+}

+ 141 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/FileSizeUtil.java

@@ -0,0 +1,141 @@
+package com.fdkankan.base.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.text.DecimalFormat;
+
+public class FileSizeUtil {
+
+    private static final String TAG=FileSizeUtil.class.getSimpleName();
+
+    public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值
+    public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值
+    public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值
+    public static final int SIZETYPE_GB = 4;//获取文件大小单位为GB的double值
+
+    /**
+     * 获取文件指定文件的指定单位的大小
+     *
+     * @param filePath 文件路径
+     * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB
+     * @return double值的大小
+     */
+    public static double getFileOrFilesSize(String filePath, int sizeType) {
+        File file = new File(filePath);
+        long blockSize = 0;
+        try {
+            if (file.isDirectory()) {
+                blockSize = getFileSizes(file);
+            } else {
+                blockSize = getFileSize(file);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return formetFileSize(blockSize, sizeType);
+    }
+
+    /**
+     * 调用此方法自动计算指定文件或指定文件夹的大小
+     *
+     * @param filePath 文件路径
+     * @return 计算好的带B、KB、MB、GB的字符串
+     */
+    public static String getAutoFileOrFilesSize(String filePath) {
+        File file = new File(filePath);
+        long blockSize = 0;
+        try {
+            if (file.isDirectory()) {
+                blockSize = getFileSizes(file);
+            } else {
+                blockSize = getFileSize(file);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return formatFileSize(blockSize);
+    }
+
+    /**
+     * 获取指定文件大小
+     */
+    private static long getFileSize(File file) throws Exception {
+        long size = 0;
+        if (file.exists()) {
+            FileInputStream fis = null;
+            fis = new FileInputStream(file);
+            size = fis.available();
+        } else {
+            file.createNewFile();
+        }
+        return size;
+    }
+
+    /**
+     * 获取指定文件夹
+     */
+    private static long getFileSizes(File f) throws Exception {
+        long size = 0;
+        File flist[] = f.listFiles();
+        assert flist != null;
+        for (File file : flist) {
+            if (file.isDirectory()) {
+                size = size + getFileSizes(file);
+            } else {
+                size = size + getFileSize(file);
+            }
+        }
+        return size;
+    }
+
+    /**
+     * 转换文件大小
+     */
+    public static String formatFileSize(long fileS) {
+        DecimalFormat df = new DecimalFormat("#.00");
+        String fileSizeString = "";
+        String wrongSize = "0B";
+        if (fileS == 0) {
+            return wrongSize;
+        }
+        if (fileS < 1024) {
+            fileSizeString = df.format((double) fileS) + "B";
+        } else if (fileS < 1048576) {
+            fileSizeString = df.format((double) fileS / 1024) + "KB";
+        } else if (fileS < 1073741824) {
+            fileSizeString = df.format((double) fileS / 1048576) + "MB";
+        } else if (fileS < 1099511627776L){
+            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
+        } else if (fileS < 1125899906842624L){
+            fileSizeString = df.format((double) fileS / 1099511627776L) + "TB";
+        } else {
+            fileSizeString = df.format((double) fileS / 1125899906842624L) + "PB";
+        }
+        return fileSizeString;
+    }
+
+    /**
+     * 转换文件大小,指定转换的类型
+     */
+    public static double formetFileSize(long fileS, int sizeType) {
+        DecimalFormat df = new DecimalFormat("#.00");
+        double fileSizeLong = 0;
+        switch (sizeType) {
+            case SIZETYPE_B:
+                fileSizeLong = Double.valueOf(df.format((double) fileS));
+                break;
+            case SIZETYPE_KB:
+                fileSizeLong = Double.valueOf(df.format((double) fileS / 1024));
+                break;
+            case SIZETYPE_MB:
+                fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576));
+                break;
+            case SIZETYPE_GB:
+                fileSizeLong = Double.valueOf(df.format((double) fileS / 1073741824));
+                break;
+            default:
+                break;
+        }
+        return fileSizeLong;
+    }
+}

+ 134 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/FileUpload.java

@@ -0,0 +1,134 @@
+package com.fdkankan.base.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+
+/**
+ * @author MeepoGuan
+ *
+ * <p>Description: 上传问题件</p>
+ *
+ * 2017年4月30日
+ *
+ */
+@Slf4j
+public class FileUpload {
+
+	/**
+	 * @param file 			//文件对象
+	 * @param filePath		//上传路径
+	 * @param fileName		//文件名
+	 * @return  文件名
+	 */
+	public static String fileUp(MultipartFile file, String filePath, String fileName) throws IOException {
+		String extName = ""; // 扩展名格式:
+
+		if (file.getOriginalFilename().lastIndexOf(".") >= 0){
+			extName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
+		}
+		copyFile(file.getInputStream(), filePath, fileName+extName).replaceAll("-", "");
+
+		return fileName+extName;
+	}
+	
+	/**
+	 * 写文件到当前目录的upload目录中
+	 * 
+	 * @param in
+	 * @param dir
+	 * @param realName
+	 * @throws IOException
+	 */
+	private static String copyFile(InputStream in, String dir, String realName)
+			throws IOException {
+		File file = new File(dir, realName);
+		if (!file.exists()) {
+			if (!file.getParentFile().exists()) {
+				file.getParentFile().mkdirs();
+			}
+			file.createNewFile();
+		}
+        org.apache.commons.io.FileUtils.copyInputStreamToFile(in, file);
+		return realName;
+	}
+
+	/**
+	 * 断点续传
+	 * @param
+     */
+	public static String fileUpAgain(InputStream in, String filePath, String fileName, String realSavePath) throws IOException {
+		try{
+			File realFile = new File(realSavePath +  fileName);
+			File tempFile = new File(filePath + fileName);
+			if(!realFile.getParentFile().exists()){
+				realFile.getParentFile().mkdirs();
+			}
+			if(!tempFile.getParentFile().exists()){
+				tempFile.getParentFile().mkdirs();
+			}
+
+//			InputStream in = file.getInputStream();
+			long needSkipBytes = 0;
+			if (tempFile.exists()) {//续传
+				needSkipBytes = tempFile.length();
+			} else {//第一次传
+				tempFile.createNewFile();
+			}
+			log.info("跳过的字节数为:" + needSkipBytes);
+			in.skip(needSkipBytes);
+			RandomAccessFile tempRandAccessFile = new RandomAccessFile(tempFile, "rw");
+			tempRandAccessFile.seek(needSkipBytes);
+			byte[] buffer = new byte[1024];
+			int len = 0;
+			int count = 0;
+			while ((len = in.read(buffer)) > 0) {
+				tempRandAccessFile.write(buffer);
+				count++;
+			}
+			in.close();
+			tempRandAccessFile.close();
+			realFile.createNewFile();
+			if (fileCopy(tempFile, realFile)) {
+				tempFile.delete();
+			}
+		}catch (Exception e){
+			e.printStackTrace();
+		}
+		return realSavePath + fileName;
+	}
+
+	private static boolean fileCopy(File sourceFile, File targetFile) {
+		boolean success = true;
+		try {
+			FileInputStream in = new FileInputStream(sourceFile);
+			FileOutputStream out = new FileOutputStream(targetFile);
+			byte[] buffer = new byte[1024];
+			int len = 0;
+			while ((len = in.read(buffer)) > 0) {
+				out.write(buffer);
+			}
+			in.close();
+			out.close();
+		} catch (FileNotFoundException e) {
+			success = false;
+		} catch (IOException e) {
+			success = false;
+		}
+		return success;
+	}
+
+
+	public static void main(String[] args) {
+		try{
+			String path = "F:\\桌面\\20190925151119-T.h264";
+			FileInputStream f = new FileInputStream(path);
+			fileUpAgain(f, "G:\\javaProject\\9b918c802c3e40282267a89b5231f9a8_201905101446434643\\videos\\", "test123-T.h264", "G:\\javaProject\\9b918c802c3e40282267a89b5231f9a8_201905101446434643\\capture\\");
+//			copyFile(f, "G:\\javaProject\\zhoushan-system\\zhoushan-system-api\\src\\main\\resources\\static\\head", "test.h264");
+		}catch (Exception e){
+			e.printStackTrace();
+		}
+
+	}
+}

+ 263 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/FileUtil.java

@@ -0,0 +1,263 @@
+package com.fdkankan.base.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+
+/**
+ * @author MeepoGuan
+ *
+ * <p>Description: file_util</p>
+ *
+ * 2017年4月30日
+ *
+ */
+@Slf4j
+public class FileUtil {
+
+/*	public static void main(String[] args) {
+		String dirName = "d:/FH/topic/";// 创建目录
+		FileUtil.createDir(dirName);
+	}*/
+
+	/**
+	 * 创建目录
+	 * 
+	 * @param destDirName
+	 *            目标目录名
+	 * @return 目录创建成功返回true,否则返回false
+	 */
+	public static boolean createDir(String destDirName) {
+		File dir = new File(destDirName);
+		if (dir.exists()) {
+			return false;
+		}
+		if (!destDirName.endsWith(File.separator)) {
+			destDirName = destDirName + File.separator;
+		}
+		// 创建单个目录
+		if (dir.mkdirs()) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * 删除文件
+	 * 
+	 * @param filePathAndName
+	 *            String 文件路径及名称 如c:/fqf.txt
+	 * @return boolean
+	 */
+	public static void delFile(String filePathAndName) {
+		try {
+			String filePath = filePathAndName;
+			filePath = filePath.toString();
+			File myDelFile = new File(filePath);
+			myDelFile.delete();
+
+		} catch (Exception e) {
+			System.out.println("删除文件操作出错");
+			e.printStackTrace();
+
+		}
+
+	}
+
+	/**
+	 * 读取到字节数组0
+	 * 
+	 * @param filePath //路径
+	 * @throws IOException
+	 */
+	public static byte[] getContent(String filePath) throws IOException {
+		File file = new File(filePath);
+		long fileSize = file.length();
+		if (fileSize > Integer.MAX_VALUE) {
+			System.out.println("file too big...");
+			return null;
+		}
+		FileInputStream fi = new FileInputStream(file);
+		byte[] buffer = new byte[(int) fileSize];
+		int offset = 0;
+		int numRead = 0;
+		while (offset < buffer.length
+				&& (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
+			offset += numRead;
+		}
+		// 确保所有数据均被读取
+		if (offset != buffer.length) {
+			throw new IOException("Could not completely read file "
+					+ file.getName());
+		}
+		fi.close();
+		return buffer;
+	}
+
+	/**
+	 * 读取到字节数组1
+	 * 
+	 * @param filePath
+	 * @return
+	 * @throws IOException
+	 */
+	public static byte[] toByteArray(String filePath) throws IOException {
+
+		File f = new File(filePath);
+		if (!f.exists()) {
+			throw new FileNotFoundException(filePath);
+		}
+		ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
+		BufferedInputStream in = null;
+		try {
+			in = new BufferedInputStream(new FileInputStream(f));
+			int buf_size = 1024;
+			byte[] buffer = new byte[buf_size];
+			int len = 0;
+			while (-1 != (len = in.read(buffer, 0, buf_size))) {
+				bos.write(buffer, 0, len);
+			}
+			return bos.toByteArray();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw e;
+		} finally {
+			try {
+				in.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			bos.close();
+		}
+	}
+
+	/**
+	 * 读取到字节数组2
+	 * 
+	 * @param filePath
+	 * @return
+	 * @throws IOException
+	 */
+	public static byte[] toByteArray2(String filePath) throws IOException {
+
+		File f = new File(filePath);
+		if (!f.exists()) {
+			throw new FileNotFoundException(filePath);
+		}
+
+		FileChannel channel = null;
+		FileInputStream fs = null;
+		try {
+			fs = new FileInputStream(f);
+			channel = fs.getChannel();
+			ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
+			while ((channel.read(byteBuffer)) > 0) {
+				// do nothing
+				// System.out.println("reading");
+			}
+			return byteBuffer.array();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw e;
+		} finally {
+			try {
+				channel.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			try {
+				fs.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/**
+	 * Mapped File way MappedByteBuffer 可以在处理大文件时,提升性能
+	 * 
+	 * @param filePath
+	 * @return
+	 * @throws IOException
+	 */
+	public static byte[] toByteArray3(String filePath) throws IOException {
+
+		FileChannel fc = null;
+		RandomAccessFile rf = null;
+		try {
+			rf = new RandomAccessFile(filePath, "r");
+			fc = rf.getChannel();
+			MappedByteBuffer byteBuffer = fc.map(MapMode.READ_ONLY, 0,
+					fc.size()).load();
+			//System.out.println(byteBuffer.isLoaded());
+			byte[] result = new byte[(int) fc.size()];
+			if (byteBuffer.remaining() > 0) {
+				// System.out.println("remain");
+				byteBuffer.get(result, 0, byteBuffer.remaining());
+			}
+			return result;
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw e;
+		} finally {
+			try {
+				rf.close();
+				fc.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+    public static File[] sort(File[] s) {
+        //中间值
+        File temp = null;
+        //外循环:我认为最小的数,从0~长度-1
+        for (int j = 0; j < s.length - 1; j++) {
+            //最小值:假设第一个数就是最小的
+            String min = s[j].getName();
+            //记录最小数的下标的
+            int minIndex = j;
+            //内循环:拿我认为的最小的数和后面的数一个个进行比较
+            for (int k = j + 1; k < s.length; k++) {
+                //找到最小值
+                if (Integer.parseInt(min.substring(0, min.indexOf("."))) > Integer.parseInt(s[k].getName().substring(0, s[k].getName().indexOf(".")))) {
+                    //修改最小
+                    min = s[k].getName();
+                    minIndex = k;
+                }
+            }
+            //当退出内层循环就找到这次的最小值
+            //交换位置
+            temp = s[j];
+            s[j] = s[minIndex];
+            s[minIndex] = temp;
+        }
+        return s;
+    }
+
+	public static boolean checkFile(MultipartFile file) {
+		//设置允许上传文件类型
+		String suffixList = ".jpg,.gif,.png,.ico,.bmp,.jpeg,.zip,.zp,.rar,.mp3,.mp4,.avi,.mov";
+		// 获取文件后缀
+		if(file == null){
+			log.info("文件流为空不可上传");
+			return false;
+		}
+		String fileName = file.getOriginalFilename();
+		String suffix = fileName.substring(fileName.lastIndexOf(".")
+				+ 1, fileName.length());
+		if (suffixList.contains(suffix.trim().toLowerCase())) {
+			log.info("无非法参数可以放行!!!");
+			return true;
+		}
+		log.info("存在非法参数不能放行!请核对上传文件格式,重新刷新页面再次上传!");
+		return false;
+	}
+}

+ 115 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/HttpHelper.java

@@ -0,0 +1,115 @@
+package com.fdkankan.base.util;
+
+import org.apache.commons.lang.StringUtils;
+
+import javax.net.ssl.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+public class HttpHelper {
+
+    private static class TrustAnyTrustManager implements X509TrustManager {
+
+        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+            // TODO Auto-generated method stub
+
+        }
+
+        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+            // TODO Auto-generated method stub
+
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+    }
+
+    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
+
+        public boolean verify(String arg0, SSLSession arg1) {
+            // TODO Auto-generated method stub
+            return false;
+        }
+    }
+
+    /**
+     * 获取请求Body
+     *
+     * @param request
+     * @return
+     */
+    public static String getBodyString(HttpServletRequest request) {
+        StringBuilder sb = new StringBuilder();
+        InputStream inputStream = null;
+        BufferedReader reader = null;
+        try {
+            inputStream = request.getInputStream();
+            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
+            String line = "";
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    public static byte[] post(String url, String content, String charset)
+            throws NoSuchAlgorithmException, KeyManagementException,
+            IOException {
+        SSLContext sc = SSLContext.getInstance("SSL");
+        sc.init(null, new TrustManager[] { new TrustAnyTrustManager() },
+                new java.security.SecureRandom());
+
+        URL console = new URL(url);
+        HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+        conn.setSSLSocketFactory(sc.getSocketFactory());
+        conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+        conn.setDoOutput(true);
+        conn.connect();
+        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
+        out.write(content.getBytes(charset));
+        // 刷新、关闭
+        out.flush();
+        out.close();
+        InputStream is = conn.getInputStream();
+        if (is != null) {
+            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int len = 0;
+            while ((len = is.read(buffer)) != -1) {
+                outStream.write(buffer, 0, len);
+            }
+            is.close();
+            return outStream.toByteArray();
+        }
+        return null;
+    }
+}

+ 90 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/MD5.java

@@ -0,0 +1,90 @@
+package com.fdkankan.base.util;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class MD5
+
+{
+
+    public static String md5Str(String str) {
+        if (str == null) return "";
+        return md5Str(str, 0);
+    }
+
+
+    public static String md5Str(String str, int offset) {
+        try {
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            byte[] b = str.getBytes("UTF8");
+            md5.update(b, offset, b.length);
+            return byteArrayToHexString(md5.digest());
+        } catch (NoSuchAlgorithmException ex) {
+            ex.printStackTrace();
+            return null;
+        } catch (UnsupportedEncodingException ex) {
+            ex.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * @param b byte[]
+     * @return String
+     */
+    public static String byteArrayToHexString(byte[] b) {
+        String result = "";
+        for (int i = 0; i < b.length; i++) {
+            result += byteToHexString(b[i]);
+        }
+        return result;
+    }
+
+    private static String[] hexDigits =
+            {
+                    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b",
+                    "c", "d", "e", "f"};
+
+    public static String byteToHexString(byte b) {
+        int n = b;
+        if (n < 0) {
+            n = 256 + n;
+        }
+        int d1 = n / 16;
+        int d2 = n % 16;
+        return hexDigits[d1] + hexDigits[d2];
+    }
+
+    public static void main(String[] args) {
+        System.out.println(byteToHexString((byte) -99));
+        String str =
+                "eeeeeeeeeeeeeewrw213123122222222222222222222222213123213213213erwer";
+        String ened = MD5.md5Str(str);
+        System.out.println(ened.length());
+        System.out.println(ened);
+    }
+
+
+    public final static String getMessageDigest(byte[] buffer) {
+        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+        try {
+            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+            mdTemp.update(buffer);
+            byte[] md = mdTemp.digest();
+            int j = md.length;
+            char str[] = new char[j * 2];
+            int k = 0;
+            for (int i = 0; i < j; i++) {
+                byte byte0 = md[i];
+                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+                str[k++] = hexDigits[byte0 & 0xf];
+            }
+            return new String(str);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+}
+

+ 465 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/RSAEncrypt.java

@@ -0,0 +1,465 @@
+package com.fdkankan.base.util;
+
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.util.ResourceUtils;
+import sun.misc.BASE64Decoder;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.*;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+
+public class RSAEncrypt {
+
+    /**
+     * 字节数据转字符串专用集合
+     */
+    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6',
+            '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+    private static final String PRIVATE_KEY = "classpath:key/private_pkcs8.pem";
+
+    private static final String PUBLIC_KEY = "classpath:key/public.pem";
+    /**
+     * RSA最大解密密文大小
+     */
+    private static final int MAX_DECRYPT_BLOCK = 128;
+    /**
+     * 随机生成密钥对
+     */
+    public static void genKeyPair(String filePath) {
+        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
+        KeyPairGenerator keyPairGen = null;
+        try {
+            keyPairGen = KeyPairGenerator.getInstance("RSA");
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        // 初始化密钥对生成器,密钥大小为96-1024位
+        keyPairGen.initialize(1024, new SecureRandom());
+        // 生成一个密钥对,保存在keyPair中
+        KeyPair keyPair = keyPairGen.generateKeyPair();
+        // 得到私钥
+        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
+        // 得到公钥
+        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
+        try {
+            // 得到公钥字符串
+            Base64 base64 = new Base64();
+            String publicKeyString = new String(base64.encode(publicKey.getEncoded()));
+            // 得到私钥字符串
+            String privateKeyString = new String(base64.encode(privateKey.getEncoded()));
+            // 将密钥对写入到文件
+            FileWriter pubfw = new FileWriter(filePath + PUBLIC_KEY);
+            FileWriter prifw = new FileWriter(filePath + PRIVATE_KEY);
+            BufferedWriter pubbw = new BufferedWriter(pubfw);
+            BufferedWriter pribw = new BufferedWriter(prifw);
+            pubbw.write(publicKeyString);
+            pribw.write(privateKeyString);
+            pubbw.flush();
+            pubbw.close();
+            pubfw.close();
+            pribw.flush();
+            pribw.close();
+            prifw.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 从文件中输入流中加载公钥
+     *
+     * @throws Exception 加载公钥时产生的异常
+     */
+    public static String loadPublicKeyByFile() throws Exception {
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(ResourceUtils.getFile(PUBLIC_KEY)));
+            String readLine = null;
+            StringBuilder sb = new StringBuilder();
+            while ((readLine = br.readLine()) != null) {
+                if (readLine.charAt(0) == '-') {
+                    continue;
+                } else {
+                    sb.append(readLine);
+                    sb.append('\r');
+                }
+            }
+            br.close();
+            return sb.toString();
+        } catch (IOException e) {
+            throw new Exception("公钥数据流读取错误");
+        } catch (NullPointerException e) {
+            throw new Exception("公钥输入流为空");
+        }
+    }
+
+    /**
+     * 从文件中输入流中加载公钥
+     *
+     * @throws Exception 加载公钥时产生的异常
+     */
+    public static String loadPublicKeyByFile(String publicKy) throws Exception {
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(new File(publicKy)));
+            String readLine = null;
+            StringBuilder sb = new StringBuilder();
+            while ((readLine = br.readLine()) != null) {
+                if (readLine.charAt(0) == '-') {
+                    continue;
+                } else {
+                    sb.append(readLine);
+                    sb.append('\r');
+                }
+            }
+            br.close();
+            return sb.toString();
+        } catch (IOException e) {
+            throw new Exception("公钥数据流读取错误");
+        } catch (NullPointerException e) {
+            throw new Exception("公钥输入流为空");
+        }
+    }
+
+    /**
+     * 从字符串中加载公钥
+     *
+     * @param publicKeyStr 公钥数据字符串
+     * @throws Exception 加载公钥时产生的异常
+     */
+    public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
+            throws Exception {
+        try {
+            BASE64Decoder base64 = new BASE64Decoder();
+            byte[] buffer = base64.decodeBuffer(publicKeyStr);
+            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
+            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此算法");
+        } catch (InvalidKeySpecException e) {
+            throw new Exception("公钥非法");
+        } catch (NullPointerException e) {
+            throw new Exception("公钥数据为空");
+        }
+    }
+
+    /**
+     * 从文件中加载私钥
+     *
+     * @return 是否成功
+     * @throws Exception
+     */
+    public static String loadPrivateKeyByFile() throws Exception {
+        try {
+            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("key/private_pkcs8.pem");
+            StringBuilder builder = new StringBuilder();
+            InputStreamReader reader = new InputStreamReader(inputStream , "UTF-8" );
+            BufferedReader bfReader = new BufferedReader( reader );
+            String tmpContent = null;
+            while ((tmpContent = bfReader.readLine()) != null) {
+                if (tmpContent.charAt(0) == '-') {
+                    continue;
+                } else {
+                    builder.append(tmpContent);
+                    builder.append('\r');
+                }
+            }
+            bfReader.close();
+            return builder.toString();
+//            BufferedReader br = new BufferedReader(new FileReader(ResourceUtils.getFile(PRIVATE_KEY)));
+//            String readLine = null;
+//            StringBuilder sb = new StringBuilder();
+//            while ((readLine = br.readLine()) != null) {
+//                if (readLine.charAt(0) == '-') {
+//                    continue;
+//                } else {
+//                    sb.append(readLine);
+//                    sb.append('\r');
+//                }
+//            }
+//            br.close();
+//            return sb.toString();
+        } catch (IOException e) {
+            throw new Exception("私钥数据读取错误");
+        } catch (NullPointerException e) {
+            throw new Exception("私钥输入流为空");
+        }
+    }
+
+    /**
+     * 从文件中加载私钥
+     *
+     * @return 是否成功
+     * @throws Exception
+     */
+    public static String loadPrivateKeyByFile(String filePath) throws Exception {
+        try {
+            InputStream inputStream = new FileInputStream(filePath);
+            StringBuilder builder = new StringBuilder();
+            InputStreamReader reader = new InputStreamReader(inputStream , "UTF-8" );
+            BufferedReader bfReader = new BufferedReader( reader );
+            String tmpContent = null;
+            while ((tmpContent = bfReader.readLine()) != null) {
+                if (tmpContent.charAt(0) == '-') {
+                    continue;
+                } else {
+                    builder.append(tmpContent);
+                    builder.append('\r');
+                }
+            }
+            bfReader.close();
+            return builder.toString();
+//            BufferedReader br = new BufferedReader(new FileReader(ResourceUtils.getFile(PRIVATE_KEY)));
+//            String readLine = null;
+//            StringBuilder sb = new StringBuilder();
+//            while ((readLine = br.readLine()) != null) {
+//                if (readLine.charAt(0) == '-') {
+//                    continue;
+//                } else {
+//                    sb.append(readLine);
+//                    sb.append('\r');
+//                }
+//            }
+//            br.close();
+//            return sb.toString();
+        } catch (IOException e) {
+            throw new Exception("私钥数据读取错误");
+        } catch (NullPointerException e) {
+            throw new Exception("私钥输入流为空");
+        }
+    }
+
+    public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
+            throws Exception {
+        try {
+            BASE64Decoder base64Decoder = new BASE64Decoder();
+            byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
+            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此算法");
+        } catch (InvalidKeySpecException e) {
+            throw new Exception("私钥非法");
+        } catch (NullPointerException e) {
+            throw new Exception("私钥数据为空");
+        }
+    }
+
+    /**
+     * 公钥加密过程
+     *
+     * @param publicKey     公钥
+     * @param plainTextData 明文数据
+     * @return
+     * @throws Exception 加密过程中的异常信息
+     */
+    public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
+            throws Exception {
+        if (publicKey == null) {
+            throw new Exception("加密公钥为空, 请设置");
+        }
+        Cipher cipher = null;
+        try {
+            // 使用默认RSA
+            cipher = Cipher.getInstance("RSA");
+            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+            byte[] output = cipher.doFinal(plainTextData);
+            return output;
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此加密算法");
+        } catch (NoSuchPaddingException e) {
+            e.printStackTrace();
+            return null;
+        } catch (InvalidKeyException e) {
+            throw new Exception("加密公钥非法,请检查");
+        } catch (IllegalBlockSizeException e) {
+            throw new Exception("明文长度非法");
+        } catch (BadPaddingException e) {
+            throw new Exception("明文数据已损坏");
+        }
+    }
+
+    /**
+     * 私钥加密过程
+     *
+     * @param privateKey    私钥
+     * @param plainTextData 明文数据
+     * @return
+     * @throws Exception 加密过程中的异常信息
+     */
+    public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
+            throws Exception {
+        if (privateKey == null) {
+            throw new Exception("加密私钥为空, 请设置");
+        }
+        Cipher cipher = null;
+        try {
+            // 使用默认RSA
+            cipher = Cipher.getInstance("RSA");
+            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+            byte[] output = cipher.doFinal(plainTextData);
+            return output;
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此加密算法");
+        } catch (NoSuchPaddingException e) {
+            e.printStackTrace();
+            return null;
+        } catch (InvalidKeyException e) {
+            throw new Exception("加密私钥非法,请检查");
+        } catch (IllegalBlockSizeException e) {
+            throw new Exception("明文长度非法");
+        } catch (BadPaddingException e) {
+            throw new Exception("明文数据已损坏");
+        }
+    }
+
+    /**
+     * 私钥解密过程
+     *
+     * @param privateKey 私钥
+     * @param cipherData 密文数据
+     * @return 明文
+     * @throws Exception 解密过程中的异常信息
+     */
+    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
+            throws Exception {
+        if (privateKey == null) {
+            throw new Exception("解密私钥为空, 请设置");
+        }
+        Cipher cipher = null;
+        try {
+            // 使用默认RSA
+            cipher = Cipher.getInstance("RSA");
+//             cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+            /*byte[] output = cipher.doFinal(cipherData);
+            return output;*/
+            return getDecrytedData(cipherData, cipher);
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此解密算法");
+        } catch (NoSuchPaddingException e) {
+            e.printStackTrace();
+            return null;
+        } catch (InvalidKeyException e) {
+            throw new Exception("解密私钥非法,请检查");
+        } catch (IllegalBlockSizeException e) {
+            throw new Exception("密文长度非法");
+        } catch (BadPaddingException e) {
+            throw new Exception("密文数据已损坏");
+        }
+    }
+
+    /**
+     * 公钥解密过程
+     *
+     * @param publicKey  公钥
+     * @param cipherData 密文数据
+     * @return 明文
+     * @throws Exception 解密过程中的异常信息
+     */
+    public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
+            throws Exception {
+        if (publicKey == null) {
+            throw new Exception("解密公钥为空, 请设置");
+        }
+        Cipher cipher = null;
+        try {
+            // 使用默认RSA
+            cipher = Cipher.getInstance("RSA");
+            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
+            cipher.init(Cipher.DECRYPT_MODE, publicKey);
+            /*byte[] output = cipher.doFinal(cipherData);
+            return output;*/
+            return getDecrytedData(cipherData, cipher);
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此解密算法");
+        } catch (NoSuchPaddingException e) {
+            e.printStackTrace();
+            return null;
+        } catch (InvalidKeyException e) {
+            throw new Exception("解密公钥非法,请检查");
+        } catch (IllegalBlockSizeException e) {
+            throw new Exception("密文长度非法");
+        } catch (BadPaddingException e) {
+            throw new Exception("密文数据已损坏");
+        }
+    }
+
+    private static byte[] getDecrytedData(byte[] cipherData, Cipher cipher) throws IllegalBlockSizeException, BadPaddingException, IOException {
+//        int inputLen = cipherData.length;
+////        ByteArrayOutputStream out = new ByteArrayOutputStream();
+////        int offSet = 0;
+////        byte[] cache;
+////        int i = 0;
+////        // 对数据分段解密
+////        while (inputLen - offSet > 0) {
+////            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
+////                cache = cipher.doFinal(cipherData, offSet, MAX_DECRYPT_BLOCK);
+////            } else {
+////                cache = cipher.doFinal(cipherData, offSet, inputLen - offSet);
+////            }
+////            out.write(cache, 0, cache.length);
+////            i++;
+////            offSet = i * MAX_DECRYPT_BLOCK;
+////        }
+////        byte[] decryptedData = out.toByteArray();
+////        out.close();
+////        return decryptedData;
+        int inputLen = cipherData.length;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+
+        for(int i = 0; inputLen - offSet > 0; offSet = i * 256) {
+            byte[] cache;
+            if(inputLen - offSet > 256) {
+                cache = cipher.doFinal(cipherData, offSet, 256);
+            } else {
+                cache = cipher.doFinal(cipherData, offSet, inputLen - offSet);
+            }
+            out.write(cache, 0, cache.length);
+            ++i;
+        }
+
+        byte[] decryptedData = out.toByteArray();
+        out.close();
+        return decryptedData;
+    }
+
+    /**
+     * 字节数据转十六进制字符串
+     *
+     * @param data 输入数据
+     * @return 十六进制内容
+     */
+    public static String byteArrayToString(byte[] data) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i = 0; i < data.length; i++) {
+            // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
+            stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
+            // 取出字节的低四位 作为索引得到相应的十六进制标识符
+            stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
+            if (i < data.length - 1) {
+                stringBuilder.append(' ');
+            }
+        }
+        return stringBuilder.toString();
+    }
+
+    public static void main(String[] args) throws Exception {
+
+
+
+    }
+
+}

+ 215 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/SnowFlakeUUidUtils.java

@@ -0,0 +1,215 @@
+package com.fdkankan.base.util;
+
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * 2 * @Author: Abner
+ * 3 * @Date: 2020/12/9 16:07
+ * 4
+ */
+@Log4j2
+public class SnowFlakeUUidUtils {
+
+    // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
+    //起始标记点
+    private final static long twepoch = 1288834974657L;
+    // 机器标识位数
+    private final static long workerIdBits = 5L;
+    // 数据中心标识位数
+    private final static long datacenterIdBits = 5L;
+    // 机器ID最大值
+    private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
+    // 数据中心ID最大值
+    private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+    // 毫秒内自增位
+    private final static long sequenceBits = 12L;
+    // 机器ID偏左移12位
+    private final static long workerIdShift = sequenceBits;
+    // 数据中心ID左移17位
+    private final static long datacenterIdShift = sequenceBits + workerIdBits;
+    // 时间毫秒左移22位
+    private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    private final static Lock myLock = new ReentrantLock();
+    /* 上次生产id时间戳 */
+    private static long lastTimestamp = -1L;
+    // 0,并发控制
+    private long sequence = 0L;
+
+    private final long workerId;
+    // 数据标识id部分
+    private final long datacenterId;
+
+    private static volatile SnowFlakeUUidUtils snowFlakeUUidUtils;
+
+
+    private static SnowFlakeUUidUtils getSingleInstance(Long workerId, Long datacenterId){
+        if(null == snowFlakeUUidUtils){
+            synchronized (SnowFlakeUUidUtils.class){
+                if(null == snowFlakeUUidUtils){
+                    if(null != workerId && null != datacenterId){
+                        snowFlakeUUidUtils = new SnowFlakeUUidUtils(workerId , datacenterId);
+                    }else{
+                        snowFlakeUUidUtils = new SnowFlakeUUidUtils();
+                    }
+                }
+            }
+        }
+        return snowFlakeUUidUtils;
+    }
+
+    /**
+     * @param workerId 自定义的应用所在的服务器的机器ID,使用默认读取本机则无需传,传个NULL即可
+     * @param datacenterId 自定义的应用所在的服务器的数据中心ID,使用默认读取本机则无需传,传个NULL即可
+     * @param preStr 自定义的ID前缀
+     * **/
+    public static String generaUUid(Long workerId, Long datacenterId , String preStr){
+        StringBuilder resultId = new StringBuilder();
+        SnowFlakeUUidUtils snowFlakeUUidUtils = getSingleInstance(workerId , datacenterId);
+        if(StringUtils.isNotBlank(preStr)){
+            return resultId.append(preStr).append(snowFlakeUUidUtils.nextId()).toString();
+        }else{
+            return resultId.append(snowFlakeUUidUtils.nextId()).toString();
+        }
+    }
+
+    public SnowFlakeUUidUtils(){
+        this.datacenterId = getDatacenterId(maxDatacenterId);
+        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
+    }
+    /**
+     * @param workerId
+     *            工作机器ID
+     * @param datacenterId
+     *            序列号
+     */
+    public SnowFlakeUUidUtils(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+    /**
+     * 获取下一个ID
+     * 线程安全
+     * @return NULL 抢锁失败,需要重新调用
+     *         数字串 抢锁成功,则生成20位的数字串
+     */
+    public  Long nextId() {
+        try {
+
+            if(myLock.tryLock(700 , TimeUnit.MILLISECONDS)){
+                try {
+                    long timestamp = timeGen();
+                    if (timestamp < lastTimestamp) {
+                        throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+                    }
+
+                    if (lastTimestamp == timestamp) {
+                        // 当前毫秒内,则+1
+                        sequence = (sequence + 1) & sequenceMask;
+                        if (sequence == 0) {
+                            // 当前毫秒内计数满了,则等待下一秒
+                            timestamp = tilNextMillis(lastTimestamp);
+                        }
+                    } else {
+                        sequence = 0L;
+                    }
+                    lastTimestamp = timestamp;
+                    // ID偏移组合生成最终的ID,并返回ID
+                    Long nextId = ((timestamp - twepoch) << timestampLeftShift)
+                            | (datacenterId << datacenterIdShift)
+                            | (workerId << workerIdShift) | sequence;
+
+                    return nextId;
+                }catch (Exception e){
+                    log.info("生成UUID抢锁失败:{}" , e);
+                }finally {
+                    myLock.unlock();
+                }
+            }else{
+                return null;
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return null;
+
+    }
+
+    private long tilNextMillis(final long lastTimestamp) {
+        long timestamp = this.timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = this.timeGen();
+        }
+        return timestamp;
+    }
+
+    private long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    /**
+     * <p>
+     * 获取 maxWorkerId
+     * </p>
+     */
+    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
+        StringBuffer mpid = new StringBuffer();
+        mpid.append(datacenterId);
+        String name = ManagementFactory.getRuntimeMXBean().getName();
+        if (!name.isEmpty()) {
+            /*
+             * GET jvmPid
+             */
+            mpid.append(name.split("@")[0]);
+        }
+        /*
+         * MAC + PID 的 hashcode 获取16个低位
+         */
+        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
+    }
+
+    /**
+     * <p>
+     * 数据标识id部分
+     * </p>
+     */
+    protected static long getDatacenterId(long maxDatacenterId) {
+        long id = 0L;
+        try {
+            InetAddress ip = InetAddress.getLocalHost();
+            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
+            if (network == null) {
+                id = 1L;
+            } else {
+                byte[] mac = network.getHardwareAddress();
+                id = ((0x000000FF & (long) mac[mac.length - 1])
+                        | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
+                id = id % (maxDatacenterId + 1);
+            }
+        } catch (Exception e) {
+            System.out.println(" getDatacenterId: " + e.getMessage());
+        }
+        return id;
+    }
+
+    public static void main(String[] args) {
+        System.out.println(SnowFlakeUUidUtils.generaUUid(null, null, null));
+    }
+
+}

+ 135 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/SnowflakeIdGenerator.java

@@ -0,0 +1,135 @@
+package com.fdkankan.base.util;
+
+/**
+ * Twitter_Snowflake<br>
+ * SnowFlake的结构如下(每部分用-分开):<br>
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
+ * 加起来刚好64位,为一个Long型。<br>
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ */
+public class SnowflakeIdGenerator {
+
+    // ==============================Fields===========================================
+    /** 开始时间截 (2015-01-01) */
+    private final long twepoch = 1420041600000L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 5L;
+
+    /** 数据标识id所占的位数 */
+    private final long datacenterIdBits = 5L;
+
+    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 支持的最大数据标识id,结果是31 */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 数据标识id向左移17位(12+5) */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /** 时间截向左移22位(5+5+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~31) */
+    private long workerId;
+
+    /** 数据中心ID(0~31) */
+    private long datacenterId;
+
+    /** 毫秒内序列(0~4095) */
+    private long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeIdGenerator(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+}

+ 230 - 0
4dkankan-base/src/main/java/com/fdkankan/base/util/ZipUtil.java

@@ -0,0 +1,230 @@
+package com.fdkankan.base.util;
+
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.util.Properties;
+import java.util.zip.GZIPInputStream;
+
+
+public class ZipUtil {
+
+    private static final Logger log = LoggerFactory.getLogger(ZipUtil.class);
+
+    /**
+     * 构建目录
+     * @param outputDir
+     * @param subDir
+     */
+    public static void createDirectory(String outputDir,String subDir){
+        File file = new File(outputDir);
+        if(!(subDir == null || subDir.trim().equals(""))){//子目录不为空
+            file = new File(outputDir + "/" + subDir);
+        }
+        if(!file.exists()){
+            if(!file.getParentFile().exists())
+                file.getParentFile().mkdirs();
+            file.mkdirs();
+        }
+    }
+
+    //------------------------------------------------------------------------------------------------------
+    /**
+     * 解压tar.gz 文件
+     * @param file 要解压的tar.gz文件对象
+     * @param outputDir 要解压到某个指定的目录下
+     * @throws IOException
+     */
+    public static void unTarGz(File file, String outputDir) throws IOException{
+        TarInputStream tarIn = null;
+        try{
+            tarIn = new TarInputStream(new GZIPInputStream(
+                    new BufferedInputStream(new FileInputStream(file))),
+                    1024 * 2);
+
+            createDirectory(outputDir,null);//创建输出目录
+
+            TarEntry entry = null;
+            while( (entry = tarIn.getNextEntry()) != null ){
+
+                if(entry.isDirectory()){//是目录
+                    entry.getName();
+                    createDirectory(outputDir,entry.getName());//创建空目录
+                }else{//是文件
+                    File tmpFile = new File(outputDir + "/" + entry.getName());
+                    createDirectory(tmpFile.getParent() + "/",null);//创建输出目录
+                    OutputStream out = null;
+                    try{
+                        out = new FileOutputStream(tmpFile);
+                        int length = 0;
+
+                        byte[] b = new byte[2048];
+
+                        while((length = tarIn.read(b)) != -1){
+                            out.write(b, 0, length);
+                        }
+
+                    }catch(IOException ex){
+                        throw ex;
+                    }finally{
+
+                        if(out!=null)
+                            out.close();
+                    }
+                }
+            }
+        }catch(IOException ex){
+            throw new IOException("解压归档文件出现异常",ex);
+        } finally{
+            try{
+                if(tarIn != null){
+                    tarIn.close();
+                }
+            }catch(IOException ex){
+                throw new IOException("关闭tarFile出现异常",ex);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws IOException, InterruptedException {
+        String path = "D:/data/575645163628527616/";
+        String fileName = "copy.tar.gz";
+        File f = new File(path);
+        File[] list = f.listFiles();
+        Properties prop = System.getProperties();
+        String os = prop.getProperty("os.name");
+        if (os != null && os.toLowerCase().indexOf("linux") > -1) {
+            // linux 执行解压命令
+            File[] files = FileUtil.sort(list);
+            StringBuffer sb = new StringBuffer(" cat ");
+            for (int i = 0; i < files.length; i++){
+                sb.append(files[i].getAbsolutePath()).append(" ");
+            }
+            sb.append(" >> ").append(path).append(File.separator).append(fileName);
+            sb.append(" & tar zxvf ").append(path).append(File.separator).append(fileName).append(" -C ").append(path);
+            System.out.println(sb.toString());
+
+            String[] cmd = new String[]{"/bin/sh", "-c", sb.toString()};
+
+            Process shellProcess = null;
+            BufferedReader shellErrorResultReader = null;
+            BufferedReader shellInfoResultReader = null;
+            try {
+                shellProcess = Runtime.getRuntime().exec(cmd);
+                shellErrorResultReader = new BufferedReader(new InputStreamReader(shellProcess.getErrorStream()));
+                shellInfoResultReader =  new BufferedReader(new InputStreamReader(shellProcess.getInputStream()));
+                String infoLine;
+                while ((infoLine = shellInfoResultReader.readLine()) != null) {
+                    log.info("linux环境脚本执行信息:{}", infoLine);
+                }
+                String errorLine;
+                while ((errorLine = shellErrorResultReader.readLine()) != null) {
+                    log.warn("linux环境脚本执行信息:{}", errorLine);
+                }
+                // 等待程序执行结束并输出状态
+                int exitCode = shellProcess.waitFor();
+                if (0 == exitCode) {
+                    log.info(path+ File.separator+fileName+":合并完成\n"+path+ File.separator+fileName+":解压完成");
+                } else {
+                    log.error("linux环境脚本执行失败:" + exitCode);
+                }
+            } catch (Exception e) {
+                log.error("linux环境shell脚本执行错误", e);
+            } finally {
+                if (null != shellInfoResultReader) {
+                    try {
+                        shellInfoResultReader.close();
+                    } catch (IOException e) {
+                        log.error("linux环境脚本流文件关闭异常:", e);
+                    }
+                }
+                if (null != shellErrorResultReader) {
+                    try {
+                        shellErrorResultReader.close();
+                    } catch (IOException e) {
+                        log.error("linux环境脚本流文件关闭异常:", e);
+                    }
+                }
+                if (null != shellProcess) {
+                    shellProcess.destroy();
+                }
+            }
+
+            /*Process process = Runtime.getRuntime().exec(cmd);
+            int exitValue = process.waitFor();
+            process.getOutputStream().close();
+            if (0 == exitValue){
+                System.out.println(path+ File.separator+fileName+":合并完成\n"+path+ File.separator+fileName+":解压完成");
+            }*/
+        } else {
+            // windows 执行命令
+            File[] files = FileUtil.sort(list);
+            StringBuffer sb = new StringBuffer("cmd.exe /c copy /b ");
+            for (int i = 0; i < files.length; i++){
+                sb.append(files[i].getAbsolutePath());
+                if (i != files.length -1){
+                    sb.append("+");
+                }
+            }
+            sb.append(" ").append(path).append(File.separator).append(fileName);
+            System.out.println(sb.toString());
+
+            Process shellProcess = null;
+            BufferedReader shellErrorResultReader = null;
+            BufferedReader shellInfoResultReader = null;
+            try {
+                shellProcess = Runtime.getRuntime().exec(sb.toString());
+                shellErrorResultReader = new BufferedReader(new InputStreamReader(shellProcess.getErrorStream()));
+                shellInfoResultReader =  new BufferedReader(new InputStreamReader(shellProcess.getInputStream()));
+                String infoLine;
+                while ((infoLine = shellInfoResultReader.readLine()) != null) {
+                    log.info("windows环境脚本执行信息:{}", infoLine);
+                }
+                String errorLine;
+                while ((errorLine = shellErrorResultReader.readLine()) != null) {
+                    log.warn("windows环境脚本执行信息:{}", errorLine);
+                }
+                // 等待程序执行结束并输出状态
+                int exitCode = shellProcess.waitFor();
+                if (0 == exitCode) {
+                    log.info(path + File.separator + fileName+":合并完成");
+                    ZipUtil.unTarGz(new File(path + File.separator + fileName), path + File.separator);
+                    log.info(path + File.separator + fileName+":解压完成");
+                } else {
+                    log.error("windows环境脚本执行失败:" + exitCode);
+                }
+            } catch (Exception e) {
+                log.error("windows环境shell脚本执行错误", e);
+            } finally {
+                if (null != shellInfoResultReader) {
+                    try {
+                        shellInfoResultReader.close();
+                    } catch (IOException e) {
+                        log.error("windows环境流文件关闭异常:", e);
+                    }
+                }
+                if (null != shellErrorResultReader) {
+                    try {
+                        shellErrorResultReader.close();
+                    } catch (IOException e) {
+                        log.error("windows环境流文件关闭异常:", e);
+                    }
+                }
+                if (null != shellProcess) {
+                    shellProcess.destroy();
+                }
+            }
+            /*Process process = Runtime.getRuntime().exec(sb.toString());
+            int exitValue = process.waitFor();
+            process.getOutputStream().close();
+            if (0 == exitValue){
+                System.out.println(path+fileName+":合并完成");
+                ZipUtil.unTarGz(new File(path + File.separator + fileName), path + File.separator);
+                System.out.println(path+fileName+":解压完成");
+            }*/
+        }
+    }
+}

+ 283 - 0
4dkankan-common/pom.xml

@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.fdkankan</groupId>
+    <artifactId>4dkankan-common</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+    <repositories>
+        <repository>
+            <id>nexus-aliyun</id>
+            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
+        </repository>
+    </repositories>
+
+    <name>4dkankan-common</name>
+    <description>4dkankan common</description>
+
+    <parent>
+        <groupId>com.fdkankan</groupId>
+        <artifactId>4dkankan_hd</artifactId>
+        <version>1.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>Greenwich.SR2</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
+                <version>0.9.0.RELEASE</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+        <!-- nacos注册中心 -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!-- nacos 依赖 -->
+        <dependency>
+            <groupId>com.alibaba.boot</groupId>
+            <artifactId>nacos-config-spring-boot-starter</artifactId>
+            <version>0.2.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-ossadmin -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-ossadmin</artifactId>
+            <version>2.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>2.8.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.8.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>joinery</groupId>
+            <artifactId>jave</artifactId>
+            <version>1.0.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <!--截取视频第一帧-->
+        <!--<dependency>-->
+            <!--<groupId>org.bytedeco</groupId>-->
+            <!--<artifactId>javacpp-presets</artifactId>-->
+            <!--<version>1.4.3</version>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>org.openpnp</groupId>
+            <artifactId>opencv</artifactId>
+            <version>3.4.2-1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>javacpp</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>javacv-platform</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.5.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>javax.mail</artifactId>
+            <version>1.5.4</version>
+        </dependency>
+
+
+        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.xingePush</groupId>
+            <artifactId>xinge</artifactId>
+            <version>1.2.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.firebase</groupId>
+            <artifactId>firebase-admin</artifactId>
+            <version>6.8.1</version>
+        </dependency>
+
+
+    </dependencies>
+
+    <distributionManagement>
+        <repository>
+            <!-- 这里的ID要和setting的id一致 -->
+            <id>releases</id>
+            <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/releases/</url>
+        </repository>
+        <!--这是打成快照版本的配置 -->
+        <snapshotRepository>
+            <id>snapshots</id>
+            <url>http://192.168.0.115:8081/nexus-2.14.2-01/content/repositories/snapshots/</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+            <resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.xml</include>
+                </includes>
+            </resource>
+        </resources>
+    </build>
+
+</project>

+ 143 - 0
4dkankan-common/src/main/java/com/fdkankan/common/api/BaseController.java

@@ -0,0 +1,143 @@
+package com.fdkankan.common.api;
+
+import com.fdkankan.common.util.DateEditor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.Date;
+
+public class BaseController {
+
+    @Autowired
+    protected HttpServletRequest request;
+
+    @Autowired
+    protected HttpServletResponse response;
+
+    @InitBinder
+    protected void initBinder(WebDataBinder webDataBinder) {
+        webDataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
+        webDataBinder.registerCustomEditor(Date.class, new DateEditor(true));
+    }
+
+    /**
+     * 带参重定向
+     *
+     * @param path
+     * @return
+     */
+    protected String redirect(String path) {
+        return "redirect:" + path;
+    }
+
+    /**
+     * 不带参重定向
+     *
+     * @param response
+     * @param path
+     * @return
+     */
+    protected String redirect(HttpServletResponse response, String path) {
+        try {
+            response.sendRedirect(path);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取分页请求
+     *
+     * @return
+     */
+    protected PageRequest getPageRequest() {
+        int page = 0;
+        int size = 10;
+        Sort sort = null;
+        String sortName = request.getParameter("sortName");
+        String sortOrder = request.getParameter("sortOrder");
+        if (!StringUtils.isEmpty(sortName) && !StringUtils.isEmpty(sortOrder)) {
+            if (sortOrder.equalsIgnoreCase("desc")) {
+                sort = new Sort(Direction.DESC, sortName);
+            } else {
+                sort = new Sort(Direction.ASC, sortName);
+            }
+        }
+        String pageNumber = request.getParameter("pageNum");
+        if (!StringUtils.isEmpty(pageNumber)) {
+            page = Integer.parseInt(pageNumber);
+        }
+        String pageSize = request.getParameter("pageSize");
+        if (!StringUtils.isEmpty(pageSize)) {
+            size = Integer.parseInt(pageSize);
+        }
+        return new PageRequest(page, size, sort);
+    }
+
+    /**
+     * 获取分页请求
+     *
+     * @param sort 排序条件
+     * @return
+     */
+    protected PageRequest getPageRequest(Sort sort) {
+        int page = 0;
+        int size = 10;
+        String sortName = request.getParameter("sortName");
+        String sortOrder = request.getParameter("sortOrder");
+        if (!StringUtils.isEmpty(sortName) && !StringUtils.isEmpty(sortOrder)) {
+            if (sortOrder.equalsIgnoreCase("desc")) {
+                sort.and(new Sort(Direction.DESC, sortName));
+            } else {
+                sort.and(new Sort(Direction.ASC, sortName));
+            }
+        }
+        String pageNumber = request.getParameter("pageNum");
+        if (!StringUtils.isEmpty(pageNumber)) {
+            page = Integer.parseInt(pageNumber);
+        }
+        String pageSize = request.getParameter("pageSize");
+        if (!StringUtils.isEmpty(pageSize)) {
+            size = Integer.parseInt(pageSize);
+        }
+        return new PageRequest(page, size, sort);
+    }
+
+    public static void output(HttpServletResponse resp, File file) {
+        OutputStream os = null;
+        BufferedInputStream bis = null;
+        byte[] buff = new byte[1024];
+        try {
+            os = resp.getOutputStream();
+            bis = new BufferedInputStream(new FileInputStream(file));
+            int i = 0;
+            while ((i = bis.read(buff)) != -1) {
+                os.write(buff, 0, i);
+                os.flush();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                bis.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    protected String getToken(){
+        return request.getHeader("token");
+    }
+
+}

+ 41 - 0
4dkankan-common/src/main/java/com/fdkankan/common/api/ModifyHttpServletRequestWrapper.java

@@ -0,0 +1,41 @@
+package com.fdkankan.common.api;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.util.*;
+
+/**
+ * Created by Hb_zzZ on 2019/7/26.
+ */
+public class ModifyHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+    private Map<String, String> customHeaders;
+
+    public ModifyHttpServletRequestWrapper(HttpServletRequest request) {
+        super(request);
+        this.customHeaders = new HashMap<>();
+    }
+
+    public void putHeader(String name, String value) {
+        this.customHeaders.put(name, value);
+    }
+
+    public String getHeader(String name) {
+        String value = this.customHeaders.get(name);
+        if (value != null) {
+            return value;
+        }
+        return ((HttpServletRequest) getRequest()).getHeader(name);
+    }
+
+    public Enumeration<String> getHeaderNames() {
+        Set<String> set = new HashSet<>(customHeaders.keySet());
+        Enumeration<String> enumeration = ((HttpServletRequest) getRequest()).getHeaderNames();
+        while (enumeration.hasMoreElements()) {
+            String name = enumeration.nextElement();
+            set.add(name);
+        }
+        return Collections.enumeration(set);
+    }
+
+}

+ 14 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/Constant.java

@@ -0,0 +1,14 @@
+package com.fdkankan.common.constant;
+
+public class Constant {
+
+    // 1GB
+    public static String EXPANSION_SPACE_VALUE_1G = "1073741824";
+    // 1TB
+    public static String EXPANSION_SPACE_VALUE_1T = "1099511627776";
+    // 1PB
+    public static String EXPANSION_SPACE_VALUE_1P = "1125899906842624";
+    // 八目相机基础容量10G
+    public static String CAMERA_BASE_SPACE_VALUE = "10737418240";
+}
+

+ 28 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantCmd.java

@@ -0,0 +1,28 @@
+package com.fdkankan.common.constant;
+
+public class ConstantCmd {
+
+	//生成模型的命令
+	public static final String BUILD_MODEL_COMMAND = "bash /home/ubuntu/bin/Launcher.sh ";
+
+	public static final String BUILD_MODEL_OLD_COMMAND = "bash /home/ubuntu/bin_old/Launcher.sh ";
+
+	public static final String OBJ_TO_TXT = "bash /home/ubuntu/bin_old/obj2txt.sh ";
+
+	//合并音频
+	public static final String MERGE_VIDEO = "bash /monchickey/ffmpeg/bin/ff_synthesis.sh ";
+
+	//生成一段静音音频
+	public static final String CREATE_MUTE_VIDEO = "bash /monchickey/ffmpeg/bin/ff_mtue.sh ";
+
+	//将mp4文件转换成flv
+	public static final String MP4_TO_FLV = "bash /monchickey/ffmpeg/bin/ff_mp4TOflv.sh ";
+
+	//删除/mnt/data/下的数据脚本
+	public static final String DELETE_FILE = "bash /monchickey/ffmpeg/bin/delete.sh ";
+
+	public static final String OSS_UTIL_CP ="bash /opt/ossutil/oss.sh ";
+
+	public static final String OSS_FILE_CP = "bash /opt/ossutil/file.sh ";
+
+}

+ 94 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantExcel.java

@@ -0,0 +1,94 @@
+//package com.fdkankan.common.constant;
+//
+//public class ConstantExcel {
+//
+//	  public static final String[] ORDEREXCELCOLENNAME = {"序号","支付时间","发货订单编号","手机号/用户号","订单金额","支付方式","收货地址","收件人电话","收件人姓名", "订单状态","付款状态","配送状态","交易号","发票类型(三种类型)","发票抬头","纳税人识别号","注册地址","注册电话","开户银行","银行账户"};
+//	  public static final String[] SUMMARYEXCELCOLENNAME = {"手机号/用户号","设备ID","期初点数","新增点数","消费点数","其他点数变动","期末点数","期初开票额度","新增开票额度","已开票额度","其他金额变动","期末开票额度"};
+//	  public static final String[] RECHARGEEXCELCOLENNAME = {"时间","订单号","手机号/用户名","设备ID","充值点数","订单金额(元)","支付方式","类型","交易号"};
+//	  public static final String[] CONSUMEEXCELCOLENNAME = {"时间","订单号","手机号/用户名","设备ID","商品名称","消费点数"};
+//	  public static final String[] INVOICEEXCELCOLENNAME = {"序号","订单编号","发票类型","开票金额","发票抬头","18位税号","注册地址","注册电话","开户银行","银行账户","收件地址","电子邮箱","手机号码","商品1","数量","价格","金额","商品2","数量","价格","金额","商品3","数量","价格","金额","更多商品"};
+//	  public static final String[] CAMEREXCELCOLENAME = {"设备ID","SN号","入库时间","出库时间","订单编号","经销商","出库时间","地区","手机号码/用户名","激活时间"};
+//	  //public static final String[] AGENT_CAMERACOLENNAME = {"设备ID","期初点数","赠送点数","已用点数","剩余点数","充值金额","兑换为点数","消耗点数","提成金额"};
+//	  public static final String[] AGENT_CAMERACOLENNAME = {"设备ID","赠送点数","已用点数","剩余点数","充值金额","兑换为点数","消耗点数","提成金额"};
+//	  public static final String[] AGENT_DETAILCHARGECOLENNAME = {"时间","充值金额","兑换成点数","状态","订单编号"};
+//	  public static final String[] AGENT_DETAILCONSUMECOLENNAME = {"时间","消费点数","订单编号"};
+//
+//	  public static final String[] MANAGEAGENT = {"代理ID","公司名称","电话","区域","邮箱","使用状态","创建时间"};
+//	  public static final String[] MANAGEAGENTQUERY = {"代理ID","公司名称","区域","电话","代理数量","库存","累计充值金额","累计消耗点数","提成金额"};
+//	  public static final String[] MANAGEAGENTDETAILQUERY = {"设备ID","初始点数","已用点数","剩余点数","充值金额","兑换为点数","消耗点数","提成金额"};
+//
+//	  public static final String[] ORDERSTATUS = {"未支付","待发货","已发货","已完成"};
+//	  public static final String[] PAYFORM = {"微信","支付宝","Paypal","其他"};
+//	  public static final String[] INVOICE = {"不需要发票","增值税普通发票","增值税专用发票"};
+//	  public static final String[] INVOICETYPE1 = {"发票抬头","纳税人识别号"};
+//	  public static final String[] INVOICETYPE2 = {"发票抬头","纳税人识别号","注册地址","注册电话","开户银行","银行账户"};
+//
+//	  public static final String getOrderStatus(String orderStatus){
+//	  	String status = "";
+//	  	switch (orderStatus){
+//			case "unprocessed":
+//				status = "未处理";
+//				break;
+//			case "processed":
+//				status = "已确认";
+//				break;
+//			case "completed":
+//				status = "已完成";
+//				break;
+//			case "invalid":
+//				status = "已取消";
+//				break;
+//		}
+//		return status;
+//	  }
+//
+//	public static final String getPaymentStatus(String paymentStatus){
+//		String status = "";
+//		switch (paymentStatus){
+//			case "unpaid":
+//				status = "未付款";
+//				break;
+//			case "paid":
+//				status = "已付款";
+//				break;
+//			case "cancel":
+//				status = "已取消";
+//				break;
+//			case "partPayment":
+//				status = "部分支付";
+//				break;
+//			case "partRefund":
+//				status = "部分退款";
+//				break;
+//			case "refunded":
+//				status = "全额退款";
+//				break;
+//		}
+//		return status;
+//	}
+//
+//	public static final String getShippingStatus(String shippingStatus){
+//		String status = "";
+//		switch (shippingStatus){
+//			case "unshipped":
+//				status = "未发货";
+//				break;
+//			case "partShipped":
+//				status = "部分发货";
+//				break;
+//			case "shipped":
+//				status = "已发货";
+//				break;
+//			case "partReshiped":
+//				status = "部分退货";
+//				break;
+//			case "reshiped":
+//				status = "已退货";
+//				break;
+//			case "received":
+//				status = "已收货";
+//				break;
+//		}
+//		return status;
+//	}
+//}

+ 20 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantFileName.java

@@ -0,0 +1,20 @@
+package com.fdkankan.common.constant;
+
+public class ConstantFileName {
+
+    public static final String SCREEN_CRP_DATAFILE = "screenCap";
+
+    //论坛过滤文档
+    public static final String BBS_SENSITIVE = "SensitiveWord.txt";
+
+    public static final String TOUR_LIST = "tourList.json";
+    public static final String VOICE_NAME = "201810";
+    public static final String WECHAT_VOICE_NAME = "wechat";
+    public static final String APP_VOICE_NAME = "app";
+
+    public static final String TOURLIST_FOLDER = "tour";
+
+    public static final String modelUUID = "dacf7dfa24ae47fab8fcebfe4dc41ab9";
+
+    public static final String BUCKET_NAME = "4dkankan";
+}

+ 17 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantFilePath.java

@@ -0,0 +1,17 @@
+package com.fdkankan.common.constant;
+
+public class ConstantFilePath {
+    public static final String BASE_PATH = "/mnt/4Dkankan";
+    // 场景
+    public static final String SCENE_PATH = "/mnt/4Dkankan/scene/";
+    // 场景二维码
+    public static final String SCENE_QR_CODE_PATH = "/mnt/4Dkankan/sceneQRcode/";
+    // logo
+    public static final String LOGO_PATH = "/mnt/4Dkankan/logo/";
+
+    public static final String PREFIX = "/home/user";
+    //生成模型的路径
+    public static final String BUILD_MODEL_PATH = "/mnt/data/";
+
+    public static final String OSS_PREFIX = "home/";
+}

+ 11 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantRegex.java

@@ -0,0 +1,11 @@
+//package com.fdkankan.common.constant;
+//
+///**
+// * Created by Hb_zzZ on 2020/5/26.
+// */
+//public class ConstantRegex {
+//
+//    public static final String PASSWORD_REGEX = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[\\da-zA-Z`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]{8,16}$";
+//
+//    public static final String EMAIL_REGEX = "^[A-Za-z\\d]+([_.-][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z\\d]{2,4}$";
+//}

+ 9 - 0
4dkankan-common/src/main/java/com/fdkankan/common/constant/ConstantUrl.java

@@ -0,0 +1,9 @@
+package com.fdkankan.common.constant;
+
+public class ConstantUrl {
+
+	public static final String DEFAULT_SCENE_PIC="https://4dkk.4dage.com/loading/thumb.jpg";
+	//亚马逊S3
+	public static final String PREFIX_AWS = "https://eurs3.4dkankan.com/";
+
+}

+ 35 - 0
4dkankan-common/src/main/java/com/fdkankan/common/exception/BaseRuntimeException.java

@@ -0,0 +1,35 @@
+package com.fdkankan.common.exception;
+
+public class BaseRuntimeException extends RuntimeException{
+
+    private static final long serialVersionUID = -1518945670203783450L;
+    private Integer code;
+    private String msg;
+
+    public BaseRuntimeException(String msg){
+        super(msg);
+        this.msg = msg;
+    }
+
+    public BaseRuntimeException(Integer code, String msg){
+        super(msg);
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

+ 46 - 0
4dkankan-common/src/main/java/com/fdkankan/common/exception/GlobalExceptionHandler.java

@@ -0,0 +1,46 @@
+package com.fdkankan.common.exception;
+
+import com.fdkankan.common.model.Result;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 全局异常捕获统一返回客户端
+ */
+@Log4j2
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+//    @ResponseBody
+//    @ExceptionHandler(Exception.class)
+//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public Result exceptionHandler(HttpServletRequest request, Exception e) {
+        log.error(request.getRequestURI() + ":" + e.getCause());
+        Result result = Result.failure("系统错误:"+ e);
+//        if (e instanceof RuntimeException){
+//            String msg = e.getCause() == null ? e.toString() : e.getCause().getMessage();
+//            if (msg.contains("Load balancer does not have available server for client")){
+//                result = Result.failure(msg.split(":")[1] + "服务不可用");
+//            }
+//            if (e instanceof BaseFeignException){
+//                result = Result.failure( Result.CODE_FAILURE, e.getMessage());
+//            }
+//        }
+        return result;
+    }
+
+    @ResponseBody
+    @ExceptionHandler(BaseRuntimeException.class)
+    @ResponseStatus(HttpStatus.OK)
+    public Result runtimeExceptionHandler(HttpServletRequest request, BaseRuntimeException e) {
+        log.error(request.getRequestURI() + ":" + e.getMsg());
+        return Result.failure(e.getCode() == null ? Result.CODE_FAILURE : e.getCode(), e.getMsg());
+    }
+
+}

+ 101 - 0
4dkankan-common/src/main/java/com/fdkankan/common/model/Result.java

@@ -0,0 +1,101 @@
+package com.fdkankan.common.model;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 通用返回类
+ *
+ * @author
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Result<T> implements Serializable {
+    private static final long serialVersionUID = -1491499610244557029L;
+    public static final String SUCCESS_MSG = "操作成功";
+    public static int CODE_SUCCESS = 0;
+    public static int CODE_FAILURE = -1;
+    public static String[] NOOP = new String[]{};
+
+    /**
+     * 处理状态:0: 成功, 1: 失败
+     */
+    @ApiModelProperty(value = "处理状态:0: 成功, 1: 失败", name = "code")
+    private int code;
+    /**
+     * 消息
+     */
+    @ApiModelProperty(value = "消息", name = "msg")
+    private String msg;
+    /**
+     * 返回数据
+     */
+    @ApiModelProperty(value = "返回数据", name = "data")
+    private T data;
+    /**
+     * 处理成功,并返回数据
+     *
+     * @param data 数据对象
+     * @return data
+     */
+    public static Result success(Object data) {
+        return new Result(CODE_SUCCESS, SUCCESS_MSG, data);
+    }
+    /**
+     * 处理成功
+     *
+     * @return data
+     */
+    public static Result success() {
+        return new Result(CODE_SUCCESS, SUCCESS_MSG, NOOP);
+    }
+    /**
+     * 处理成功
+     *
+     * @param msg 消息
+     * @return data
+     */
+    public static Result success(String msg) {
+        return new Result(CODE_SUCCESS, msg, NOOP);
+    }
+    /**
+     * 处理成功
+     *
+     * @param msg  消息
+     * @param data 数据对象
+     * @return data
+     */
+    public static Result success(String msg, Object data) {
+        return new Result(CODE_SUCCESS, msg, data);
+    }
+    /**
+     * 处理失败,并返回数据(一般为错误信息)
+     *
+     * @param code 错误代码
+     * @param msg  消息
+     * @return data
+     */
+    public static Result failure(int code, String msg) {
+        return new Result(code, msg, NOOP);
+    }
+    /**
+     * 处理失败
+     *
+     * @param msg 消息
+     * @return data
+     */
+    public static Result failure(String msg) {
+        return failure(CODE_FAILURE, msg);
+    }
+
+    @Override
+    public String toString() {
+        return "JsonResult [code=" + code + ", msg=" + msg + ", data="
+                + data + "]";
+    }
+}

+ 23 - 0
4dkankan-common/src/main/java/com/fdkankan/common/model/SSOUser.java

@@ -0,0 +1,23 @@
+package com.fdkankan.common.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * sso user
+ *
+ *  2018-04-02 19:59:49
+ */
+@Data
+public class SSOUser implements Serializable {
+
+    private static final long serialVersionUID = -2560069033053679931L;
+
+    private Long id;
+
+    private Long departmentId;
+
+
+}

+ 199 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/AndroidNotification.java

@@ -0,0 +1,199 @@
+package com.fdkankan.common.push;
+
+import org.json.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class AndroidNotification extends UmengNotification {
+	// Keys can be set in the payload level
+	protected static final HashSet<String> PAYLOAD_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"display_type"}));
+	
+	// Keys can be set in the body level
+	protected static final HashSet<String> BODY_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"ticker", "title", "text", "builder_id", "icon", "largeIcon", "img", "play_vibrate", "play_lights", "play_sound",
+			"sound", "after_open", "url", "activity", "custom"}));
+
+	public enum DisplayType{
+		NOTIFICATION{public String getValue(){return "notification";}},///通知:消息送达到用户设备后,由友盟SDK接管处理并在通知栏上显示通知内容。
+		MESSAGE{public String getValue(){return "message";}};///消息:消息送达到用户设备后,消息内容透传给应用自身进行解析处理。
+		public abstract String getValue();
+	}
+	public enum AfterOpenAction{
+        go_app,//打开应用
+        go_url,//跳转到URL
+        go_activity,//打开特定的activity
+        go_custom//用户自定义内容。
+	}
+	// Set key/value in the rootJson, for the keys can be set please see ROOT_KEYS, PAYLOAD_KEYS, 
+	// BODY_KEYS and POLICY_KEYS.
+	@Override
+	public boolean setPredefinedKeyValue(String key, Object value) throws Exception {
+		if (ROOT_KEYS.contains(key)) {
+			// This key should be in the root level
+			rootJson.put(key, value);
+		} else if (PAYLOAD_KEYS.contains(key)) {
+			// This key should be in the payload level
+			JSONObject payloadJson = null;
+			if (rootJson.has("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			payloadJson.put(key, value);
+		} else if (BODY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject bodyJson = null;
+			JSONObject payloadJson = null;
+			// 'body' is under 'payload', so build a payload if it doesn't exist
+			if (rootJson.has("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			// Get body JSONObject, generate one if not existed
+			if (payloadJson.has("body")) {
+				bodyJson = payloadJson.getJSONObject("body");
+			} else {
+				bodyJson = new JSONObject();
+				payloadJson.put("body", bodyJson);
+			}
+			bodyJson.put(key, value);
+		} else if (POLICY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject policyJson = null;
+			if (rootJson.has("policy")) {
+				policyJson = rootJson.getJSONObject("policy");
+			} else {
+				policyJson = new JSONObject();
+				rootJson.put("policy", policyJson);
+			}
+			policyJson.put(key, value);
+		} else {
+			if (key == "payload" || key == "body" || key == "policy" || key == "extra") {
+				throw new Exception("You don't need to set value for " + key + " , just set values for the sub keys in it.");
+			} else {
+				throw new Exception("Unknown key: " + key);
+			}
+		}
+		return true;
+	}
+	
+	// Set extra key/value for Android notification
+	public boolean setExtraField(String key, String value) throws Exception {
+		JSONObject payloadJson = null;
+		JSONObject extraJson = null;
+		if (rootJson.has("payload")) {
+			payloadJson = rootJson.getJSONObject("payload");
+		} else {
+			payloadJson = new JSONObject();
+			rootJson.put("payload", payloadJson);
+		}
+		
+		if (payloadJson.has("extra")) {
+			extraJson = payloadJson.getJSONObject("extra");
+		} else {
+			extraJson = new JSONObject();
+			payloadJson.put("extra", extraJson);
+		}
+		extraJson.put(key, value);
+		return true;
+	}
+	
+	//
+	public void setDisplayType(DisplayType d) throws Exception {
+		setPredefinedKeyValue("display_type", d.getValue());
+	}
+	///通知栏提示文字
+	public void setTicker(String ticker) throws Exception {
+		setPredefinedKeyValue("ticker", ticker);
+	}
+	///通知标题
+	public void setTitle(String title) throws Exception {
+		setPredefinedKeyValue("title", title);
+	}
+	///通知文字描述
+	public void setText(String text) throws Exception {
+		setPredefinedKeyValue("text", text);
+	}
+	///用于标识该通知采用的样式。使用该参数时, 必须在SDK里面实现自定义通知栏样式。
+	public void setBuilderId(Integer builder_id) throws Exception {
+		setPredefinedKeyValue("builder_id", builder_id);
+	}
+	///状态栏图标ID, R.drawable.[smallIcon],如果没有, 默认使用应用图标。
+	public void setIcon(String icon) throws Exception {
+		setPredefinedKeyValue("icon", icon);
+	}
+	///通知栏拉开后左侧图标ID
+	public void setLargeIcon(String largeIcon) throws Exception {
+		setPredefinedKeyValue("largeIcon", largeIcon);
+	}
+	///通知栏大图标的URL链接。该字段的优先级大于largeIcon。该字段要求以http或者https开头。
+	public void setImg(String img) throws Exception {
+		setPredefinedKeyValue("img", img);
+	}
+	///收到通知是否震动,默认为"true"
+	public void setPlayVibrate(Boolean play_vibrate) throws Exception {
+		setPredefinedKeyValue("play_vibrate", play_vibrate.toString());
+	}
+	///收到通知是否闪灯,默认为"true"
+	public void setPlayLights(Boolean play_lights) throws Exception {
+		setPredefinedKeyValue("play_lights", play_lights.toString());
+	}
+	///收到通知是否发出声音,默认为"true"
+	public void setPlaySound(Boolean play_sound) throws Exception {
+		setPredefinedKeyValue("play_sound", play_sound.toString());
+	}
+	///通知声音,R.raw.[sound]. 如果该字段为空,采用SDK默认的声音
+	public void setSound(String sound) throws Exception {
+		setPredefinedKeyValue("sound", sound);
+	}
+	///收到通知后播放指定的声音文件
+	public void setPlaySound(String sound) throws Exception {
+		setPlaySound(true);
+		setSound(sound);
+	}
+	
+	///点击"通知"的后续行为,默认为打开app。
+	public void goAppAfterOpen() throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_app);
+	}
+	public void goUrlAfterOpen(String url) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_url);
+		setUrl(url);
+	}
+	public void goActivityAfterOpen(String activity) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_activity);
+		setActivity(activity);
+	}
+	public void goCustomAfterOpen(String custom) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_custom);
+		setCustomField(custom);
+	}
+	public void goCustomAfterOpen(JSONObject custom) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_custom);
+		setCustomField(custom);
+	}
+	
+	///点击"通知"的后续行为,默认为打开app。原始接口
+	public void setAfterOpenAction(AfterOpenAction action) throws Exception {
+		setPredefinedKeyValue("after_open", action.toString());
+	}
+	public void setUrl(String url) throws Exception {
+		setPredefinedKeyValue("url", url);
+	}
+	public void setActivity(String activity) throws Exception {
+		setPredefinedKeyValue("activity", activity);
+	}
+	///can be a string of json
+	public void setCustomField(String custom) throws Exception {
+		setPredefinedKeyValue("custom", custom);
+	}
+	public void setCustomField(JSONObject custom) throws Exception {
+		setPredefinedKeyValue("custom", custom);
+	}
+	
+}

+ 6 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/App.java

@@ -0,0 +1,6 @@
+package com.fdkankan.common.push;
+
+
+public class App {
+
+}

+ 304 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/Demo.java

@@ -0,0 +1,304 @@
+package com.fdkankan.common.push;
+
+
+import com.fdkankan.common.push.android.*;
+import com.fdkankan.common.push.ios.*;
+import com.fdkankan.common.util.DateUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.Date;
+
+@Slf4j
+public class Demo {
+	private String appkey = null;
+	private String appMasterSecret = null;
+	private String timestamp = null;
+	private PushClient client = new PushClient();
+
+	public static final String ANDROID_KEY = "5ee71c03dbc2ec076dd488cb";
+	public static final String ANDROID_SECRET = "gzw4r8frbhq6eigxrvgjkdrm7wgtu83g";
+	public static final String IOS_KEY = "5ee71ca9978eea081640f22a";
+	public static final String IOS_SECRET = "tpuhyojch16pcha2qmpidlbnzkielv9w";
+
+	public Demo(String key, String secret) {
+		try {
+			appkey = key;
+			appMasterSecret = secret;
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+	}
+	
+	public void sendAndroidBroadcast() throws Exception {
+		AndroidBroadcast broadcast = new AndroidBroadcast(appkey,appMasterSecret);
+		broadcast.setTicker( "Android broadcast ticker");
+		broadcast.setTitle(  "中文的title");
+		broadcast.setText(   "Android broadcast text");
+		broadcast.goAppAfterOpen();
+		broadcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		broadcast.setProductionMode();
+		// Set customized fields
+		broadcast.setExtraField("test", "helloworld");
+		//厂商通道相关参数
+		broadcast.setChannelActivity("your channel activity");
+		broadcast.setChannelProperties("abc");
+		client.send(broadcast);
+	}
+	
+	public void sendAndroidUnicast(String token, String ticker, String title, String text, String url) throws Exception {
+		AndroidUnicast unicast = new AndroidUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		unicast.setTicker(ticker);
+		unicast.setTitle(title);
+		unicast.setText(text);
+		unicast.goUrlAfterOpen(url);
+		unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		unicast.setProductionMode();
+		// Set customized fields
+		unicast.setExtraField("test", "helloworld");
+		unicast.setChannelActivity("com.fdage.eight.module.EightPushMsgHandlerActivity");
+//		unicast.setChannelProperties("abc");
+
+		client.send(unicast);
+	}
+	
+	public void sendAndroidGroupcast() throws Exception {
+		AndroidGroupcast groupcast = new AndroidGroupcast(appkey,appMasterSecret);
+		/*  TODO
+		 *  Construct the filter condition:
+		 *  "where": 
+		 *	{
+    	 *		"and": 
+    	 *		[
+      	 *			{"tag":"test"},
+      	 *			{"tag":"Test"}
+    	 *		]
+		 *	}
+		 */
+		JSONObject filterJson = new JSONObject();
+		JSONObject whereJson = new JSONObject();
+		JSONArray tagArray = new JSONArray();
+		JSONObject testTag = new JSONObject();
+		JSONObject TestTag = new JSONObject();
+		testTag.put("tag", "test");
+		TestTag.put("tag", "Test");
+		tagArray.put(testTag);
+		tagArray.put(TestTag);
+		whereJson.put("and", tagArray);
+		filterJson.put("where", whereJson);
+
+		groupcast.setFilter(filterJson);
+		groupcast.setTicker( "Android groupcast ticker");
+		groupcast.setTitle(  "中文的title");
+		groupcast.setText(   "Android groupcast text");
+		groupcast.goAppAfterOpen();
+		groupcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		groupcast.setChannelActivity("your channel activity");
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		groupcast.setProductionMode();
+		//厂商通道相关参数
+		groupcast.setChannelActivity("your channel activity");
+		groupcast.setChannelProperties("abc");
+		client.send(groupcast);
+	}
+	
+	public void sendAndroidCustomizedcast() throws Exception {
+		AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		customizedcast.setAlias("alias", "alias_type");
+		customizedcast.setTicker( "Android customizedcast ticker");
+		customizedcast.setTitle(  "中文的title");
+		customizedcast.setText(   "Android customizedcast text");
+		customizedcast.goAppAfterOpen();
+		customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		customizedcast.setProductionMode();
+		//厂商通道相关参数
+		customizedcast.setChannelActivity("your channel activity");
+		customizedcast.setChannelProperties("abc");
+		client.send(customizedcast);
+	}
+	
+	public void sendAndroidCustomizedcastFile() throws Exception {
+		AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb"+"\n"+"alias");
+		customizedcast.setFileId(fileId, "alias_type");
+		customizedcast.setTicker( "Android customizedcast ticker");
+		customizedcast.setTitle(  "中文的title");
+		customizedcast.setText(   "Android customizedcast text");
+		customizedcast.goAppAfterOpen();
+		customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		customizedcast.setProductionMode();
+		//厂商通道相关参数
+		customizedcast.setChannelActivity("your channel activity");
+		customizedcast.setChannelProperties("abc");
+		client.send(customizedcast);
+	}
+	
+	public void sendAndroidFilecast() throws Exception {
+		AndroidFilecast filecast = new AndroidFilecast(appkey,appMasterSecret);
+		// TODO upload your device tokens, and use '\n' to split them if there are multiple tokens 
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb");
+		filecast.setFileId( fileId);
+		filecast.setTicker( "Android filecast ticker");
+		filecast.setTitle(  "中文的title");
+		filecast.setText(   "Android filecast text");
+		filecast.goAppAfterOpen();
+		filecast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		//厂商通道相关参数
+		filecast.setChannelActivity("your channel activity");
+		filecast.setChannelProperties("abc");
+		client.send(filecast);
+	}
+	
+	public void sendIOSBroadcast() throws Exception {
+		IOSBroadcast broadcast = new IOSBroadcast(appkey,appMasterSecret);
+        //alert值设置为字符串
+		//broadcast.setAlert("IOS 广播测试");
+		//alert的值设置为字典
+//		broadcast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		broadcast.setBadge( 0);
+		broadcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		broadcast.setTestMode();
+		// Set customized fields
+		broadcast.setCustomizedField("test", "helloworld");
+		client.send(broadcast);
+	}
+	
+	public void sendIOSUnicast(String token, String title ,String subtitle , String body, String url) throws Exception {
+		IOSUnicast unicast = new IOSUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		//alert值设置为字符串
+		//unicast.setAlert("IOS 单播测试");
+		//alert的值设置为字典
+		unicast.setAlert(title, subtitle, body, url);
+//		unicast.setBadge( 0);
+		unicast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		unicast.setProductionMode();
+//		unicast.setTestMode();
+		unicast.setDescription(title);
+		unicast.setExpireTime(DateUtil.date2String(DateUtil.daysCalculate(new Date(), 1), null));
+		// Set customized fields
+//		unicast.setCustomizedField("url", url);
+		client.send(unicast);
+	}
+
+	
+	public void sendIOSGroupcast() throws Exception {
+		IOSGroupcast groupcast = new IOSGroupcast(appkey,appMasterSecret);
+		/*  TODO
+		 *  Construct the filter condition:
+		 *  "where": 
+		 *	{
+    	 *		"and": 
+    	 *		[
+      	 *			{"tag":"iostest"}
+    	 *		]
+		 *	}
+		 */
+		JSONObject filterJson = new JSONObject();
+		JSONObject whereJson = new JSONObject();
+		JSONArray tagArray = new JSONArray();
+		JSONObject testTag = new JSONObject();
+		testTag.put("tag", "iostest");
+		tagArray.put(testTag);
+		whereJson.put("and", tagArray);
+		filterJson.put("where", whereJson);
+		log.info(filterJson.toString());
+		
+		// Set filter condition into rootJson
+		groupcast.setFilter(filterJson);
+		//groupcast.setAlert("IOS 组播测试");
+		//alert的值设置为字典
+//		groupcast.setAlert("今日天气" , "subtitle" , "今日可能下雨🌂");
+		groupcast.setBadge( 0);
+		groupcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		groupcast.setTestMode();
+		client.send(groupcast);
+	}
+	
+	public void sendIOSCustomizedcast() throws Exception {
+		IOSCustomizedcast customizedcast = new IOSCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias and alias_type here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		customizedcast.setAlias("alias", "alias_type");
+		//customizedcast.setAlert("IOS 个性化测试");
+		//alert的值设置为字典
+//		customizedcast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		customizedcast.setBadge( 0);
+		customizedcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		customizedcast.setTestMode();
+		client.send(customizedcast);
+	}
+	
+	public void sendIOSFilecast() throws Exception {
+		IOSFilecast filecast = new IOSFilecast(appkey,appMasterSecret);
+		// TODO upload your device tokens, and use '\n' to split them if there are multiple tokens 
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb");
+		filecast.setFileId( fileId);
+		//filecast.setAlert("IOS 文件播测试");
+		//alert的值设置为字典
+//		filecast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		filecast.setBadge( 0);
+		filecast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		filecast.setTestMode();
+		client.send(filecast);
+	}
+	
+	public static void main(String[] args) {
+		// TODO set your appkey and master secret here
+		//安卓
+//		Demo demo = new Demo(ANDROID_KEY, ANDROID_SECRET);
+		//ios
+		Demo demo = new Demo(IOS_KEY, IOS_SECRET);
+		try {
+//			demo.sendAndroidUnicast("AneqkEZahjbW3cF7gu8juNYqz54ZFfK7kjMpTOiQL9dl",
+//					"测试项目计算完成", "四维看看Pro", "您上传的测试项目计算完成,点击查看",
+//					"https://test.4dkankan.com/smobile.html?m=t-e9uHHdn");
+			demo.sendIOSUnicast("ec61a2aa52673c96c12024e07ce267e391ca560e0c60f15ee09e65c8843ef7f4",
+					"四维看看Pro", "测试项目计算完成", "您上传的测试项目计算完成,点击查看",
+					"https://test.4dkankan.com/smobile.html?m=t-e9uHHdn");
+			/* TODO these methods are all available, just fill in some fields and do the test
+			 * demo.sendAndroidCustomizedcastFile();
+			 * demo.sendAndroidBroadcast();
+			 * demo.sendAndroidGroupcast();
+			 * demo.sendAndroidCustomizedcast();
+			 * demo.sendAndroidFilecast();
+			 * 
+			 * demo.sendIOSBroadcast();
+			 * demo.sendIOSUnicast();
+			 * demo.sendIOSGroupcast();
+			 * demo.sendIOSCustomizedcast();
+			 * demo.sendIOSFilecast();
+			 */
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+	}
+	
+
+}

+ 95 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/IOSNotification.java

@@ -0,0 +1,95 @@
+package com.fdkankan.common.push;
+
+import org.json.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class IOSNotification extends UmengNotification {
+
+	// Keys can be set in the aps level
+	protected static final HashSet<String> APS_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"alert", "badge", "sound", "content-available", "url", "mutable-content"
+	}));
+	
+	@Override
+	public boolean setPredefinedKeyValue(String key, Object value) throws Exception {
+		if (ROOT_KEYS.contains(key)) {
+			// This key should be in the root level
+			rootJson.put(key, value);
+		} else if (APS_KEYS.contains(key)) {
+			// This key should be in the aps level
+			JSONObject apsJson = null;
+			JSONObject payloadJson = null;
+			if (rootJson.has("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			if (payloadJson.has("aps")) {
+				apsJson = payloadJson.getJSONObject("aps");
+			} else {
+				apsJson = new JSONObject();
+				payloadJson.put("aps", apsJson);
+			}
+			apsJson.put(key, value);
+		} else if (POLICY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject policyJson = null;
+			if (rootJson.has("policy")) {
+				policyJson = rootJson.getJSONObject("policy");
+			} else {
+				policyJson = new JSONObject();
+				rootJson.put("policy", policyJson);
+			}
+			policyJson.put(key, value);
+		} else {
+			if (key == "payload" || key == "aps" || key == "policy") {
+				throw new Exception("You don't need to set value for " + key + " , just set values for the sub keys in it.");
+			} else {
+				throw new Exception("Unknownd key: " + key);
+			}
+		}
+		
+		return true;
+	}
+	// Set customized key/value for IOS notification
+	public boolean setCustomizedField(String key, String value) throws Exception {
+		//rootJson.put(key, value);
+		JSONObject payloadJson = null;
+		if (rootJson.has("payload")) {
+			payloadJson = rootJson.getJSONObject("payload");
+		} else {
+			payloadJson = new JSONObject();
+			rootJson.put("payload", payloadJson);
+		}
+		payloadJson.put(key, value);
+		return true;
+	}
+
+	public void setAlert(String token) throws Exception {
+    	setPredefinedKeyValue("alert", token);
+    }
+
+    public void setAlert(String title ,String subtitle , String body, String url) throws Exception{
+		JSONObject object = new JSONObject();
+		object.put("title" , title);
+		object.put("subtitle" , subtitle);
+		object.put("body" , body);
+		setPredefinedKeyValue("alert",object );
+		setPredefinedKeyValue("url", url);
+		setPredefinedKeyValue("mutable-content", 1);
+	}
+	public void setBadge(Integer badge) throws Exception {
+    	setPredefinedKeyValue("badge", badge);
+    }
+	
+	public void setSound(String sound) throws Exception {
+    	setPredefinedKeyValue("sound", sound);
+    }
+	
+	public void setContentAvailable(Integer contentAvailable) throws Exception {
+    	setPredefinedKeyValue("content-available", contentAvailable);
+    }
+}

+ 103 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/PushClient.java

@@ -0,0 +1,103 @@
+package com.fdkankan.common.push;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+@Slf4j
+public class PushClient {
+	
+	// The user agent
+	protected final String USER_AGENT = "Mozilla/5.0";
+
+	// This object is used for sending the post request to Umeng
+	protected HttpClient client = new DefaultHttpClient();
+	
+	// The host
+	protected static final String host = "http://msg.umeng.com";
+	
+	// The upload path
+	protected static final String uploadPath = "/upload";
+	
+	// The post path
+	protected static final String postPath = "/api/send";
+
+	public boolean send(UmengNotification msg) throws Exception {
+		String timestamp = Integer.toString((int)(System.currentTimeMillis() / 1000));
+		msg.setPredefinedKeyValue("timestamp", timestamp);
+        String url = host + postPath;
+        String postBody = msg.getPostBody();
+        String sign = DigestUtils.md5Hex(("POST" + url + postBody + msg.getAppMasterSecret()).getBytes("utf8"));
+        url = url + "?sign=" + sign;
+        HttpPost post = new HttpPost(url);
+        post.setHeader("User-Agent", USER_AGENT);
+        StringEntity se = new StringEntity(postBody, "UTF-8");
+        post.setEntity(se);
+        // Send the post request and get the response
+        HttpResponse response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        log.info("Response Code : " + status);
+        BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+        StringBuffer result = new StringBuffer();
+        String line = "";
+        while ((line = rd.readLine()) != null) {
+            result.append(line);
+        }
+        log.info(result.toString());
+        if (status == 200) {
+            log.info("Notification sent successfully.");
+        } else {
+            log.info("Failed to send the notification!");
+        }
+        return true;
+    }
+
+	// Upload file with device_tokens to Umeng
+	public String uploadContents(String appkey,String appMasterSecret,String contents) throws Exception {
+		// Construct the json string
+		JSONObject uploadJson = new JSONObject();
+		uploadJson.put("appkey", appkey);
+		String timestamp = Integer.toString((int)(System.currentTimeMillis() / 1000));
+		uploadJson.put("timestamp", timestamp);
+		uploadJson.put("content", contents);
+		// Construct the request
+		String url = host + uploadPath;
+		String postBody = uploadJson.toString();
+		String sign = DigestUtils.md5Hex(("POST" + url + postBody + appMasterSecret).getBytes("utf8"));
+		url = url + "?sign=" + sign;
+		HttpPost post = new HttpPost(url);
+		post.setHeader("User-Agent", USER_AGENT);
+		StringEntity se = new StringEntity(postBody, "UTF-8");
+		post.setEntity(se);
+		// Send the post request and get the response
+		HttpResponse response = client.execute(post);
+		log.info("Response Code : " + response.getStatusLine().getStatusCode());
+		BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+		StringBuffer result = new StringBuffer();
+		String line = "";
+		while ((line = rd.readLine()) != null) {
+			result.append(line);
+		}
+		log.info(result.toString());
+		// Decode response string and get file_id from it
+		JSONObject respJson = new JSONObject(result.toString());
+		String ret = respJson.getString("ret");
+		if (!ret.equals("SUCCESS")) {
+			throw new Exception("Failed to upload file");
+		}
+		JSONObject data = respJson.getJSONObject("data");
+		String fileId = data.getString("file_id");
+		// Set file_id into rootJson using setPredefinedKeyValue
+		
+		return fileId;
+	}
+
+}

+ 86 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/UmengNotification.java

@@ -0,0 +1,86 @@
+package com.fdkankan.common.push;
+
+import org.json.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class UmengNotification {
+	// This JSONObject is used for constructing the whole request string.
+	protected final JSONObject rootJson = new JSONObject();
+	
+	
+	// The app master secret
+	protected String appMasterSecret;
+	
+	// Keys can be set in the root level
+	protected static final HashSet<String> ROOT_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"appkey", "timestamp", "type", "device_tokens", "alias", "alias_type", "file_id", 
+			"filter", "production_mode", "feedback", "description", "thirdparty_id" , "mipush" , "mi_activity" , "channel_properties"}));
+	
+	// Keys can be set in the policy level
+	protected static final HashSet<String> POLICY_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"start_time", "expire_time", "max_send_num"
+	}));
+	
+	// Set predefined keys in the rootJson, for extra keys(Android) or customized keys(IOS) please 
+	// refer to corresponding methods in the subclass.
+	public abstract boolean setPredefinedKeyValue(String key, Object value) throws Exception;
+	public void setAppMasterSecret(String secret) {
+		appMasterSecret = secret;
+	}
+	
+	public String getPostBody(){
+		return rootJson.toString();
+	}
+	
+	protected final String getAppMasterSecret(){
+		return appMasterSecret;
+	}
+	
+	protected void setProductionMode(Boolean prod) throws Exception {
+    	setPredefinedKeyValue("production_mode", prod.toString());
+    }
+
+	///正式模式
+    public void setProductionMode() throws Exception {
+    	setProductionMode(true);
+    }
+
+    ///测试模式
+    public void setTestMode() throws Exception {
+    	setProductionMode(false);
+    }
+
+    ///发送消息描述,建议填写。
+    public void setDescription(String description) throws Exception {
+    	setPredefinedKeyValue("description", description);
+    }
+
+    ///定时发送时间,若不填写表示立即发送。格式: "YYYY-MM-DD hh:mm:ss"。
+    public void setStartTime(String startTime) throws Exception {
+    	setPredefinedKeyValue("start_time", startTime);
+    }
+    ///消息过期时间,格式: "YYYY-MM-DD hh:mm:ss"。
+    public void setExpireTime(String expireTime) throws Exception {
+    	setPredefinedKeyValue("expire_time", expireTime);
+    }
+    ///发送限速,每秒发送的最大条数。
+    public void setMaxSendNum(Integer num) throws Exception {
+    	setPredefinedKeyValue("max_send_num", num);
+    }
+
+    //厂商弹窗activity
+	public void setChannelActivity(String activity) throws Exception{
+       setPredefinedKeyValue("mipush", "true");
+       setPredefinedKeyValue("mi_activity",activity );
+	}
+
+	//厂商属性配置
+	public void setChannelProperties(String xiaoMiChannelId) throws Exception{
+		JSONObject object = new JSONObject();
+		object.put("xiaomi_channel_id" , xiaoMiChannelId);
+		setPredefinedKeyValue("channel_properties", object);
+	}
+
+}

+ 11 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidBroadcast.java

@@ -0,0 +1,11 @@
+package com.fdkankan.common.push.android;
+
+import com.fdkankan.common.push.AndroidNotification;
+
+public class AndroidBroadcast extends AndroidNotification {
+	public AndroidBroadcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "broadcast");	
+	}
+}

+ 22 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidCustomizedcast.java

@@ -0,0 +1,22 @@
+package com.fdkankan.common.push.android;
+
+import com.fdkankan.common.push.AndroidNotification;
+
+public class AndroidCustomizedcast extends AndroidNotification {
+	public AndroidCustomizedcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "customizedcast");	
+	}
+	
+	public void setAlias(String alias,String aliasType) throws Exception {
+    	setPredefinedKeyValue("alias", alias);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+			
+	public void setFileId(String fileId,String aliasType) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+
+}

+ 15 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidFilecast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.common.push.android;
+
+import com.fdkankan.common.push.AndroidNotification;
+
+public class AndroidFilecast extends AndroidNotification {
+	public AndroidFilecast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "filecast");	
+	}
+	
+	public void setFileId(String fileId) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    }
+}

+ 16 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidGroupcast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.common.push.android;
+
+import com.fdkankan.common.push.AndroidNotification;
+import org.json.JSONObject;
+
+public class AndroidGroupcast extends AndroidNotification {
+	public AndroidGroupcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "groupcast");	
+	}
+	
+	public void setFilter(JSONObject filter) throws Exception {
+    	setPredefinedKeyValue("filter", filter);
+    }
+}

+ 16 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/android/AndroidUnicast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.common.push.android;
+
+import com.fdkankan.common.push.AndroidNotification;
+
+public class AndroidUnicast extends AndroidNotification {
+	public AndroidUnicast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "unicast");	
+	}
+	
+	public void setDeviceToken(String token) throws Exception {
+    	setPredefinedKeyValue("device_tokens", token);
+    }
+
+}

+ 12 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSBroadcast.java

@@ -0,0 +1,12 @@
+package com.fdkankan.common.push.ios;
+
+import com.fdkankan.common.push.IOSNotification;
+
+public class IOSBroadcast extends IOSNotification {
+	public IOSBroadcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "broadcast");	
+		
+	}
+}

+ 23 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSCustomizedcast.java

@@ -0,0 +1,23 @@
+package com.fdkankan.common.push.ios;
+
+
+import com.fdkankan.common.push.IOSNotification;
+
+public class IOSCustomizedcast extends IOSNotification {
+	public IOSCustomizedcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "customizedcast");	
+	}
+	
+	public void setAlias(String alias,String aliasType) throws Exception {
+    	setPredefinedKeyValue("alias", alias);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+		
+	public void setFileId(String fileId, String aliasType) throws Exception {
+		setPredefinedKeyValue("file_id", fileId);
+		setPredefinedKeyValue("alias_type", aliasType);
+	}
+
+}

+ 15 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSFilecast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.common.push.ios;
+
+import com.fdkankan.common.push.IOSNotification;
+
+public class IOSFilecast extends IOSNotification {
+	public IOSFilecast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "filecast");	
+	}
+	
+	public void setFileId(String fileId) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    }
+}

+ 16 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSGroupcast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.common.push.ios;
+
+import com.fdkankan.common.push.IOSNotification;
+import org.json.JSONObject;
+
+public class IOSGroupcast extends IOSNotification {
+	public IOSGroupcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "groupcast");	
+	}
+	
+	public void setFilter(JSONObject filter) throws Exception {
+    	setPredefinedKeyValue("filter", filter);
+    }
+}

+ 15 - 0
4dkankan-common/src/main/java/com/fdkankan/common/push/ios/IOSUnicast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.common.push.ios;
+
+import com.fdkankan.common.push.IOSNotification;
+
+public class IOSUnicast extends IOSNotification {
+	public IOSUnicast(String appkey,String appMasterSecret) throws Exception{
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "unicast");	
+	}
+	
+	public void setDeviceToken(String token) throws Exception {
+    	setPredefinedKeyValue("device_tokens", token);
+    }
+}

+ 83 - 0
4dkankan-common/src/main/java/com/fdkankan/common/util/Base64Converter.java

@@ -0,0 +1,83 @@
+package com.fdkankan.common.util;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+
+/**
+ * Created by Hb_zzZ on 2020/4/17.
+ */
+public class Base64Converter {
+
+    final static Base64.Encoder encoder = Base64.getEncoder();
+    final static Base64.Decoder decoder = Base64.getDecoder();
+
+    /**
+     * 给字符串加密
+     * @param text
+     * @return
+     */
+    public static String encode(String text) {
+        byte[] textByte = new byte[0];
+        try {
+            textByte = text.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        String encodedText = encoder.encodeToString(textByte);
+        return encodedText;
+    }
+
+    /**
+     * 将加密后的字符串进行解密
+     * @param encodedText
+     * @return
+     */
+    public static String decode(String encodedText) {
+        String text = null;
+        try {
+            text = new String(decoder.decode(encodedText), "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return text;
+    }
+
+    /**
+     * 根据逻辑截取加密后的密码
+     * @param text
+     * @return
+     */
+    public static String subText(String text){
+        //去掉前8位字符串
+        text = text.substring(8);
+        //去掉后8位字符串
+        text = text.substring(0, text.length() - 8);
+        //最后两个字符串换到前面,并且去掉剩下的后8位字符串
+        String result = text.substring(text.length() - 2) + text.substring(0, text.length() - 10);
+        return result;
+    }
+
+    public static void main(String[] args) throws UnsupportedEncodingException {
+
+//        String username = "Miracle Luna";
+        String password = "TzFfcV2U5kZWZpbmVk7AYAyCdQdWwOa6TOf1";
+
+        password = password.substring(8);
+        System.out.println(password);
+        password = password.substring(0, password.length() - 8);
+        System.out.println(password);
+        String key = password.substring(password.length() - 2) + password.substring(0, password.length() - 10);
+        System.out.println(key);
+
+
+        // 加密
+//        System.out.println("====  [加密后] 用户名/密码  =====");
+//        System.out.println(Base64Converter.encode(username));
+//        System.out.println(Base64Converter.encode(password));
+
+        // 解密
+        System.out.println("\n====  [解密后] 用户名/密码  =====");
+//        System.out.println(Base64Converter.decode(Base64Converter.encode(username)));
+        System.out.println(Base64Converter.decode(key));
+    }
+}

+ 47 - 0
4dkankan-common/src/main/java/com/fdkankan/common/util/DateEditor.java

@@ -0,0 +1,47 @@
+package com.fdkankan.common.util;
+
+import org.apache.commons.lang3.time.DateUtils;
+
+import java.beans.PropertyEditorSupport;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+public class DateEditor extends PropertyEditorSupport {
+
+    private boolean emptyAsNull;
+    private String dateFormat = "yyyy-MM-dd HH:mm:ss";
+    public static final String[] DATE_PATTERNS = {"yyyy", "yyyy-MM", "yyyyMM", "yyyy/MM", "yyyy-MM-dd", "yyyyMMdd",
+            "yyyy/MM/dd", "yyyy-MM-dd HH:mm:ss", "yyyyMMddHHmmss", "yyyy/MM/dd HH:mm:ss"};
+
+    public DateEditor(boolean emptyAsNull) {
+        this.emptyAsNull = emptyAsNull;
+    }
+
+    public DateEditor(boolean emptyAsNull, String dateFormat) {
+        this.emptyAsNull = emptyAsNull;
+        this.dateFormat = dateFormat;
+    }
+
+    public String getAsText() {
+        Date date = (Date) getValue();
+        return date != null ? new SimpleDateFormat(this.dateFormat).format(date) : "";
+    }
+
+    public void setAsText(String text) {
+        if (text == null) {
+            setValue(null);
+        } else {
+            String str = text.trim();
+            if ((this.emptyAsNull) && ("".equals(str)))
+                setValue(null);
+            else
+                try {
+                    setValue(DateUtils.parseDate(str, DATE_PATTERNS));
+                } catch (ParseException e) {
+                    setValue(null);
+                }
+        }
+    }
+}

+ 404 - 0
4dkankan-common/src/main/java/com/fdkankan/common/util/DateUtil.java

@@ -0,0 +1,404 @@
+/*
+ * PROJECT NAME: openplatform
+ * CREATED TIME: 15-4-30 下午4:16
+ *       AUTHOR: lizhiming
+ *    COPYRIGHT: Copyright(c) 2015~2020 All Rights Reserved.
+ *
+ */
+package com.fdkankan.common.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 日期工具类
+ *
+ * @author lizhiming
+ */
+@Slf4j
+public final class DateUtil {
+
+	/**
+     * 时间格式
+     */
+    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+    public static final String YYYY_MM_DD_DATE_FORMAT = "yyyy-MM-dd";
+
+    public static final String YYYYMMDD_DATA_FORMAT = "yyyyMMdd";
+
+    public static final String HHMMSS_DATA_FORMAT = "HHmmss";
+
+    public static final String YYYYMMDDHHMMSSSSS_DATA_FORMAT = "yyyyMMddHHmmssSSS";
+
+    public static final String YYYYMMDDHHMMSS_DATA_FORMAT = "yyyyMMddHHmmss";
+    
+    public static final String YYMMDDHHMMSS_DATA_FORMAT = "yyMMddHHmmss";
+    
+    public static final String YYMMDDHHMM_DATA_FORMAT = "yyyyMMddHHmm";
+    
+	
+	/**
+	 * 过去的Date对象,TIMESTAMP值可以从1970的某时的开始一直到2037年
+	 */
+	public static final Date PASSED_DATE = DateUtil.string2Date("2000-01-01 00:00:00",
+			DEFAULT_DATE_FORMAT);;
+	/**
+	 * 永久的Date对象,TIMESTAMP值可以从1970的某时的开始一直到2037年
+	 */
+	public static final Date FOREVER_DATE = DateUtil.string2Date("9999-12-31 23:59:59",
+			DEFAULT_DATE_FORMAT);
+
+	private DateUtil() {
+	}
+
+	/**
+	 * 把时间转成北京时间的时间戳
+	 *
+	 * @param input
+	 * @return
+	 */
+	public static long convert2CST(String input) {
+		SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		dff.setTimeZone(TimeZone.getTimeZone("GMT+08"));
+
+		long result = -1;
+		try {
+			Date cstDate = dff.parse(input);
+			result = cstDate.getTime();
+		} catch (Exception e) {
+			log.error("convert2CST meet exception.", e);
+		}
+
+		return result;
+	}
+
+	/**
+	 * 把时间戳转成北京时间的字符串表示
+	 *
+	 * @param input
+	 * @return
+	 */
+	public static String convert2CST(long input) {
+		SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		dff.setTimeZone(TimeZone.getTimeZone("GMT+08"));
+
+		try {
+			return dff.format(new Date(input));
+		} catch (Exception e) {
+			log.error("convert2CST meet exception.", e);
+		}
+
+		return "";
+	}
+
+
+	/**
+	 * 判断两个日期是否是同一天
+	 *
+	 * @param dateA
+	 *            日期1
+	 * @param dateB
+	 *            日期2
+	 * @return true:false
+	 */
+	public static boolean isSameDay(Date dateA, Date dateB) {
+		Calendar calDateA = Calendar.getInstance();
+		calDateA.setTime(dateA);
+
+		Calendar calDateB = Calendar.getInstance();
+		calDateB.setTime(dateB);
+
+		return calDateA.get(Calendar.YEAR) == calDateB.get(Calendar.YEAR)
+				&& calDateA.get(Calendar.MONTH) == calDateB.get(Calendar.MONTH)
+				&& calDateA.get(Calendar.DAY_OF_MONTH) == calDateB.get(Calendar.DAY_OF_MONTH);
+	}
+
+	/**
+	 * 将Java日期转成以秒为单位,去除毫秒信息
+	 * java中Date类中的getTime()是获取时间戳的,java中生成的时间戳精确到毫秒级别,而unix中精确到秒级别,
+	 * 所以通过java生成的时间戳需要除以1000
+	 *
+	 * @param date
+	 * @return
+	 */
+	public static Date truncMesc(Date date) {
+		String strDate = DateUtil.date2String(date, DEFAULT_DATE_FORMAT);
+
+		Date result = null;
+		try {
+			SimpleDateFormat dateFmt = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
+			result = dateFmt.parse(strDate);
+		} catch (Exception e) {
+			log.error("truncMesc meet exception", e);
+		}
+
+		return result;
+	}
+
+	/**
+	 * 判断当前时间是否在指定的有效期内
+	 *
+	 * @param beginDate
+	 *            开始时间
+	 * @param endDate
+	 *            结束时间
+	 * @return true : false
+	 */
+	public static boolean isInPeriod(Date beginDate, Date endDate) {
+		Date now = new Date();
+
+		if (beginDate == null || endDate == null) {
+			log.error("isInPeriod meet null argument.");
+			throw new IllegalArgumentException("isInPeriod meet null argument.");
+		}
+
+		if (beginDate.before(endDate) == false) {
+			log.error("isInPeriod meet invalid date argument.");
+			throw new IllegalArgumentException("isInPeriod meet invalid date argument.");
+		}
+
+		if (now.after(beginDate) && now.before(endDate)) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * 判断目标时间是否比当前时间早
+	 *
+	 * @param targetDate
+	 *            需比较的时间
+	 * @return
+	 */
+	public static boolean isBeforeNow(Date targetDate) {
+		if (targetDate == null) {
+			log.error("isBeforeNow meet null argument.");
+			throw new IllegalArgumentException("isBeforeNow meet null argument.");
+		}
+
+		Date now = new Date();
+
+		return (now.after(targetDate)) ? true : false;
+	}
+
+	/**
+	 * @param beginDate
+	 *            开始时期
+	 * @param days
+	 *            偏离天数,> 0 往后推算; < 0 往前推算
+	 * @return
+	 */
+	public static Date daysCalculate(Date beginDate, int days) {
+		return timesCalculate(beginDate, days, GregorianCalendar.DATE);
+	}
+
+	/**
+	 * @param beginDate
+	 *            开始时期
+	 * @return
+	 */
+	public static Date hoursCalculate(Date beginDate, int hours) {
+		return timesCalculate(beginDate, hours, GregorianCalendar.HOUR);
+	}
+
+	public static Date timesCalculate(Date beginDate, int times, int type) {
+		/*
+		 * GregorianCalendar类的add(int field,int amount)方法表示年月日加减.
+		 * field参数表示年,月,周,日等. amount参数表示要加减的数量.
+		 */
+		GregorianCalendar gc = new GregorianCalendar();
+		gc.setTime(beginDate);
+		gc.add(type, times);
+		return gc.getTime();
+	}
+
+	/**
+	 * 将日期对象按照格式转成字符串
+	 *
+	 * @param date
+	 *            日期对象
+	 * @param format
+	 *            日期格式
+	 * @return 字符串
+	 */
+	public static String date2String(Date date, String format) {
+		if (date == null) {
+			log.error("date2String meet null argument.");
+			throw new IllegalArgumentException("argument is null.");
+		}
+
+		if (format == null) {
+			format = DEFAULT_DATE_FORMAT;
+		}
+
+		String result = null;
+		try {
+			DateFormat fmt = new SimpleDateFormat(format);
+			result = fmt.format(date);
+		} catch (Exception e) {
+			log.error("date2String meet exception. " + e.getLocalizedMessage());
+		}
+		return result;
+	}
+
+	/**
+	 * 将字符串转成日期对象
+	 *
+	 * @param date
+	 *            日期字符串
+	 * @param format
+	 *            日期格式
+	 * @return 日期对象
+	 */
+	public static Date string2Date(String date, String format) {
+		if (date == null) {
+			log.error("string2Date meet null argument.");
+			throw new IllegalArgumentException("argument is null.");
+		}
+
+		if (format == null) {
+			format = DEFAULT_DATE_FORMAT;
+		}
+
+		Date result = null;
+		try {
+			DateFormat fmt = new SimpleDateFormat(format);
+			result = fmt.parse(date);
+		} catch (Exception e) {
+			log.error("string2Date meet exception. " + e.getLocalizedMessage());
+		}
+
+		return result;
+	}
+
+	/**
+	 * java时间戳转换到php时间戳
+	 *
+	 * @param time
+	 * @return
+	 */
+	public static long javaTimestamp(long time) {
+		if (time <= 0) {
+			log.error("javaTimestamp meet null argument.");
+			throw new IllegalArgumentException("argument is null.");
+		}
+		// mysql 时间戳只有10位,只精确到秒,而Java时间戳精确到毫秒,故要做处理
+		String dateline = String.valueOf(time);
+		dateline = dateline.substring(0, 10);
+		return Long.parseLong(dateline);
+	}
+
+	public static long javaTimestamp(Date now) {
+		return javaTimestamp(now.getTime());
+	}
+
+	/**
+	 * 计算两个日期之间相差的天数
+	 *
+	 * @param smdate
+	 *            较小的时间
+	 * @param bdate
+	 *            较大的时间
+	 * @return 相差天数
+	 * @throws ParseException
+	 */
+	public static int daysBetween(Date smdate, Date bdate) {
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+		try {
+			smdate = sdf.parse(sdf.format(smdate));
+			bdate = sdf.parse(sdf.format(bdate));
+		} catch (ParseException e) {
+			log.error("ParseException:", e);
+		}
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(smdate);
+		long time1 = cal.getTimeInMillis();
+		cal.setTime(bdate);
+		long time2 = cal.getTimeInMillis();
+		long between_days = (time2 - time1) / (1000 * 3600 * 24);
+
+		return Integer.parseInt(String.valueOf(between_days));
+	}
+
+	/**
+	 * 把日期推后一天
+	 * @return 相差天数
+	 * @throws ParseException
+	 */
+	public static Date dayDelay(String dateTime) {
+		Date date = string2Date(dateTime, "yyyy-MM-dd");
+		Calendar calendar = new GregorianCalendar();
+		calendar.setTime(date);
+		calendar.add(calendar.DATE, 1);// 把日期往后增加一天.整数往后推,负数往前移动
+		date = calendar.getTime(); // 这个时间就是日期往后推一天的结果
+
+		return date;
+	}
+
+	/**
+	 * 获取某年某月的最后一天日期
+	 */
+	public static Date getLastDayOfMonth(int year, int month) {
+		Calendar cal = Calendar.getInstance();
+		cal.set(Calendar.YEAR, year);
+		cal.set(Calendar.MONTH, month - 1);
+		int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+		cal.set(Calendar.DAY_OF_MONTH, lastDay);
+		return cal.getTime();
+	}
+
+	/**
+	 * 获取某年某月的第一天 日期
+	 */
+	public static Date getFisrtDayOfMonth(int year, int month) {
+		Calendar cal = Calendar.getInstance();
+		cal.set(Calendar.YEAR, year);
+		cal.set(Calendar.MONTH, month - 1);
+		int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
+		cal.set(Calendar.DAY_OF_MONTH, firstDay);
+		return cal.getTime();
+	}
+
+	/**
+	 * 根据开始时间和结束时间返回时间段内的时间集合
+	 *
+	 * @param beginDate
+	 * @param endDate
+	 * int calendarType 差距的时间 如获取间隔为一天 输入Calendar.DAY_OF_MONTH
+	 * @return List
+	 */
+	public static List<Date> getDatesBetweenTwoDate(Date beginDate, Date endDate,int calendarType) {
+		List<Date> lDate = new ArrayList<Date>();
+		lDate.add(beginDate);// 把开始时间加入集合
+		Calendar cal = Calendar.getInstance();
+		// 使用给定的 Date 设置此 Calendar 的时间
+		cal.setTime(beginDate);
+		boolean bContinue = true;
+		while (bContinue) {
+			// 根据日历的规则,为给定的日历字段添加或减去指定的时间量
+			cal.add(calendarType, 1);
+			// 测试此日期是否在指定日期之后
+			if (endDate.after(cal.getTime())) {
+				lDate.add(cal.getTime());
+			} else {
+				break;
+			}
+		}
+		lDate.add(endDate);// 把结束时间加入集合
+		return lDate;
+	}
+
+	public static boolean after(Date date1,Date date2){
+		Calendar c1 = Calendar.getInstance();
+		c1.setTime(date1);
+		Calendar c2 = Calendar.getInstance();
+		c2.setTime(date2);
+		return c2.after(c1);
+	}
+}

+ 958 - 0
4dkankan-common/src/main/java/com/fdkankan/common/util/FileUtils.java

@@ -0,0 +1,958 @@
+package com.fdkankan.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.constant.ConstantFilePath;
+import it.sauronsoftware.jave.*;
+import lombok.extern.slf4j.Slf4j;
+
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.*;
+
+import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.zip.ZipFile;
+import org.apache.tools.zip.ZipOutputStream;
+import org.bytedeco.javacpp.opencv_core;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.Frame;
+import org.bytedeco.javacv.Java2DFrameConverter;
+import org.bytedeco.javacv.OpenCVFrameConverter;
+import org.springframework.util.ResourceUtils;
+import sun.misc.BASE64Decoder;
+
+import javax.imageio.ImageIO;
+
+@Slf4j
+public class FileUtils {
+
+    //文件路径+名称
+    private static String fileNameTemp;
+
+    public static void uploadImg(String path, String base64Data)
+            throws Exception {
+        byte[] bt = null;
+        try {
+            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
+            if (base64Data.startsWith("data:image/png;base64,")) {
+                bt = decoder.decodeBuffer(base64Data.replace("data:image/png;base64,", ""));
+            } else if (base64Data.startsWith("data:image/jpeg;base64,")) {
+                bt = decoder.decodeBuffer(base64Data.replace("data:image/jpeg;base64,", ""));
+            } else if (base64Data.startsWith("data:image/bmp;base64,")) {
+                bt = decoder.decodeBuffer(base64Data.replace("data:image/bmp;base64,", ""));
+            } else {
+                return;
+            }
+            writeBinary(bt, path);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static void writeBinary(byte[] buf, String filePath) throws Exception {
+        File fout = new File(filePath);
+        if (!fout.getParentFile().exists()) {
+            fout.getParentFile().mkdirs();
+        }
+        FileOutputStream fos = new FileOutputStream(fout);
+        ByteArrayInputStream stream = new ByteArrayInputStream(buf);
+        BufferedOutputStream bos = new BufferedOutputStream(fos);//设置输出路径
+        BufferedInputStream bis = new BufferedInputStream(stream);
+        int b = -1;
+        while ((b = bis.read()) != -1) {
+            bos.write(b);
+        }
+        bis.close();
+        bos.close();
+    }
+	
+	public static boolean createDir(String destDirName) {
+        File dir = new File(destDirName);  
+        if (dir.exists()) {  
+            System.out.println("创建目录" + destDirName + "失败,目标目录已经存在");  
+            return false;  
+        }  
+        if (!destDirName.endsWith(File.separator)) {  
+            destDirName = destDirName + File.separator;  
+        }  
+        //创建目录  
+        if (dir.mkdirs()) {  
+            System.out.println("创建目录" + destDirName + "成功!");  
+            return true;  
+        } else {  
+            System.out.println("创建目录" + destDirName + "失败!");  
+            return false;  
+        }  
+    }
+	
+
+    /**
+     * 创建文件
+     * @param fileName  文件名称
+     * @param fileContent   文件内容
+     * @return  是否创建成功,成功则返回true
+     */
+    public static boolean createFile(String path, String fileName,String fileContent){
+        Boolean bool = false;
+        fileNameTemp = path+fileName+".json";//文件路径+名称+文件类型
+        File file = new File(fileNameTemp);
+        try {
+        	File folder = new File(path);
+        	if (!folder.exists()){
+        		folder.mkdirs();
+        	}
+            //如果文件不存在,则创建新的文件
+            if(!file.exists()){
+                file.createNewFile();
+                bool = true;
+                System.out.println("success create file,the file is "+ fileNameTemp);
+                //创建文件成功后,写入内容到文件里
+                writeFileContent(fileNameTemp, fileContent);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        
+        return bool;
+    }
+    
+    /**
+     * 向文件中写入内容
+     * @param filePath 文件路径与名称
+     * @param newstr  写入的内容
+     * @return
+     * @throws IOException
+     */
+    public static boolean writeFileContent(String filePath, String newstr) throws IOException{
+        Boolean bool = false;
+        String filein = newstr+"\r\n";//新写入的行,换行
+        String temp  = "";
+        
+        FileInputStream fis = null;
+        InputStreamReader isr = null;
+        BufferedReader br = null;
+        FileOutputStream fos  = null;
+        PrintWriter pw = null;
+        try {
+            File file = new File(filePath);//文件路径(包括文件名称)
+            //将文件读入输入流
+            fis = new FileInputStream(file);
+            isr = new InputStreamReader(fis);
+            br = new BufferedReader(isr);
+            StringBuffer buffer = new StringBuffer();
+            
+            //文件原有内容
+            for(int i=0;(temp =br.readLine())!=null;i++){
+                buffer.append(temp);
+                // 行与行之间的分隔符 相当于“\n”
+                buffer = buffer.append(System.getProperty("line.separator"));
+            }
+            buffer.append(filein);
+            
+            fos = new FileOutputStream(file);
+            pw = new PrintWriter(fos);
+            pw.write(buffer.toString().toCharArray());
+            pw.flush();
+            bool = true;
+        } catch (Exception e) {
+            // TODO: handle exception
+            e.printStackTrace();
+        }finally {
+            //不要忘记关闭
+            if (pw != null) {
+                pw.close();
+            }
+            if (fos != null) {
+                fos.close();
+            }
+            if (br != null) {
+                br.close();
+            }
+            if (isr != null) {
+                isr.close();
+            }
+            if (fis != null) {
+                fis.close();
+            }
+        }
+        return bool;
+    }
+    
+    /**
+     * 删除单个文件
+     *
+     * @param fileName
+     *            要删除的文件的文件名
+     * @return 单个文件删除成功返回true,否则返回false
+     */
+    public static boolean deleteFile(String fileName) {
+        File file = new File(fileName);
+        if (file.exists() && file.isFile()) {
+            if (file.delete()) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+    
+    /** 
+     *  根据路径删除指定的目录,无论存在与否 
+     *@param sPath  要删除的目录path 
+     *@return 删除成功返回 true,否则返回 false。 
+     */  
+    public static boolean deleteFolder(String sPath) {
+        boolean flag = false;
+        File file = new File(sPath);
+        // 判断目录或文件是否存在
+        if (!file.exists()) {  // 不存在返回 false
+            return flag;
+        } else {
+            // 判断是否为文件
+            if (file.isFile()) {  // 为文件时调用删除文件方法
+                return deleteFile(sPath);
+            } else {  // 为目录时调用删除目录方法
+                return deleteDirectory(sPath);
+            }
+        }
+    }
+    
+    /**
+     * 删除目录以及目录下的文件
+     * @param   sPath 被删除目录的路径
+     * @return  目录删除成功返回true,否则返回false
+     */
+    public static boolean deleteDirectory(String sPath) {
+        //如果sPath不以文件分隔符结尾,自动添加文件分隔符
+        if (!sPath.endsWith(File.separator)) {
+            sPath = sPath + File.separator;
+        }
+        File dirFile = new File(sPath);
+        //如果dir对应的文件不存在,或者不是一个目录,则退出
+        if (!dirFile.exists() || !dirFile.isDirectory()) {
+            return false;
+        }
+        boolean flag = true;
+        //删除文件夹下的所有文件(包括子目录)
+        File[] files = dirFile.listFiles();
+        for (int i = 0; i < files.length; i++) {
+            //删除子文件
+            if (files[i].isFile()) {
+                flag = deleteFile(files[i].getAbsolutePath());
+                if (!flag) break;
+            } //删除子目录
+            else {
+                flag = deleteDirectory(files[i].getAbsolutePath());
+                if (!flag) break;
+            }
+        }
+        if (!flag) return false;
+        //删除当前目录
+        if (dirFile.delete()) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    //按行读文件
+    public static String readFile(String path) throws Exception {
+        File f = new File(path);
+        if (!f.exists()) {
+            return null;
+        }
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
+        BufferedInputStream in = null;
+        try {
+            in = new BufferedInputStream(new FileInputStream(f));
+            int buf_size = 1024;
+            byte[] buffer = new byte[buf_size];
+            int len = 0;
+            while (-1 != (len = in.read(buffer, 0, buf_size))) {
+                bos.write(buffer, 0, len);
+            }
+            return bos.toString();
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw e;
+        } finally {
+            try {
+                in.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            bos.close();
+        }
+    }
+
+    public static boolean copyFile(String srcFileName, String destFileName, boolean overlay) {
+        File srcFile = new File(srcFileName);
+        // 判断源文件是否存在
+        if (!srcFile.exists()) {
+            return false;
+        } else if (!srcFile.isFile()) {
+            return false;
+        }
+        // 判断目标文件是否存在
+        File destFile = new File(destFileName);
+        if (destFile.exists()) {
+            // 如果目标文件存在并允许覆盖
+            if (overlay) {
+                // 删除已经存在的目标文件,无论目标文件是目录还是单个文件
+                new File(destFileName).delete();
+            }
+        } else {
+            // 如果目标文件所在目录不存在,则创建目录
+            if (!destFile.getParentFile().exists()) {
+                // 目标文件所在目录不存在
+                if (!destFile.getParentFile().mkdirs()) {
+                    // 复制文件失败:创建目标文件所在目录失败
+                    return false;
+                }
+            }
+        }
+        // 复制文件
+        int byteread = 0; // 读取的字节数
+        InputStream in = null;
+        OutputStream out = null;
+        try {
+            in = new FileInputStream(srcFile);
+            out = new FileOutputStream(destFile);
+            byte[] buffer = new byte[1024];
+
+            while ((byteread = in.read(buffer)) != -1) {
+                out.write(buffer, 0, byteread);
+            }
+            return true;
+        } catch (IOException e) {
+            return false;
+        } finally {
+            try {
+                if (out != null)
+                    out.close();
+                if (in != null)
+                    in.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 从网络Url中下载文件
+     *
+     * @param urlStr
+     * @param fileName
+     * @param savePath
+     * @return
+     * @throws IOException
+     */
+    public static boolean downLoadFromUrl(String urlStr, String fileName, String savePath){
+        FileOutputStream fos = null;
+        InputStream inputStream = null;
+        try {
+            URL url = new URL(urlStr);
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            // 设置超时间为3秒
+            conn.setConnectTimeout(3 * 1000);
+            // 防止屏蔽程序抓取而返回403错误
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+
+            // 得到输入流
+            inputStream = conn.getInputStream();
+            // 获取自己数组
+            byte[] getData = readInputStream(inputStream);
+
+            // 文件保存位置
+            File saveDir = new File(savePath);
+            if (!saveDir.exists()) {
+                saveDir.mkdirs();
+            }
+            String filePath = saveDir + File.separator + fileName;
+            String filePathFolder = filePath.substring(0, filePath.lastIndexOf("/") + 1);
+            FileUtils.createDir(filePathFolder);
+
+            File file = new File(filePath);
+            fos = new FileOutputStream(file);
+            fos.write(getData);
+            if (fos != null) {
+                fos.close();
+            }
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            System.out.println("info:" + url + " download success");
+        } catch(FileNotFoundException e){
+            e.printStackTrace();
+            return false;
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }finally {
+            if (fos != null) {
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 从输入流中获取字节数组
+     *
+     * @param inputStream
+     * @return
+     * @throws IOException
+     */
+    private static byte[] readInputStream(InputStream inputStream) throws IOException {
+        byte[] buffer = new byte[1024];
+        int len = 0;
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        while ((len = inputStream.read(buffer)) != -1) {
+            bos.write(buffer, 0, len);
+        }
+        bos.close();
+        return bos.toByteArray();
+    }
+
+    public static void writeFile(String filePath,String str) throws IOException {
+        File fout = new File(filePath);
+        if(!fout.getParentFile().exists()){
+            fout.getParentFile().mkdirs();
+        }
+        if(!fout.exists()){
+            fout.createNewFile();
+        }
+        FileOutputStream fos = new FileOutputStream(fout);
+        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
+        bw.write(str);
+        bw.close();
+    }
+
+    /**
+     * 将byte数组写入文件
+     *
+     * @param path
+     * @param fileName
+     * @param content
+     * @throws IOException
+     */
+    public static void writeFile(String path, String fileName, byte[] content)
+            throws IOException {
+        try {
+            File f = new File(path);
+            if (!f.exists()) {
+                f.mkdirs();
+            }
+            FileOutputStream fos = new FileOutputStream(path + fileName);
+            fos.write(content);
+            fos.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 向json文件写入参数,重复的覆盖,多的新增
+     * @return
+     */
+    public static void writeJsonFile(String path, Map<String, Object> map) throws Exception{
+        String str = readFile(path);
+        JSONObject json = new JSONObject();
+        if(str!=null){
+            json = JSONObject.parseObject(str);
+        }
+        else{
+            File file = new File(path);
+            if(!file.getParentFile().exists())
+            {
+                file.getParentFile().mkdirs();
+            }
+            if(!file.exists())
+            {
+                file.createNewFile();
+            }
+        }
+        Iterator entries = map.entrySet().iterator();
+        while (entries.hasNext()) {
+            Map.Entry entry = (Map.Entry) entries.next();
+            json.put(String.valueOf(entry.getKey()), entry.getValue());
+        }
+
+        writeFile(path, json.toString());
+    }
+
+    public static void decompress(String srcPath, String dest) throws Exception {
+
+        File file = new File(srcPath);
+
+        if (!file.exists()) {
+
+            throw new RuntimeException(srcPath + "所指文件不存在");
+
+        }
+
+        ZipFile zf = new ZipFile(file);
+
+        Enumeration entries = zf.getEntries();
+
+        ZipEntry entry = null;
+
+        while (entries.hasMoreElements()) {
+
+            entry = (ZipEntry) entries.nextElement();
+
+            log.info("解压" + entry.getName());
+
+            if (entry.isDirectory()) {
+
+                String dirPath = dest + File.separator + entry.getName();
+
+                File dir = new File(dirPath);
+
+                dir.mkdirs();
+
+            } else {
+
+                // 表示文件
+
+                File f = new File(dest + File.separator + entry.getName());
+
+                if (!f.exists()) {
+
+                    //String dirs = FileUtils.getParentPath(f);
+                    String dirs =  f.getParent();
+
+                    File parentDir = new File(dirs);
+
+                    parentDir.mkdirs();
+
+
+
+                }
+
+                f.createNewFile();
+
+                // 将压缩文件内容写入到这个文件中
+
+                InputStream is = zf.getInputStream(entry);
+
+                FileOutputStream fos = new FileOutputStream(f);
+
+
+
+                int count;
+
+                byte[] buf = new byte[8192];
+
+                while ((count = is.read(buf)) != -1) {
+
+                    fos.write(buf, 0, count);
+
+                }
+
+                is.close();
+
+                fos.close();
+
+            }
+
+        }
+
+    }
+
+    public static void zipFile(String zipFileName, String inputFileName)
+            throws Exception {
+        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
+        out.setEncoding("UTF-8");
+        File inputFile = new File(inputFileName);
+        zipIt(out, inputFile, "", true);
+        out.close();
+    }
+
+    /*
+     * 能支持中文的压缩 参数base 开始为"" first 开始为true
+     */
+    public static void zipIt(ZipOutputStream out, File f,
+                             String base, boolean first) throws Exception {
+        if (f.isDirectory()) {
+            File[] fl = f.listFiles();
+            if (first) {
+                first = false;
+            } else {
+                base = base + "/";
+            }
+            for (int i = 0; i < fl.length; i++) {
+                zipIt(out, fl[i], base + fl[i].getName(), first);
+            }
+        } else {
+            if (first) {
+                base = f.getName();
+            }
+            out.putNextEntry(new org.apache.tools.zip.ZipEntry(base));
+            FileInputStream in = new FileInputStream(f);
+            int b;
+            while ((b = in.read()) != -1) {
+                out.write(b);
+            }
+            in.close();
+        }
+    }
+
+    //删除文件夹
+    public static void delFolder(String folderPath) {
+        try {
+            delAllFile(folderPath); //删除完里面所有内容
+            String filePath = folderPath;
+            filePath = filePath.toString();
+            java.io.File myFilePath = new java.io.File(filePath);
+            myFilePath.delete(); //删除空文件夹
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    //删除指定文件夹下的所有文件
+    public static boolean delAllFile(String path) {
+        boolean flag = false;
+        File file = new File(path);
+        if (!file.exists()) {
+            return flag;
+        }
+        if (!file.isDirectory()) {
+            return flag;
+        }
+        String[] tempList = file.list();
+        File temp = null;
+        if(tempList!=null)
+        {
+            for (int i = 0; i < tempList.length; i++) {
+                if (path.endsWith(File.separator)) {
+                    temp = new File(path + tempList[i]);
+                } else {
+                    temp = new File(path + File.separator + tempList[i]);
+                }
+                if (temp.isFile()) {
+                    temp.delete();
+                }
+                if (temp.isDirectory()) {
+                    delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
+                    delFolder(path + "/" + tempList[i]);//再删除空文件夹
+                    flag = true;
+                }
+            }
+        }
+
+        //再删除当前空文件夹
+        file.delete();
+        return flag;
+    }
+
+    public static List<String> readfileNamesForDirectory(String path, String except)
+    {
+        try{
+            File file = new File(path);
+            if(file.isDirectory())
+            {
+                String[] fileNames = file.list();
+                List<String> list = new ArrayList<String>();
+                if(fileNames!=null)
+                {
+                    for(int i=0;i<fileNames.length;++i)
+                    {
+                        if(fileNames[i].toLowerCase().endsWith(except) )
+                        {
+                            list.add(fileNames[i]);
+                        }
+                    }
+                }
+
+                return list;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    //递归获取文件中所有文件的路径
+    public static List<String> readfilePath(String path, List<String> urlList) {
+        try{
+            File file = new File(path);
+            if(file != null && file.isDirectory()) {
+                File[] files = file.listFiles();
+
+                if(files != null) {
+                    for(int i=0;i<files.length;++i) {
+                        if(files[i].isDirectory()){
+                            readfilePath(files[i].getAbsolutePath(), urlList);
+                        }else {
+                            urlList.add(files[i].getAbsolutePath());
+                        }
+                    }
+                }
+                return urlList;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return urlList;
+    }
+
+    public static void saveImageToDisk(String accessToken, String mediaId, String picName, String picPath,InputStream inputStream)
+            throws Exception {
+        byte[] data = new byte[10240];
+        int len = 0;
+        FileOutputStream fileOutputStream = null;
+        try {
+            fileOutputStream = new FileOutputStream(picPath+picName+".amr");
+            while ((len = inputStream.read(data)) != -1) {
+                fileOutputStream.write(data, 0, len);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (fileOutputStream != null) {
+                try {
+                    fileOutputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    //音频转换(To Mp3)
+    public static void changeVoiceToMp3(String sourcePath,String targetPath) throws InputFormatException {
+        File source = new File(sourcePath);
+        File target = new File(targetPath);
+        if(target.exists())
+        {
+            target.delete();
+        }
+        AudioAttributes audio = new AudioAttributes();
+        Encoder encoder = new Encoder();
+        audio.setChannels(2);
+        audio.setCodec("libmp3lame");
+        EncodingAttributes attrs = new EncodingAttributes();
+        attrs.setFormat("mp3");
+        attrs.setAudioAttributes(audio);
+
+        try {
+            encoder.encode(source, target, attrs);
+        } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        } catch (InputFormatException e) {
+            e.printStackTrace();
+        } catch (EncoderException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 获取指定视频的帧并保存为图片至指定目录
+     * @param filePath 视频存放的地址
+     * @param targerFilePath 截图存放的地址
+     * @param targetFileName 截图保存的文件名称
+     * @return
+     * @throws Exception
+     */
+    public static boolean executeCodecs(String filePath, String targerFilePath, String targetFileName) throws Exception {
+        try{
+            FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
+            ff.start();
+            String rotate =ff.getVideoMetadata("rotate");
+            Frame f;
+            int i = 0;
+            while (i <1) {
+                f =ff.grabImage();
+                opencv_core.IplImage src = null;
+                if(null !=rotate &&rotate.length() > 1) {
+                    OpenCVFrameConverter.ToIplImage converter =new OpenCVFrameConverter.ToIplImage();
+                    src =converter.convert(f);
+                    f =converter.convert(rotate(src, Integer.valueOf(rotate)));
+                }
+                doExecuteFrame(f,targerFilePath,targetFileName);
+                i++;
+            }
+            ff.stop();
+            return true;
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /*
+     * 旋转角度的
+     */
+    public static opencv_core.IplImage rotate(opencv_core.IplImage src, int angle) {
+        opencv_core.IplImage img = opencv_core.IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
+        opencv_core.cvTranspose(src, img);
+        opencv_core.cvFlip(img, img, angle);
+        return img;
+    }
+
+
+    public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName) {
+
+        if (null ==f ||null ==f.image) {
+            return;
+        }
+        Java2DFrameConverter converter =new Java2DFrameConverter();
+        String imageMat ="jpg";
+        String FileName =targerFilePath + File.separator +targetFileName +"." +imageMat;
+        BufferedImage bi =converter.getBufferedImage(f);
+        System.out.println("width:" + bi.getWidth());//打印宽、高
+        System.out.println("height:" + bi.getHeight());
+        File output =new File(FileName);
+        try {
+            ImageIO.write(bi,imageMat,output);
+        }catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取音频时长
+     * @throws IOException
+     */
+    public static long getAudioPlayTime(File source){
+        Encoder encoder = new Encoder();
+        long ls = 0;
+        try {
+            MultimediaInfo m = encoder.getInfo(source);
+            ls = m.getDuration();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return ls;
+    }
+
+    public static void main(String[] args) {
+        try{
+//            executeCodecs("F:\\data\\hotEvGtWd618310.mp4", "F:\\data", "test");
+
+//            System.out.print("音频长度:" + getAudioPlayTime(new File("F:\\桌面\\voicet-P4bJVAp\\part\\0.mp3")));
+//            System.out.print("音频长度:" + getAudioPlayTime(new File("F:\\桌面\\voicet-P4bJVAp\\part\\1.mp3")));
+//            System.out.print("音频长度:" + getAudioPlayTime(new File("F:\\桌面\\voicet-P4bJVAp\\part\\2.mp3")));
+//            System.out.print("音频长度:" + getAudioPlayTime(new File("F:\\桌面\\voicet-P4bJVAp\\sound201810.mp3")));
+//            InetAddress addr = InetAddress.getLocalHost();
+//            System.out.println("Local HostAddress: "+addr.getHostAddress());
+//                    String hostname = addr.getHostName();
+//            System.out.println("Local host name: "+hostname);
+
+//            String topLogo = "/agent/company/1601195024633_topLog.png";
+//            FileUtils.downLoadFromUrl("https://test.4dkankan.com/" + topLogo + "?t=" + System.currentTimeMillis(),
+//                    topLogo.substring(topLogo.lastIndexOf("/") + 1),
+//                    "F:\\桌面\\c11m-T11-EA" + topLogo.substring(0, topLogo.lastIndexOf("/")));
+            File file = new File("F:\\文档\\WeChat Files\\Iove-bing\\FileStorage\\File\\2020-10\\texture1.jpg");
+            if(file.getName().endsWith(".jpg") || file.getName().endsWith(".png")){
+
+                System.out.println(file.length());
+                System.out.println(checkFileSizeIsLimit(file.length(), 1.5, "M"));
+            }
+
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+
+
+    /**
+     *
+     * @param content base64内容
+     * @param path 输出文件路径,需要后缀名
+     * @return
+     */
+    public static  boolean base64ToFileWriter(String content, String path) {
+        if (content == null) {
+            return false;
+        }
+        BASE64Decoder decoder = new BASE64Decoder();
+        try {
+            // decoder
+            byte[] b = decoder.decodeBuffer(content);
+            // processing data
+            for (int i = 0; i < b.length; ++i) {
+                if (b[i] < 0) {
+                    b[i] += 256;
+                }
+            }
+            OutputStream out = new FileOutputStream(path);
+            out.write(b);
+            out.flush();
+            out.close();
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * 获取类路径(classes路径)
+     */
+    public static String getResource(){
+        String path = "";
+        try {
+            path = ResourceUtils.getURL("classpath:").getPath();
+            path = URLDecoder.decode(path,"utf-8");
+        } catch (Exception e) {
+        }
+        return path;
+    }
+
+    /**
+     * 判断文件大小处于限制内
+     *
+     * @param fileLen 文件长度
+     * @param fileSize 限制大小
+     * @param fileUnit 限制的单位(B,K,M,G)
+     * @return
+     */
+    public static boolean checkFileSizeIsLimit(Long fileLen, double fileSize, String fileUnit) {
+//        long len = file.length();
+        double fileSizeCom = 0;
+        if ("B".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen;
+        } else if ("K".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen / 1024;
+        } else if ("M".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen / (1024*1024);
+        } else if ("G".equals(fileUnit.toUpperCase())) {
+            fileSizeCom = (double) fileLen / (1024*1024*1024);
+        }
+        if (fileSizeCom > fileSize) {
+            return false;
+        }
+        return true;
+
+    }
+
+}

+ 405 - 0
4dkankan-common/src/main/java/com/fdkankan/common/util/HttpRequestorUtil.java

@@ -0,0 +1,405 @@
+package com.fdkankan.common.util;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.entity.mime.content.StringBody;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+
+import java.io.*;
+import java.net.*;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+@Slf4j
+public class HttpRequestorUtil {
+
+	private static String charset = "utf-8";
+    private Integer connectTimeout = null;
+    private Integer socketTimeout = null;
+    private static String proxyHost = null;
+    private static Integer proxyPort = null;
+    
+    /**
+     * Do GET request
+     * @param url
+     * @return
+     * @throws Exception
+     * @throws IOException
+     */
+    public static String doGet(String url) throws Exception {
+
+        URL localURL = new URL(url);
+        
+        URLConnection connection = openConnection(localURL);
+        HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
+        
+        httpURLConnection.setRequestProperty("Accept-Charset", charset);
+        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+        
+        InputStream inputStream = null;
+        InputStreamReader inputStreamReader = null;
+        BufferedReader reader = null;
+        StringBuffer resultBuffer = new StringBuffer();
+        String tempLine = null;
+        
+        if (httpURLConnection.getResponseCode() >= 300) {
+            log.info("message:" + httpURLConnection.getResponseMessage());
+            throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
+        }
+        
+        try {
+            inputStream = httpURLConnection.getInputStream();
+            inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
+            reader = new BufferedReader(inputStreamReader);
+            
+            while ((tempLine = reader.readLine()) != null) {
+                resultBuffer.append(tempLine);
+            }
+            
+        } finally {
+            
+            if (reader != null) {
+                reader.close();
+            }
+            
+            if (inputStreamReader != null) {
+                inputStreamReader.close();
+            }
+            
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            
+        }
+
+        return resultBuffer.toString();
+    }
+    
+    /**
+     * Do POST request
+     * @param url
+     * @param parameterMap
+     * @return
+     * @throws Exception 
+     */
+    public static String doPost(String url, Map parameterMap) throws Exception {
+        
+        /* Translate parameter map to parameter date string */
+        StringBuffer parameterBuffer = new StringBuffer();
+        if (parameterMap != null) {
+            Iterator iterator = parameterMap.keySet().iterator();
+            String key = null;
+            String value = null;
+            while (iterator.hasNext()) {
+                key = (String)iterator.next();
+                if (parameterMap.get(key) != null) {
+                    value = (String)parameterMap.get(key);
+                } else {
+                    value = "";
+                }
+                
+                parameterBuffer.append(key).append("=").append(value);
+                if (iterator.hasNext()) {
+                    parameterBuffer.append("&");
+                }
+            }
+        }
+        
+        log.info("POST parameter : " + parameterBuffer.toString());
+        
+        URL localURL = new URL(url);
+        log.info("POST URL : " + url);
+        HttpURLConnection connection = (HttpURLConnection) localURL.openConnection();
+        HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
+        
+        httpURLConnection.setDoOutput(true);
+        httpURLConnection.setRequestMethod("POST");
+        httpURLConnection.setRequestProperty("Accept-Charset", "UTF-8");
+        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+        httpURLConnection.setRequestProperty("Content-Length", String.valueOf(parameterBuffer.length()));
+
+        
+        OutputStream outputStream = null;
+        OutputStreamWriter outputStreamWriter = null;
+        InputStream inputStream = null;
+        InputStreamReader inputStreamReader = null;
+        BufferedReader reader = null;
+        StringBuffer resultBuffer = new StringBuffer();
+        String tempLine = null;
+        
+        try {
+            outputStream = httpURLConnection.getOutputStream();
+            outputStreamWriter = new OutputStreamWriter(outputStream);
+            
+            outputStreamWriter.write(parameterBuffer.toString());
+            outputStreamWriter.flush();
+            
+            if (httpURLConnection.getResponseCode() >= 300) {
+                throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
+            }
+            log.info("POST finish.");
+            
+            inputStream = httpURLConnection.getInputStream();
+            inputStreamReader = new InputStreamReader(inputStream);
+            reader = new BufferedReader(inputStreamReader);
+            
+            while ((tempLine = reader.readLine()) != null) {
+                resultBuffer.append(tempLine);
+            }
+            
+        } finally {
+            
+            if (outputStreamWriter != null) {
+                outputStreamWriter.close();
+            }
+            
+            if (outputStream != null) {
+                outputStream.close();
+            }
+            
+            if (reader != null) {
+                reader.close();
+            }
+            
+            if (inputStreamReader != null) {
+                inputStreamReader.close();
+            }
+            
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            
+        }
+
+        return resultBuffer.toString();
+    }
+
+    /**
+     * 文件上传支持中文
+     *
+     * @param reportUrl
+     * @param filepath
+     * @param savepath
+     * @throws IOException
+     */
+    public static void uploadReport(String reportUrl, String filepath,
+                                    String savepath) {
+        CloseableHttpClient closeableHttpClient = null;
+        CloseableHttpResponse response = null;
+        try {
+            closeableHttpClient = HttpClients.createDefault();
+            HttpPost httpPost = new HttpPost(reportUrl);
+            String filename = filepath.split("/")[filepath.split("/").length - 1];
+            File file = new File(filepath);
+
+            FileBody fileBody = new FileBody(file, ContentType.create("multipart/form-data", "UTF-8"), filename);
+            StringBody userIdStringBody = new StringBody(savepath, ContentType.create("multipart/form-data", "UTF-8"));
+            StringBody reportNameStringBody = new StringBody(filename, ContentType.create("multipart/form-data", "UTF-8"));
+
+            HttpEntity httpEntity = MultipartEntityBuilder
+                    .create()
+                    .setCharset(Charset.forName("UTF-8"))
+                    .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
+                    .addPart("file", fileBody)
+                    .addPart("savepath", userIdStringBody)
+                    .addPart("reportName", reportNameStringBody)
+                    .build();
+
+            httpPost.setEntity(httpEntity);
+            response = closeableHttpClient.execute(httpPost);
+            HttpEntity responseEntity = response.getEntity();
+            int statusCode = response.getStatusLine().getStatusCode();
+            if (statusCode == 200) {
+                log.info("上传成功:" + savepath);
+            } else {
+                BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent()));
+                StringBuffer buffer = new StringBuffer();
+                String str = "";
+                while ((str = reader.readLine()) != null && (str = reader.readLine()).trim().length() > 0) {
+                    buffer.append(str);
+                }
+                log.info(buffer.toString());
+                log.info("上传失败:" + statusCode);
+            }
+            closeableHttpClient.close();
+            if (response != null) {
+                response.close();
+            }
+
+        } catch (Exception ex) {
+            log.info("uploadReport发生异常:" + ex);
+        } finally {
+            try {
+                if (closeableHttpClient != null) {
+                    closeableHttpClient.close();
+                }
+                if (response != null) {
+                    response.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 发送HttpPost请求
+     *
+     * @param strURL
+     *            服务地址
+     * @param params
+     *            json字符串,例如: "{ \"id\":\"12345\" }" ;其中属性名必须带双引号<br/>
+     * @return 成功:返回json字符串<br/>
+     */
+    public static String postJson(String strURL, String params, String type) {
+        log.info(strURL);
+        log.info(params);
+        BufferedReader reader = null;
+        try {
+            URL url = new URL(strURL);// 创建连接
+            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            connection.setUseCaches(false);
+            connection.setInstanceFollowRedirects(true);
+            connection.setRequestMethod(type); // 设置请求方式
+            // connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
+            connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
+            connection.setRequestProperty("Authorizations", "Y9z$w*WA%z!uz0O$dcCQ@i1KHKs5rhQW");
+            connection.connect();
+            //一定要用BufferedReader 来接收响应, 使用字节来接收响应的方法是接收不到内容的
+            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); // utf-8编码
+            out.append(params);
+            out.flush();
+            out.close();
+            // 读取响应
+            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
+            String line;
+            String res = "";
+            while ((line = reader.readLine()) != null) {
+                res += line;
+            }
+            reader.close();
+
+            //如果一定要使用如下方式接收响应数据, 则响应必须为: response.getWriter().print(StringUtils.join("{\"errCode\":\"1\",\"errMsg\":\"", message, "\"}")); 来返回
+//            int length = (int) connection.getContentLength();// 获取长度
+//            if (length != -1) {
+//                byte[] data = new byte[length];
+//                byte[] temp = new byte[512];
+//                int readLen = 0;
+//                int destPos = 0;
+//                while ((readLen = is.read(temp)) > 0) {
+//                    System.arraycopy(temp, 0, data, destPos, readLen);
+//                    destPos += readLen;
+//                }
+//                String result = new String(data, "UTF-8"); // utf-8编码
+//                log.info(result);
+//                return result;
+//            }
+
+            return res;
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return "error"; // 自定义错误信息
+    }
+
+    public static void main(String[] args) {
+        try{
+            Map postData = new HashMap();
+//            postData.put("vrBuilding", "http://192.168.0.47:8086/showProMobile.html?m=001-zFzxA5FkS");
+//            postData.put("editBuilding", "http://192.168.0.47:8086/editProMobile.html?m=001-zFzxA5FkS");
+//            postData.put("siweiId", "001-zFzxA5FkS");
+//            postData.put("name", "中国银行2");
+//            String result = doPost("http://49.4.86.68:8080/bankBack/back/vrhome/insertbuilding.htm", postData);
+            HttpRequestorUtil util = new HttpRequestorUtil();
+            String result = util.doGet("https://4dkk.4dage.com/data/datagu6HmTLKp/hot.json");
+            log.info(result);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+
+//        uploadReport("http://114.215.208.201:8080/filecommon/file/uploadsiweifile.htm", "F:\\桌面\\迁移场景\\bi8u5kUcn\\tex\\texture1.jpg",
+//                "scene/data/datat-KvqDwm3/");
+    }
+
+    private static URLConnection openConnection(URL localURL) throws IOException {
+        URLConnection connection;
+        if (proxyHost != null && proxyPort != null) {
+            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
+            connection = localURL.openConnection(proxy);
+        } else {
+            connection = localURL.openConnection();
+        }
+        return connection;
+    }
+    
+    /**
+     * Render request according setting
+     */
+    private void renderRequest(URLConnection connection) {
+        
+        if (connectTimeout != null) {
+            connection.setConnectTimeout(connectTimeout);
+        }
+        
+        if (socketTimeout != null) {
+            connection.setReadTimeout(socketTimeout);
+        }
+        
+    }
+
+    /*
+     * Getter & Setter
+     */
+    public Integer getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    public void setConnectTimeout(Integer connectTimeout) {
+        this.connectTimeout = connectTimeout;
+    }
+
+    public Integer getSocketTimeout() {
+        return socketTimeout;
+    }
+
+    public void setSocketTimeout(Integer socketTimeout) {
+        this.socketTimeout = socketTimeout;
+    }
+
+    public String getProxyHost() {
+        return proxyHost;
+    }
+
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public Integer getProxyPort() {
+        return proxyPort;
+    }
+
+    public void setProxyPort(Integer proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+
+    public String getCharset() {
+        return charset;
+    }
+
+    public void setCharset(String charset) {
+        this.charset = charset;
+    }
+}

+ 0 - 0
4dkankan-common/src/main/java/com/fdkankan/common/util/JwtUtil.java


Деякі файли не було показано, через те що забагато файлів було змінено