Browse Source

首次提交

wuweihao 4 years ago
parent
commit
8977d3bda9
81 changed files with 27701 additions and 2 deletions
  1. 2 2
      README.md
  2. 45 0
      gis_application/pom.xml
  3. 13 0
      gis_application/src/main/java/com/gis/GisApplication.java
  4. 13 0
      gis_application/src/main/java/com/gis/ServletInitializer.java
  5. 86 0
      gis_application/src/main/resources/application-dev.properties
  6. 81 0
      gis_application/src/main/resources/application-sit.properties
  7. 38 0
      gis_application/src/main/resources/application.properties
  8. 156 0
      gis_application/src/main/resources/logback-spring.xml
  9. 179 0
      gis_common/pom.xml
  10. 95 0
      gis_common/src/main/java/com/gis/common/config/Swagger2.java
  11. 71 0
      gis_common/src/main/java/com/gis/common/config/WebMvcConfig.java
  12. 76 0
      gis_common/src/main/java/com/gis/common/constant/ConfigConstant.java
  13. 30 0
      gis_common/src/main/java/com/gis/common/constant/MsgCode.java
  14. 32 0
      gis_common/src/main/java/com/gis/common/constant/TypeCode.java
  15. 35 0
      gis_common/src/main/java/com/gis/common/exception/BaseRuntimeException.java
  16. 34 0
      gis_common/src/main/java/com/gis/common/exception/JwtAuthenticationException.java
  17. 7340 0
      gis_common/src/main/java/com/gis/common/proto/BigSceneProto.java
  18. 4654 0
      gis_common/src/main/java/com/gis/common/proto/Common.java
  19. 4345 0
      gis_common/src/main/java/com/gis/common/proto/Visionmodeldata.java
  20. 37 0
      gis_common/src/main/java/com/gis/common/proto/constant/ConstantCmd.java
  21. 41 0
      gis_common/src/main/java/com/gis/common/proto/constant/ConstantFileName.java
  22. 61 0
      gis_common/src/main/java/com/gis/common/proto/constant/ConstantFilePath.java
  23. 156 0
      gis_common/src/main/java/com/gis/common/proto/format/CouchDBFormat.java
  24. 703 0
      gis_common/src/main/java/com/gis/common/proto/format/HtmlFormat.java
  25. 1338 0
      gis_common/src/main/java/com/gis/common/proto/format/JavaPropsFormat.java
  26. 1603 0
      gis_common/src/main/java/com/gis/common/proto/format/JsonFormat.java
  27. 602 0
      gis_common/src/main/java/com/gis/common/proto/format/SmileFormat.java
  28. 1333 0
      gis_common/src/main/java/com/gis/common/proto/format/XmlFormat.java
  29. 162 0
      gis_common/src/main/java/com/gis/common/proto/util/ConvertUtils.java
  30. 234 0
      gis_common/src/main/java/com/gis/common/proto/util/CreateObjUtil.java
  31. 61 0
      gis_common/src/main/java/com/gis/common/proto/util/StreamGobbler.java
  32. 229 0
      gis_common/src/main/java/com/gis/common/util/FileUtils.java
  33. 356 0
      gis_common/src/main/java/com/gis/common/util/HttpUtils.java
  34. 317 0
      gis_common/src/main/java/com/gis/common/util/JwtUtil.java
  35. 194 0
      gis_common/src/main/java/com/gis/common/util/PasswordUtils.java
  36. 20 0
      gis_common/src/main/java/com/gis/common/util/RandomUtils.java
  37. 20 0
      gis_common/src/main/java/com/gis/common/util/RegexUtil.java
  38. 101 0
      gis_common/src/main/java/com/gis/common/util/Result.java
  39. 30 0
      gis_common/src/main/java/com/gis/common/util/WxUtil.java
  40. 22 0
      gis_domain/pom.xml
  41. 28 0
      gis_domain/src/main/java/com/gis/domain/dto/LoginDto.java
  42. 27 0
      gis_domain/src/main/java/com/gis/domain/dto/PageDateDto.java
  43. 26 0
      gis_domain/src/main/java/com/gis/domain/dto/PageDto.java
  44. 21 0
      gis_domain/src/main/java/com/gis/domain/dto/PasswordRequest.java
  45. 58 0
      gis_domain/src/main/java/com/gis/domain/dto/RegisterDto.java
  46. 21 0
      gis_domain/src/main/java/com/gis/domain/dto/ResetPasswordDto.java
  47. 24 0
      gis_domain/src/main/java/com/gis/domain/dto/RoamViableDto.java
  48. 39 0
      gis_domain/src/main/java/com/gis/domain/dto/SceneDataDto.java
  49. 62 0
      gis_domain/src/main/java/com/gis/domain/dto/UserDto.java
  50. 39 0
      gis_domain/src/main/java/com/gis/domain/po/BaseEntity.java
  51. 41 0
      gis_domain/src/main/java/com/gis/domain/po/SceneEntity.java
  52. 62 0
      gis_domain/src/main/java/com/gis/domain/po/SysUserEntity.java
  53. 22 0
      gis_mapper/pom.xml
  54. 18 0
      gis_mapper/src/main/java/com/gis/mapper/IBaseMapper.java
  55. 38 0
      gis_mapper/src/main/java/com/gis/mapper/SceneMapper.java
  56. 28 0
      gis_mapper/src/main/java/com/gis/mapper/SysUserMapper.java
  57. 41 0
      gis_mapper/src/main/java/com/gis/mapper/provider/CommentProvider.java
  58. 41 0
      gis_mapper/src/main/java/com/gis/mapper/provider/GiftProvider.java
  59. 34 0
      gis_mapper/src/main/java/com/gis/mapper/provider/SceneProvider.java
  60. 60 0
      gis_mapper/src/main/java/com/gis/mapper/provider/UserProvider.java
  61. 23 0
      gis_service/pom.xml
  62. 47 0
      gis_service/src/main/java/com/gis/service/IBaseService.java
  63. 30 0
      gis_service/src/main/java/com/gis/service/SceneService.java
  64. 22 0
      gis_service/src/main/java/com/gis/service/SysUserService.java
  65. 16 0
      gis_service/src/main/java/com/gis/service/WxService.java
  66. 13 0
      gis_service/src/main/java/com/gis/service/aop/WebControllerLog.java
  67. 131 0
      gis_service/src/main/java/com/gis/service/aop/WebLogAspect.java
  68. 210 0
      gis_service/src/main/java/com/gis/service/impl/IBaseServiceImpl.java
  69. 395 0
      gis_service/src/main/java/com/gis/service/impl/SceneServiceImpl.java
  70. 42 0
      gis_service/src/main/java/com/gis/service/impl/SysUserServiceImpl.java
  71. 100 0
      gis_service/src/main/java/com/gis/service/impl/WxServiceImpl.java
  72. 135 0
      gis_service/src/main/java/com/gis/service/shiro/JWTFilter.java
  73. 23 0
      gis_service/src/main/java/com/gis/service/shiro/JWTToken.java
  74. 110 0
      gis_service/src/main/java/com/gis/service/shiro/MyRealm.java
  75. 114 0
      gis_service/src/main/java/com/gis/service/shiro/ShiroConfig.java
  76. 23 0
      gis_web/pom.xml
  77. 120 0
      gis_web/src/main/java/com/gis/web/controller/BaseController.java
  78. 129 0
      gis_web/src/main/java/com/gis/web/controller/ExceptionController.java
  79. 46 0
      gis_web/src/main/java/com/gis/web/controller/WxLoginController.java
  80. 45 0
      gis_web/src/test/java/com/gis/web/controller/SceneControllerTest.java
  81. 252 0
      pom.xml

+ 2 - 2
README.md

@@ -1,3 +1,3 @@
-# wx_reload_beijing
+# wx_reload_beijing 2021-04-22
+AI一键换装-东方一贤-北京
 
-AI一键换装-东方一贤-北京

+ 45 - 0
gis_application/pom.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>wx_reload_beijing</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+
+
+    <groupId>com.gis</groupId>
+    <artifactId>gis_application</artifactId>
+    <version>1.0.0</version>
+    <packaging>war</packaging>
+    <name>gis_application</name>
+    <description>项目入口</description>
+
+
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_web</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+        <finalName>wx_reload_beijing</finalName>
+    </build>
+
+
+
+</project>

+ 13 - 0
gis_application/src/main/java/com/gis/GisApplication.java

@@ -0,0 +1,13 @@
+package com.gis;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class GisApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(GisApplication.class, args);
+    }
+
+}

+ 13 - 0
gis_application/src/main/java/com/gis/ServletInitializer.java

@@ -0,0 +1,13 @@
+package com.gis;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+public class ServletInitializer extends SpringBootServletInitializer {
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        return application.sources(GisApplication.class);
+    }
+
+}

+ 86 - 0
gis_application/src/main/resources/application-dev.properties

@@ -0,0 +1,86 @@
+
+#DB
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+#spring.datasource.druid.url=jdbc:mysql://localhost:3306/${project.name}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+#spring.datasource.druid.password=root
+spring.datasource.druid.username=root
+spring.datasource.druid.url=jdbc:mysql://8.135.106.227:3306/${project.name}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.druid.password=4dkk2021testproject%
+
+
+# \u521D\u59CB\u8FDE\u63A5\u6570
+spring.datasource.druid.initial-size=5
+# \u6700\u5C0F\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.min-idle=10
+# \u6700\u5927\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.max-active=20
+# \u914D\u7F6E\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u7684\u65F6\u95F4
+spring.datasource.druid.max-wait=60000
+# \u914D\u7F6E\u95F4\u9694\u591A\u4E45\u624D\u8FDB\u884C\u4E00\u6B21\u68C0\u6D4B\uFF0C\u68C0\u6D4B\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.time-between-eviction-runs-millis=60000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5C0F\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.min-evictable-idle-time-millis=30000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5927\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.max-evictable-idle-time-millis=90000
+# \u914D\u7F6E\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548
+spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
+spring.datasource.druid.test-while-idle=true
+spring.datasource.druid.test-on-borrow=false
+spring.datasource.druid.test-on-return=false
+spring.datasource.druid.web-stat-filter.enabled=true
+spring.datasource.druid.stat-view-servlet.enabled=true
+
+
+# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=0
+spring.redis.host=127.0.0.1
+spring.redis.port=6379
+spring.redis.password=
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D ms\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=3000ms
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F8\u3002
+spring.redis.jedis.pool.max-idle=8
+#\u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F0\u3002
+spring.redis.jedis.pool.min-idle=0
+# \u5982\u679C\u8D4B\u503C\u4E3A-1\uFF0C\u5219\u8868\u793A\u4E0D\u9650\u5236\uFF1B\u5982\u679Cpool\u5DF2\u7ECF\u5206\u914D\u4E86maxActive\u4E2Ajedis\u5B9E\u4F8B\uFF0C\u5219\u6B64\u65F6pool\u7684\u72B6\u6001\u4E3Aexhausted(\u8017\u5C3D)\u3002
+spring.redis.jedis.pool.max-active=8
+# \u7B49\u5F85\u53EF\u7528\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u95F4\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF0C\u9ED8\u8BA4\u503C\u4E3A-1\uFF0C\u8868\u793A\u6C38\u4E0D\u8D85\u65F6\u3002\u5982\u679C\u8D85\u8FC7\u7B49\u5F85\u65F6\u95F4\uFF0C\u5219\u76F4\u63A5\u629B\u51FAJedisConnectionException
+spring.redis.jedis.pool.max-wait=-1ms
+
+#oss
+oss.point=http://oss-cn-shenzhen.aliyuncs.com
+oss.key=LTAIUrvuHqj8pvry
+oss.secrecy=JLOVl0k8Ke0aaM8nLMMiUAZ3EiiqI4
+oss.bucket=oss-xiaoan
+oss.type=oss
+oss.file.path=${project.name}/
+oss.domain=http://ossxiaoan.4dage.com/
+
+
+#log
+logging.path=E:/javaProject/${project.name}_log
+logging.config=classpath:logback-spring.xml
+logging.level.com.gis=debug
+
+# file info
+server.file.path=F:\\test\\ngin\\${project.name}_data\\
+
+# url info
+server.url.prefix=/data/
+
+# swagger2 \u8BBE\u7F6E\u5168\u5C40\u5B57\u4F53\u683C\u5F0F\u4E3Autf-8
+swagger.package=com.gis.web.controller
+swagger.title=AI\u6362\u88C5-\u4E1C\u65B9\u4E00\u8D24-dev
+swagger.description=${swagger.title}
+swagger.version=1.0
+
+# \u5FAE\u4FE1\u4FE1\u606F
+wx.appId=wxbd0f9ff2a5621bf3
+wx.appSecret=94f6cf81ce63fbbf19a155070bb29b60
+
+
+
+
+
+

+ 81 - 0
gis_application/src/main/resources/application-sit.properties

@@ -0,0 +1,81 @@
+
+#DB
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+#spring.datasource.druid.url=jdbc:mysql://localhost:3306/${project.name}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+#spring.datasource.druid.username=root
+#spring.datasource.druid.password=4dkk2020test%
+
+spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/${project.name}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.druid.username=root
+spring.datasource.druid.password=4dkk2021testproject%
+
+
+# \u521D\u59CB\u8FDE\u63A5\u6570
+spring.datasource.druid.initial-size=5
+# \u6700\u5C0F\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.min-idle=10
+# \u6700\u5927\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.max-active=20
+# \u914D\u7F6E\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u7684\u65F6\u95F4
+spring.datasource.druid.max-wait=60000
+# \u914D\u7F6E\u95F4\u9694\u591A\u4E45\u624D\u8FDB\u884C\u4E00\u6B21\u68C0\u6D4B\uFF0C\u68C0\u6D4B\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.time-between-eviction-runs-millis=60000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5C0F\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.min-evictable-idle-time-millis=30000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5927\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.max-evictable-idle-time-millis=90000
+# \u914D\u7F6E\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548
+spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
+spring.datasource.druid.test-while-idle=true
+spring.datasource.druid.test-on-borrow=false
+spring.datasource.druid.test-on-return=false
+spring.datasource.druid.web-stat-filter.enabled=true
+spring.datasource.druid.stat-view-servlet.enabled=true
+
+
+# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=0
+spring.redis.host=127.0.0.1
+spring.redis.port=6379
+spring.redis.password=
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D ms\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=3000ms
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F8\u3002
+spring.redis.jedis.pool.max-idle=8
+#\u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F0\u3002
+spring.redis.jedis.pool.min-idle=0
+# \u5982\u679C\u8D4B\u503C\u4E3A-1\uFF0C\u5219\u8868\u793A\u4E0D\u9650\u5236\uFF1B\u5982\u679Cpool\u5DF2\u7ECF\u5206\u914D\u4E86maxActive\u4E2Ajedis\u5B9E\u4F8B\uFF0C\u5219\u6B64\u65F6pool\u7684\u72B6\u6001\u4E3Aexhausted(\u8017\u5C3D)\u3002
+spring.redis.jedis.pool.max-active=8
+# \u7B49\u5F85\u53EF\u7528\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u95F4\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF0C\u9ED8\u8BA4\u503C\u4E3A-1\uFF0C\u8868\u793A\u6C38\u4E0D\u8D85\u65F6\u3002\u5982\u679C\u8D85\u8FC7\u7B49\u5F85\u65F6\u95F4\uFF0C\u5219\u76F4\u63A5\u629B\u51FAJedisConnectionException
+spring.redis.jedis.pool.max-wait=-1ms
+
+
+#log
+logging.path=/root/user/${project.name}_log
+logging.config=classpath:logback-spring.xml
+logging.level.com.gis=debug
+
+
+
+# file info
+server.file.path=/root/user/${project.name}_data/
+
+# url prefix
+server.url.prefix=/data/
+
+# swagger2 \u8BBE\u7F6E\u5168\u5C40\u5B57\u4F53\u683C\u5F0F\u4E3Autf-8
+swagger.package=com.gis.web.controller
+swagger.title=AI\u6362\u88C5-\u4E1C\u65B9\u4E00\u8D24-sit
+swagger.description=${swagger.title}
+swagger.version=1.0
+
+
+# swagger login
+# \uFFFD\uFFFD\uFFFD\uFFFDbasic\uFFFD\uFFFD\u00BC\uFFFD\uFFFD\u05A4
+#knife4j.basic.enable=true
+#knife4j.basic.username=owen
+#knife4j.basic.password=owen
+
+
+

+ 38 - 0
gis_application/src/main/resources/application.properties

@@ -0,0 +1,38 @@
+server.port=8004
+
+spring.profiles.active=dev
+
+# \u9879\u76EE\u540D\u79F0
+project.name=scene_wisdom
+
+# \u8BBF\u95EE\u9759\u6001\u8D44\u6E90\u8BBE\u7F6E
+spring.resources.static-locations=classpath:templates/,classpath:static/,classpath:web/
+
+#\u4E0A\u4F20\u6587\u4EF6\u5927\u5C0F
+spring.servlet.multipart.enabled=true
+spring.servlet.multipart.max-file-size=2048MB
+spring.servlet.multipart.max-request-size=2048MB
+
+
+
+#\u914D\u7F6E\u81EA\u52A8\u8BC6\u522B\u5B57\u6BB5\u8F6C\u6362
+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
+
+
+
+
+
+
+
+
+
+
+
+

+ 156 - 0
gis_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>

+ 179 - 0
gis_common/pom.xml

@@ -0,0 +1,179 @@
+<?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">
+    <parent>
+        <artifactId>wx_reload_beijing</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gis_common</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+
+        <!--springboot-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- JPA -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!--springboot中的redis依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+
+        <!-- lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <!-- fastjson -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <!-- mysql -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!--阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+
+        <!-- knife4j aip 包-->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 工具类 -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!-- shiro -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring</artifactId>
+        </dependency>
+
+
+        <!-- jwt -->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+        </dependency>
+
+        <!--aliyun sdk-->
+        <!--<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>com.aliyun.oss</groupId>-->
+            <!--<artifactId>aliyun-sdk-oss</artifactId>-->
+        <!--</dependency>-->
+
+
+        <!--tk.mybatis 依赖-->
+        <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>
+
+
+
+
+        <!-- 针对proto包 转换格式用-->
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.protobuf-java-format</groupId>
+            <artifactId>protobuf-java-format</artifactId>
+            <version>1.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.11</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-smile</artifactId>
+            <version>1.9.12</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.belerweb</groupId>
+            <artifactId>pinyin4j</artifactId>
+            <version>2.5.1</version>
+        </dependency>
+
+
+        <!-- httpclient -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+
+
+
+    </dependencies>
+
+
+</project>

+ 95 - 0
gis_common/src/main/java/com/gis/common/config/Swagger2.java

@@ -0,0 +1,95 @@
+package com.gis.common.config;
+
+import com.gis.common.constant.ConfigConstant;
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+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 不需要字启动类配置注解
+ */
+@Slf4j
+@Configuration
+@EnableSwagger2
+@EnableKnife4j
+public class Swagger2 {
+
+    @Autowired
+    ConfigConstant configConstant;
+
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage(configConstant.swaggerPackage))
+                .paths(PathSelectors.any())
+                .build()
+                //添加登录认证,可以使用token
+                .securityContexts(securityContexts())
+                .securitySchemes(securitySchemes())
+                ;
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title(configConstant.swaggerTitle)
+                .description(configConstant.swaggerDescription)
+                .version(configConstant.swaggerVersion)
+                .build();
+    }
+
+    private List<ApiKey> securitySchemes() {
+        //设置请求头信息
+        List<ApiKey> result = new ArrayList<>();
+        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;
+    }
+}

+ 71 - 0
gis_common/src/main/java/com/gis/common/config/WebMvcConfig.java

@@ -0,0 +1,71 @@
+package com.gis.common.config;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by owen on 2020/2/18 0018 12:01
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+    /**
+     * 配置全局跨域
+     */
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("*")
+                .allowCredentials(true)
+                .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
+                .maxAge(3600);
+    }
+
+
+
+    /**
+     * fastJson相关设置
+     * Dto包含json,需要配置不然会异常
+     * @return
+     */
+    @Bean
+    public HttpMessageConverters customConverters() {
+
+        FastJsonHttpMessageConverter fastJson = new FastJsonHttpMessageConverter();
+        // 创建FastJson信息转换对象
+        FastJsonConfig fastJsonConfig = new FastJsonConfig();
+
+
+        // 设置全程返回时间
+        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
+        // 设置返回值为null是时输出,不写的话,null 字段 不返回。也可以设置返回空串, 可以同时设置多个
+        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
+
+        fastJson.setFastJsonConfig(fastJsonConfig);
+
+        //3、中文乱码解决方案
+        List<MediaType> mediaTypeList = new ArrayList<>();
+        mediaTypeList.add(MediaType.APPLICATION_JSON_UTF8);
+        mediaTypeList.add(MediaType.valueOf("text/html;charset=UTF-8"));
+
+        //4、将转换规则应用于转换对象
+        fastJson.setSupportedMediaTypes(mediaTypeList);
+
+        return new HttpMessageConverters(fastJson);
+    }
+
+
+
+}

+ 76 - 0
gis_common/src/main/java/com/gis/common/constant/ConfigConstant.java

@@ -0,0 +1,76 @@
+package com.gis.common.constant;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by owen on 2020/12/31 0031 14:22
+ *
+ * 全局动态参数
+ */
+@Component
+public class ConfigConstant {
+
+    /** 服务器文件地址*/
+    @Value("${server.file.path}")
+    public  String serverBasePath;
+
+    /** 服务器域名*/
+//    @Value("${server.domain}")
+//    public  String serverDomain;
+
+    @Value("${server.url.prefix}")
+    public String serverUrlPrefix;
+
+    @Value("${project.name}")
+    public String projectName;
+
+//    @Value("${project.name}")
+//    public String serverDomain;
+
+    @Value("${oss.point}")
+    public  String ossPoint;
+
+    @Value("${oss.key}")
+    public  String ossKey;
+
+    @Value("${oss.secrecy}")
+    public  String ossSecrecy;
+
+    @Value("${oss.bucket}")
+    public  String ossBucket;
+
+    @Value("${oss.file.path}")
+    public  String ossBasePath;
+
+    @Value("${oss.domain}")
+    public  String ossDomain;
+
+
+    @Value("${swagger.package}")
+    public  String swaggerPackage;
+
+    @Value("${swagger.title}")
+    public  String swaggerTitle;
+
+    @Value("${swagger.description}")
+    public  String swaggerDescription;
+
+    @Value("${swagger.version}")
+    public  String swaggerVersion;
+
+
+
+    @Value("${wx.appId}")
+    public  String wxAppId;
+
+    @Value("${wx.appSecret}")
+    public  String wxAppSecret;
+
+
+
+
+
+
+
+}

+ 30 - 0
gis_common/src/main/java/com/gis/common/constant/MsgCode.java

@@ -0,0 +1,30 @@
+package com.gis.common.constant;
+
+/**
+ * Created by owen on 2021/3/19 0019 10:13
+ *
+ * 错误码
+ */
+public class MsgCode {
+
+    public final static Integer e3001 = 3001;
+    public final static String m3001 = "场景已使用";
+
+    public final static Integer e3002 = 3002;
+    public final static String m3002 = "请至少保留一个场景";
+
+    /** 文件过大 */
+    public final static Integer e3004 = 3004;
+
+    /** 不是该用户作品 */
+    public final static Integer e3005 = 3005;
+
+    /** 作品已被删除,无法编辑 */
+    public final static Integer e3006 = 3006;
+
+    public final static Integer e5003 = 5003;
+    public final static String m5003 = "不支持此图片";
+
+    public final static Integer e5004 = 5004;
+    public final static String m5004 = "密码错误";
+}

+ 32 - 0
gis_common/src/main/java/com/gis/common/constant/TypeCode.java

@@ -0,0 +1,32 @@
+package com.gis.common.constant;
+
+/**
+ * Created by owen on 2020/5/14 0014 8:56
+ */
+public class TypeCode {
+
+    /**redis token 前缀*/
+    public static final String REDIS_LOGIN_TOKEN = "cms_army_token_";
+
+    /**api token key*/
+    public static final String TOKEN_API_KEY = "apiKey";
+
+    /**文件外键id前缀*/
+    public static final String FILE_GOODS = "goods_";
+
+
+    public static final String MODEL_GOODS_IMG = "goodsImg";
+
+    public static final String MODEL_GOODS_MODEL = "goodsModel";
+
+    public static final String MODEL_GOODS_VIDEO = "goodsVideo";
+
+    public static final String MODEL_FODDER_IMG = "fodderImg";
+
+    public static final String MODEL_FODDER_VIDEO = "fodderVideo";
+
+
+    /**redis wxToken 前缀*/
+    public static final String REDIS_LOGIN_WXTOKEN = "AI_RELOAD_wxToken_";
+}
+

+ 35 - 0
gis_common/src/main/java/com/gis/common/exception/BaseRuntimeException.java

@@ -0,0 +1,35 @@
+package com.gis.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;
+    }
+}

+ 34 - 0
gis_common/src/main/java/com/gis/common/exception/JwtAuthenticationException.java

@@ -0,0 +1,34 @@
+package com.gis.common.exception;
+
+import org.apache.shiro.ShiroException;
+
+public class JwtAuthenticationException extends ShiroException {
+
+    private static final long serialVersionUID = 2899335020273674736L;
+
+    private int code;
+
+    private String msg;
+
+    public JwtAuthenticationException(int code, String msg){
+        super(msg);
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

File diff suppressed because it is too large
+ 7340 - 0
gis_common/src/main/java/com/gis/common/proto/BigSceneProto.java


File diff suppressed because it is too large
+ 4654 - 0
gis_common/src/main/java/com/gis/common/proto/Common.java


File diff suppressed because it is too large
+ 4345 - 0
gis_common/src/main/java/com/gis/common/proto/Visionmodeldata.java


+ 37 - 0
gis_common/src/main/java/com/gis/common/proto/constant/ConstantCmd.java

@@ -0,0 +1,37 @@
+package com.gis.common.proto.constant;
+
+public class ConstantCmd {
+
+	  //生成模型的命令
+	  public static final String BUILD_MODEL_COMMAND = "bash /home/ubuntu/bin/Launcher.sh ";
+
+	  // 生成切片图
+	  public static final String SLICE_SKYBOX = "bash /home/ubuntu/bin/Skybox.sh ";
+
+	  // 把obj文件传txt文件
+	  public static final String OBJ_TO_TXT = "bash /home/ubuntu/bin/obj2txt.sh ";
+
+//	  public static final String BUILD_MODEL_SFM_COMMAND = "bash /home/ubuntu/run_sfm.sh ";
+//
+//	  public static final String REBUILD_MODEL_FLLOR = "bash /home/ubuntu/bin/Panoramix_Floorplan.sh ";
+//	  //切图命令
+//	  public static final String CUT_IMG_COMMAND = "bash /home/ubuntu/OpenSfM/bin/run_cube.sh ";
+//	  //调整图片的命令
+//	  public static final String ADJUST_IMG_COMMAND = "/home/ubuntu/OpenSfM/bin/run_skybox ";
+//
+//
+//
+//	  //转台拼图命令
+//	  public static final String BUILD_PANORAMA = "AutopanoGiga /home/ubuntu/data/";
+//	  //六目,拼图,计算,切图(二代)
+//	  public static final String BUILD_FOR_SIX = "bash /home/ubuntu/run_all_m6.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 ";
+//
+//	public static final String OSS_UTIL_CP ="bash /opt/ossutil/oss.sh ";
+
+}

+ 41 - 0
gis_common/src/main/java/com/gis/common/proto/constant/ConstantFileName.java

@@ -0,0 +1,41 @@
+package com.gis.common.proto.constant;
+
+public class ConstantFileName {
+//    //背景音乐
+//    public static final String BACKGROUND_MUSIC = "bg.mp3";
+//    //编辑页面,第二代
+//    public static final String MODEL_DATAFILE = "modeldata.json";
+//    public static final String HOT_DATAFILE = "hot.json";
+//    public static final String MEDIA_DATAFILE = "mediaInfo.json";
+//    public static final String SCREEN_CRP_DATAFILE = "screenCap";
+//    //导览(一代)
+//    public static final String GUIDE_DATAFILE = "tour.json";
+//
+//    //文件夹名称
+//    public static final String GUIDE_MEDIA_FOLDER = "guide";
+//    public static final String HOT_MEDIA_FOLDER = "hot";
+//    public static final String OTHER_MEDIA_FOLDER = "other";
+//
+//    //论坛过滤文档
+//    public static final String BBS_SENSITIVE = "SensitiveWord.txt";
+//    public static final String LOGO_NAME = "logo.jpg";
+//
+//    //app部分
+//    public static final String APP_FOLDER = "appupload";
+//
+//    public static final String FLOOR_LOGO_PIC_NAME = "floorLogoImg.png";
+//
+//    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 TOURLIST_FOLDER = "tour";
+//    //public static final String TEMPFILES = "tempFiles";
+//
+//
+//
+//    public static final String BUCKET_NAME = "4dkankan";
+
+    // 这个码要跟前端一致
+    public static final String modelUUID = "dacf7dfa24ae47fab8fcebfe4dc41ab9";
+}

+ 61 - 0
gis_common/src/main/java/com/gis/common/proto/constant/ConstantFilePath.java

@@ -0,0 +1,61 @@
+package com.gis.common.proto.constant;
+
+public class ConstantFilePath {
+//    public static final String BASE_PATH = "/mnt/4Dkankan";
+//    //论坛上传图片后,服务器存放的地址
+//    public static final String BBS_IMAGES_PATH = "/mnt/4Dkankan/bbs/upload/image/";
+//    // 用户上传图片
+//    public static final String USER_IMAGES_PATH = "/mnt/4Dkankan/user/";
+//    // 图片暂存地址(创建二维码等)
+//    public static final String TEMP_IMAGES_PATH = "/mnt/4Dkankan/temp/upload/image/";
+//    // 场景
+////    public static final String SCENE_PATH = "/mnt/4Dkankan/scene/";
+//
+//    // 代理商
+//    public static final String AGENT_PATH = "/mnt/4Dkankan/agent/";
+//    // 场景二维码
+//    public static final String SCENE_QR_CODE_PATH = "/mnt/4Dkankan/sceneQRcode/";
+//    // excel
+//    public static final String EXCEL_PATH = "/mnt/4Dkankan/excel/";
+//    // medias
+//    public static final String MEDIAS_PATH = "/mnt/4Dkankan/medias/";
+//    // logo
+//    public static final String LOGO_PATH = "/mnt/4Dkankan/logo/";
+//    // login qr code
+//    public static final String LOGIN_QR_CODE_PATH = "/mnt/4Dkankan/login/qrcode/";
+//
+//    public static final String WEIXIN_CERT = "/mnt/home/ubuntu/user/apiclient_cert.p12";
+//
+//    public static final String PREFIX = "/home/user";
+//    public static final String CREATE_MODEL_PATH = PREFIX + "/photo_data/model/";
+//    //大场景
+//    public static final String CREATE_BIG_SCENE_PATH = PREFIX + "/photo_data/bigscene/";
+//    //生成模型的路径
+////    public static final String BUILD_MODEL_PATH = "/mnt/data/";
+//
+//
+//    //支付二维码图片存放路径
+//    public static final String ALI_QRCODE_FOLDER = "/mnt/4Dkankan/alicode/";
+//    public static final String WEIXIN_QRCODE_FOLDER = "/mnt/4Dkankan/weixincode/";
+//
+//    public static final String OSS_PREFIX = "home/";
+
+    //生成模型的路径, 计算模型使用
+//    public static final String BUILD_MODEL_PATH = "/data/kanfang/pano/";
+
+
+    // 123kanfang 保存到阿里云位置, 前面不能有/
+//    public static final String UPLOAD_SCENE_PATH = "4dkktmp/images/images";
+
+    // oss 存放路径
+    public static final String UPLOAD_HOUSE_PATH = "kanfang/house/";
+
+    // oss 算法生成文件存放路径(high: 垂直校验全景图, low: 生成模型缩略图)
+    /**
+     * oss 算法生成文件存放路径(high: 垂直校验全景图, low: 生成模型缩略图)
+     * images/images + d_场景码
+     * 场景码建议9位
+     */
+    public static final String OSS_IMAGE_PATH = "images/images";
+
+}

+ 156 - 0
gis_common/src/main/java/com/gis/common/proto/format/CouchDBFormat.java

@@ -0,0 +1,156 @@
+package com.gis.common.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
gis_common/src/main/java/com/gis/common/proto/format/HtmlFormat.java

@@ -0,0 +1,703 @@
+package com.gis.common.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;
+    }
+}

File diff suppressed because it is too large
+ 1338 - 0
gis_common/src/main/java/com/gis/common/proto/format/JavaPropsFormat.java


File diff suppressed because it is too large
+ 1603 - 0
gis_common/src/main/java/com/gis/common/proto/format/JsonFormat.java


+ 602 - 0
gis_common/src/main/java/com/gis/common/proto/format/SmileFormat.java

@@ -0,0 +1,602 @@
+package com.gis.common.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;
+    }
+}

File diff suppressed because it is too large
+ 1333 - 0
gis_common/src/main/java/com/gis/common/proto/format/XmlFormat.java


+ 162 - 0
gis_common/src/main/java/com/gis/common/proto/util/ConvertUtils.java

@@ -0,0 +1,162 @@
+package com.gis.common.proto.util;
+
+import com.gis.common.proto.Visionmodeldata;
+import com.gis.common.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();
+        }
+    }
+
+}

+ 234 - 0
gis_common/src/main/java/com/gis/common/proto/util/CreateObjUtil.java

@@ -0,0 +1,234 @@
+package com.gis.common.proto.util;
+
+import com.gis.common.proto.BigSceneProto;
+import com.gis.common.proto.Common;
+import com.gis.common.proto.Visionmodeldata;
+import com.gis.common.proto.constant.ConstantCmd;
+import com.gis.common.proto.constant.ConstantFileName;
+import com.gis.common.proto.format.JsonFormat;
+import com.google.protobuf.TextFormat;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+
+import java.io.*;
+
+/**
+ * Created by Owen on 2019/12/17 0017 11:40
+ *
+ * 3d模型数据转换工具类
+ */
+@Log4j2
+public class CreateObjUtil {
+
+
+    /**
+     * 调用算法 xx.sh 脚本
+     * @param command
+     */
+    public static void callshell(String command){
+        try {
+            Process process = Runtime.getRuntime().exec(command);
+            StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");
+            errorGobbler.start();
+            StreamGobbler outGobbler = new StreamGobbler(process.getInputStream(), "STDOUT");
+            outGobbler.start();
+            process.waitFor();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * txt to dam
+     * @param srcpath txt 地址
+     * @param despath 生成dam地址
+     * @throws Exception
+     */
+    public static void convertTxtToDam(String srcpath,String despath)throws Exception
+    {
+        try
+        {
+            BigSceneProto.binary_mesh.Builder builder= BigSceneProto.binary_mesh.newBuilder();
+            InputStream inputStream = new FileInputStream(srcpath);
+            InputStreamReader reader = new InputStreamReader(inputStream, "ASCII");
+            TextFormat.merge(reader, 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 convertDamToLzma(String folderName)throws Exception {
+        log.info("folderName: {}", folderName);
+        try {
+            String command = "lzma "+ folderName + ConstantFileName.modelUUID+"_50k.dam";
+            log.info("开始转换lzma :{}", command );
+            callshell(command);
+            log.info("转换lzma完毕");
+        }
+        catch(Exception e)
+        {
+            StringWriter trace=new StringWriter();
+            e.printStackTrace(new PrintWriter(trace));
+            log.error(trace.toString());
+        }
+
+    }
+
+
+    /**
+     * vision.txt转vision.modeldata
+     * @param srcpath
+     * @param despath
+     * @throws Exception
+     */
+    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 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;
+                    //log.info(lineTxt);
+                }
+                read.close();
+                return result;
+            }else{
+                return null;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+
+    }
+
+    //开始建模
+    public static void build3dModel(String folderName,String isModel) throws Exception{
+        log.info("开始建模");
+        String command = ConstantCmd.BUILD_MODEL_COMMAND+folderName;
+        // cmd: bash /home/ubuntu/bin/Launcher.sh /data/kanfang/10002/pano
+        log.info("cmd: {}",command);
+        callshell(command);
+        log.info("计算完毕:" + command);
+    }
+
+    public static void convertTxtToVisionmodeldataCommon(String srcpath,String despath)throws Exception
+    {
+        try
+        {
+            Common.NavigationInfo.Builder builder = Common.NavigationInfo.newBuilder();
+            String jsonFormat = readTxtFileToJson(srcpath);
+            log.warn("jsonFormat: {}", jsonFormat);
+
+            // 临时处理,等算法处理好这个问题,可以删除此方法
+            jsonFormat = deviceJson(jsonFormat);
+
+            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());
+        }
+    }
+
+
+    private static String deviceJson(String str) {
+        String rep = "\"device\":vision_\\d,";
+        if (str.contains("\"device\":vision")) {
+            log.warn("device 临时特殊处理一下");
+            str = StringUtils.replaceAll(str, rep, "");
+        }
+        log.info("update json: {}", str);
+        return str;
+    }
+
+    public static void main(String[] args) {
+
+        String path = "F:\\test\\army\\convert\\";
+        try {
+            convertTxtToVisionmodeldata(path+"vision.txt", path+"vision.modeldata");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    @Test
+    public void modelDataTxtToDamTest(){
+        String path = "F:\\test\\army\\convert\\";
+//        ConstantFileName.modelUUID+"_50k.dam"
+        try {
+            convertTxtToDam(path+"test.txt", path+ConstantFileName.modelUUID+"_50k.dam");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

+ 61 - 0
gis_common/src/main/java/com/gis/common/proto/util/StreamGobbler.java

@@ -0,0 +1,61 @@
+package com.gis.common.proto.util;
+
+import java.io.*;
+
+public class StreamGobbler extends Thread {
+
+	InputStream is;  
+    String type;  
+    OutputStream os;  
+
+    public StreamGobbler(InputStream is, String type) {  
+        this(is, type, null);  
+    }  
+
+    StreamGobbler(InputStream is, String type, OutputStream redirect) {  
+        this.is = is;  
+        this.type = type;  
+        this.os = redirect;  
+    }  
+
+    public void run() {  
+        InputStreamReader isr = null;  
+        BufferedReader br = null;  
+        PrintWriter pw = null;  
+        try {  
+            if (os != null)  
+                pw = new PrintWriter(os);  
+
+            isr = new InputStreamReader(is);  
+            br = new BufferedReader(isr);  
+            String line=null;  
+            while ( (line = br.readLine()) != null) {  
+                if (pw != null)  
+                    pw.println(line);  
+                System.out.println(type + ">" + line);      
+            }  
+
+            if (pw != null)  
+                pw.flush();  
+        } catch (IOException ioe) {  
+            ioe.printStackTrace();    
+        } finally{  
+            try {  
+            	if(pw!=null)
+            	{
+            		 pw.close();  
+            	}
+            	if(br!=null)
+            	{
+            		br.close();  
+            	}
+            	if(isr!=null)
+            	{
+            		isr.close();  
+            	}
+            } catch (IOException e) {  
+                e.printStackTrace();  
+            }  
+        }  
+    }  
+}

+ 229 - 0
gis_common/src/main/java/com/gis/common/util/FileUtils.java

@@ -0,0 +1,229 @@
+package com.gis.common.util;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.img.ImgUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.URLUtil;
+import com.gis.common.exception.BaseRuntimeException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * Created by owen on 2020/5/12 0012 17:21
+ */
+@Slf4j
+public class FileUtils {
+
+
+    /**
+     * 多文件上传
+     * savePath 路径(目录)
+     */
+    public static List<Map<String, String>> uploads(MultipartFile[] files, String savePath) throws IOException {
+        if (files == null) {
+            log.error("文件不能为空");
+            return null;
+        }
+
+        String time = DateUtil.format(new Date(), "yyyyMMdd_HHmmssSSS");
+        savePath = savePath + time + File.separator;
+        FileUtil.mkdir(time);
+
+        ArrayList<Map<String, String>> list = new ArrayList<>();
+
+        String path;
+        int i = 0;
+        for (MultipartFile file : files) {
+            String fileName = file.getOriginalFilename();
+            String suffix = StringUtils.substringAfterLast(fileName, ".");
+            suffix = StringUtils.lowerCase(suffix);
+            String newName = time + "_" + i + "."  +suffix;
+            path = savePath + newName;
+            FileUtil.writeFromStream(file.getInputStream(), path);
+
+            HashMap<String, String> fileInfo = new HashMap<>();
+            fileInfo.put("path", path);
+            fileInfo.put("name", fileName);
+            fileInfo.put("newName", newName);
+            fileInfo.put("dir", time);
+
+            list.add(fileInfo);
+            ++ i;
+        }
+
+        return list;
+
+    }
+
+
+    /**
+     * 单文件上传
+     * @param file
+     * @param savePath
+     * @return
+     * @throws IOException
+     */
+    public static HashMap<String, String> upload(MultipartFile file, String savePath) throws IOException {
+        if (file == null) {
+            log.error("文件不能为空");
+            return null;
+        }
+
+        String time = DateUtil.format(new Date(), "yyyyMMdd_HHmmssSSS");
+
+        String fileName = file.getOriginalFilename();
+
+//        if (Validator.hasChinese(fileName)) {
+//            log.error("文件名不能有中文字符: {}", fileName);
+//            throw new BaseRuntimeException("文件名不能有中文字符:" + fileName);
+//        }
+
+        String suffix = StringUtils.substringAfterLast(fileName, ".");
+
+        suffix = StringUtils.lowerCase(suffix);
+
+        String newName = time  + "."  +suffix;
+        savePath = savePath  + newName;
+
+        FileUtil.writeFromStream(file.getInputStream(), savePath);
+        HashMap<String, String> fileInfo = new HashMap<>();
+
+        fileInfo.put("path", savePath);
+        fileInfo.put("name", fileName);
+        fileInfo.put("newName", newName);
+
+        return fileInfo;
+
+    }
+
+
+    /**
+     * 根据路径写入文件,适合oss
+     * @param inPath 网络输入路径
+     * @param outPath 保存文件路径
+     * @throws IOException
+     */
+    public static void fielWrite(String inPath, String outPath) throws IOException {
+        InputStream in = URLUtil.getStream(new URL(inPath));
+        FileUtil.writeFromStream(in, outPath);
+    }
+
+
+    /**
+     * 获取文件资源路径
+     * 这方法,测试时是用当前类路径,当打包成jar包时时,会变成跟目录下。所以要把资源文件放入口类的资源文件夹
+     * @param filePath 文件路径
+     * @return
+     * @throws IOException
+     */
+    public static String getResourceUrl(String filePath) throws IOException {
+        String path = ResourceUtils.getURL("classpath:").getPath();
+        path = path + filePath;
+        return path;
+    }
+
+    @Test
+    public void test(){
+        String a = "aaaa.JPG";
+
+        String s = StringUtils.substringAfterLast(a, ".");
+
+        System.out.println(StringUtils.lowerCase(s));
+    }
+
+
+    public static void main(String[] args) {
+        batchThumb();
+    }
+
+    public static void batchThumb(){
+        String base = "C:\\Users\\4dage\\Desktop\\army_doc\\img\\";
+
+        String path = null;
+        String savePath = null;
+        for (int i = 1; i < 2 ; i++) {
+            path = base + i + ".png";
+            log.info("path: {}", path);
+            savePath = base + "thumb\\thumb_" + i + ".png";
+            createThumb(path, savePath);
+        }
+    }
+
+
+    private static String createThumb(String filePath, String savePath){
+        ImgUtil.scale(FileUtil.file(filePath), FileUtil.file(savePath), 0.2f);
+
+        return null;
+    }
+
+
+    /**
+     * @param fileName 文件名
+     * @return 文件的type
+     */
+    public static String getFileType(String fileName) {
+        log.info("getContentType:" + fileName);
+        // 文件的后缀名
+        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+        if (".bmp".equalsIgnoreCase(fileExtension)) {
+            return "image";
+        }
+        if (".gif".equalsIgnoreCase(fileExtension)) {
+            return "image";
+        }
+        if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)
+                || ".png".equalsIgnoreCase(fileExtension)) {
+            return "image";
+        }
+        if (".txt".equalsIgnoreCase(fileExtension)) {
+            return "doc";
+        }
+        if (".mp4".equalsIgnoreCase(fileExtension)) {
+            return "video";
+        }
+        if (".4dage".equalsIgnoreCase(fileExtension)) {
+            return "model";
+        }
+
+        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
+            return "doc";
+        }
+        if (".xls".equalsIgnoreCase(fileExtension) || "xlsx".equalsIgnoreCase(fileExtension)) {
+            return "doc";
+        }
+        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
+            return "doc";
+        }
+        // 默认返回类型
+        return "image";
+    }
+
+    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;
+    }
+}

+ 356 - 0
gis_common/src/main/java/com/gis/common/util/HttpUtils.java

@@ -0,0 +1,356 @@
+package com.gis.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.*;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class HttpUtils {
+
+    protected static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
+
+    /**
+     * get
+     *
+     * @param host
+     * @param path
+     * @param headers
+     * @param querys
+     * @return
+     * @throws Exception
+     */
+    public static String doGet(String host, String path,
+                                     Map<String, String> headers,
+                                     Map<String, String> querys)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpGet request = new HttpGet(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        HttpResponse httpResponse = httpClient.execute(request);
+        String restResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
+        return restResult;
+    }
+
+    /**
+     * 20201-04-22
+     * post json
+     * @param url 请求地址
+     * @param headers 请求头
+     * @param body json参数
+     * @return
+     * @throws Exception
+     */
+    public static String doPostJson(String url, Map<String, String> headers, JSONObject body) throws Exception {
+        // 获得Http客户端(
+        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+        // 创建Post请求
+        HttpPost httpPost = new HttpPost(url);
+        LOGGER.info("request url: " + url);
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            httpPost.addHeader(e.getKey(), e.getValue());
+        }
+
+        StringEntity stringEntity = new StringEntity(body.toJSONString(), "UTF-8");
+        httpPost.setEntity(stringEntity);
+
+        HttpResponse httpResponse = httpClient.execute(httpPost);
+        String restResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
+
+        return restResult;
+    }
+
+
+    /**
+     * post form
+     *
+     * @param host
+     * @param path
+     * @param headers
+     * @param querys
+     * @param bodys
+     * @return
+     * @throws Exception
+     */
+    public static String doPost(String host, String path,
+                                      Map<String, String> headers,
+                                      Map<String, String> querys,
+                                      Map<String, String> bodys)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPost request = new HttpPost(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (bodys != null) {
+            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
+
+            for (String key : bodys.keySet()) {
+                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
+            }
+            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
+            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
+            request.setEntity(formEntity);
+        }
+        HttpResponse httpResponse = httpClient.execute(request);
+        String restResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
+
+        return restResult;
+    }
+
+    /**
+     * Post String
+     *
+     * @param host
+     * @param path
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static String doPost(String host, String path,
+                                      Map<String, String> headers,
+                                      Map<String, String> querys,
+                                      String body)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPost request = new HttpPost(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (StringUtils.isNotBlank(body)) {
+            request.setEntity(new StringEntity(body, "utf-8"));
+        }
+
+        HttpResponse httpResponse = httpClient.execute(request);
+        String restResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
+
+        return restResult;
+    }
+
+    /**
+     * Post stream
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPost(String host, String path, String method,
+                                      Map<String, String> headers,
+                                      Map<String, String> querys,
+                                      byte[] body)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPost request = new HttpPost(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (body != null) {
+            request.setEntity(new ByteArrayEntity(body));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Put String
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPut(String host, String path, String method,
+                                     Map<String, String> headers,
+                                     Map<String, String> querys,
+                                     String body)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPut request = new HttpPut(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (StringUtils.isNotBlank(body)) {
+            request.setEntity(new StringEntity(body, "utf-8"));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Put stream
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @param body
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doPut(String host, String path, String method,
+                                     Map<String, String> headers,
+                                     Map<String, String> querys,
+                                     byte[] body)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpPut request = new HttpPut(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        if (body != null) {
+            request.setEntity(new ByteArrayEntity(body));
+        }
+
+        return httpClient.execute(request);
+    }
+
+    /**
+     * Delete
+     *
+     * @param host
+     * @param path
+     * @param method
+     * @param headers
+     * @param querys
+     * @return
+     * @throws Exception
+     */
+    public static HttpResponse doDelete(String host, String path, String method,
+                                        Map<String, String> headers,
+                                        Map<String, String> querys)
+            throws Exception {
+        HttpClient httpClient = wrapClient(host);
+
+        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
+        for (Map.Entry<String, String> e : headers.entrySet()) {
+            request.addHeader(e.getKey(), e.getValue());
+        }
+
+        return httpClient.execute(request);
+    }
+
+    public static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
+        StringBuilder sbUrl = new StringBuilder();
+        sbUrl.append(host);
+        if (!StringUtils.isBlank(path)) {
+            sbUrl.append(path);
+        }
+        LOGGER.info("request api: " + sbUrl.toString());
+        if (null != querys) {
+            StringBuilder sbQuery = new StringBuilder();
+            for (Map.Entry<String, String> query : querys.entrySet()) {
+                if (0 < sbQuery.length()) {
+                    sbQuery.append("&");
+                }
+                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
+                    sbQuery.append(query.getValue());
+                }
+                if (!StringUtils.isBlank(query.getKey())) {
+                    sbQuery.append(query.getKey());
+                    if (!StringUtils.isBlank(query.getValue())) {
+                        sbQuery.append("=");
+                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
+                    }
+                }
+            }
+            if (0 < sbQuery.length()) {
+                sbUrl.append("?").append(sbQuery);
+            }
+        }
+
+        return sbUrl.toString();
+    }
+
+    private static HttpClient wrapClient(String host) {
+        HttpClient httpClient = new DefaultHttpClient();
+        if (host.startsWith("https://")) {
+            sslClient(httpClient);
+        }
+        return httpClient;
+    }
+
+    private static void sslClient(HttpClient httpClient) {
+        try {
+            SSLContext ctx = SSLContext.getInstance("TLS");
+            X509TrustManager tm = new X509TrustManager() {
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+
+                public void checkClientTrusted(X509Certificate[] xcs, String str) {
+
+                }
+
+                public void checkServerTrusted(X509Certificate[] xcs, String str) {
+
+                }
+            };
+            ctx.init(null, new TrustManager[]{tm}, null);
+            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
+            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            ClientConnectionManager ccm = httpClient.getConnectionManager();
+            SchemeRegistry registry = ccm.getSchemeRegistry();
+            registry.register(new Scheme("https", 443, ssf));
+        } catch (KeyManagementException ex) {
+            throw new RuntimeException(ex);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+
+
+}

+ 317 - 0
gis_common/src/main/java/com/gis/common/util/JwtUtil.java

@@ -0,0 +1,317 @@
+package com.gis.common.util;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.interfaces.Claim;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.gis.common.exception.BaseRuntimeException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+import org.springframework.util.Assert;
+
+import java.util.*;
+
+@Log4j2
+public class JwtUtil {
+
+    //生成签名的时候使用的秘钥secret
+    private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK&sdfkjsdrow32234545fdf>?N<:{LWPW";
+
+    /**
+     * 用户登录成功后生成Jwt
+     * 使用Hs256算法  私匙使用用户密码
+     *
+     * @param ttlMillis jwt过期时间
+     * @param userName  用户名
+     * @return
+     */
+    public static String createJWT(long ttlMillis, String userName) {
+        //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+
+        //生成JWT的时间
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        //创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
+        Map<String, Object> claims = new HashMap<String, Object>();
+        claims.put("userName", userName);
+
+        //下面就是在为payload添加各种标准声明和私有声明了
+        //这里其实就是new一个JwtBuilder,设置jwt的body
+        JwtBuilder builder = Jwts.builder()
+                //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
+                .setClaims(claims)
+                //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
+                .setId(UUID.randomUUID().toString())
+                //iat: jwt的签发时间
+                .setIssuedAt(now)
+                //代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
+                .setSubject(userName)
+                //设置签名使用的签名算法和签名使用的秘钥
+                .signWith(signatureAlgorithm, SECRET);
+
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            //设置过期时间
+            builder.setExpiration(exp);
+        }/*else{
+            //设置过期时间半小时
+            DateTime expDate = new DateTime().plusMinutes(30);
+            builder.setExpiration(expDate.toDate());
+        }*/
+        return builder.compact();
+    }
+
+    public static String createWxJWT(long ttlMillis, Map<String, Object> paramMap) {
+        //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+
+
+        //生成JWT的时间
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+        String openId = paramMap.get("openId").toString();
+
+        //创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
+        Map<String, Object> claims = new HashMap<String, Object>();
+        claims.put("openId", openId);
+        claims.put("sessionKey", paramMap.get("sessionKey"));
+
+        //下面就是在为payload添加各种标准声明和私有声明了
+        //这里其实就是new一个JwtBuilder,设置jwt的body
+        JwtBuilder builder = Jwts.builder()
+                //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
+                .setClaims(claims)
+                //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
+                .setId(UUID.randomUUID().toString())
+                //iat: jwt的签发时间
+                .setIssuedAt(now)
+                //代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
+                .setSubject(openId)
+                //设置签名使用的签名算法和签名使用的秘钥
+                .signWith(signatureAlgorithm, SECRET);
+
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            //设置过期时间
+            builder.setExpiration(exp);
+        }/*else{
+            //设置过期时间半小时
+            DateTime expDate = new DateTime().plusMinutes(30);
+            builder.setExpiration(expDate.toDate());
+        }*/
+        return builder.compact();
+    }
+
+
+    /**
+     * Token的解密
+     *
+     * @param token 加密后的token
+     * @return
+     */
+    public static Claims parseJWT(String token) {
+        //得到DefaultJwtParser
+        Claims claims = Jwts.parser()
+                //设置签名的秘钥
+                .setSigningKey(SECRET)
+                //设置需要解析的jwt
+                .parseClaimsJws(token).getBody();
+        return claims;
+    }
+
+    public static String getTokenStringValueByKey(String token, String key) {
+        DecodedJWT jwt = JWT.decode(token);
+        Claim value = jwt.getClaim(key);
+
+        if (value == null) {
+            log.error("token key is null");
+            throw new BaseRuntimeException(5001, "token invalid");
+        }
+        return value.asString();
+    }
+
+
+    /**
+     * 校验token
+     * 在这里可以使用官方的校验,我这里校验的是token中携带的密码于数据库一致的话就校验通过
+     *
+     * @param token
+     * @param userName
+     * @return
+     */
+    public static Boolean isVerify(String token, String userName) {
+
+        //得到DefaultJwtParser
+        Claims claims = Jwts.parser()
+                //设置签名的秘钥
+                .setSigningKey(SECRET)
+                //设置需要解析的jwt
+                .parseClaimsJws(token).getBody();
+
+        return claims.get("userName").equals(userName);
+    }
+
+    /**
+     * 获得token中的信息无需secret解密也能获得
+     *
+     * @return token中包含的用户名
+     */
+    public static String getUsername(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        Claim userName = jwt.getClaim("userName");
+        Assert.notNull(userName, "token userName is null ");
+        return userName.asString();
+    }
+
+
+    public static List getUserRole(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        Claim role = jwt.getClaim("role");
+        Assert.notNull(role, "token role is null ");
+        return role.as(List.class);
+    }
+
+
+    public static String createJWT(long ttlMillis, Map<String, Object> paramMap) {
+        //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+
+        String userName = paramMap.get("userName").toString();
+
+        //生成JWT的时间
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        //创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
+        Map<String, Object> claims = new HashMap<String, Object>();
+        claims.put("userName", userName);
+        claims.put("id", paramMap.get("id"));
+        claims.put("role", paramMap.get("role"));
+        claims.put("manager", paramMap.get("manager"));
+
+        //下面就是在为payload添加各种标准声明和私有声明了
+        //这里其实就是new一个JwtBuilder,设置jwt的body
+        JwtBuilder builder = Jwts.builder()
+                //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
+                .setClaims(claims)
+                //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
+                .setId(UUID.randomUUID().toString())
+                //iat: jwt的签发时间
+                .setIssuedAt(now)
+                //代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
+                .setSubject(userName)
+                //设置签名使用的签名算法和签名使用的秘钥
+                .signWith(signatureAlgorithm, SECRET);
+
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            //设置过期时间
+            builder.setExpiration(exp);
+        }/*else{
+            //设置过期时间半小时
+            DateTime expDate = new DateTime().plusMinutes(30);
+            builder.setExpiration(expDate.toDate());
+        }*/
+        return builder.compact();
+    }
+
+    /**
+     * 获取用户id
+     */
+    public static Long getUserId(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        Claim id = jwt.getClaim("id");
+        Assert.notNull(id, "token id is null ");
+        return id.asLong();
+    }
+
+
+    /**
+     * 管理者 ,0:是, 1:否
+     */
+    public static Boolean getUserManager(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        Claim id = jwt.getClaim("manager");
+        Assert.notNull(id, "token manager is null ");
+        Integer integer = id.asInt();
+        return integer == 0;
+    }
+
+    public static void main(String[] args) {
+        long nowMillis = System.currentTimeMillis();
+        System.out.println(nowMillis);
+        Date exp = new Date(nowMillis);
+        System.out.println(exp);
+    }
+
+    public static void test2() {
+        String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOlsiYWRtaW4iLCJyb290Il0sImlkIjoxLCJ1c2VyTmFtZSI6ImFkbWluIiwiaWF0IjoxNTgzODA5MzkzLCJqdGkiOiJkNjZiZTFkYi00MTQ0LTQxMTYtYTNlNi01ZDBjNjhlNTI3ODAifQ.-4AdsVP2RwmPS2grtO4aC8ov9PwkilzaGdThGetBJok";
+        System.out.println(getUserRole(token));
+
+    }
+
+    public static void test3() {
+        HashMap<String, Object> map = new HashMap<>();
+
+        ArrayList<Object> list = new ArrayList<>();
+        list.add("admin");
+        list.add("root");
+
+        map.put("userName", "admin");
+        map.put("id", Long.valueOf("1"));
+        map.put("role", list);
+
+        String token = createJWT(-1, map);
+        System.out.println(token);
+
+        Boolean isVerify = isVerify(token, "admin");
+        System.out.println(isVerify);
+
+    }
+
+    private static void testList() {
+        ArrayList<Object> list = new ArrayList<>();
+        list.add("admin");
+        list.add("root");
+    }
+
+    /**
+     * 检查token是否有效
+     */
+    @Test
+    public void testCheckToken(){
+        String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMzExMjMxMTE3OCIsInVzZXJOYW1lIjoiMTMxMTIzMTExNzgiLCJpYXQiOjE2MTM2MjAzNjcsImp0aSI6IjMyYTAwZDNiLTE2ODctNDUzNi04NmIwLWY4OTMzODQzNzNjMiJ9.5sV47Yf0HU4m6u77jmCziR3KhAGfiL5aUKxo57MImTI";
+        String username = getUsername(token);
+        Long userId = getUserId(token);
+        System.out.println(username);
+        System.out.println("id: " + userId );
+    }
+
+
+    @Test
+    public void testIsVerify(){
+        String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMzExMjMxMTE3OCIsInVzZXJOYW1lIjoiMTMxMTIzMTExNzgiLCJpYXQiOjE2MTM2MjAzNjcsImp0aSI6IjMyYTAwZDNiLTE2ODctNDUzNi04NmIwLWY4OTMzODQzNzNjMiJ9.5sV47Yf0HU4m6u77jmCziR3KhAGfiL5aUKxo57MImTI";
+        String userName = "13112311178";
+        Boolean verify = isVerify(token, userName);
+        System.out.println(verify);
+    }
+
+
+    /**
+     * 解析出来是一个对象
+     */
+    @Test
+    public void testParseJWT(){
+        String token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOlsiYWRtaW4iLCJyb290Il0sImlkIjoxLCJ1c2VyTmFtZSI6ImFkbWluIiwiaWF0IjoxNTgzODA5MzkzLCJqdGkiOiJkNjZiZTFkYi00MTQ0LTQxMTYtYTNlNi01ZDBjNjhlNTI3ODAifQ.-4AdsVP2RwmPS2grtO4aC8ov9PwkilzaGdThGetBJok";
+        System.out.println(parseJWT(token));
+    }
+
+}

+ 194 - 0
gis_common/src/main/java/com/gis/common/util/PasswordUtils.java

@@ -0,0 +1,194 @@
+package com.gis.common.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import java.security.Key;
+import java.security.SecureRandom;
+
+public class PasswordUtils {
+
+
+    /**
+     * JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES
+     * PBEWITHSHAANDDESEDE PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1
+     * */
+
+    /**
+     * 定义使用的算法为:PBEWITHMD5andDES算法
+     */
+    public static final String ALGORITHM = "PBEWithMD5AndDES";//加密算法
+    public static final String Salt = "63293188";//密钥
+
+    /**
+     * 定义迭代次数为1000次
+     */
+    private static final int ITERATIONCOUNT = 1000;
+
+    /**
+     * 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节
+     *
+     * @return byte[] 盐值
+     */
+    public static byte[] getSalt() throws Exception {
+        // 实例化安全随机数
+        SecureRandom random = new SecureRandom();
+        // 产出盐
+        return random.generateSeed(8);
+    }
+
+    public static byte[] getStaticSalt() {
+        // 产出盐
+        return Salt.getBytes();
+    }
+
+    /**
+     * 根据PBE密码生成一把密钥
+     *
+     * @param password 生成密钥时所使用的密码
+     * @return Key PBE算法密钥
+     */
+    private static Key getPBEKey(String password) {
+        // 实例化使用的算法
+        SecretKeyFactory keyFactory;
+        SecretKey secretKey = null;
+        try {
+            keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
+            // 设置PBE密钥参数
+            PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
+            // 生成密钥
+            secretKey = keyFactory.generateSecret(keySpec);
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+        return secretKey;
+    }
+
+    /**
+     * 加密明文字符串
+     *
+     * @param plaintext 待加密的明文字符串
+     * @param password  生成密钥时所使用的密码
+     * @param salt      盐值
+     * @return 加密后的密文字符串
+     * @throws Exception
+     */
+    public static String encrypt(String plaintext, String password, byte[] salt) {
+
+        Key key = getPBEKey(password);
+        byte[] encipheredData = null;
+        PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, ITERATIONCOUNT);
+        try {
+            Cipher cipher = Cipher.getInstance(ALGORITHM);
+
+            cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
+
+            encipheredData = cipher.doFinal(plaintext.getBytes());
+        } catch (Exception e) {
+        }
+        return bytesToHexString(encipheredData);
+    }
+
+    /**
+     * 解密密文字符串
+     *
+     * @param ciphertext 待解密的密文字符串
+     * @param password   生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致)
+     * @param salt       盐值(如需解密,该参数需要与加密时使用的一致)
+     * @return 解密后的明文字符串
+     * @throws Exception
+     */
+    public static Boolean decrypt(String ciphertext, String password, byte[] salt) {
+
+        Key key = getPBEKey(password);
+        byte[] passDec = null;
+        PBEParameterSpec parameterSpec = new PBEParameterSpec(getStaticSalt(), ITERATIONCOUNT);
+        try {
+            Cipher cipher = Cipher.getInstance(ALGORITHM);
+
+            cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
+
+            passDec = cipher.doFinal(hexStringToBytes(ciphertext));
+            return true;
+        } catch (Exception e) {
+            // TODO: handle exception
+            return false;
+        }
+//        return new String(passDec);
+    }
+
+    /**
+     * 将字节数组转换为十六进制字符串
+     *
+     * @param src 字节数组
+     * @return
+     */
+    public static String bytesToHexString(byte[] src) {
+        StringBuilder stringBuilder = new StringBuilder("");
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        for (int i = 0; i < src.length; i++) {
+            int v = src[i] & 0xFF;
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    /**
+     * 将十六进制字符串转换为字节数组
+     *
+     * @param hexString 十六进制字符串
+     * @return
+     */
+    public static byte[] hexStringToBytes(String hexString) {
+        if (hexString == null || hexString.equals("")) {
+            return null;
+        }
+        hexString = hexString.toUpperCase();
+        int length = hexString.length() / 2;
+        char[] hexChars = hexString.toCharArray();
+        byte[] d = new byte[length];
+        for (int i = 0; i < length; i++) {
+            int pos = i * 2;
+            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
+        }
+        return d;
+    }
+
+    private static byte charToByte(char c) {
+        return (byte) "0123456789ABCDEF".indexOf(c);
+    }
+
+    public static void main(String[] args) {
+
+        String userName = "hao";
+        String password = "123456";
+
+        try {
+            byte[] salt = PasswordUtils.getStaticSalt();
+            String ciphertext = PasswordUtils.encrypt(userName, password, salt);
+            System.out.println("密文:" + ciphertext);
+            Boolean plaintext = PasswordUtils.decrypt(ciphertext, password, salt);
+            System.out.println("明文" + plaintext);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+
+
+
+
+
+    }
+
+
+}

+ 20 - 0
gis_common/src/main/java/com/gis/common/util/RandomUtils.java

@@ -0,0 +1,20 @@
+package com.gis.common.util;
+
+import cn.hutool.core.util.RandomUtil;
+
+/**
+ * Created by owen on 2020/4/26 0026 10:07
+ *
+ *
+ */
+public class RandomUtils {
+
+    public static String randowString(int length){
+        String baseString = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        return RandomUtil.randomString(baseString, length);
+    }
+
+    public static void main(String[] args) {
+        System.out.println(randowString(9));
+    }
+}

+ 20 - 0
gis_common/src/main/java/com/gis/common/util/RegexUtil.java

@@ -0,0 +1,20 @@
+package com.gis.common.util;
+
+public class RegexUtil {
+    //specific symbol
+
+    /** 处理特殊符号,变空值*/
+    public static String specificSymbol(String str){
+
+        String regEx = "[\\s`~!@#$%^&*()+=|{}':;\\[\\]<>/?·~!@#¥%……&*()——+|{}【】‘;:“”。,、?]";
+        return str.replaceAll(regEx, "");
+    }
+
+    public static void main(String[] args) {
+        String str = "我·是 中—国(人), 你-在{干嘛}--哈—哈。 ddd.jpg";
+        System.out.println(specificSymbol(str));
+    }
+
+}
+
+

+ 101 - 0
gis_common/src/main/java/com/gis/common/util/Result.java

@@ -0,0 +1,101 @@
+package com.gis.common.util;
+
+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 + "]";
+    }
+}

+ 30 - 0
gis_common/src/main/java/com/gis/common/util/WxUtil.java

@@ -0,0 +1,30 @@
+package com.gis.common.util;
+
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.log4j.Log4j2;
+
+
+/**
+ * Created by owen on 2020/7/31 0031 18:20
+ */
+@Log4j2
+public class WxUtil {
+
+
+    public static String getAccessToken(String appId, String appSecret ){
+
+            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
+            String s = HttpUtil.get(url);
+            log.info("s: {}", s);
+            JSONObject result = JSONObject.parseObject(s);
+            String accessToken = result.getString("access_token");
+            log.info("access_token: {}", accessToken);
+            if (accessToken == null) {
+                log.error(result);
+                return null;
+            }
+
+        return accessToken;
+    }
+}

+ 22 - 0
gis_domain/pom.xml

@@ -0,0 +1,22 @@
+<?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">
+    <parent>
+        <artifactId>wx_reload_beijing</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gis_domain</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_common</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 28 - 0
gis_domain/src/main/java/com/gis/domain/dto/LoginDto.java

@@ -0,0 +1,28 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class LoginDto {
+
+    @NotBlank(message = "用户名不能为空")
+    @ApiModelProperty(value = "用户名", name = "userName", required = true)
+    private String userName;
+
+
+    @NotBlank(message = "密码不能为空")
+    @ApiModelProperty(value = "密码", name = "password", required = true)
+    private String password;
+//
+//    @NotBlank(message = "from不能为空")
+//    @ApiModelProperty(value = "区分用户去向,cms:管理后台,web:展示页")
+//    private String from;
+
+
+}

+ 27 - 0
gis_domain/src/main/java/com/gis/domain/dto/PageDateDto.java

@@ -0,0 +1,27 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * Created by Owen on 2019/10/28 0028 12:24
+ * 有时间
+ */
+@Data
+public class PageDateDto extends PageDto {
+
+    /**
+     * 开始时间
+     * 需要用字符串接收
+     */
+    @ApiModelProperty(value = "开始时间", name = "startTime")
+    private String startTime;
+
+
+    @ApiModelProperty(value = "结束时间", name = "endTime")
+    private String endTime;
+
+
+
+}

+ 26 - 0
gis_domain/src/main/java/com/gis/domain/dto/PageDto.java

@@ -0,0 +1,26 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * Created by Owen on 2019/10/28 0028 12:24
+ */
+@Data
+public class PageDto {
+
+
+    @ApiModelProperty(value = "起始页码,默认1为第一页", name = "pageNum")
+    private Integer pageNum;
+
+    @ApiModelProperty(value = "每页数量", name = "pageSize")
+    private Integer pageSize;
+
+    @ApiModelProperty(value = "搜索条件", name = "searchKey")
+    private String searchKey;
+
+
+
+
+}

+ 21 - 0
gis_domain/src/main/java/com/gis/domain/dto/PasswordRequest.java

@@ -0,0 +1,21 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class PasswordRequest {
+
+    @NotBlank(message = "旧密码不能为空")
+    @ApiModelProperty(value = "旧密码", name = "oldPassword", required = true)
+    private String oldPassword;
+
+    @NotBlank(message = "新密码不能为空")
+    @ApiModelProperty(value = "新密码", name = "newPassword", required = true)
+    private String newPassword;
+}

+ 58 - 0
gis_domain/src/main/java/com/gis/domain/dto/RegisterDto.java

@@ -0,0 +1,58 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2020/5/28 0028 16:36
+ * 游客注册
+ */
+@Data
+public class RegisterDto {
+
+    @NotBlank(message = "真实姓名不能为空")
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+
+    @NotBlank(message = "身份证号(军号)不能为空")
+    @ApiModelProperty(value = "身份证号(军号)", required = true)
+    private String userName;
+
+    @NotBlank(message = "昵称不能为空")
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @NotNull(message = "性别不能为空")
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+//    @NotBlank(message = "单位不能为空")
+    @ApiModelProperty(value = "单位")
+    private String unit;
+
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+    @Length(min = 6,message = "长度不能小于6位")
+    @Length(max = 12, message = "长度不能大于12位")
+    @ApiModelProperty(value = "登录密码")
+    private String password;
+
+    @Length(min = 6,message = "长度不能小于6位")
+    @Length(max = 12, message = "长度不能大于12位")
+    @ApiModelProperty(value = "确认密码")
+    private String verifyPassword;
+
+
+
+}

+ 21 - 0
gis_domain/src/main/java/com/gis/domain/dto/ResetPasswordDto.java

@@ -0,0 +1,21 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class ResetPasswordDto {
+
+    @NotBlank(message = "注册姓名不能为空")
+    @ApiModelProperty(value = "姓名",  required = true)
+    private String realName;
+
+    @NotBlank(message = "身份证号不能为空")
+    @ApiModelProperty(value = "身份证号",  required = true)
+    private String userName;
+}

+ 24 - 0
gis_domain/src/main/java/com/gis/domain/dto/RoamViableDto.java

@@ -0,0 +1,24 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/7/27 0027 16:01
+ *
+ * 漫游可行
+ */
+
+@Data
+public class RoamViableDto {
+
+    @NotBlank(message = "场景码不能为空")
+    @ApiModelProperty(value = "场景码")
+    private String sceneCode;
+
+    @NotBlank(message = "漫游数据不能为空")
+    @ApiModelProperty(value = "漫游数据")
+    private String data;
+}

+ 39 - 0
gis_domain/src/main/java/com/gis/domain/dto/SceneDataDto.java

@@ -0,0 +1,39 @@
+package com.gis.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+
+/**
+ * Created by Owen on 2019/10/28 0028 12:24
+ *
+ * 编辑场景使用
+ */
+@Data
+public class SceneDataDto {
+
+//    private String name;
+
+    @NotBlank(message = "场景码不能为空")
+    @ApiModelProperty(value = "场景码", required = true)
+    private String sceneCode;
+
+    /** data2.js */
+    private String hots;
+
+    private String guides;
+
+    /** someData.json model */
+    private String info;
+
+    /** data2.js */
+    private String tourAudio;
+
+    /** data2.js 数组*/
+    private String overlays;
+
+
+}

+ 62 - 0
gis_domain/src/main/java/com/gis/domain/dto/UserDto.java

@@ -0,0 +1,62 @@
+package com.gis.domain.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2020/5/28 0028 16:36
+ */
+@Data
+public class UserDto {
+
+    @ApiModelProperty(value = "id, 修改时必须传,新增忽略", name = "id")
+    private Long id;
+
+
+//    @NotBlank(message = "真实姓名不能为空")
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+
+    @NotBlank(message = "管理员账号不能为空")
+    @ApiModelProperty(value = "管理员账号", required = true)
+    private String userName;
+
+//    @NotBlank(message = "昵称不能为空")
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+//    @NotNull(message = "性别不能为空")
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+//    @NotBlank(message = "单位不能为空")
+    @ApiModelProperty(value = "单位")
+    private String unit;
+
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+    @NotNull(message = "启用状态不能为空")
+    @ApiModelProperty(value = "状态 1:启用  0:停用 ")
+    private Integer status;
+
+    @ApiModelProperty(value = "高清图url")
+    private String img;
+
+    @ApiModelProperty(value = "缩略图url")
+    private String thumb;
+
+
+    @NotNull(message = "角色不能为空")
+    @ApiModelProperty(value = "角色,sys_admin:系统管理员,sys_high:高级管理员, sys_normal:普通管理员, sys_visitor:游客" ,required = true)
+    private String role;
+
+}

+ 39 - 0
gis_domain/src/main/java/com/gis/domain/po/BaseEntity.java

@@ -0,0 +1,39 @@
+package com.gis.domain.po;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Data
+@MappedSuperclass
+public abstract class BaseEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    @ApiModelProperty(value = "对象ID")
+    private Long id;
+
+    @ApiModelProperty(value = "创建时间")
+    @Temporal(TemporalType.TIMESTAMP)
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty(value = "修改时间")
+    @Temporal(TemporalType.TIMESTAMP)
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+     * 用来批量操作的
+     * 0代表未删除 , 1代表已经删除,默认写0
+     * 需要使用对象类型
+     */
+    @JsonIgnore
+    @JSONField(serialize = false)
+    private Integer isDelete;
+}

+ 41 - 0
gis_domain/src/main/java/com/gis/domain/po/SceneEntity.java

@@ -0,0 +1,41 @@
+package com.gis.domain.po;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+@Data
+@Entity
+@Table(name = "tb_scene")
+public class SceneEntity extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = -8093446477843493946L;
+
+    @ApiModelProperty(value = "场景码")
+    private String sceneCode;
+
+    @ApiModelProperty(value = "存放地址")
+    private String path;
+
+    @ApiModelProperty(value = "场景名称")
+    private String sceneTitle;
+
+//    @ApiModelProperty(value = "场景url")
+//    private String webSite;
+
+//    @ApiModelProperty(value = "简介")
+//    private String description;
+
+
+    @ApiModelProperty(value = "是否显示,1:是, 0:否")
+    private Integer display;
+
+
+
+//    @ApiModelProperty(value = "排序")
+//    private Integer sort;
+
+}

+ 62 - 0
gis_domain/src/main/java/com/gis/domain/po/SysUserEntity.java

@@ -0,0 +1,62 @@
+package com.gis.domain.po;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * 用户表
+ */
+@Data
+@Entity
+@Table(name = "sys_user")
+public class SysUserEntity extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = -853504493430501564L;
+
+    @ApiModelProperty(value = "用户名")
+    private String userName;
+
+    @JSONField(serialize = false)
+    private String password;
+
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+//    @ApiModelProperty(value = "单位")
+//    private String unit;
+
+//    @ApiModelProperty(value = "地址")
+//    private String address;
+
+//    @ApiModelProperty(value = "超级管理员,1:是, 0:否")
+//    private Integer sysManager;
+
+    @ApiModelProperty(value = "状态 1:启用  0:停用 ")
+    private Integer status;
+
+//    @ApiModelProperty(value = "高清图url")
+//    private String img;
+
+    @ApiModelProperty(value = "缩略图url")
+    private String thumb;
+
+    @ApiModelProperty(value = "角色,sys_admin:系统管理员, sys_normal:普通管理员")
+    private String role;
+
+
+
+}

+ 22 - 0
gis_mapper/pom.xml

@@ -0,0 +1,22 @@
+<?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">
+    <parent>
+        <artifactId>wx_reload_beijing</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gis_mapper</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_domain</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 18 - 0
gis_mapper/src/main/java/com/gis/mapper/IBaseMapper.java

@@ -0,0 +1,18 @@
+package com.gis.mapper;
+
+import com.gis.domain.po.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;
+
+/**
+ * Created by owen on 2020/2/18 0018 11:27
+ */
+
+public interface IBaseMapper<T extends BaseEntity, ID extends Serializable> extends BaseMapper<T>,
+        ConditionMapper<T>, IdsMapper<T>, InsertListMapper<T> {
+}

+ 38 - 0
gis_mapper/src/main/java/com/gis/mapper/SceneMapper.java

@@ -0,0 +1,38 @@
+package com.gis.mapper;
+
+
+import com.gis.domain.dto.PageDto;
+import com.gis.domain.po.SceneEntity;
+import com.gis.mapper.provider.SceneProvider;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@Mapper
+public interface SceneMapper extends IBaseMapper<SceneEntity, Long> {
+
+    @Select("select * from tb_scene where scene_code = #{m}")
+    SceneEntity findBySceneCode(String m);
+
+//    @SelectProvider(type = SceneProvider.class, method = "search")
+//    List<SceneEntity> search(ScenePageDto param);
+
+    @SelectProvider(type = SceneProvider.class, method = "search")
+    List<SceneEntity> search(PageDto param);
+
+
+
+    @Update("update tb_scene set display = 0 where display = 1 ")
+    void setDisable();
+
+    @Update("update tb_scene set display = 1 where id = #{id} ")
+    void setDisplay(Long id);
+
+    @Update("update tb_scene set display = 0 where is_delete = '0' and display = 1 and type = #{type}")
+    void setDisableByType(String type);
+}

+ 28 - 0
gis_mapper/src/main/java/com/gis/mapper/SysUserMapper.java

@@ -0,0 +1,28 @@
+package com.gis.mapper;
+
+
+import com.gis.domain.dto.PageDateDto;
+import com.gis.domain.po.SysUserEntity;
+import com.gis.mapper.provider.UserProvider;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@Mapper
+public interface SysUserMapper extends IBaseMapper<SysUserEntity, Long> {
+
+
+    @Select(value = "select * from sys_user where is_delete = '0' AND user_name= #{userName}")
+    SysUserEntity findByUserName(String userName);
+
+    @Select(value = "select * from sys_user where is_delete = '0' AND phone = #{phone}")
+    SysUserEntity findByPhone(String phone);
+
+    @SelectProvider(type = UserProvider.class, method = "search")
+    List<SysUserEntity> search(PageDateDto param);
+
+}

+ 41 - 0
gis_mapper/src/main/java/com/gis/mapper/provider/CommentProvider.java

@@ -0,0 +1,41 @@
+package com.gis.mapper.provider;
+
+import com.gis.domain.dto.PageDateDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class CommentProvider {
+
+
+    public String search(PageDateDto param, Integer display){
+        StringBuffer sql = new StringBuffer(
+                "select * from tb_comment where is_delete = '0' ");
+
+        if(StringUtils.isNotBlank(param.getStartTime()) ){
+
+            sql.append(" and create_time >= ").append("'").append(param.getStartTime()).append("'");
+
+        }
+
+        if (StringUtils.isNotBlank(param.getEndTime())) {
+            sql.append(" and create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+        String searchKey = param.getSearchKey();
+        if(StringUtils.isNotBlank(searchKey)){
+            sql.append(" and ( msg like '%").append(searchKey).append("%' )");
+        }
+
+        if (display != null) {
+            sql.append(" and display = ").append(display);
+        }
+
+        sql.append(" order by create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+}

+ 41 - 0
gis_mapper/src/main/java/com/gis/mapper/provider/GiftProvider.java

@@ -0,0 +1,41 @@
+package com.gis.mapper.provider;
+
+import com.gis.domain.dto.PageDateDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class GiftProvider {
+
+
+    public String search(PageDateDto param, Integer display){
+        StringBuffer sql = new StringBuffer(
+                "select * from tb_comment where is_delete = '0' ");
+
+        if(StringUtils.isNotBlank(param.getStartTime()) ){
+
+            sql.append(" and create_time >= ").append("'").append(param.getStartTime()).append("'");
+
+        }
+
+        if (StringUtils.isNotBlank(param.getEndTime())) {
+            sql.append(" and create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+        String searchKey = param.getSearchKey();
+        if(StringUtils.isNotBlank(searchKey)){
+            sql.append(" and ( name like '%").append(searchKey).append("%' )");
+        }
+
+        if (display != null) {
+            sql.append(" and display = ").append(display);
+        }
+
+        sql.append(" order by create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+}

+ 34 - 0
gis_mapper/src/main/java/com/gis/mapper/provider/SceneProvider.java

@@ -0,0 +1,34 @@
+package com.gis.mapper.provider;
+
+import com.gis.domain.dto.PageDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class SceneProvider {
+
+
+    public String search(PageDto param){
+        StringBuffer sql = new StringBuffer(
+                "select * from tb_scene where is_delete = '0' ");
+
+        String searchKey = param.getSearchKey();
+        if(!StringUtils.isAllBlank(searchKey)){
+            sql.append(" and ( scene_title like '%").append(searchKey).append("%' )");
+        }
+
+//        String type = param.getType();
+//        if (StringUtils.isNotBlank(type)){
+//            sql.append(" and type = '").append(type).append("'");
+//        }
+
+
+        sql.append(" order by display desc, create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+}

+ 60 - 0
gis_mapper/src/main/java/com/gis/mapper/provider/UserProvider.java

@@ -0,0 +1,60 @@
+package com.gis.mapper.provider;
+
+import com.gis.domain.dto.PageDateDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class UserProvider {
+
+
+    public String search(PageDateDto param){
+        StringBuffer sql = new StringBuffer(
+                "select * from sys_user where is_delete = '0' ");
+
+        if(StringUtils.isNotBlank(param.getStartTime()) ){
+
+            sql.append(" and create_time >= ").append("'").append(param.getStartTime()).append("'");
+
+        }
+
+        if (StringUtils.isNotBlank(param.getEndTime())) {
+            sql.append(" and create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+        String searchKey = param.getSearchKey();
+        if(StringUtils.isNotBlank(searchKey)){
+            sql.append(" and ( real_name like '%").append(searchKey).append("%' )");
+        }
+
+//        String roleKey = param.getRole();
+//        if (StringUtils.isNotBlank(roleKey)) {
+//            sql.append(" and role = '").append(roleKey).append("'");
+//        }
+
+
+//        // 区分系统管理员跟游客
+//        int type = param.getType();
+//        if (type == 0) {
+//            sql.append(" and role = '").append("sys_visitor'");
+//        } else {
+//
+//
+//
+//
+//            sql.append(" and role <> '").append("sys_visitor'");
+//        }
+
+        sql.append(" order by create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+
+
+
+
+}

+ 23 - 0
gis_service/pom.xml

@@ -0,0 +1,23 @@
+<?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">
+    <parent>
+        <artifactId>wx_reload_beijing</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gis_service</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_mapper</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 47 - 0
gis_service/src/main/java/com/gis/service/IBaseService.java

@@ -0,0 +1,47 @@
+package com.gis.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);
+
+}

+ 30 - 0
gis_service/src/main/java/com/gis/service/SceneService.java

@@ -0,0 +1,30 @@
+package com.gis.service;
+
+
+import com.gis.common.util.Result;
+import com.gis.domain.dto.PageDto;
+import com.gis.domain.dto.RoamViableDto;
+import com.gis.domain.dto.SceneDataDto;
+import com.gis.domain.po.SceneEntity;
+
+import java.util.List;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface SceneService extends IBaseService<SceneEntity, Long> {
+
+
+    SceneEntity findBySceneCode(String m);
+
+//    List<SceneEntity> search(ScenePageDto param);
+
+    Result<SceneEntity> search(PageDto param);
+
+    Result roamViable(RoamViableDto param) throws Exception;
+
+    Result edit(SceneDataDto param);
+
+    Result display(Long id);
+}

+ 22 - 0
gis_service/src/main/java/com/gis/service/SysUserService.java

@@ -0,0 +1,22 @@
+package com.gis.service;
+
+
+import com.gis.domain.dto.PageDateDto;
+import com.gis.domain.po.SysUserEntity;
+
+import java.util.List;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface SysUserService extends IBaseService<SysUserEntity, Long> {
+
+
+    SysUserEntity findByUserName(String userName);
+
+
+
+    List<SysUserEntity> search(PageDateDto param);
+
+}

+ 16 - 0
gis_service/src/main/java/com/gis/service/WxService.java

@@ -0,0 +1,16 @@
+package com.gis.service;
+
+
+import com.gis.common.util.Result;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface WxService {
+
+
+    Result login(String code);
+
+    Result logout();
+}

+ 13 - 0
gis_service/src/main/java/com/gis/service/aop/WebControllerLog.java

@@ -0,0 +1,13 @@
+package com.gis.service.aop;
+
+import java.lang.annotation.*;
+
+/**
+ * Created by Hb_zzZ on 2020/2/27.
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface WebControllerLog {
+    String description() default "";
+}

+ 131 - 0
gis_service/src/main/java/com/gis/service/aop/WebLogAspect.java

@@ -0,0 +1,131 @@
+package com.gis.service.aop;
+
+import com.gis.common.util.JwtUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by owen on 2020/2/25 0025 9:24
+ *
+ * 日志aop
+ */
+@Slf4j
+@Aspect
+@Component
+public class WebLogAspect {
+
+    @Autowired
+    private HttpServletRequest request;
+
+
+
+    @Pointcut("execution(* com.gis.web.controller.*.*(..))")//切入点描述 这个是controller包的切入点
+    public void controllerLog(){}//签名,可以理解成这个切入点的一个名称
+
+    @Before("controllerLog()") //在切入点的方法run之前要干的
+    public void logBeforeController(JoinPoint joinPoint) throws Exception {
+
+        // 记录下请求内容
+        log.warn("start : {}" , request.getRequestURI());
+        log.info("request Method : {}" , request.getMethod());
+        log.info("request IP : {}" , request.getRemoteAddr());
+        log.info("request Args : {}" , Arrays.toString(joinPoint.getArgs()));
+
+        // 获取token
+        String token = request.getHeader("token");
+        if (StringUtils.isBlank(token)) {
+            return;
+        }
+
+
+        // 排查登录接口
+        if (request.getRequestURI().contains("/admin/login") || request.getRequestURI().contains("/api/")) {
+            return;
+        }
+
+
+        Long userId = null;
+        if (StringUtils.isNotBlank(token)) {
+            userId = JwtUtil.getUserId(token);
+        }
+
+
+        String description = getControllerLogDescription(joinPoint);
+
+        if (StringUtils.isNotBlank(description)) {
+            log.info("request description : {}", description);
+            // 保存数据库
+            List<String> detail = getDetail(description);
+//            logService.save(new LogEntity(userId, detail.get(0), detail.get(1)));
+        }
+
+        //下面这个getSignature().getDeclaringTypeName()是获取包+类名的   然后后面的joinPoint.getSignature.getName()获取了方法名
+        log.info("request Class_Method : {}" , joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
+
+
+
+    }
+
+
+    //使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
+    @AfterReturning(returning = "ret", pointcut = "controllerLog()")
+    public void doAfterReturning(Object ret) throws Throwable {
+        // 处理完请求,返回内容
+//        log.info("响应RESPONSE : " + ret.toString());
+        log.warn("end : {}", request.getRequestURI());
+    }
+
+    /**
+     * 获取注解中对方法的描述信息 用于Controller层注解
+     *
+     * @param joinPoint
+     *            切点
+     * @return 方法描述
+     * @throws Exception
+     */
+    public static String getControllerLogDescription(JoinPoint joinPoint) throws Exception {
+        String targetName = joinPoint.getTarget().getClass().getName();
+        String methodName = joinPoint.getSignature().getName();
+        Object[] arguments = joinPoint.getArgs();
+        Class targetClass = Class.forName(targetName);
+        Method[] methods = targetClass.getMethods();
+        String description = "";
+        for (Method method : methods) {
+            if (method.getName().equals(methodName)) {
+                Class[] clazzs = method.getParameterTypes();
+                if (clazzs.length == arguments.length) {
+                    WebControllerLog annotation = method.getAnnotation(WebControllerLog.class);
+                    if (annotation != null) {
+                        description = annotation.description();
+                        break;
+                    }
+                }
+            }
+        }
+        return description;
+    }
+
+    private static List<String> getDetail(String str){
+        String[] split = str.split("-");
+        return Arrays.asList(split);
+    }
+
+
+    public static void main(String[] args) {
+        String url = "api/";
+        System.out.println("api/scene".contains(url));
+        System.out.println("api/".contains("api/scene"));
+    }
+}

+ 210 - 0
gis_service/src/main/java/com/gis/service/impl/IBaseServiceImpl.java

@@ -0,0 +1,210 @@
+package com.gis.service.impl;
+
+import com.gis.common.constant.ConfigConstant;
+import com.gis.common.util.JwtUtil;
+import com.gis.domain.dto.PageDto;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.gis.mapper.IBaseMapper;
+import com.gis.domain.po.BaseEntity;
+import com.gis.service.IBaseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import tk.mybatis.mapper.entity.Condition;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.io.Serializable;
+import java.lang.reflect.ParameterizedType;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Created by owen on 2020/2/18 0018 11:22
+ */
+@Transactional
+public abstract class IBaseServiceImpl<T extends BaseEntity, ID extends Serializable> implements IBaseService<T, ID> {
+
+
+    @Autowired
+    ConfigConstant configConstant;
+
+    /**
+     * 2021-04-20
+     * 这里不能使用 @Autowired 注入HttpServletRequest 会报已注入的错误
+     */
+//    @Autowired
+//    HttpServletRequest request;
+
+    public abstract IBaseMapper<T, ID> getBaseMapper();
+
+    private Class<T> entityClass;
+
+    public IBaseServiceImpl(){
+        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.and().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) {
+        //migration之后要删掉判断
+        if (entity.getCreateTime() == null){
+            entity.setCreateTime(new Date());
+        }
+        if (entity.getUpdateTime() == null){
+            entity.setUpdateTime(new Date());
+        }
+        entity.setIsDelete(0);
+        return getBaseMapper().insertSelective(entity);
+    }
+
+    @Override
+    public int update(T entity) {
+        //migration之后要删掉判断
+        if (entity.getUpdateTime() == null){
+            entity.setUpdateTime(new Date());
+        }
+        return getBaseMapper().updateByPrimaryKeySelective(entity);
+    }
+
+    @Override
+    public int updateAll(T entity) {
+        //migration之后要删掉判断
+        if (entity.getUpdateTime() == null){
+            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));
+    }
+
+
+    /**
+     * 设置请求分页数据
+     */
+    public void startPage(PageDto param){
+        Integer pageNum = param.getPageNum();
+        Integer pageSize = param.getPageSize();
+        if (pageNum == null || pageNum <= 0) {
+            pageNum = 0;
+        }
+        if (pageSize == null || pageSize <= 0) {
+            pageSize = 10;
+        }
+        PageHelper.startPage(pageNum, pageSize);
+    }
+
+    /** 获取用户id*/
+    Long getTokenUserId(HttpServletRequest request){
+        return JwtUtil.getUserId(getToken(request));
+    }
+
+    /** 获取header token */
+    String getToken(HttpServletRequest request){
+        return request.getHeader("token");
+    }
+}

+ 395 - 0
gis_service/src/main/java/com/gis/service/impl/SceneServiceImpl.java

@@ -0,0 +1,395 @@
+package com.gis.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.gis.common.proto.util.ConvertUtils;
+import com.gis.common.util.Result;
+import com.gis.domain.dto.PageDto;
+import com.gis.domain.dto.RoamViableDto;
+import com.gis.domain.dto.SceneDataDto;
+import com.gis.domain.po.SceneEntity;
+import com.gis.mapper.SceneMapper;
+import com.gis.mapper.IBaseMapper;
+import com.gis.service.SceneService;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:16
+ */
+@Log4j2
+@Service
+public class SceneServiceImpl extends IBaseServiceImpl<SceneEntity, Long> implements SceneService {
+
+    @Autowired
+    private SceneMapper entityMapper;
+
+    @Override
+    public IBaseMapper<SceneEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+
+    @Override
+    public SceneEntity findBySceneCode(String m) {
+        return entityMapper.findBySceneCode(m);
+    }
+
+//    @Override
+//    public List<SceneEntity> search(ScenePageDto param) {
+//        return entityMapper.search(param);
+//    }
+
+    @Override
+    public Result<SceneEntity> search(PageDto param) {
+        startPage(param);
+        PageInfo<SceneEntity> page = new PageInfo<>(entityMapper.search(param));
+        return Result.success(page);
+    }
+
+    /**
+     * 漫游可行
+     */
+    @Override
+    public Result roamViable(RoamViableDto param) throws Exception {
+        String sceneCode = param.getSceneCode();
+        SceneEntity entity = entityMapper.findBySceneCode(param.getSceneCode());
+        if (entity == null) {
+            log.error("场景不存在:{}", sceneCode);
+            return Result.failure("场景不存在");
+        }
+
+
+        // 1. 从oss下载vision.modeldata
+        String visionModelDataName = "vision.modeldata";
+        // 注意网络下载会有缓存,必须加时间戳
+//        log.info("网络下载文件地址: {}", urlPath);
+//        String localBasePath = FILE_PATH + sceneCode;
+        String localBasePath = configConstant.serverBasePath + sceneCode;
+
+        // 2. 将vision.modeldata 转 vision.json
+        String visionModelDataPath = localBasePath + "/" + visionModelDataName;
+        if (!FileUtil.exist(visionModelDataPath)) {
+            log.error("vision.modeldata不存在 : {}", visionModelDataPath);
+            return Result.failure("vision.modeldata不存在");
+        }
+//        log.info(visionModelDataName+ "下载完成");
+
+
+        String visionJsonPath = localBasePath + "/vision.json";
+        ConvertUtils.convertVisionModelDataToTxt(visionModelDataPath, visionJsonPath);
+        if (!FileUtil.exist(visionJsonPath)) {
+            log.error("vision.json不存在 : {}", visionJsonPath);
+            return Result.failure("vision.modeldata不存在");
+        }
+
+        // 3. 编辑新数据到vision.json
+        JSONArray inputDates = JSONObject.parseArray(param.getData());
+
+        JSONObject visionJson = JSONObject.parseObject(FileUtil.readUtf8String(visionJsonPath));
+        JSONArray sweepLocations = visionJson.getJSONArray("sweepLocations");
+
+        for (int i = 0; i < sweepLocations.size(); i++) {
+            JSONObject pano = sweepLocations.getJSONObject(i);
+
+            for (int j = 0; j < inputDates.size(); j++) {
+                JSONObject jo = inputDates.getJSONObject(j);
+                String panoID = jo.getString("panoID");
+                JSONArray visibles3 = jo.getJSONArray("visibles3");
+
+                // 去掉uuid 的“-”
+                String uuid = pano.getString("uuid");
+                String s = StringUtils.replaceAll(uuid, "-", "");
+                if (s.equals(panoID)) {
+                    log.info("uuid: {}, panoID: {}", uuid, panoID);
+                    pano.put("visibles", visibles3);
+                    log.info("visibles: {},visibles3:{}", pano.get("visibles"), visibles3);
+                }
+            }
+        }
+
+
+        // 删除旧vision.json,vision.modeldata
+        FileUtil.del(visionJsonPath);
+        FileUtil.del(visionModelDataPath);
+
+        // 写入新vision.json
+        FileUtil.writeUtf8String(visionJson.toJSONString(), visionJsonPath);
+        if (!FileUtil.exist(visionJsonPath)) {
+            log.error("new vision.json不存在");
+        }
+
+        log.info( "新vision.json创建完成 :{}", visionJsonPath);
+
+
+
+
+        // 4. 将vision.json转vision.modeldata
+        ConvertUtils.convertTxtToVisionModelData(visionJsonPath, visionModelDataPath);
+
+        // 5. 将新的vision.modeldata上传到oss
+        if (!FileUtil.exist(visionModelDataPath)) {
+            log.error("vision.modeldata不存在");
+        }
+        log.info("新" + visionModelDataName+ "创建完成 :{}", visionModelDataPath);
+
+
+        return Result.success();
+    }
+
+    @Override
+    public Result edit(SceneDataDto param) {
+        String sceneCode = param.getSceneCode();
+        SceneEntity entity = this.findBySceneCode(param.getSceneCode());
+        if (entity == null) {
+            log.error("场景不存在 : {}", sceneCode);
+            return Result.failure("场景不存在");
+        }
+
+        String basePath = configConstant.serverBasePath + sceneCode;
+
+
+        // 处理someData.json
+
+//        String someDataPath = entity.getPath() + "/someData.json";
+        String someDataPath = basePath + "/someData.json";
+        if (!FileUtil.isFile(someDataPath)) {
+            log.error("someData.json文件不存在");
+            return Result.failure("someData.json文件不存在");
+        }
+
+        // 读取someDataJson
+        String someData = FileUtil.readUtf8String(someDataPath);
+        JSONObject someDataJson = JSONObject.parseObject(someData);
+
+
+
+        String info = param.getInfo();
+        String guides = param.getGuides();
+        JSONArray guidesArray = new JSONArray();
+        if (guides != null) {
+            guidesArray = JSONObject.parseArray(guides);
+
+        }
+
+
+        if (info != null) {
+            JSONObject infoJson = JSONObject.parseObject(info);
+
+            // 处理model
+            JSONObject model = someDataJson.getJSONObject("model");
+            if (model != null) {
+                if (guidesArray != null) {
+                    model.put("images", guidesArray);
+                }
+
+            }
+
+            // 更新someDataJson
+            someDataJson.put("model", model);
+
+            // info信息添加到someDataJson最外层
+            Set<String> infoKey = infoJson.keySet();
+            for (String key : infoKey) {
+
+                someDataJson.put(key, infoJson.get(key));
+            }
+
+            // 删除旧someDataJson
+            FileUtil.del(someDataPath);
+            // 写入新someDataJson
+            FileUtil.writeUtf8String(someDataJson.toJSONString(), someDataPath);
+            log.info("someData.json写入完成");
+        }
+
+        // 处理data2.js
+        String data2Path = basePath + "/data2.js";
+        boolean file = FileUtil.isFile(data2Path);
+        if (!file) {
+            log.error("data2.js文件不存在");
+            return Result.failure("data2.js文件不存在");
+        }
+
+        String data2 = FileUtil.readUtf8String(data2Path);
+        JSONObject data2Json = JSONObject.parseObject(data2);
+
+        String tourAudio = param.getTourAudio();
+        if (tourAudio != null) {
+            data2Json.put("tourAudio", JSONObject.parseObject(tourAudio));
+        } else {
+            data2Json.put("tourAudio", new JSONObject());
+        }
+
+        // overlays是数组
+        String overlays = param.getOverlays();
+        if (overlays != null) {
+            data2Json.put("overlays", JSONObject.parseArray(overlays));
+        } else {
+            data2Json.put("overlays", new JSONArray());
+        }
+
+        // 处理guidesArray,将scan_id的值作为key, value:  time":40000
+        JSONObject audioJson = new JSONObject();
+        JSONObject timeJson = new JSONObject();
+        timeJson.put("time", 40000);
+        if (guidesArray != null) {
+
+            // 将旧的audio字段删除
+            data2Json.remove("audio");
+
+            for (int i = 0; i < guidesArray.size() ; i++) {
+                JSONObject metadata = guidesArray.getJSONObject(i).getJSONObject("metadata");
+                if (metadata != null) {
+                    String scanId = metadata.getString("scan_id");
+                    if (scanId == null) {
+                        log.error("guides.metadata.scan_id为空: {}", i);
+                        return Result.failure("guides.metadata.scan_id为空: " + i);
+                    }
+                    // Fastjson-fastjson中$ref对象重复引用问题,拿不到想要的效果
+                    audioJson.put(scanId, JSON.toJSONString(timeJson, SerializerFeature.DisableCircularReferenceDetect));
+
+                }
+            }
+
+            // 新增audio
+            data2Json.put("audio", audioJson);
+        }
+
+
+        // host在data2.js、data.js都需要处理
+        String hots = param.getHots();
+        log.info("input hots: {}", hots);
+        if (hots != null) {
+            // 获取所有key
+            JSONObject hotJson = JSONObject.parseObject(hots);
+
+            Set<String> strings = hotJson.keySet();
+            for (String key: strings) {
+                JSONObject subJson = hotJson.getJSONObject(key);
+
+                // 2021.04.02 处理link
+                String link = getLink(subJson, key);
+
+                // 将link 添加进去
+                subJson.put("link", link);
+            }
+            data2Json.put("hots", hotJson);
+        } else {
+            data2Json.put("hots", new JSONObject());
+        }
+
+
+        // 删除旧data2.js
+        FileUtil.del(data2Path);
+
+
+        // 写入新data2.js
+        FileUtil.writeUtf8String(data2Json.toJSONString(), data2Path);
+        log.info("新data2.js写入完成");
+
+
+        //处理data.js 文件
+        editDataJs(entity, hots);
+
+        return Result.success();
+    }
+
+    @Override
+    public Result display(Long id) {
+        SceneEntity entity = findById(id);
+        if (entity == null) {
+            return Result.failure("场景不存在, id: " + id);
+        }
+        // 需求:只有一个是可用;先禁用,再启用
+        entityMapper.setDisable();
+        entityMapper.setDisplay(id);
+        return Result.success();
+    }
+
+    /**
+     * 2021.04.02 处理infoAttribute的m_title
+     * String url  = "https://www.4dmodel.com/SuperTwo/hot_online/index.html?m=" + key;
+     * String url  = SERVER_DOMAIN + "edit-backstage/hot_online/index.html?m=" + key;
+     * m_title:[]
+     * 有值: link = "/edit-backstage/hot_online1/index.html?m=" + key
+     * 无值: link = "/edit-backstage/hot_online/index.html?m=" + key
+     */
+    private String getLink(JSONObject param, String key){
+        JSONObject infoAttribute = param.getJSONObject("infoAttribute");
+        // m_title可能会没有这个属性key, 需要判断
+        JSONArray m_title = infoAttribute.getJSONArray("m_title");
+        String url  = "/edit-backstage/hot_online/index.html#/?m=" + key;
+        if (m_title != null && m_title.size() > 0){
+            url  = "/edit-backstage/hot_online1/index.html#/?m=" + key;
+        }
+        return url;
+    }
+
+    /**
+     * 处理data.js 文件
+     */
+    private void editDataJs(SceneEntity entity, String hots )  {
+
+        // 因为data.js只是热点信息,所以直接创建上传oss
+        JSONObject dataJsJson = new JSONObject();
+        if (hots != null) {
+            dataJsJson = JSONObject.parseObject(hots);
+
+            Set<String> strings = dataJsJson.keySet();
+            for (String key: strings) {
+                JSONObject subJson = dataJsJson.getJSONObject(key);
+                JSONObject infoAttribute = subJson.getJSONObject("infoAttribute");
+                if (infoAttribute != null) {
+                    Set<String> infoKey = infoAttribute.keySet();
+
+                    for (String s: infoKey) {
+                        Object val = null;
+                        // 添加到第一层, 空值不添加
+                        if ("images".equals(s) || "styleImg".equals(s) || "model".equals(s) || "video".equals(s) || "iframe".equals(s)) {
+                            JSONArray jsonArray = infoAttribute.getJSONArray(s);
+                            if (jsonArray.size() == 0) {
+                                continue;
+                            }
+                            val = jsonArray;
+
+                        } else {
+                            String a = infoAttribute.getString(s);
+                            if (StringUtils.isBlank(a)){
+                                continue;
+                            }
+                            val = a;
+                        }
+
+
+                        subJson.put(s, val);
+                    }
+
+                }
+
+                // 删除infoAttribute
+                subJson.remove("infoAttribute");
+
+            }
+
+        }
+
+        log.info("out data.js : {}", dataJsJson);
+        String basePath = configConstant.serverBasePath + entity.getSceneCode();
+
+        String dataPath = basePath + "/hot/js/data.js";
+        FileUtil.writeUtf8String(dataJsJson.toJSONString(), dataPath);
+
+        log.info("新data.js写入完成: {}", dataPath);
+
+
+    }
+}

+ 42 - 0
gis_service/src/main/java/com/gis/service/impl/SysUserServiceImpl.java

@@ -0,0 +1,42 @@
+package com.gis.service.impl;
+
+import com.gis.domain.dto.PageDateDto;
+import com.gis.domain.po.SysUserEntity;
+import com.gis.mapper.IBaseMapper;
+import com.gis.mapper.SysUserMapper;
+import com.gis.service.SysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:16
+ */
+@Service
+public class SysUserServiceImpl extends IBaseServiceImpl<SysUserEntity, Long> implements SysUserService {
+
+    @Autowired
+    private SysUserMapper entityMapper;
+
+    @Override
+    public IBaseMapper<SysUserEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+    @Override
+    public SysUserEntity findByUserName(String userName) {
+        return entityMapper.findByUserName(userName);
+    }
+
+
+
+    @Override
+    public List<SysUserEntity> search(PageDateDto param) {
+        return entityMapper.search(param);
+    }
+
+
+
+}

+ 100 - 0
gis_service/src/main/java/com/gis/service/impl/WxServiceImpl.java

@@ -0,0 +1,100 @@
+package com.gis.service.impl;
+
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.gis.common.constant.ConfigConstant;
+import com.gis.common.constant.TypeCode;
+import com.gis.common.util.JwtUtil;
+import com.gis.common.util.Result;
+import com.gis.service.WxService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:16
+ */
+@Slf4j
+@Service
+public class WxServiceImpl implements WxService {
+
+
+    @Autowired
+    ConfigConstant configConstant;
+
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    @Autowired
+    protected HttpServletRequest request;
+
+    private static Integer TOKEN_EXPIRE = 1000 * 60 * 60 * 24;
+
+
+    @Override
+    public Result login(String code) {
+
+
+        StringBuffer param = new StringBuffer();
+        //GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
+        param.append("https://api.weixin.qq.com/sns/jscode2session?");
+        param.append("appid=").append(configConstant.wxAppId);
+        param.append("&secret=").append(configConstant.wxAppSecret);
+        param.append("&js_code=").append(code);
+        param.append("&grant_type=").append("authorization_code");
+
+        String s = HttpUtil.get(param.toString());
+        log.info("s: {}", s);
+        JSONObject result = JSONObject.parseObject(s);
+        String openid = result.getString("openid");
+        if (openid == null) {
+            log.info("登录失败");
+            return Result.failure(result.toJSONString());
+        }
+
+        // 封装openid、session_key 到token
+        /**
+         * openid: id
+         * session_key: userName
+         */
+
+        // 创建新token
+        HashMap<String, Object> tokenMap = new HashMap<>();
+        tokenMap.put("sessionKey", result.getString("session_key"));
+        tokenMap.put("openId", openid);
+
+        // 创建新token
+        String wxToken = JwtUtil.createWxJWT(TOKEN_EXPIRE, tokenMap);
+        log.info("wxToken: {}", wxToken);
+        // wxToken存到Redis
+        // 更新到 redis, 有效期24h, 旧token无效, 做单用户登录
+        redisTemplate.opsForValue().set(TypeCode.REDIS_LOGIN_WXTOKEN + wxToken, wxToken, Long.parseLong("23"), TimeUnit.HOURS);
+
+        // 应该要把openId给回前端
+        HashMap<Object, Object> res = new HashMap<>();
+        res.put("wxToken", wxToken);
+        res.put("openId", openid);
+
+        return Result.success(wxToken);
+    }
+
+    @Override
+    public Result logout() {
+        String token = getWxToken();
+        if (token == null) {
+            log.info("token is null");
+        }
+        redisTemplate.delete(TypeCode.REDIS_LOGIN_WXTOKEN + token);
+        return Result.success();
+    }
+
+    String getWxToken(){
+        return request.getHeader("wXToken");
+    }
+}

+ 135 - 0
gis_service/src/main/java/com/gis/service/shiro/JWTFilter.java

@@ -0,0 +1,135 @@
+package com.gis.service.shiro;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gis.common.exception.JwtAuthenticationException;
+import lombok.extern.log4j.Log4j2;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+
+/**
+ * 自定义拦截规则
+ */
+@Log4j2
+public class JWTFilter extends BasicHttpAuthenticationFilter {
+
+    /**
+     * 执行登录验证
+     */
+    @Override
+    protected boolean executeLogin(ServletRequest request, ServletResponse response) {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        String authorization = httpServletRequest.getHeader("token");
+        JWTToken token = new JWTToken(authorization);
+
+        // 提交给realm进行登入,如果错误他会抛出异常并被捕获
+        getSubject(request, response).login(token);
+
+        // 如果没有抛出异常则代表登入成功,返回true
+        return true;
+    }
+
+    /**
+     * 这里我们详细说明下为什么最终返回的都是true,即允许访问
+     * 例如我们提供一个地址 GET /article
+     * 登入用户和游客看到的内容是不同的
+     * 如果在这里返回了false,请求会被直接拦截,用户看不到任何东西
+     * 所以我们在这里返回true,Controller中可以通过 subject.isAuthenticated() 来判断用户是否登入
+     * 如果有些资源只有登入用户才能访问,我们只需要在方法上面加上 @RequiresAuthentication 注解即可
+     * 但是这样做有一个缺点,就是不能够对GET,POST等请求进行分别过滤鉴权(因为我们重写了官方的方法),但实际上对应用影响不大
+     *
+     * owen:
+     *  return false ,表示全局拦截,必须登录才可以访问接口,除非配置了免拦截
+     *  "" @RequiresAuthentication 现在不需要配置这个注解来免登录
+     *
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+        try {
+            executeLogin(request, response);
+        } catch (Exception e) {
+            /**
+             * 这个异常需要自己写,全局捕获不了
+             * 认证出现异常,传递错误信息msg
+             */
+            exceptionMsg(e, response);
+        }
+        // return false 前端没有响应,接收不到异常
+        return true;
+
+
+    }
+
+    /**
+     * 对跨域提供支持
+     * 只对需要token验证的有效,不需要验证的还是需要用注解处理一下
+     *
+     */
+    @Override
+    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+        httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
+        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
+        httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
+        // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态
+        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
+            httpServletResponse.setStatus(HttpStatus.OK.value());
+            return false;
+        }
+        return super.preHandle(request, response);
+    }
+
+
+    /**
+     * 无需转发,直接返回Response信息
+     *
+     */
+    private void writeResponse(ServletResponse response, JSONObject msg) {
+        response.setCharacterEncoding("UTF-8");
+        response.setContentType("application/json; charset=utf-8");
+        ServletOutputStream outputStream = null;
+        try {
+            outputStream = response.getOutputStream();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        assert outputStream != null;
+        PrintWriter printWriter = new PrintWriter(outputStream, true);
+        printWriter.write(msg.toString());//直接将json输出到页面
+        printWriter.flush();
+        printWriter.close();
+
+    }
+
+    /**
+     * 封装异常信息
+     */
+    private void exceptionMsg(Exception e, ServletResponse response) {
+        // 认证出现异常,传递错误信息msg
+        String msg = e.getMessage();
+        // 获取应用异常(该Cause是导致抛出此throwable(异常)的throwable(异常))
+        Throwable throwable = e.getCause();
+        JSONObject jsonObject = new JSONObject();
+        if (throwable instanceof JwtAuthenticationException) {
+            jsonObject.put("code", ((JwtAuthenticationException) throwable).getCode());
+            jsonObject.put("msg", ((JwtAuthenticationException) throwable).getMsg());
+        } else {
+            log.error(msg);
+            jsonObject.put("code", 5002);
+            jsonObject.put("msg", "token invalid");
+        }
+        // 直接返回Response信息
+        this.writeResponse(response, jsonObject);
+
+    }
+}

+ 23 - 0
gis_service/src/main/java/com/gis/service/shiro/JWTToken.java

@@ -0,0 +1,23 @@
+package com.gis.service.shiro;
+
+import org.apache.shiro.authc.AuthenticationToken;
+
+public class JWTToken implements AuthenticationToken {
+
+    // 密钥
+    private String token;
+
+    public JWTToken(String token) {
+        this.token = token;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return token;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return token;
+    }
+}

+ 110 - 0
gis_service/src/main/java/com/gis/service/shiro/MyRealm.java

@@ -0,0 +1,110 @@
+package com.gis.service.shiro;
+
+import com.gis.common.constant.TypeCode;
+import com.gis.common.exception.JwtAuthenticationException;
+import com.gis.common.util.JwtUtil;
+import com.gis.domain.po.SysUserEntity;
+import com.gis.service.SysUserService;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+/**
+ * 配置不校验的话,是不会走这个方法的
+ */
+@Log4j2
+@Service
+public class MyRealm extends AuthorizingRealm {
+
+
+
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    @Autowired
+    private SysUserService userService;
+
+
+    /**
+     * 大坑!,必须重写此方法,不然Shiro会报错
+     */
+    @Override
+    public boolean supports(AuthenticationToken token) {
+        return token instanceof JWTToken;
+    }
+
+
+
+
+    /**
+     * 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的
+     *
+     * principals: 是token
+     */
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+        String username = JwtUtil.getUsername(principals.toString());
+
+        SysUserEntity dbUserEntity = userService.findByUserName(username);
+
+        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
+
+        simpleAuthorizationInfo.addRole(dbUserEntity.getRole());
+        return simpleAuthorizationInfo;
+    }
+
+
+    /**
+     * 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。
+     */
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
+        String token = (String) auth.getCredentials();
+
+        if (StringUtils.isBlank(token)) {
+            log.error("oken is null ");
+            throw new JwtAuthenticationException(5001, "header token is null");
+        }
+
+
+        // 解密获得username,用于和数据库进行对比
+        String username = JwtUtil.getUsername(token);
+        if (username == null) {
+            log.error("error token username");
+            throw new JwtAuthenticationException(5001, "token invalid");
+        }
+
+        SysUserEntity userEntity = userService.findByUserName(username);
+        if (userEntity == null) {
+            log.error("error token userEntity");
+            throw new JwtAuthenticationException(5001, "User didn't existed!");
+        }
+
+        // 校验请求token是否跟redis token一致
+        String redisToken = redisTemplate.opsForValue().get(TypeCode.REDIS_LOGIN_TOKEN + token);
+
+        if (!token.equals(redisToken)) {
+            log.error("redis token is null");
+            throw new JwtAuthenticationException(5001, "redis token is null");
+
+        }
+
+
+        if (! JwtUtil.isVerify(token, username)) {
+            log.error("error token username or password");
+            throw new JwtAuthenticationException(5001, "token invalid");
+        }
+
+        return new SimpleAuthenticationInfo(token, token, "my_realm");
+    }
+}

+ 114 - 0
gis_service/src/main/java/com/gis/service/shiro/ShiroConfig.java

@@ -0,0 +1,114 @@
+package com.gis.service.shiro;
+
+import lombok.extern.log4j.Log4j2;
+import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
+import org.apache.shiro.mgt.DefaultSubjectDAO;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+
+import javax.servlet.Filter;
+import java.util.HashMap;
+import java.util.Map;
+
+@Log4j2
+@Configuration
+public class ShiroConfig {
+
+    @Bean("securityManager")
+    public DefaultWebSecurityManager getManager(MyRealm realm) {
+        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
+        // 使用自己的realm
+        manager.setRealm(realm);
+
+        /*
+         * 关闭shiro自带的session,详情见文档
+         * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
+         */
+        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
+        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
+        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
+        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
+        manager.setSubjectDAO(subjectDAO);
+
+        return manager;
+    }
+
+    @Bean("shiroFilter")
+    public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
+        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
+
+        // 添加自己的过滤器并且取名为jwt
+        Map<String, Filter> filterMap = new HashMap<>();
+        filterMap.put("jwt", new JWTFilter());
+
+
+
+
+        factoryBean.setFilters(filterMap);
+
+        factoryBean.setSecurityManager(securityManager);
+        factoryBean.setUnauthorizedUrl("/401");
+
+        /*
+         * 自定义url规则
+         * http://shiro.apache.org/web.html#urls-
+         */
+        Map<String, String> filterRuleMap = new HashMap<>();
+
+        // 不拦截
+        filterRuleMap.put("/login", "anon");
+        filterRuleMap.put("/logout", "anon");
+        filterRuleMap.put("/admin", "anon");
+        filterRuleMap.put("/admin/login", "anon");
+        filterRuleMap.put("/test/**", "anon");
+
+
+        // swagger 不拦截
+        filterRuleMap.put("/swagger-resources/**", "anon");
+        filterRuleMap.put("/webjars/**", "anon");
+        filterRuleMap.put("/v2/**", "anon");
+        filterRuleMap.put("/swagger-ui.html/**", "anon");
+
+
+        // 所有请求通过我们自己的JWT Filter
+        filterRuleMap.put("/manage/**", "jwt");
+
+
+        // 访问401和404页面不通过我们的Filter
+        filterRuleMap.put("/401", "anon");
+        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
+        return factoryBean;
+    }
+
+    /**
+     * 下面的代码是添加注解支持
+     */
+    @Bean
+    @DependsOn("lifecycleBeanPostProcessor")
+    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+        // 强制使用cglib,防止重复代理和可能引起代理出错的问题
+        // https://zhuanlan.zhihu.com/p/29161098
+        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
+        return defaultAdvisorAutoProxyCreator;
+    }
+
+    @Bean
+    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+        return new LifecycleBeanPostProcessor();
+    }
+
+    @Bean
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
+        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+        advisor.setSecurityManager(securityManager);
+        return advisor;
+    }
+
+}

+ 23 - 0
gis_web/pom.xml

@@ -0,0 +1,23 @@
+<?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">
+    <parent>
+        <artifactId>wx_reload_beijing</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gis_web</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_service</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 120 - 0
gis_web/src/main/java/com/gis/web/controller/BaseController.java

@@ -0,0 +1,120 @@
+package com.gis.web.controller;
+
+import cn.hutool.core.io.FileUtil;
+import com.gis.common.constant.ConfigConstant;
+
+import com.gis.common.util.JwtUtil;
+import com.gis.service.SysUserService;
+import com.github.pagehelper.PageHelper;
+
+import com.gis.domain.dto.PageDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Created by owen on 2020/2/20 0020 15:20
+ */
+@Log4j2
+public class BaseController {
+
+    @Autowired
+    protected HttpServletRequest request;
+
+    @Autowired
+    public SysUserService sysUserService;
+
+
+
+
+
+    @Autowired
+    ConfigConstant configConstant;
+
+
+
+    // 目前是24h
+    public static Integer TOKEN_EXPIRE = 1000 * 60 * 60 * 24;
+
+
+
+    /** 获取用户名*/
+    String getTokenUserName(){
+        String token = getToken();
+        return JwtUtil.getUsername(token);
+    }
+
+    /** 获取用户id*/
+    Long getTokenUserId(){
+        return JwtUtil.getUserId(getToken());
+    }
+
+
+
+    /** 获取header token */
+    String getToken(){
+        return request.getHeader("token");
+    }
+
+
+
+
+    /**
+     * 设置请求分页数据
+     */
+    void startPage(PageDto param){
+        Integer pageNum = param.getPageNum();
+        Integer pageSize = param.getPageSize();
+        if (pageNum == null || pageNum <= 0) {
+            pageNum = 1;
+        }
+
+        if (pageSize == null || pageSize <= 0) {
+            pageSize = 10;
+        }
+
+        PageHelper.startPage(pageNum, pageSize);
+
+    }
+
+
+
+    /**
+     * 截取文件路径
+     * @param path
+     * @return 物理位置
+     */
+    public String subStringAfter(String path){
+        log.info("input param: {}", path);
+        if (StringUtils.isNotBlank(path)) {
+            String s = StringUtils.substringAfter(path, "/data/");
+            s = configConstant.serverBasePath + s;
+            log.info("filePath: {}", s);
+            return s;
+        }
+        return null;
+
+    }
+
+    /**
+     * FileUtil.del:删除空字符串会造成linux环境的Tomcat.lib删除
+     * 删除
+     * @param path
+     */
+    public void deleteFile(String path){
+        String filePath = subStringAfter(path);
+        if (FileUtil.isFile(filePath)) {
+            log.info("执行删除: {}", filePath);
+            FileUtil.del(filePath);
+            log.info("删除成功: {}", filePath);
+        }
+    }
+
+
+
+
+
+
+}

+ 129 - 0
gis_web/src/main/java/com/gis/web/controller/ExceptionController.java

@@ -0,0 +1,129 @@
+package com.gis.web.controller;
+
+import com.gis.common.exception.BaseRuntimeException;
+import com.gis.common.util.Result;
+import lombok.extern.log4j.Log4j2;
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+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 org.springframework.web.servlet.NoHandlerFoundException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+
+/**
+ * 统一捕捉异常,自定义返回参数
+ * 这里只可以捕获controller层的异常。
+ */
+@Log4j2
+@RestControllerAdvice
+public class ExceptionController {
+
+    // 捕捉shiro的异常
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ExceptionHandler(ShiroException.class)
+    public Result handle401(ShiroException e) {
+//        return Result.failure(5001, e.getMessage());
+        log.error("没有授权1");
+        return Result.failure(5001, "没有授权");
+    }
+
+
+
+    /**
+     * 捕捉UnauthorizedException
+     *
+     * 权限不够,会抛这个异常
+     */
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ExceptionHandler(UnauthorizedException.class)
+    public Result handle401() {
+        log.error("没有权限");
+        return Result.failure(5003, "没有权限");
+    }
+
+    // 捕捉其他所有异常
+    @ExceptionHandler(Exception.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public Result globalException(HttpServletRequest request, Throwable ex) {
+        log.error(ex);
+        return Result.failure(getStatus(request).value(), ex.getMessage());
+    }
+
+
+    private HttpStatus getStatus(HttpServletRequest request) {
+        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
+        if (statusCode == null) {
+            return HttpStatus.INTERNAL_SERVER_ERROR;
+        }
+        return HttpStatus.valueOf(statusCode);
+    }
+
+    @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());
+        return Result.failure(e.getCode(), e.getMsg());
+    }
+
+    /**
+     * 方法参数校验
+     *
+     * 注解验证异常
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+        return Result.failure(60001, e.getBindingResult().getFieldError().getDefaultMessage());
+    }
+
+    /**
+     * ValidationException
+     */
+    @ExceptionHandler(ValidationException.class)
+    public Result handleValidationException(ValidationException e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60002, e.getCause().getMessage());
+    }
+
+    /**
+     * ConstraintViolationException
+     */
+    @ExceptionHandler(ConstraintViolationException.class)
+    public Result handleConstraintViolationException(ConstraintViolationException e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60003, e.getMessage());
+    }
+
+    @ExceptionHandler(NoHandlerFoundException.class)
+    public Result handlerNoFoundException(Exception e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60004, "路径不存在,请检查路径是否正确");
+    }
+
+    /**
+     * 防止表单重复提交
+     * 需要结合数据库某个字段设置唯一字段使用
+     *
+     * 例如userName
+     *
+     * 也可以结合redis使用
+     */
+    @ExceptionHandler(DuplicateKeyException.class)
+    public Result handleDuplicateKeyException(DuplicateKeyException e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60005, "数据重复,请检查后提交: " + e.getMessage());
+    }
+
+
+
+}
+

+ 46 - 0
gis_web/src/main/java/com/gis/web/controller/WxLoginController.java

@@ -0,0 +1,46 @@
+package com.gis.web.controller;
+
+import com.gis.common.util.Result;
+import com.gis.service.WxService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+
+/**
+ * Created by owen on 2020/4/22 0029 15:42
+ */
+@Log4j2
+@Api(tags = "wx登录")
+@RestController
+@RequestMapping("api/wx")
+public class WxLoginController extends BaseController {
+
+
+    @Autowired
+    WxService wxService;
+
+
+    @ApiOperation("微信登录")
+    @GetMapping("login/{code}")
+    public Result login(@PathVariable String code)  {
+        return wxService.login(code);
+    }
+
+
+    @ApiOperation("微信退出")
+    @GetMapping("logout")
+    public Result logout() {
+        return wxService.logout();
+    }
+
+
+
+
+}

+ 45 - 0
gis_web/src/test/java/com/gis/web/controller/SceneControllerTest.java

@@ -0,0 +1,45 @@
+package com.gis.web.controller;
+
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.ReUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.pinyin.PinyinEngine;
+import cn.hutool.extra.pinyin.PinyinUtil;
+import org.junit.Test;
+
+
+/**
+ * Created by owen on 2020/8/4 0004 18:02
+ */
+public class SceneControllerTest {
+
+    @Test
+    public void testChinese(){
+        String path = "xxxxxxxsssss.jpg";
+        boolean b = Validator.hasChinese(path);
+        System.out.println(b);
+    }
+
+
+    /**
+     * 测试中文转拼音
+     */
+    @Test
+    public void testPingYin(){
+        String path1 = "室外展板01";
+        String path2 = "室外展板02.jpg";
+        String path3 = "室外展板nnn02AAA.jpg";
+//        PinyinEngine engine = PinyinUtil.getEngine();
+        System.out.println(PinyinUtil.getPinyin(path1));
+
+        System.out.println(PinyinUtil.getPinyin(path2));
+        System.out.println(PinyinUtil.getPinyin(path3,""));
+
+    }
+
+
+    public static void main(String[] args) {
+        String path1 = "室外展板";
+        System.out.println(PinyinUtil.getPinyin(path1));
+    }
+}

+ 252 - 0
pom.xml

@@ -0,0 +1,252 @@
+<?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>
+
+    <!-- museum parent-->
+    <groupId>com.gis</groupId>
+    <artifactId>wx_reload_beijing</artifactId>
+    <packaging>pom</packaging>
+    <version>1.0.0</version>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.1.0.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <modules>
+        <module>gis_common</module>
+        <module>gis_web</module>
+        <module>gis_domain</module>
+        <module>gis_service</module>
+        <module>gis_mapper</module>
+        <module>gis_application</module>
+    </modules>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <spring.boot.version>2.1.0.RELEASE</spring.boot.version>
+        <gis.version>1.0.0</gis.version>
+        <druid.version>1.1.14</druid.version>
+        <hutool.version>5.3.3</hutool.version>
+        <httpclient.version>4.5.12</httpclient.version>
+        <lombok.version>1.18.2</lombok.version>
+        <fastjson.version>1.2.51</fastjson.version>
+        <lang3.version>3.7</lang3.version>
+        <knife4j.version>2.0.2</knife4j.version>
+        <mysql.version>8.0.15</mysql.version>
+        <shiro.version>1.4.0</shiro.version>
+        <jwt.version>3.2.0</jwt.version>
+        <jjwt.version>0.6.0</jjwt.version>
+        <aliyun.core.version>4.0.3</aliyun.core.version>
+        <aliyun.dysmsapi.version>1.1.0</aliyun.dysmsapi.version>
+        <aliyun.oss.version>2.5.0</aliyun.oss.version>
+        <tk.mybatis.version>2.0.2</tk.mybatis.version>
+        <tk.mapper.version>4.0.3</tk.mapper.version>
+        <pagehelper.version>1.2.5</pagehelper.version>
+
+    </properties>
+
+
+    <!--dependencyManagement用于管理依赖版本号, 必须写版本号,不然依赖不上-->
+    <dependencyManagement>
+        <dependencies>
+            <!--模块版本管理-->
+
+            <dependency>
+                <groupId>com.gis</groupId>
+                <artifactId>gis_application</artifactId>
+                <version>${gis.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.gis</groupId>
+                <artifactId>gis_common</artifactId>
+                <version>${gis.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.gis</groupId>
+                <artifactId>gis_domain</artifactId>
+                <version>${gis.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.gis</groupId>
+                <artifactId>gis_service</artifactId>
+                <version>${gis.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.gis</groupId>
+                <artifactId>gis_mapper</artifactId>
+                <version>${gis.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.gis</groupId>
+                <artifactId>gis_web</artifactId>
+                <version>${gis.version}</version>
+            </dependency>
+
+
+            <!-- springboot -->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-data-jpa</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-web</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-test</artifactId>
+                <scope>test</scope>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <!--springboot中的redis依赖-->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-data-redis</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+
+            <!-- lombok -->
+            <dependency>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok</artifactId>
+                <version>${lombok.version}</version>
+            </dependency>
+
+            <!-- fastjson -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+
+            <!--阿里数据库连接池 -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid-spring-boot-starter</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+
+            <!-- mysql -->
+            <dependency>
+                <groupId>mysql</groupId>
+                <artifactId>mysql-connector-java</artifactId>
+                <version>${mysql.version}</version>
+            </dependency>
+
+            <!-- 工具类 -->
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-all</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <!-- StringUtils -->
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-lang3</artifactId>
+                <version>${lang3.version}</version>
+            </dependency>
+
+            <!-- knife4j aip 包-->
+            <dependency>
+                <groupId>com.github.xiaoymin</groupId>
+                <artifactId>knife4j-spring-boot-starter</artifactId>
+                <version>${knife4j.version}</version>
+            </dependency>
+
+            <!-- shiro -->
+            <dependency>
+                <groupId>org.apache.shiro</groupId>
+                <artifactId>shiro-spring</artifactId>
+                <version>${shiro.version}</version>
+            </dependency>
+
+
+            <!-- jwt -->
+            <dependency>
+                <groupId>com.auth0</groupId>
+                <artifactId>java-jwt</artifactId>
+                <version>${jwt.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>io.jsonwebtoken</groupId>
+                <artifactId>jjwt</artifactId>
+                <version>${jjwt.version}</version>
+            </dependency>
+
+            <!--aliyun sdk-->
+            <!--<dependency>-->
+                <!--<groupId>com.aliyun</groupId>-->
+                <!--<artifactId>aliyun-java-sdk-core</artifactId>-->
+                <!--<version>${aliyun.core.version}</version>-->
+            <!--</dependency>-->
+
+            <!--<dependency>-->
+                <!--<groupId>com.aliyun</groupId>-->
+                <!--<artifactId>aliyun-java-sdk-dysmsapi</artifactId>-->
+                <!--<version>${aliyun.dysmsapi.version}</version>-->
+            <!--</dependency>-->
+
+            <!--&lt;!&ndash;aliyun oss&ndash;&gt;-->
+            <!--<dependency>-->
+                <!--<groupId>com.aliyun.oss</groupId>-->
+                <!--<artifactId>aliyun-sdk-oss</artifactId>-->
+                <!--<version>${aliyun.oss.version}</version>-->
+            <!--</dependency>-->
+
+
+            <!--tk.mybatis 依赖-->
+            <dependency>
+                <groupId>tk.mybatis</groupId>
+                <artifactId>mapper-spring-boot-starter</artifactId>
+                <version>${tk.mybatis.version}</version>
+                <!-- tk.mybatis 跟springboot jap 包冲突-->
+                <exclusions>
+                    <exclusion>
+                        <groupId>javax.persistence</groupId>
+                        <artifactId>persistence-api</artifactId>
+                    </exclusion>
+                </exclusions>
+
+            </dependency>
+
+
+            <!--分页插件-->
+            <dependency>
+                <groupId>com.github.pagehelper</groupId>
+                <artifactId>pagehelper-spring-boot-starter</artifactId>
+                <version>${pagehelper.version}</version>
+            </dependency>
+
+
+            <!-- httpclient -->
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpclient</artifactId>
+                <version>${httpclient.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+
+</project>