andyliu 1 год назад
Сommit
8bd34e1744
100 измененных файлов с 6802 добавлено и 0 удалено
  1. 32 0
      .gitignore
  2. BIN
      .mvn/wrapper/maven-wrapper.jar
  3. 2 0
      .mvn/wrapper/maven-wrapper.properties
  4. BIN
      libs/gbase.1.0.2.jar
  5. 329 0
      pom.xml
  6. 43 0
      sql.properties
  7. 133 0
      src/main/java/com/shkpr/service/aimodelpower/AimodelpowerApplication.java
  8. 52 0
      src/main/java/com/shkpr/service/aimodelpower/SpringContextUtil.java
  9. 55 0
      src/main/java/com/shkpr/service/aimodelpower/busihandler/ZoneInfoDataHelper.java
  10. 819 0
      src/main/java/com/shkpr/service/aimodelpower/commtools/BytesUtils.java
  11. 483 0
      src/main/java/com/shkpr/service/aimodelpower/commtools/CommTool.java
  12. 260 0
      src/main/java/com/shkpr/service/aimodelpower/commtools/ExcelUtils.java
  13. 157 0
      src/main/java/com/shkpr/service/aimodelpower/commtools/HttpTool.java
  14. 569 0
      src/main/java/com/shkpr/service/aimodelpower/commtools/TimeTool.java
  15. 16 0
      src/main/java/com/shkpr/service/aimodelpower/components/TrimStringField.java
  16. 83 0
      src/main/java/com/shkpr/service/aimodelpower/components/locks/BaseLockMgr.java
  17. 134 0
      src/main/java/com/shkpr/service/aimodelpower/components/locks/CountDownLatchEx.java
  18. 26 0
      src/main/java/com/shkpr/service/aimodelpower/components/validators/IntInitOrRange.java
  19. 30 0
      src/main/java/com/shkpr/service/aimodelpower/components/validators/IntInitOrRangeV.java
  20. 25 0
      src/main/java/com/shkpr/service/aimodelpower/components/validators/ListNullOrSize.java
  21. 26 0
      src/main/java/com/shkpr/service/aimodelpower/components/validators/ListNullOrSizeV.java
  22. 25 0
      src/main/java/com/shkpr/service/aimodelpower/components/validators/StrNullOrSize.java
  23. 25 0
      src/main/java/com/shkpr/service/aimodelpower/components/validators/StrNullOrSizeV.java
  24. 22 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/CaffeineConfiguration.java
  25. 60 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/DBMgrConfiguration.java
  26. 69 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/GlobalParamConfiguration.java
  27. 117 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/MainSourceConfiguration.java
  28. 35 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/RestTemplateConfig.java
  29. 45 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/RetryTemplateConfig.java
  30. 77 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/ScheduleTaskConfiguration.java
  31. 116 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/SecondSourceConfiguration.java
  32. 45 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/TaskQueueConfiguration.java
  33. 53 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/ValidatorConfiguration.java
  34. 96 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/WebMvcConfiguration.java
  35. 71 0
      src/main/java/com/shkpr/service/aimodelpower/configuration/WebSecurityConfiguration.java
  36. 116 0
      src/main/java/com/shkpr/service/aimodelpower/constants/ApiURI.java
  37. 10 0
      src/main/java/com/shkpr/service/aimodelpower/constants/CacheHandleType.java
  38. 13 0
      src/main/java/com/shkpr/service/aimodelpower/constants/CommDefine.java
  39. 16 0
      src/main/java/com/shkpr/service/aimodelpower/constants/CommFieldStatus.java
  40. 12 0
      src/main/java/com/shkpr/service/aimodelpower/constants/DispatchAnalysisResultNote.java
  41. 16 0
      src/main/java/com/shkpr/service/aimodelpower/constants/DispatchFrequency.java
  42. 8 0
      src/main/java/com/shkpr/service/aimodelpower/constants/DispatchPointType.java
  43. 9 0
      src/main/java/com/shkpr/service/aimodelpower/constants/DispatchSource.java
  44. 11 0
      src/main/java/com/shkpr/service/aimodelpower/constants/FaultExtendType.java
  45. 13 0
      src/main/java/com/shkpr/service/aimodelpower/constants/FaultOrderStatus.java
  46. 10 0
      src/main/java/com/shkpr/service/aimodelpower/constants/LinkMode.java
  47. 162 0
      src/main/java/com/shkpr/service/aimodelpower/constants/LogFlagBusiType.java
  48. 17 0
      src/main/java/com/shkpr/service/aimodelpower/constants/MsgNotifyDefine.java
  49. 9 0
      src/main/java/com/shkpr/service/aimodelpower/constants/SampleCompareResult.java
  50. 29 0
      src/main/java/com/shkpr/service/aimodelpower/constants/SampleFieldDefine.java
  51. 21 0
      src/main/java/com/shkpr/service/aimodelpower/constants/TDKind.java
  52. 27 0
      src/main/java/com/shkpr/service/aimodelpower/constants/TaskQueueDataTypeEx.java
  53. 37 0
      src/main/java/com/shkpr/service/aimodelpower/constants/UrlMethodType.java
  54. 17 0
      src/main/java/com/shkpr/service/aimodelpower/constants/UserCurStateType.java
  55. 7 0
      src/main/java/com/shkpr/service/aimodelpower/constants/UserFlagType.java
  56. 57 0
      src/main/java/com/shkpr/service/aimodelpower/controllerapi/ThirdBaseController.java
  57. 66 0
      src/main/java/com/shkpr/service/aimodelpower/controllerapi/ThirdFilesTransController.java
  58. 81 0
      src/main/java/com/shkpr/service/aimodelpower/controllerapi/ThirdInternalController.java
  59. 176 0
      src/main/java/com/shkpr/service/aimodelpower/controllercheck/JWTControllerCheck.java
  60. 27 0
      src/main/java/com/shkpr/service/aimodelpower/controllercheck/ThirdCommReportFormCheck.java
  61. 28 0
      src/main/java/com/shkpr/service/aimodelpower/controllercheck/ThirdCostomXXXControllerCheck.java
  62. 32 0
      src/main/java/com/shkpr/service/aimodelpower/controllercheck/ThirdTaskFilesControllerCheck.java
  63. 25 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/CustomAuthenticationProvider.java
  64. 88 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/GrantedAuthorityImpl.java
  65. 126 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/JWTAuthenticationFilter.java
  66. 392 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/TokenAuthenticationService.java
  67. 72 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTBusiFilterMgr.java
  68. 45 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTCommReportFormFilter.java
  69. 46 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTCustomXXXFilter.java
  70. 46 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTTaskFilesBusiFilter.java
  71. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidAccept.java
  72. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidAddNote.java
  73. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidCheck.java
  74. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidClose.java
  75. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidDeal.java
  76. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidDel.java
  77. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidList.java
  78. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidNew.java
  79. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidRefuse.java
  80. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidResend.java
  81. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidReset.java
  82. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidSK.java
  83. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidSS.java
  84. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidTurn.java
  85. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidUrge.java
  86. 4 0
      src/main/java/com/shkpr/service/aimodelpower/controllervalid/OrderParamValidTotal.java
  87. 56 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/DBMgrProxy.java
  88. 14 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/FileAttachmentMapper.java
  89. 45 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/PartitionInfoMapper.java
  90. 45 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/RoleInfoMapper.java
  91. 24 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/RolePowerMapper.java
  92. 92 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/TestGeomInfoMapper.java
  93. 63 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/TypeDefineMapper.java
  94. 20 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/UserMapper.java
  95. 67 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper2th/PatrolObjectAttMapper.java
  96. 48 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/AbstractGeometryTypeHandlerPg.java
  97. 41 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/BoolTypeHandlerPg.java
  98. 54 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/DateTypeHandlerPg.java
  99. 172 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/GisPointTypeHandlePg.java
  100. 0 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/JSONTypeHandlerPg.java

+ 32 - 0
.gitignore

@@ -0,0 +1,32 @@
+target/
+trilog/
+upload/
+download/
+.idea/
+.idea/inspectionProfiles/
+.idea/libraries/
+*.bak
+### !.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+### *.iml
+*.ipr
+*.iml
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/

BIN
.mvn/wrapper/maven-wrapper.jar


+ 2 - 0
.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

BIN
libs/gbase.1.0.2.jar


+ 329 - 0
pom.xml

@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.1.3.RELEASE</version>
+		<relativePath/> <!-- lookup parent from repository -->
+	</parent>
+
+	<groupId>com.shkpr.service</groupId>
+	<artifactId>aimodelpower</artifactId>
+	<version>1.0.0</version>
+	<name>aimodelpower</name>
+	<description>Demo project for Spring Boot</description>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>1.8</java.version>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<fasterxml.version>2.9.5</fasterxml.version><!-- 2.8.11.2 -->
+		<fastercore.version>2.9.5</fastercore.version>
+		<fasterannot.version>2.9.5</fasterannot.version>
+	</properties>
+
+	<!--工具包jar版本不一致,解决方案,以下配置促使本应用工程中的相应jar强制使用规定版本-->
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>com.fasterxml.jackson.core</groupId>
+				<artifactId>jackson-databind</artifactId>
+				<version>${fasterxml.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.fasterxml.jackson.core</groupId>
+				<artifactId>jackson-core</artifactId>
+				<version>${fastercore.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>com.fasterxml.jackson.core</groupId>
+				<artifactId>jackson-annotations</artifactId>
+				<version>${fasterannot.version}</version>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<exclusions>
+				<exclusion>
+					<groupId>ch.qos.logback</groupId>
+					<artifactId>logback-classic</artifactId>
+				</exclusion>
+				<!--排除默认的tomcat-jdbc-->
+				<exclusion>
+					<groupId>org.apache.tomcat</groupId>
+					<artifactId>tomcat-jdbc</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<dependency>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+			<version>2.0.1</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-jdbc</artifactId>
+			<version>2.1.3.RELEASE</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.postgresql</groupId>
+			<artifactId>postgresql</artifactId>
+			<version>42.2.5</version>
+			<!--<scope>runtime</scope>-->
+		</dependency>
+
+		<!-- spring-security 和 jwt -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-security</artifactId>
+			<version>2.1.3.RELEASE</version>
+		</dependency>
+
+		<!-- 整合redis -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+			<version>2.1.3.RELEASE</version>
+		</dependency>
+
+		<!-- spring-mvc -->
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-webmvc</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>javax.validation</groupId>
+			<artifactId>validation-api</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-validator</artifactId>
+			<version>6.0.14.Final</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.json</groupId>
+			<artifactId>json</artifactId>
+			<version>20180813</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>fastjson</artifactId>
+			<version>1.2.47</version>
+		</dependency>
+
+		<!--Gson-->
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>2.8.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt</artifactId>
+			<version>0.9.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+			<version>1.7.25</version>
+		</dependency>
+
+		<dependency>
+			<groupId>ch.qos.logback</groupId>
+			<artifactId>logback-classic</artifactId>
+			<version>1.2.3</version>
+			<exclusions>
+				<exclusion>
+					<groupId>ch.qos.logback</groupId>
+					<artifactId>logback-core</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<dependency>
+			<groupId>ch.qos.logback</groupId>
+			<artifactId>logback-core</artifactId>
+			<version>1.2.3</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+			<version>4.5.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>redis.clients</groupId>
+			<artifactId>jedis</artifactId>
+			<version>2.9.0</version>
+		</dependency>
+
+		<!--caffeine依赖包-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-cache</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>com.github.ben-manes.caffeine</groupId>
+			<artifactId>caffeine</artifactId>
+			<version>2.6.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+			<version>3.5</version>
+		</dependency>
+
+		<!-- Apache Commons Collections -->
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-collections4</artifactId>
+			<version>4.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-thymeleaf</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.retry</groupId>
+			<artifactId>spring-retry</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-aop</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>3.17</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi</artifactId>
+			<version>3.17</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.opencsv</groupId>
+			<artifactId>opencsv</artifactId>
+			<version>4.6</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.github.tobato</groupId>
+			<artifactId>fastdfs-client</artifactId>
+			<version>1.27.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>net.postgis</groupId>
+			<artifactId>postgis-jdbc</artifactId>
+			<version>2.5.0</version>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<!-- 打成jar包的名称 -->
+		<finalName>v1-alam-ai-model-power-as-1.0.0</finalName>
+		<plugins>
+			<!--运用SpringBoot 插件  使用spring-boot-devtools模块的应用,当classpath中的文件有改变时,会自动重启! -->
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<fork>true</fork>
+					<executable>true</executable>
+				</configuration>
+				<executions>
+					<execution>
+						<goals>
+							<goal>build-info</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-resources-plugin</artifactId>
+				<configuration>
+					<encoding>UTF-8</encoding>
+					<!-- 过滤后缀为pem、pfx的证书文件 -->
+					<nonFilteredFileExtensions>
+						<nonFilteredFileExtension>pem</nonFilteredFileExtension>
+						<nonFilteredFileExtension>pfx</nonFilteredFileExtension>
+						<nonFilteredFileExtension>p12</nonFilteredFileExtension>
+					</nonFilteredFileExtensions>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+					<encoding>UTF-8</encoding>
+					<compilerArguments>
+						<extdirs>${project.basedir}/libs</extdirs>
+					</compilerArguments>
+				</configuration>
+			</plugin>
+
+		</plugins>
+		<resources>
+			<resource>
+				<directory>${project.basedir}/libs</directory>
+				<targetPath>BOOT-INF/lib/</targetPath>
+				<includes>
+					<include>**/*.jar</include>
+				</includes>
+			</resource>
+			<!--very important!!! 打包时将 src/main/resources 下的所有配置文件一并打包-->
+			<resource>
+				<directory>src/main/resources</directory>
+				<includes>
+					<include>**/**</include>
+				</includes>
+				<filtering>true</filtering>
+			</resource>
+		</resources>
+	</build>
+
+</project>

+ 43 - 0
sql.properties

@@ -0,0 +1,43 @@
+spring.datasource.data.jdbc-url=jdbc:postgresql_postGIS://119.96.165.176:5432/watersmart?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+spring.datasource.data.username=postgres
+spring.datasource.data.password=kpr.23417.postgres
+spring.datasource.data.driver-class-name=org.postgis.DriverWrapper
+
+
+spring.datasource.data2.jdbc-url=jdbc:postgresql://119.96.165.176:5432/water_smart_central?useSSL=false&useAffectedRows=false&allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8
+spring.datasource.data2.username=postgres
+spring.datasource.data2.password=kpr.23417.postgres
+spring.datasource.data2.driver-class-name=org.postgresql.Driver
+
+
+spring.datasource.data2.max-wait=60000
+spring.datasource.data2.maximum-pool-size=200
+spring.datasource.data2.minimum-idle=1
+spring.datasource.data2.validation-query=SELECT 1
+spring.datasource.data2.connection-test-query=SELECT 1
+spring.datasource.data2.test-on-borrow=false
+spring.datasource.data2.test-on-return=false
+spring.datasource.data2.test-while-idle=true
+spring.datasource.data2.max-lifetime=60000
+spring.datasource.data2.idle-timeout=30000
+spring.datasource.data2.connection-timeout=30000
+# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+spring.datasource.data2.time-between-eviction-runs-millis=60000
+# 配置一个连接在池中最小生存的时间,单位是毫秒
+spring.datasource.data2.minEvictableIdleTimeMillis=300000
+
+spring.datasource.data.max-wait=60000
+spring.datasource.data.maximum-pool-size=200
+spring.datasource.data.minimum-idle=1
+spring.datasource.data.validation-query=SELECT 1
+spring.datasource.data.connection-test-query=SELECT 1
+spring.datasource.data.test-on-borrow=false
+spring.datasource.data.test-on-return=false
+spring.datasource.data.test-while-idle=true
+spring.datasource.data.max-lifetime=120000
+spring.datasource.data.idle-timeout=30000
+spring.datasource.data.connection-timeout=30000
+# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+spring.datasource.data.time-between-eviction-runs-millis=60000
+# 配置一个连接在池中最小生存的时间,单位是毫秒
+spring.datasource.data.minEvictableIdleTimeMillis=300000

+ 133 - 0
src/main/java/com/shkpr/service/aimodelpower/AimodelpowerApplication.java

@@ -0,0 +1,133 @@
+package com.shkpr.service.aimodelpower;
+
+import com.global.base.component.SnowFlakeEx;
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.aimodelpower.constants.LogFlagBusiType;
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import com.shkpr.service.aimodelpower.globalmgr.ThreadTaskMgr;
+import com.shkpr.service.aimodelpower.interfaces.sinks.LogPrintSink;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.AprLifecycleListener;
+import org.apache.coyote.AbstractProtocol;
+import org.apache.coyote.http11.Http11AprProtocol;
+import org.apache.coyote.http11.Http11NioProtocol;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.annotation.PostConstruct;
+
+@EnableTransactionManagement //开启数据库事务
+@SpringBootApplication
+@EnableRetry
+public class AimodelpowerApplication {
+	@Value("${global.server.apr:false}")
+	private boolean mBUseApr = false;
+
+	@Value("${server.port:9001}")
+	private int mNPort;
+
+	@Value("${global.server.id:tri.adbs.v100}")
+	private String mStrServerId;           //本服务的ID
+
+	@Value("${global.machine.index:0}")
+	private int mOwnerMachineIndex;      //本服务所在的部署机器的索引编号
+
+	@Value("${global.service.index:0}")
+	private int mOwnerServiceIndex;     //本服务在部署机器上的服务索引编号
+
+	@Value("${global.max.tomcat.concurrent.request:10000}")
+	private int mNMaxConcurrentRequest; //tomcat同一时刻可接收的第三方最大并发连接数(Java NIO模式下默认是10000)
+
+	@Value("${global.max.tomcat.threads:200}")
+	private int mNMaxThreads;           //tomcat可启动的最大线程数(默认值为200),调优取值[200,1000]
+
+	@Value("${global.max.tomcat.accept.queue:100}")
+	private int mNMaxAcceptCounts;     //tomcat启动的线程数达到最大时,接受排队的请求个数(默认值为100),调优取值[100,400]
+
+	@Value("${global.switch.trace.log:true}")
+	private boolean mBSwitchTraceLog = true; //是否开启基于TraceId的log记录
+
+	public static void main(String[] args) {
+		GlobalData.getInstance().setCpuCores(Runtime.getRuntime().availableProcessors());
+		LogPrintMgr.getInstance().initRes(2, new LogPrintSink());//io型线程池=CPU Core*2;计算型线程池=CPU Core
+		SpringApplication.run(AimodelpowerApplication.class, args);
+	}
+
+	@PostConstruct
+	public void init(){
+		ThreadTaskMgr.initThreadResource();
+		LogPrintMgr.getInstance().setSwitchTraceLog(mBSwitchTraceLog);
+		GlobalData.getInstance().setServerId(mStrServerId);
+		GlobalData.getInstance().setNOwnerMachineIndex(mOwnerMachineIndex);
+		GlobalData.getInstance().setNOwnerServiceIndex(mOwnerServiceIndex);
+		GlobalData.getInstance().setSwitchTraceLog(mBSwitchTraceLog);
+		SnowFlakeEx.init(mOwnerMachineIndex, mOwnerServiceIndex);
+	}
+
+	@Component
+	class GlobalWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
+		@Override
+		public void customize(ConfigurableServletWebServerFactory factory) {
+			TomcatServletWebServerFactory factoryReal = (TomcatServletWebServerFactory)factory;
+			if (mBUseApr){
+				factoryReal.setProtocol("org.apache.coyote.http11.Http11AprProtocol");
+				factoryReal.addContextLifecycleListeners(new AprLifecycleListener());
+			}
+			factoryReal.addConnectorCustomizers(new MyTomcatConnectorCustomizer());
+			factoryReal.setPort(mNPort);
+		}
+	}
+
+	class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer
+	{
+		public void customize(Connector connector)
+		{
+			connector.setEnableLookups(false);
+			if (mBUseApr){
+				Http11AprProtocol protocol = (Http11AprProtocol) connector.getProtocolHandler();
+				initTomcatParam(protocol);
+			}else{
+				Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
+				initTomcatParam(protocol);
+			}
+		}
+
+		private  <T> void initTomcatParam(AbstractProtocol<T> protocol){
+			/*
+			 * application.properties中的参数优先级高于代码设置的参数
+			 * 即代码设置参数后若application.properties中有同名参数,application.properties中的优先生效
+			 * */
+			/**
+			 *Tomcat在MaxThreads和AcceptCount队列设置基础上,对请求连接多做了一层保护,也就是MaxConnections的大小限制。
+			 *当Client端的大量请求过来时,首先进入MaxThreads,MaxThreads满了则进入AcceptCount队列,
+			 *若AcceptCount队列也满了则后续的连接无法进入AcceptCount队列,无法交由工作线程处理,Client将得到connection refused或者connection reset的错误。
+			 *第二层保护就是:在acceptor线程里头进行缓冲,当连接的socket超过MaxConnections的时候,则进行阻塞等待,控制acceptor转给worker线程连接的速度,稍微缓缓,等待worker线程处理响应client。
+			 */
+			protocol.setMaxConnections(mNMaxConcurrentRequest);
+			protocol.setMaxThreads(mNMaxThreads);
+			protocol.setAcceptCount(mNMaxAcceptCounts);
+			protocol.setMinSpareThreads(mNMaxThreads/10);//初始化时创建的线程数
+
+			LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO
+					, LogFlagBusiType.BUSI_INIT.toStrValue(), this.getClass().getSimpleName()
+					, String.format("tomcat pramas:{mode=%s max-threads=%d max-conns=%d accept-counts=%d conn-timeout=%d minSpareThreads=%d} server-id:{%s}"
+							, mBUseApr?"Apr":"Nio"
+							, protocol.getMaxThreads()
+							, protocol.getMaxConnections()
+							, protocol.getAcceptCount()
+							, protocol.getConnectionTimeout()
+							, protocol.getMinSpareThreads()
+							, mStrServerId));
+		}
+	}
+
+}

+ 52 - 0
src/main/java/com/shkpr/service/aimodelpower/SpringContextUtil.java

@@ -0,0 +1,52 @@
+package com.shkpr.service.aimodelpower;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+//@Lazy(false) //true为懒加载,在第一次被引用的时候才会创建;false为Spring容器在启动时会立即创建
+//若要明确指定为懒加载,则必须使用@Lazy(true),否则bean对象默认取值lazy-init="false"即@Lazy(false)
+public class SpringContextUtil implements ApplicationContextAware {
+    //Spring应用上下文环境
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringContextUtil.applicationContext = applicationContext;
+    }
+
+    public static ApplicationContext getApplicationContext(){
+        return applicationContext;
+    }
+
+    public static boolean containsBean(String beanName){
+        return applicationContext.containsBean(beanName);
+    }
+
+    public static boolean isSingleton(String beanName) throws NoSuchBeanDefinitionException {
+        return applicationContext.isSingleton(beanName);
+    }
+
+    public static Class getType(String beanName) throws NoSuchBeanDefinitionException {
+        return applicationContext.getType(beanName);
+    }
+
+    public static String[] getAliases(String beanName) throws NoSuchBeanDefinitionException {
+        return applicationContext.getAliases(beanName);
+    }
+
+    public static Object getBean(String beanName) throws BeansException {
+        return applicationContext.getBean(beanName);
+    }
+
+    public static <T> T getBean(Class<T> className) throws BeansException {
+        return applicationContext.getBean(className);
+    }
+
+    public static <T> T getBean(String beanName, Class<T> className) throws BeansException{
+        return applicationContext.getBean(beanName, className);
+    }
+}

+ 55 - 0
src/main/java/com/shkpr/service/aimodelpower/busihandler/ZoneInfoDataHelper.java

@@ -0,0 +1,55 @@
+package com.shkpr.service.aimodelpower.busihandler;
+
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.aimodelpower.commtools.CommTool;
+import com.shkpr.service.aimodelpower.dto.*;
+import com.shkpr.service.aimodelpower.jsonbean.JPZoneList;
+import com.shkpr.service.aimodelpower.services.ServiceMgrProxy;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ZoneInfoDataHelper {
+    private final static String mStrClassName = "ZoneInfoDataHelper";
+    private final static String EMPTY_NULL = "NULL";
+
+    public static List<String> listZoneIds(String roleId, List<String> filterZoneTypes){
+        List<String> zoneIds = null;
+        if (StringUtils.isEmpty(roleId))
+            return CommTool.safeList(zoneIds);
+
+        ZoneTreeListRes zoneLists = null;
+        try {
+            JPZoneList queryParam = new JPZoneList();
+            queryParam.setRoleid(roleId);
+            queryParam.setTypes(filterZoneTypes);
+            ResponseRes<String> resHttp = ServiceMgrProxy.getInstance().applyBaseServiceApi().zoneLists(queryParam);
+            if (ResponseCode.RESULT_NORMAL.toStrCode().equals(resHttp.getRescode())){
+                zoneLists = FastJsonUtil.fromJSONByGson(resHttp.getResdata(), ZoneTreeListRes.class);
+            }
+        }catch (Exception e){}
+
+        if (zoneLists != null){
+            zoneIds = new ArrayList<>();
+            if (CommTool.listSize(zoneLists.getData()) > 0){
+                Set<String> extendZoneIds = new HashSet<>();
+                for (ZoneTreeList zoneList:zoneLists.getData()){
+                    if (CommTool.listSize(zoneList.getExtensions()) > 0){
+                        for (ZoneNode oNode:zoneList.getExtensions())
+                            extendZoneIds.add(oNode.getUid());
+                    }
+                    if (CommTool.listSize(zoneList.getZones()) > 0){
+                        for (ZoneNode oNode:zoneList.getZones()){
+                            if (!extendZoneIds.contains(oNode.getUid()))
+                                zoneIds.add(oNode.getUid());
+                        }
+                    }
+                }
+            }
+        }
+        return zoneIds;
+    }
+}

+ 819 - 0
src/main/java/com/shkpr/service/aimodelpower/commtools/BytesUtils.java

@@ -0,0 +1,819 @@
+package com.shkpr.service.aimodelpower.commtools;
+import java.nio.charset.Charset;
+/**
+ * Created by Ti on 2018/8/7.
+ */
+
+/**
+ * 字节数组转换工具类
+ */
+public class BytesUtils {
+    public static final String GBK = "GBK";
+    public static final String UTF8 = "utf-8";
+    public static final char[] ascii = "0123456789ABCDEF".toCharArray();
+    private static final char[] HEX_VOCABLE = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+    /**
+     * 将short整型数值转换为字节数组
+     *
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(short data) {
+        byte[] bytes = new byte[2];
+        bytes[0] = (byte) ((data & 0xff00) >> 8);
+        bytes[1] = (byte) (data & 0xff);
+        return bytes;
+    }
+
+    /**
+     * 将字符转换为字节数组
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(char data) {
+        byte[] bytes = new byte[2];
+        bytes[0] = (byte) (data >> 8);
+        bytes[1] = (byte) (data);
+        return bytes;
+    }
+
+    /**
+     * 将布尔值转换为字节数组
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(boolean data) {
+        byte[] bytes = new byte[1];
+        bytes[0] = (byte) (data ? 1 : 0);
+        return bytes;
+    }
+
+    /**
+     * 将整型数值转换为字节数组
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(int data) {
+        byte[] bytes = new byte[4];
+        bytes[0] = (byte) ((data & 0xff000000) >> 24);
+        bytes[1] = (byte) ((data & 0xff0000) >> 16);
+        bytes[2] = (byte) ((data & 0xff00) >> 8);
+        bytes[3] = (byte) (data & 0xff);
+        return bytes;
+    }
+
+    /**
+     * 将long整型数值转换为字节数组
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(long data) {
+        byte[] bytes = new byte[8];
+        bytes[0] = (byte) ((data >> 56) & 0xff);
+        bytes[1] = (byte) ((data >> 48) & 0xff);
+        bytes[2] = (byte) ((data >> 40) & 0xff);
+        bytes[3] = (byte) ((data >> 32) & 0xff);
+        bytes[4] = (byte) ((data >> 24) & 0xff);
+        bytes[5] = (byte) ((data >> 16) & 0xff);
+        bytes[6] = (byte) ((data >> 8) & 0xff);
+        bytes[7] = (byte) (data & 0xff);
+        return bytes;
+    }
+
+    /**
+     * 将float型数值转换为字节数组
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(float data) {
+        int intBits = Float.floatToIntBits(data);
+        return getBytes(intBits);
+    }
+
+    /**
+     * 将double型数值转换为字节数组
+     * @param data
+     * @return
+     */
+    public static byte[] getBytes(double data) {
+        long intBits = Double.doubleToLongBits(data);
+        return getBytes(intBits);
+    }
+
+    /**
+     * 将字符串按照charsetName编码格式的字节数组
+     * @param data 字符串
+     * @param charsetName 编码格式
+     * @return
+     */
+    public static byte[] getBytes(String data, String charsetName) {
+        Charset charset = Charset.forName(charsetName);
+        return data.getBytes(charset);
+    }
+
+    /**
+     * 将字节数组第0字节转换为布尔值
+     * @param bytes
+     * @return
+     */
+    public static boolean getBoolean(byte[] bytes) {
+        return bytes[0] == 1;
+    }
+
+    /**
+     * 将字节数组的第index字节转换为布尔值
+     * @param bytes
+     * @param index
+     * @return
+     */
+    public static boolean getBoolean(byte[] bytes, int index) {
+        return bytes[index] == 1;
+    }
+
+    /**
+     * 将字节数组前2字节转换为short整型数值
+     * @param bytes
+     * @return
+     */
+    public static short getShort(byte[] bytes) {
+        return (short) ((0xff00 & (bytes[0] << 8)) | (0xff & bytes[1]));
+    }
+
+    /**
+     * 将字节数组从startIndex开始的2个字节转换为short整型数值
+     * @param bytes
+     * @param startIndex
+     * @return
+     */
+    public static short getShort(byte[] bytes, int startIndex) {
+        return (short) ((0xff00 & (bytes[startIndex] << 8)) | (0xff & bytes[startIndex + 1]));
+    }
+
+    /**
+     * 将字节数组前2字节转换为字符
+     * @param bytes
+     * @return
+     */
+    public static char getChar(byte[] bytes) {
+        return (char) ((0xff00 & (bytes[0] << 8)) | (0xff & bytes[1]));
+    }
+
+    /**
+     * 将字节数组从startIndex开始的2个字节转换为字符
+     * @param bytes
+     * @param startIndex
+     * @return
+     */
+    public static char getChar(byte[] bytes, int startIndex) {
+        return (char) ((0xff00 & (bytes[startIndex] << 8)) | (0xff & bytes[startIndex + 1]));
+    }
+
+    /**
+     * 将字节数组前4字节转换为整型数值
+     * @param bytes
+     * @return
+     */
+    public static int getInt(byte[] bytes) {
+        return (0xff000000 & (bytes[0] << 24) | (0xff0000 & (bytes[1] << 16))
+                | (0xff00 & (bytes[2] << 8)) | (0xff & bytes[3]));
+    }
+
+    /**
+     * 将字节数组从startIndex开始的4个字节转换为整型数值
+     * @param bytes
+     * @param startIndex
+     * @return
+     */
+    public static int getInt(byte[] bytes, int startIndex) {
+        return (0xff000000 & (bytes[startIndex] << 24)
+                | (0xff0000 & (bytes[startIndex + 1] << 16))
+                | (0xff00 & (bytes[startIndex + 2] << 8)) | (0xff & bytes[startIndex + 3]));
+    }
+
+    /**
+     * 将字节数组前8字节转换为long整型数值
+     * @param bytes
+     * @return
+     */
+    public static long getLong(byte[] bytes) {
+        return (0xff00000000000000L & ((long) bytes[0] << 56)
+                | (0xff000000000000L & ((long) bytes[1] << 48))
+                | (0xff0000000000L & ((long) bytes[2] << 40))
+                | (0xff00000000L & ((long) bytes[3] << 32))
+                | (0xff000000L & ((long) bytes[4] << 24))
+                | (0xff0000L & ((long) bytes[5] << 16))
+                | (0xff00L & ((long) bytes[6] << 8)) | (0xffL & (long) bytes[7]));
+    }
+
+    /**
+     * 将字节数组从startIndex开始的8个字节转换为long整型数值
+     * @param bytes
+     * @param startIndex
+     * @return
+     */
+    public static long getLong(byte[] bytes, int startIndex) {
+        return (0xff00000000000000L & ((long) bytes[startIndex] << 56)
+                | (0xff000000000000L & ((long) bytes[startIndex + 1] << 48))
+                | (0xff0000000000L & ((long) bytes[startIndex + 2] << 40))
+                | (0xff00000000L & ((long) bytes[startIndex + 3] << 32))
+                | (0xff000000L & ((long) bytes[startIndex + 4] << 24))
+                | (0xff0000L & ((long) bytes[startIndex + 5] << 16))
+                | (0xff00L & ((long) bytes[startIndex + 6] << 8)) | (0xffL & (long) bytes[startIndex + 7]));
+    }
+
+    /**
+     * 将字节数组前4字节转换为float型数值
+     * @param bytes
+     * @return
+     */
+    public static float getFloat(byte[] bytes) {
+        return Float.intBitsToFloat(getInt(bytes));
+    }
+
+    /**
+     * 将字节数组从startIndex开始的4个字节转换为float型数值
+     * @param bytes
+     * @param startIndex
+     * @return
+     */
+    public static float getFloat(byte[] bytes, int startIndex) {
+        byte[] result = new byte[4];
+        System.arraycopy(bytes, startIndex, result, 0, 4);
+        return Float.intBitsToFloat(getInt(result));
+    }
+
+    /**
+     * 将字节数组前8字节转换为double型数值
+     * @param bytes
+     * @return
+     */
+    public static double getDouble(byte[] bytes) {
+        long l = getLong(bytes);
+        return Double.longBitsToDouble(l);
+    }
+
+    /**
+     * 将字节数组从startIndex开始的8个字节转换为double型数值
+     * @param bytes
+     * @param startIndex
+     * @return
+     */
+    public static double getDouble(byte[] bytes, int startIndex) {
+        byte[] result = new byte[8];
+        System.arraycopy(bytes, startIndex, result, 0, 8);
+        long l = getLong(result);
+        return Double.longBitsToDouble(l);
+    }
+
+    /**
+     * 将charsetName编码格式的字节数组转换为字符串
+     * @param bytes
+     * @param charsetName
+     * @return
+     */
+    public static String getString(byte[] bytes, String charsetName) {
+        return new String(bytes, Charset.forName(charsetName));
+    }
+
+    /**
+     * 将GBK编码格式的字节数组转换为字符串
+     * @param bytes
+     * @return
+     */
+    public static String getString(byte[] bytes) {
+        return getString(bytes, GBK);
+    }
+
+    /**
+     * 将字节数组转换为16进制字符串
+     * @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().toUpperCase();
+    }
+
+    /**
+     * 将16进制字符串转换为字节数组
+     * @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;
+    }
+
+    /**
+     * 将16进制字符转换为字节
+     * @param c
+     * @return
+     */
+    private static byte charToByte(char c) {
+        return (byte) "0123456789ABCDEF".indexOf(c);
+    }
+
+    /**
+     * 将16进制字符串转换为字节数组
+     *
+     * @param hex
+     * @return
+     */
+    /*public static byte[] hexToBytes(String hex) {
+        if (hex.length() % 2 != 0)
+            throw new IllegalArgumentException(
+                    "input string should be any multiple of 2!");
+        hex.toUpperCase();
+
+        byte[] byteBuffer = new byte[hex.length() / 2];
+
+        byte padding = 0x00;
+        boolean paddingTurning = false;
+        for (int i = 0; i < hex.length(); i++) {
+            if (paddingTurning) {
+                char c = hex.charAt(i);
+                int index = indexOf(hex, c);
+                padding = (byte) ((padding << 4) | index);
+                byteBuffer[i / 2] = padding;
+                padding = 0x00;
+                paddingTurning = false;
+            } else {
+                char c = hex.charAt(i);
+                int index = indexOf(hex, c);
+                padding = (byte) (padding | index);
+                paddingTurning = true;
+            }
+
+        }
+        return byteBuffer;
+    }
+
+    private static int indexOf(String input, char c) {
+        int index = ArrayUtils.indexOf(HEX_VOCABLE, c);
+
+        if (index < 0) {
+            throw new IllegalArgumentException("err input:" + input);
+        }
+        return index;
+
+    }*/
+
+    /**
+     * 将BCD编码的字节数组转换为字符串
+     * @param bcds
+     * @return
+     */
+    public static String bcdToString(byte[] bcds) {
+        if (bcds == null || bcds.length == 0) {
+            return null;
+        }
+        byte[] temp = new byte[2 * bcds.length];
+        for (int i = 0; i < bcds.length; i++) {
+            temp[i * 2] = (byte) ((bcds[i] >> 4) & 0x0f);
+            temp[i * 2 + 1] = (byte) (bcds[i] & 0x0f);
+        }
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < temp.length; i++) {
+            res.append(ascii[temp[i]]);
+        }
+        return res.toString();
+    }
+
+    /**
+     * 字节转整形
+     * @param value
+     * @return
+     */
+    public static int bcdToInt(byte value){
+        return ((value>>4) * 10) + (value&0x0F);
+    }
+
+    /**
+     * 字节数组转16进制字符串
+     * @param bs
+     * @return
+     */
+    public static String bytesToHex(byte[] bs) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bs) {
+            int high = (b >> 4) & 0x0f;
+            int low = b & 0x0f;
+            sb.append(HEX_VOCABLE[high]);
+            sb.append(HEX_VOCABLE[low]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 字节数组取前len个字节转16进制字符串
+     * @param bs
+     * @param len
+     * @return
+     */
+    public static String bytesToHex(byte[] bs, int len) {
+        StringBuilder sb = new StringBuilder();
+        for (int i=0; i<len; i++ ) {
+            byte b = bs[i];
+            int high = (b >> 4) & 0x0f;
+            int low = b & 0x0f;
+            sb.append(HEX_VOCABLE[high]);
+            sb.append(HEX_VOCABLE[low]);
+        }
+        return sb.toString();
+    }
+    /**
+     * 字节数组偏移offset长度之后的取len个字节转16进制字符串
+     * @param bs
+     * @param offset
+     * @param len
+     * @return
+     */
+    public static String bytesToHex(byte[] bs, int offset, int len) {
+        StringBuilder sb = new StringBuilder();
+        for (int i=0; i<len; i++ ) {
+            byte b = bs[offset + i];
+            int high = (b >> 4) & 0x0f;
+            int low = b & 0x0f;
+            sb.append(HEX_VOCABLE[high]);
+            sb.append(HEX_VOCABLE[low]);
+        }
+        return sb.toString();
+    }
+    /**
+     * 字节转16进制字符串
+     * @return
+     */
+    public static String byteToHex(byte b) {
+        StringBuilder sb = new StringBuilder();
+        int high = (b >> 4) & 0x0f;
+        int low = b & 0x0f;
+        sb.append(HEX_VOCABLE[high]);
+        sb.append(HEX_VOCABLE[low]);
+        return sb.toString();
+    }
+    /**
+     * 将字节数组取反
+     * @param src
+     * @return
+     */
+    public static String negate(byte[] src) {
+        if (src == null || src.length == 0) {
+            return null;
+        }
+        byte[] temp = new byte[2 * src.length];
+        for (int i = 0; i < src.length; i++) {
+            byte tmp = (byte) (0xFF ^ src[i]);
+            temp[i * 2] = (byte) ((tmp >> 4) & 0x0f);
+            temp[i * 2 + 1] = (byte) (tmp & 0x0f);
+        }
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < temp.length; i++) {
+            res.append(ascii[temp[i]]);
+        }
+        return res.toString();
+    }
+
+    /**
+     * 比较字节数组是否相同
+     * @param a
+     * @param b
+     * @return
+     */
+    public static boolean compareBytes(byte[] a, byte[] b) {
+        if (a == null || a.length == 0 || b == null || b.length == 0
+                || a.length != b.length) {
+            return false;
+        }
+        if (a.length == b.length) {
+            for (int i = 0; i < a.length; i++) {
+                if (a[i] != b[i]) {
+                    return false;
+                }
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+    /**
+     * 只比对指定长度byte
+     * @param a
+     * @param b
+     * @param len
+     * @return
+     */
+    public static boolean compareBytes(byte[] a, byte[] b, int len) {
+        if (a == null || a.length == 0 || b == null || b.length == 0
+                || a.length < len || b.length < len) {
+            return false;
+        }
+        for (int i = 0; i < len; i++) {
+            if (a[i] != b[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 将字节数组转换为二进制字符串
+     * @param items
+     * @return
+     */
+    public static String bytesToBinaryString(byte[] items) {
+        if (items == null || items.length == 0) {
+            return null;
+        }
+        StringBuffer buf = new StringBuffer();
+        for (byte item : items) {
+            buf.append(byteToBinaryString(item));
+        }
+        return buf.toString();
+    }
+
+    /**
+     * 将字节转换为二进制字符串
+     * @return
+     */
+    public static String byteToBinaryString(byte item) {
+        byte a = item;
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0; i < 8; i++) {
+            buf.insert(0, a % 2);
+            a = (byte) (a >> 1);
+        }
+        return buf.toString();
+    }
+
+    /**
+     * 对数组a,b进行异或运算
+     * @param a
+     * @param b
+     * @return
+     */
+    public static byte[] xor(byte[] a, byte[] b) {
+        if (a == null || a.length == 0 || b == null || b.length == 0
+                || a.length != b.length) {
+            return null;
+        }
+        byte[] result = new byte[a.length];
+        for (int i = 0; i < a.length; i++) {
+            result[i] = (byte) (a[i] ^ b[i]);
+        }
+        return result;
+    }
+
+    /**
+     * 对数组a,b进行异或运算 运算长度len
+     * @param a
+     * @param b
+     * @param len
+     * @return
+     */
+    public static byte[] xor(byte[] a, byte[] b, int len) {
+        if (a == null || a.length == 0 || b == null || b.length == 0) {
+            return null;
+        }
+        if (a.length < len || b.length < len){
+            return null;
+        }
+        byte[] result = new byte[len];
+        for (int i = 0; i < len; i++) {
+            result[i] = (byte) (a[i] ^ b[i]);
+        }
+        return result;
+    }
+    /**
+     * 将short整型数值转换为字节数组
+     * @param num
+     * @return
+     */
+    public static byte[] shortToBytes(int num) {
+        byte[] temp = new byte[2];
+        for (int i = 0; i < 2; i++) {
+            temp[i] = (byte) ((num >>> (8 - i * 8)) & 0xFF);
+        }
+        return temp;
+    }
+
+    /**
+     * 将字节数组转为整型
+     * @return
+     */
+    public static int bytesToShort(byte[] arr) {
+        int mask = 0xFF;
+        int temp = 0;
+        int result = 0;
+        for (int i = 0; i < 2; i++) {
+            result <<= 8;
+            temp = arr[i] & mask;
+            result |= temp;
+        }
+        return result;
+    }
+
+    /**
+     * 将整型数值转换为指定长度的字节数组
+     * @param num
+     * @return
+     */
+    public static byte[] intToBytes(int num) {
+        byte[] temp = new byte[4];
+        for (int i = 0; i < 4; i++) {
+            temp[i] = (byte) ((num >>> (24 - i * 8)) & 0xFF);
+        }
+        return temp;
+    }
+
+    /**
+     * 将整型数值转换为指定长度的字节数组
+     * @param src
+     * @param len
+     * @return
+     */
+    public static byte[] intToBytes(int src, int len) {
+        if (len < 1 || len > 4) {
+            return null;
+        }
+        byte[] temp = new byte[len];
+        for (int i = 0; i < len; i++) {
+            temp[len - 1 - i] = (byte) ((src >>> (8 * i)) & 0xFF);
+        }
+        return temp;
+    }
+
+    /**
+     * 将字节数组转换为整型数值
+     * @param arr
+     * @return
+     */
+    public static int bytesToInt(byte[] arr) {
+        int mask = 0xFF;
+        int temp = 0;
+        int result = 0;
+        for (int i = 0; i < 4; i++) {
+            result <<= 8;
+            temp = arr[i] & mask;
+            result |= temp;
+        }
+        return result;
+    }
+
+    /**
+     * 将long整型数值转换为字节数组
+     * @param num
+     * @return
+     */
+    public static byte[] longToBytes(long num) {
+        byte[] temp = new byte[8];
+        for (int i = 0; i < 8; i++) {
+            temp[i] = (byte) ((num >>> (56 - i * 8)) & 0xFF);
+        }
+        return temp;
+    }
+
+    /**
+     * 将字节数组转换为long整型数值
+     * @param arr
+     * @return
+     */
+    public static long bytesToLong(byte[] arr) {
+        int mask = 0xFF;
+        int temp = 0;
+        long result = 0;
+        int len = Math.min(8, arr.length);
+        for (int i = 0; i < len; i++) {
+            result <<= 8;
+            temp = arr[i] & mask;
+            result |= temp;
+        }
+        return result;
+    }
+
+    /**
+     * 功能描述:把两个字节的字节数组转化为整型数据,高位补零,例如:<br/>
+     * 有字节数组byte[] data = new byte[]{1,2};转换后int数据的字节分布如下:<br/>
+     * 00000000  00000000 00000001 00000010,函数返回258
+     * @param lenData 需要进行转换的字节数组
+     * @return  字节数组所表示整型值的大小
+     */
+    public static int bytesToIntWhereByteLengthEquals2(byte lenData[]) {
+        if(lenData.length != 2){
+            return -1;
+        }
+        byte fill[] = new byte[]{0,0};
+        byte real[] = new byte[4];
+        System.arraycopy(fill, 0, real, 0, 2);
+        System.arraycopy(lenData, 0, real, 2, 2);
+        int len = byteToInt(real);
+        return len;
+
+    }
+
+    /**
+     * 功能描述:将byte数组转化为int类型的数据
+     * @param byteVal 需要转化的字节数组
+     * @return 字节数组所表示的整型数据
+     */
+    public static int byteToInt(byte[] byteVal) {
+        int result = 0;
+        for(int i = 0;i < byteVal.length;i++) {
+            int tmpVal = (byteVal[i]<<(8*(3-i)));
+            switch(i) {
+                case 0:
+                    tmpVal = tmpVal & 0xFF000000;
+                    break;
+                case 1:
+                    tmpVal = tmpVal & 0x00FF0000;
+                    break;
+                case 2:
+                    tmpVal = tmpVal & 0x0000FF00;
+                    break;
+                case 3:
+                    tmpVal = tmpVal & 0x000000FF;
+                    break;
+            }
+
+            result = result | tmpVal;
+        }
+        return result;
+    }
+
+    public static byte CheckXORSum(byte[] bData){
+        byte sum = 0x00;
+        for (int i = 0; i < bData.length; i++) {
+            sum ^= bData[i];
+        }
+        return sum;
+    }
+
+    /**
+     * 异或校验和
+     * @param src ascii码字符串
+     * @return 长度为2的十六进制字符串
+     */
+    public static String CheckXORSum(String src){
+        if (src == null || src.length() <= 0)
+            return "";
+        byte[] by = src.getBytes();
+        return byteToHex(CheckXORSum(by));
+    }
+    /**
+     * 从offset开始 将后续长度为len的byte字节转为int
+     * @param data
+     * @param offset
+     * @param len
+     * @return
+     */
+    public static int bytesToInt(byte[] data, int offset, int len){
+        int mask = 0xFF;
+        int temp = 0;
+        int result = 0;
+        len = Math.min(len, 4);
+        for (int i = 0; i < len; i++) {
+            result <<= 8;
+            temp = data[offset + i] & mask;
+            result |= temp;
+        }
+        return result;
+    }
+
+    /**
+     * byte字节数组中的字符串的长度
+     * @param data
+     * @return
+     */
+    public static int getBytesStringLen(byte[] data)
+    {
+        int count = 0;
+        for (byte b : data) {
+            if(b == 0x00)
+                break;
+            count++;
+        }
+        return count;
+    }
+
+}

+ 483 - 0
src/main/java/com/shkpr/service/aimodelpower/commtools/CommTool.java

@@ -0,0 +1,483 @@
+package com.shkpr.service.aimodelpower.commtools;
+
+import com.global.base.component.SnowFlakeEx;
+import com.global.base.tools.CastUtil;
+import com.global.base.tools.EncryptionUtil;
+import com.global.base.tools.RandomUtil;
+import com.shkpr.service.aimodelpower.constants.CommDefine;
+import com.shkpr.service.aimodelpower.dto.CommUNBean;
+import com.shkpr.service.aimodelpower.dto.LatLngBean;
+import org.springframework.util.StringUtils;
+
+import java.awt.geom.Path2D;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CommTool {
+    public static String getPlatformByAgent(String strClientType, String strUserAgent){
+        return getPlatformByAgent(!StringUtils.isEmpty(strClientType)?strClientType:strUserAgent);
+    }
+
+    public static String getPlatformByAgent(String strUserAgent){
+        String type = "_";
+        if (StringUtils.isEmpty(strUserAgent))
+            return type;
+
+        if(strUserAgent.contains("Android") || strUserAgent.contains("Linux")) {
+            type = "apk";
+        } else if (strUserAgent.contains("iPhone") || strUserAgent.contains("iPod") || strUserAgent.contains("iPad")){
+            type = "ios";
+        } else if (strUserAgent.indexOf("micromessenger") > -1){
+            type = "wx";
+        } else if (strUserAgent.indexOf("Windows") > -1){
+            type = "pc";
+        }else if (strUserAgent.contains("tri.")){
+            type = strUserAgent;
+        }
+        return type;
+    }
+
+    public static boolean isMobilePlatform(String platform){
+        return ("apk".equals(platform) || "ios".equals(platform) || "wx".equals(platform));
+    }
+
+    public static boolean isTheThisFormatMatch(final String strFormatFilter, String strDesData){
+        if (!StringUtils.isEmpty(strFormatFilter) && !StringUtils.isEmpty(strDesData)) {
+            //正则表达式的模式
+            Pattern p = Pattern.compile(strFormatFilter);
+            //正则表达式的匹配器
+            Matcher m = p.matcher(strDesData);
+            //进行正则匹配
+            return m.matches();
+        }
+        return false;
+    }
+
+    public static int listSize(List<? extends Object> listSrc){
+        return (listSrc==null)?0:listSrc.size();
+    }
+
+    public static int collectionSize(Collection<? extends Object> cc){
+        return (cc==null)?0:cc.size();
+    }
+
+    public static int mapSize(Map<? extends Object, ? extends Object> mapSrc){
+        return (mapSrc==null)?0:mapSrc.size();
+    }
+
+    public static int lenString(String strSrc) {
+        if (StringUtils.isEmpty(strSrc))
+            return 0;
+        return strSrc.length();
+    }
+
+    public static boolean strBetweenLen(String strSrc, int nMinLen, int nMaxLen){
+        if (strSrc == null || nMinLen > nMaxLen)
+            return false;
+        return strSrc.length() >= nMinLen && strSrc.length() <= nMaxLen;
+    }
+
+    public static String genPatrolObjectID(String sn){
+        if (StringUtils.isEmpty(sn)){
+            String prefix = SnowFlakeEx.getInstance().nextHexStrId(2);
+            return (new StringBuilder("POD")).append(prefix).toString();
+        }else
+            return String.format("PODSN%s", EncryptionUtil.MD5Hash(sn).substring(8,24));//MD5取16位
+    }
+
+    public static String genPatrolPointID(){
+        String prefix = SnowFlakeEx.getInstance().nextHexStrId(2);
+        return (new StringBuilder("PPD")).append(prefix).toString();
+    }
+
+    public static String genPatrolZoneID(){
+        return (new StringBuilder("PZD")).append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static String genOrderMatTypeID(){
+        return (new StringBuilder("OMT")).append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static String genOrderTimeCycleID(int type){
+        return (new StringBuilder("CLE"))
+                .append(String.format("%02d",type%100))
+                .append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static String genPatrolPlanPointID(){
+        return (new StringBuilder("PP")).append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static String genPatrolPlanRouteID(){
+        return (new StringBuilder("PR")).append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static String genAppApisID(){
+        return (new StringBuilder("AA")).append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static String genApisCaseID(){
+        return (new StringBuilder("AC")).append(SnowFlakeEx.getInstance().nextHexStrId(2)).toString();
+    }
+
+    public static boolean isAlarmOrder(String strOrderId){
+        if (!StringUtils.isEmpty(strOrderId))
+            return strOrderId.startsWith("AMD");
+        return false;
+    }
+
+    public static String genNotifyEventID(){
+        return (new StringBuilder("PNE")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genPushReqID(){
+        return (new StringBuilder("PEQ")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genPatrolItemTypeId(String puid){
+        return String.format("%s%s%s"
+                ,puid
+                ,RandomUtil.getDigitalRandomStr(3)
+                ,EncryptionUtil.MD5Hash(String.valueOf(System.currentTimeMillis())).substring(0,3));
+    }
+
+    public static String genFileAttachmentId(String fileName, int type, String strExtend){
+        String time = TimeTool.convertUTC2DateStr(System.currentTimeMillis(), TimeTool.TIMESTAMP_FORMAT_EX2);
+        String fileNameHash = (StringUtils.isEmpty(fileName))?RandomUtil.getDigitalRandomStr(4):EncryptionUtil.MD5Hash(fileName).substring(0,4);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(4):strExtend;
+        return (new StringBuilder("FT"))
+                .append(time==null?"":time)
+                .append(String.format("%02d",type%100))
+                .append(fileNameHash==null?"":fileNameHash)
+                .append(extend==null?"":extend).toString();
+    }
+
+    /**
+     * 创建预警工单号
+     * @param createTime:创建时间,要求只精确到秒UTC时间
+     * @param type:预警类型:流量、压力、MNF等等
+     * @return
+     */
+    public static String genAlarmOrderId(long createTime, int type, String strExtend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(4):strExtend;
+        return (new StringBuilder("AMD"))
+                .append(time==null?"":time) //为保证订单相对有序递增,需要将时间戳放前面
+                .append(String.format("%02d",type%100))
+                .append(extend==null?"":extend).toString();
+    }
+
+    /**
+     * 创建维修工单号
+     * @param createTime 创建时间,要求只精确到秒UTC时间
+     * @param type 工单主类型
+     * @param subType 工单子类型
+     * @param strExtend
+     * @return
+     */
+    public static String genRepairOrderId(long createTime, int type, int subType, String strExtend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(4):strExtend;
+        return (new StringBuilder("RPD"))
+                .append(time==null?"":time) //为保证订单相对有序递增,需要将时间戳放前面
+                .append(String.format("%s%s", Integer.toHexString(type%16).toUpperCase(), Integer.toHexString(subType%16).toUpperCase()))
+                .append(extend==null?"":extend).toString();
+    }
+
+    public static String genPatrolJobId(long createTime, String extend, int index){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        return (new StringBuilder("PJD"))
+                .append(time==null?"":time) //为保证订单相对有序递增,需要将时间戳放前面
+                .append(/*String.format("%03d", index%1000)*/RandomUtil.getRandomStr(3).toUpperCase())
+                .append(StringUtils.isEmpty(extend)?RandomUtil.getDigitalRandomStr(3):extend)
+                .toString();
+    }
+
+    public static String genFaultOrderId(long createTime, int type, String strExtend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(6):strExtend;
+        return (new StringBuilder("FTD"))
+                .append(time==null?"":time) //为保证订单相对有序递增,需要将时间戳放前面
+                //.append(String.format("%02d",type%100))
+                .append(extend==null?"":extend).toString();
+    }
+
+    public static String genAddedFeedback(){
+        return (new StringBuilder("AFB")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genRepairTeamId(){
+        return (new StringBuilder("UGG")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genPatrolPlanId(long createTime, String strExtend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(4):strExtend;
+        return (new StringBuilder("PPL"))
+                .append(time==null?"":time)
+                .append(extend==null?"":extend).toString();
+    }
+
+    public static String genDispatchEventId(long createTime, String extend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        return (new StringBuilder("DET"))
+                .append(time==null?"":time) //为保证订单相对有序递增,需要将时间戳放前面
+                .append(/*String.format("%03d", index%1000)*/RandomUtil.getRandomStr(3).toUpperCase())
+                .append(StringUtils.isEmpty(extend)?RandomUtil.getDigitalRandomStr(3):extend)
+                .toString();
+    }
+
+    public static String genDispatchOrderId(long createTime, String extend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        return (new StringBuilder("DOD"))
+                .append(time==null?"":time) //为保证订单相对有序递增,需要将时间戳放前面
+                .append(/*String.format("%03d", index%1000)*/RandomUtil.getRandomStr(3).toUpperCase())
+                .append(StringUtils.isEmpty(extend)?RandomUtil.getDigitalRandomStr(3):extend)
+                .toString();
+    }
+
+    public static String genDispatchPlanId(long createTime, String strExtend){
+        String time = TimeTool.convertUTC2DateStr(createTime, TimeTool.TIMESTAMP_FORMAT_EX2);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(4):strExtend;
+        return (new StringBuilder("DPP"))
+                .append(time==null?"":time)
+                .append(extend==null?"":extend).toString();
+    }
+
+    public static String genDispatchPlanPointId(String strExtend){
+        String time = TimeTool.convertUTC2DateStr(System.currentTimeMillis(), TimeTool.TIMESTAMP_FORMAT_EX2);
+        String extend = (StringUtils.isEmpty(strExtend))?RandomUtil.getDigitalRandomStr(4):strExtend;
+        return (new StringBuilder("DPO"))
+                .append(time==null?"":time)
+                .append(extend==null?"":extend).toString();
+    }
+
+    public static String genDispatchSuggestionId(String planId){
+        return String.format("%s%s%s"
+                ,planId.substring(planId.length()-3)
+                ,EncryptionUtil.MD5Hash(String.valueOf(System.currentTimeMillis())).substring(0,2)
+                ,RandomUtil.getDigitalRandomStr(4));
+    }
+
+    /**
+     * 从订单id中提取订单的创建时间,并以yyyyMMddHHmmss时间格式返回
+     * @param strOrderId
+     * @return
+     */
+    public static String getOrderTmStrFromOrderID(String strOrderId){
+        try {
+            String time = "";
+            int nStartIndex = 3; //所有工单的标识为前三个字符标识
+            time = strOrderId.substring(nStartIndex, nStartIndex+TimeTool.TIMESTAMP_FORMAT_EX2.length());
+            return time.trim();
+        }catch (Exception e){}
+        return "";
+    }
+
+    /**
+     * 从订单id中提取订单的创建时间,并以UTC时间格式(精确到毫秒)返回
+     * @param strOrderId
+     * @return
+     */
+    public static long getOrderUTCFromOrderID(String strOrderId){
+        try {
+            return new SimpleDateFormat(TimeTool.TIMESTAMP_FORMAT_EX2).parse(getOrderTmStrFromOrderID(strOrderId)).getTime();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    public static List<String> splitStr2ReadOnlyList(String srcData, String splitTag){
+        if (StringUtils.isEmpty(srcData) || StringUtils.isEmpty(splitTag))
+            return new ArrayList<>();
+        String []arrTmp = srcData.split(splitTag);
+        return (arrTmp==null||arrTmp.length<=0)?new ArrayList<>():Arrays.asList(arrTmp);
+    }
+
+    public static <T> List<T>  splitTBean2ReadOnlyList(String srcData, Class<T> tClass){
+        List<T> arrRes = new ArrayList<>();
+        if (!StringUtils.isEmpty(srcData)){
+            String[] arrUNBean = srcData.split(",");
+            if (arrUNBean != null && arrUNBean.length > 0){
+                for (String oItem:arrUNBean){
+                    if (!StringUtils.isEmpty(oItem)){
+                        String[] arrItemFiled = oItem.split("\\|");
+                        if (arrItemFiled == null || arrItemFiled.length <= 0)
+                            continue;
+
+                        try {
+                            T bean = tClass.newInstance();
+                            if (bean != null){
+                                Method initMethod = tClass.getMethod("init", new Class[]{String[].class});
+                                if (initMethod != null)
+                                    initMethod.invoke(bean, (Object)arrItemFiled);
+                                arrRes.add(bean);
+                            }
+                        }catch (Exception e){
+                        }
+                    }
+                }
+            }
+        }
+        return arrRes;
+    }
+
+    public static List<CommUNBean> splitUNBean2ReadOnlyList(String srcData){
+        return splitTBean2ReadOnlyList(srcData, CommUNBean.class);
+    }
+
+    public static List<String> splitStr2List(String srcData, String splitTag){
+        if (StringUtils.isEmpty(srcData) || StringUtils.isEmpty(splitTag))
+            return new ArrayList<>();
+        String []arrTmp = srcData.split(splitTag);
+        return (arrTmp==null||arrTmp.length<=0)?new ArrayList<>():new ArrayList<>(Arrays.asList(arrTmp));
+    }
+
+    public static String list2QueryIn(Collection<? extends Object> listSrc){
+        StringBuilder str = new StringBuilder("");
+        if (listSrc != null && listSrc.size() > 0){
+            str.append("(");
+            int nStart = 0;
+            for (Object item:listSrc){
+                if (nStart++ > 0)
+                    str.append(",");
+                if (item instanceof String){
+                    str.append("'"+item+"'");
+                }else{
+                    str.append(item);
+                }
+            }
+            str.append(")");
+        }
+        return str.toString();
+    }
+
+    public static int totalCharCountsInStr(String srcStr, char chDes){
+        int nums = 0;
+        if (StringUtils.isEmpty(srcStr))
+            return nums;
+
+        char[] arr = srcStr.toCharArray();
+        for (char ch:arr){
+            if (ch == chDes)
+                nums++;
+        }
+        return nums;
+    }
+
+    public static List safeList(List<? extends Object> listSrc){
+        if (listSrc == null)
+            return new ArrayList();
+        else
+            return listSrc;
+    }
+
+    public static <T> Collection<T> safeCollection(Collection<T> collection) { return collection==null?Collections.EMPTY_SET:collection;}
+
+    public static <TK, TV> Map<TK, TV> safeMap(Map<TK, TV> map) { return map==null?Collections.EMPTY_MAP:map;}
+
+
+    /**
+     * 指定经纬度是否在指定区域内
+     * @param areaGis
+     * @param lng
+     * @param lat
+     * @return
+     */
+    public static boolean isGisPointInArea(List<LatLngBean> areaGis, double lng, double lat){
+        if (listSize(areaGis) <= 2)
+            return false;
+
+        Path2D.Double generalPath = new Path2D.Double();
+        LatLngBean firstPoint = areaGis.get(0);
+        if (firstPoint == null)
+            return false;
+
+        generalPath.moveTo(firstPoint.getLng(), firstPoint.getLat());
+        for (int i=1;i<areaGis.size();i++){
+            LatLngBean nextPoint = areaGis.get(i);
+            if (nextPoint == null)
+                return false;
+
+            generalPath.lineTo(nextPoint.getLng(), nextPoint.getLat());
+        }
+        generalPath.lineTo(firstPoint.getLng(), firstPoint.getLat());
+        generalPath.closePath();
+        return generalPath.contains(lng, lat);
+    }
+
+    public static String exchangeMD5(String md5){
+        StringBuilder res = new StringBuilder("");
+        int len = md5.length()/2;
+        for (int i=0; i<len; i++){
+            int index = i*2;
+            res.append(Integer.toHexString((Integer.parseInt(String.valueOf(md5.charAt(index+1)), 16)<<4 | Integer.parseInt(String.valueOf(md5.charAt(index)), 16)) % 16).toUpperCase());
+        }
+        //for (int i = 0,j = md5.length()-1; i<=j; i++,j--){
+        //    res.append(Integer.toHexString(((0x0F & md5.charAt(i)) ^ (0x0F & md5.charAt(j)))).toUpperCase());
+        //}
+        return res.toString();
+    }
+
+    public static boolean isContainSplitChar(String source){
+        if (source != null
+                && source.length() > 0
+                && (source.contains("\\|") || source.contains(",")))
+            return true;
+        return false;
+    }
+
+    private static final double EARTH_RADIUS = 6378137; //地球半径:米
+    public static long getGisDistance(double lng1, double lat1, double lng2, double lat2) {
+        lat1 = Math.toRadians(lat1);
+        lat2 = Math.toRadians(lat2);
+        lng1 = Math.toRadians(lng1);
+        lng2 = Math.toRadians(lng2);
+
+        double a = lat1 - lat2;    // 纬度之差
+        double b = lng1 - lng2;     // 经度之差
+        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
+                Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));// 计算两点距离的公式
+        s =  s * EARTH_RADIUS;
+        return Math.round(s * 10000) / 10000;
+    }
+
+    public static long toUTCLong(Object value, long defValue){
+        if (value == null)
+            return defValue;
+        if (value instanceof Timestamp){
+            try {
+                return ((Timestamp)value).getTime();
+            }catch (Exception e){}
+            return defValue;
+        }else
+            return CastUtil.castLong(value, defValue);
+    }
+
+    public static int compareFloat(String oneValue, String twoValue) throws Exception{
+        try {
+            return new BigDecimal(oneValue).compareTo(new BigDecimal(twoValue));
+        }catch (Exception e){
+            throw e;
+        }
+    }
+
+    private static final String PHONE_MATCH_FILTER = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
+    public static String adjustMobilePhone(String phone){
+        if (!StringUtils.isEmpty(phone)
+                && phone.length() == 11
+                && isTheThisFormatMatch(PHONE_MATCH_FILTER, phone)){
+            return phone;
+        }
+        return "";
+    }
+
+    public static boolean isRootAdminID(String userID){
+        return CommDefine.ADMIN_USER_ID.equals(userID)
+                || CommDefine.INTERNAL_OPERATOR_ID.equals(userID);
+    }
+}

+ 260 - 0
src/main/java/com/shkpr/service/aimodelpower/commtools/ExcelUtils.java

@@ -0,0 +1,260 @@
+package com.shkpr.service.aimodelpower.commtools;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.*;
+import org.springframework.util.StringUtils;
+
+import java.io.*;
+import java.text.DecimalFormat;
+import java.util.*;
+
+public class ExcelUtils {
+    public static class SheetObj{
+        private int index = 0; //sheet索引
+        private List<Map<String, Object>> rows2Col = new ArrayList<>();
+
+        public SheetObj() {
+        }
+
+        public SheetObj(int index, List<Map<String, Object>> rows2Col) {
+            this.index = index;
+            this.rows2Col = rows2Col;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public void setIndex(int index) {
+            this.index = index;
+        }
+
+        public List<Map<String, Object>> getRows2Col() {
+            return rows2Col;
+        }
+
+        public void setRows2Col(List<Map<String, Object>> rows2Col) {
+            this.rows2Col = rows2Col;
+        }
+    }
+
+    public static List<SheetObj> parseExcelFile(String filePath){
+        List<SheetObj> arrRes = null;
+        if (StringUtils.isEmpty(filePath))
+            return arrRes;
+
+        Workbook wb = getExcelWorkObj(filePath);
+        if (wb == null)
+            return arrRes;
+
+        do {
+            int sheetsNum = wb.getNumberOfSheets();
+            if (sheetsNum <= 0)
+                break;
+            arrRes = new ArrayList<>();
+
+            for (int i = 0; i < sheetsNum; i++)
+                arrRes.add(new SheetObj(i, parseSheetObj(wb.getSheetAt(i))));
+        }while (false);
+
+        if (wb != null){
+            try {
+                wb.close();
+            }catch (Exception e){}
+        }
+        return arrRes;
+    }
+
+    public static List<SheetObj> parseExcelFile(InputStream is, String ext){
+        List<SheetObj> arrRes = null;
+        Workbook wb = getExcelWorkObj(is, ext);
+        if (wb == null)
+            return arrRes;
+
+        do {
+            int sheetsNum = wb.getNumberOfSheets();
+            if (sheetsNum <= 0)
+                break;
+            arrRes = new ArrayList<>();
+
+            for (int i = 0; i < sheetsNum; i++)
+                arrRes.add(new SheetObj(i, parseSheetObj(wb.getSheetAt(i))));
+        }while (false);
+
+        if (wb != null){
+            try {
+                wb.close();
+            }catch (Exception e){}
+        }
+        return arrRes;
+    }
+
+    private static Workbook getExcelWorkObj(InputStream is, String ext){
+        Workbook wb = null;
+        if (is != null && !StringUtils.isEmpty(ext)){
+            try {
+                if("xls".equalsIgnoreCase(ext)){
+                    wb = new HSSFWorkbook(is);
+                }else if("xlsx".equalsIgnoreCase(ext)){
+                    wb = new XSSFWorkbook(is);
+                }
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return wb;
+    }
+
+    private static Workbook getExcelWorkObj(String filePath){
+        Workbook wb = null;
+        String ext = filePath.substring(filePath.lastIndexOf("."));
+        try {
+            InputStream is = new FileInputStream(filePath);
+            if(".xls".equalsIgnoreCase(ext)){
+                wb = new HSSFWorkbook(is);
+            }else if(".xlsx".equalsIgnoreCase(ext)){
+                wb = new XSSFWorkbook(is);
+            }
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return wb;
+    }
+
+    private static List<Map<String, Object>> parseSheetObj(Sheet sheet){
+        List<Map<String, Object>> rows2Col = new ArrayList<>();
+        if (sheet == null)
+            return rows2Col;
+
+        int rowsNum = sheet.getPhysicalNumberOfRows();
+        int colsNum = (rowsNum>0)?sheet.getRow(0).getPhysicalNumberOfCells():0;
+        if (rowsNum <= 1)
+            return rows2Col;
+
+        Row rowHead = sheet.getRow(0);
+        List<String> colsHeads = new ArrayList<>();
+        for (int j = 0; j < colsNum; j++){
+            Cell cell = (rowHead!=null)?rowHead.getCell(j):null;
+            String colHeadName = cell!=null?getCellValue(cell):String.format("col%d",j);
+            colsHeads.add(!StringUtils.isEmpty(colHeadName)?colHeadName:String.format("col%d",j));
+        }
+
+        for (int i = 1; i < rowsNum; i++){
+            Row row = sheet.getRow(i);
+            if (row == null)
+                continue;
+
+            Map<String, Object> oneRow2Cols = new HashMap<>();
+            for (int j = 0; j < colsNum; j++){
+                Cell cell = row.getCell(j);
+                oneRow2Cols.put(colsHeads.get(j), cell!=null?getCellValue(cell):"");
+            }
+            if (oneRow2Cols.size() > 0)
+                rows2Col.add(oneRow2Cols);
+        }
+        return rows2Col;
+    }
+
+    private static String getCellValue(Cell cell) {
+        String result = "";
+        if (cell == null)
+            return result;
+
+        try {
+            switch (cell.getCellTypeEnum()){
+                case NUMERIC:{
+                    if (DateUtil.isCellDateFormatted(cell)){
+                        result = TimeTool.convertDateObj2DateStr(cell.getDateCellValue(), cell.getCellStyle().getDataFormatString());
+                    }else if(String.valueOf(cell.getNumericCellValue()).contains(".")){
+                        DecimalFormat df = new DecimalFormat("#.####");
+                        result = df.format(cell.getNumericCellValue());
+                    }else
+                        result = String.valueOf(cell.getNumericCellValue());;
+                }
+                break;
+                case STRING:{
+                    result = cell.getRichStringCellValue().toString();
+                }
+                break;
+                case BOOLEAN:{
+                    result = String.valueOf(cell.getBooleanCellValue());
+                }
+                break;
+                case FORMULA:{
+                    result = String.valueOf(cell.getNumericCellValue());
+                }
+                break;
+                default:{
+                    result = "";
+                }
+                break;
+            }
+        }catch (Exception e){}
+        return result==null?"":result.trim();
+    }
+
+    /**
+     *
+     * @param rowsWithColsData
+     * @param outputStream
+     */
+    public static void writeExcel(List<List<Object>> rowsWithColsData, OutputStream outputStream, boolean hasHeader){
+        if (rowsWithColsData == null || rowsWithColsData.size() <= 0 || outputStream == null)
+            return;
+        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
+        XSSFSheet xssfSheet = xssfWorkbook.createSheet("sheet1");
+
+        XSSFCellStyle colHeaderStyle = null;
+        if (hasHeader){
+            colHeaderStyle = xssfWorkbook.createCellStyle();
+            XSSFFont colHeaderFont = xssfWorkbook.createFont();
+            colHeaderFont.setBold(true);
+            colHeaderStyle.setFont(colHeaderFont);
+        }
+
+        for (int i=0,j=rowsWithColsData.size();i<j;i++){
+            XSSFRow xssfRow = xssfSheet.createRow(i);
+            List<Object> columnData = rowsWithColsData.get(i);
+            if (columnData == null)
+                continue;
+
+            for (int m=0,n=columnData.size();m<n;m++){
+                XSSFCell xssfCell = xssfRow.createCell(m);
+                Object col = columnData.get(m);
+                if (i == 0 && colHeaderStyle != null)
+                    xssfCell.setCellStyle(colHeaderStyle);
+
+                if (col == null){
+                    xssfCell.setCellValue("");
+                }else {
+                    if (col instanceof String){
+                        xssfCell.setCellValue(new XSSFRichTextString((String)col));
+                    }else if (col instanceof Date){
+                        xssfCell.setCellValue((Date)col);
+                    }else if (col instanceof Boolean){
+                        xssfCell.setCellValue((Boolean)col);
+                    }else if (col instanceof Double){
+                        xssfCell.setCellValue((Double)col);
+                    }else
+                        xssfCell.setCellValue(new XSSFRichTextString(String.valueOf(col)));
+                }
+
+                if (i != 0 && i == j-1)
+                    xssfSheet.autoSizeColumn(m);
+            }
+        }
+
+        try {
+            xssfWorkbook.write(outputStream);
+            outputStream.flush();
+            outputStream.close();
+        }catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

Разница между файлами не показана из-за своего большого размера
+ 157 - 0
src/main/java/com/shkpr/service/aimodelpower/commtools/HttpTool.java


+ 569 - 0
src/main/java/com/shkpr/service/aimodelpower/commtools/TimeTool.java

@@ -0,0 +1,569 @@
+package com.shkpr.service.aimodelpower.commtools;
+import org.springframework.util.StringUtils;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+public class TimeTool {
+    public static final long MS_HTTP_REQ_TIMEOUT = 120*1000;  //两分钟的毫秒数
+    public static final long MS_ONE_HALF_MIN = 90*1000;  //一分半钟的毫秒数
+    public static final long MS_ONE_MIN = 60*1000;       //一分钟的毫秒数
+    public static final long MIN_ONE_DAY = 24*60;        //一天中的分
+    public static final long SEC_ONE_DAY = 24*60*60;     //一天中的秒
+    public static final long MS_ONE_DAY = 24*60*60*1000; //一天中的毫秒
+    public static final long MS_ONE_YEAR = 365*MS_ONE_DAY;//一年中的毫秒
+    public static final long MS_ONE_HOUR = 60*60*1000;   //一小时的毫秒
+    public static final String YEAR_FORMAT = "yyyy";
+    public static final String YEAR_MONTH_FORMAT_EX = "yyyyMM";
+    public static final String YEAR_MONTH_FORMAT = "yyyy-MM";
+    public static final String YEAR_MONTH_DAY_FORMAT = "yyyy-MM-dd";
+    public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    public static final String TIMESTAMP_FORMAT_EX = "yyyy-MM-dd HH:mm:ss.SSS";
+    public static final String TIMESTAMP_FORMAT_EX2 = "yyyyMMddHHmmss";
+    public static final String TIMESTAMP_FORMAT_EX3 = "yyyyMMddHH";
+    public static final long UTC_MS_START_ONLINE = 1538323200000L;//2018-10-01 00:00:00
+    public static volatile long UTC_MS_TODAY_BEGIN = 0L;
+    public static volatile long UTC_MS_TODAY_END = 0L;
+    public static volatile long UTC_MS_THIS_MONTH_BEGIN = 0L;
+    public static volatile long UTC_MS_THIS_MONTH_END = 0L;
+
+    private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);
+    private static final DateTimeFormatter TIMESTAMP_EX_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT_EX);
+    private static final DateTimeFormatter TIMESTAMP_EX2_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT_EX2);
+    private static final DateTimeFormatter TIMESTAMP_EX3_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT_EX3);
+    private static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern(YEAR_MONTH_FORMAT);
+    private static final DateTimeFormatter YEAR_MONTH_DAY_FORMATTER = DateTimeFormatter.ofPattern(YEAR_MONTH_DAY_FORMAT);
+
+    public static void refreshUTCTimeRes(){
+        UTC_MS_TODAY_BEGIN = getTodayBeginUTC();
+        UTC_MS_TODAY_END = getTodayEndUTC();
+        UTC_MS_THIS_MONTH_BEGIN = getMonthBeginUTC(System.currentTimeMillis());
+        UTC_MS_THIS_MONTH_END = getMonthEndUTC(System.currentTimeMillis());
+    }
+
+    private static LocalDateTime strTime2LocalDateTime(String time, String format) {
+        switch (format){
+            case YEAR_MONTH_FORMAT:
+                return LocalDateTime.parse(time, YEAR_MONTH_FORMATTER);
+            case YEAR_MONTH_DAY_FORMAT:
+                return LocalDateTime.parse(time, YEAR_MONTH_DAY_FORMATTER);
+            case TIMESTAMP_FORMAT:
+                return LocalDateTime.parse(time, TIMESTAMP_FORMATTER);
+            case TIMESTAMP_FORMAT_EX:
+                return LocalDateTime.parse(time, TIMESTAMP_EX_FORMATTER);
+            case TIMESTAMP_FORMAT_EX2:
+                return LocalDateTime.parse(time, TIMESTAMP_EX2_FORMATTER);
+            default:
+                return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
+        }
+    }
+
+    private static String localDateTime2StrTime(LocalDateTime localDateTime, String format) {
+        switch (format){
+            case YEAR_MONTH_FORMAT:
+                return localDateTime.format(YEAR_MONTH_FORMATTER);
+            case YEAR_MONTH_DAY_FORMAT:
+                return localDateTime.format(YEAR_MONTH_DAY_FORMATTER);
+            case TIMESTAMP_FORMAT:
+                return localDateTime.format(TIMESTAMP_FORMATTER);
+            case TIMESTAMP_FORMAT_EX:
+                return localDateTime.format(TIMESTAMP_EX_FORMATTER);
+            case TIMESTAMP_FORMAT_EX2:
+                return localDateTime.format(TIMESTAMP_EX2_FORMATTER);
+            case TIMESTAMP_FORMAT_EX3:
+                return localDateTime.format(TIMESTAMP_EX3_FORMATTER);
+            default:
+                return localDateTime.format(DateTimeFormatter.ofPattern(format));
+        }
+    }
+
+    private static LocalDateTime utcMsTime2LocalDateTime(long lUTC) {
+        if (!isMsUTC(lUTC)){
+            lUTC = lUTC*1000;
+        }
+        Instant instant = Instant.ofEpochMilli(lUTC);
+        ZoneId zone = ZoneId.systemDefault();
+        return LocalDateTime.ofInstant(instant, zone);
+    }
+
+    private static long localDateTime2UtcMsTime(LocalDateTime localDateTime) {
+        ZoneId zone = ZoneId.systemDefault();
+        Instant instant = localDateTime.atZone(zone).toInstant();
+        return instant.toEpochMilli();
+    }
+
+    private static long strTime2UtcMsTime(String dateStr, String format){
+        return localDateTime2UtcMsTime(strTime2LocalDateTime(dateStr, format));
+    }
+
+    private static String utcMsTime2StrTime(long lUTC, String format){
+        return localDateTime2StrTime(utcMsTime2LocalDateTime(lUTC), format);
+    }
+
+    public static long convertDateStr2UTC(String dateStr){
+        try {
+            dateStr = dateStr.trim();
+            int len = dateStr.length();
+            if (len >= 23)
+                return strTime2UtcMsTime(dateStr, TIMESTAMP_FORMAT_EX);
+            else if (len >= 19)
+                return strTime2UtcMsTime(dateStr, TIMESTAMP_FORMAT);
+            else if (len >= 14)
+                return strTime2UtcMsTime(dateStr, TIMESTAMP_FORMAT_EX2);
+            else if (len >= 10)//即dataStr为yyyy-MM-dd
+                return strTime2UtcMsTime(String.format("%s 00:00:00", dateStr), TIMESTAMP_FORMAT);
+            else if (len >= 8)//即dataStr为yyyyMMdd
+                return strTime2UtcMsTime(String.format("%s000000", dateStr), TIMESTAMP_FORMAT_EX2);
+            else if (len >= 7)//即dataStr为yyyy-MM
+                return strTime2UtcMsTime(String.format("%s-01 00:00:00", dateStr), TIMESTAMP_FORMAT);
+            else if (len >= 6)//即dataStr为yyyyMM
+                return strTime2UtcMsTime(String.format("%s01000000", dateStr), TIMESTAMP_FORMAT_EX2);
+            else if (len >= 4)//即dataStr为yyyy
+                return strTime2UtcMsTime(String.format("%s-01-01 00:00:00", dateStr), TIMESTAMP_FORMAT);
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    /**
+     * 指定UTC是否为精确到毫秒的UTC时间
+     * @param lUTC
+     * @return
+     */
+    public static boolean isMsUTC(long lUTC){
+        return lUTC > 10000000000L;
+    }
+
+    public static long getCurSecUTC(){
+        return (System.currentTimeMillis()/1000)*1000;
+    }
+
+    public static long getCurMsUTC(){
+        return System.currentTimeMillis();
+    }
+
+    /**
+     *
+     * @param lUTC  UTC时间格式(单位:毫秒)
+     * @param strDateFormat 日期格式模板:如:yyyy-MM-dd HH:mm:ss
+     * @return
+     */
+    public static String convertUTC2DateStr(long lUTC, String strDateFormat){
+        try {
+            return utcMsTime2StrTime(lUTC<=0?System.currentTimeMillis():lUTC
+                    , StringUtils.isEmpty(strDateFormat)?TIMESTAMP_FORMAT:strDateFormat);
+        }catch (Exception e){}
+        return "";
+    }
+
+    /**
+     * 从当前时间算起,还有多少毫秒今天将结束
+     * @return 所剩的毫秒数
+     */
+    public static long hasMsWhenTodayEnd(){
+        long lR = UTC_MS_TODAY_END+1-System.currentTimeMillis();
+        if (lR <= 0)
+            lR = 1;
+        return lR;
+    }
+
+    /**
+     * 获取过期时间
+     * @param nSeconds 从当前时间算起,nSeconds秒后过期
+     * @return UTC时间格式(单位:毫秒)
+     */
+    public static long createExpiredTime(long nSeconds){
+        nSeconds = nSeconds<0?0:nSeconds;
+        long nowMillis = System.currentTimeMillis();
+        return nowMillis+(nSeconds*1000);
+    }
+
+    /**
+     * 获取当天的开始时间
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:00:00:00.000所对应的时间戳
+     */
+    public static long getTodayBeginUTC(){
+        return LocalDateTime.of(LocalDate.now(), LocalTime.MIN)
+                .atZone(ZoneId.systemDefault())
+                .toInstant()
+                .toEpochMilli();
+        /*Calendar todayStart = Calendar.getInstance();
+        todayStart.set(Calendar.HOUR_OF_DAY, 0);
+        todayStart.set(Calendar.MINUTE, 0);
+        todayStart.set(Calendar.SECOND, 0);
+        todayStart.set(Calendar.MILLISECOND, 0);
+        return todayStart.getTime().getTime();*/
+    }
+
+    /**
+     * 获取当天距离最近的整点时刻
+     * @return UTC时间格式(单位:毫秒)
+     * @return
+     */
+    public static long getTodayLastHourUTC(){
+        return LocalDateTime.now().withMinute(0).withSecond(0).withNano(0)
+                .atZone(ZoneId.systemDefault())
+                .toInstant()
+                .toEpochMilli();
+    }
+
+    /**
+     * 获取指定时间当日的起始时刻(即00:00:00.000)
+     * @param tmMS
+     * @return
+     */
+    public static long getBeginUTCOfTime(long tmMS){
+        if (!isMsUTC(tmMS)){
+            tmMS = tmMS*1000;
+        }
+        LocalDateTime startOfDay = LocalDateTime.ofInstant(Instant.ofEpochMilli(tmMS), ZoneId.systemDefault()).with(LocalTime.MIN);
+        return startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    /**
+     * 获取指定时间当日的结束时刻(即23:59:59.999)
+     * @param tmMS
+     * @return
+     */
+    public static long getEndUTCOfTime(long tmMS){
+        if (!isMsUTC(tmMS)){
+            tmMS = tmMS*1000;
+        }
+        LocalDateTime startOfDay = LocalDateTime.ofInstant(Instant.ofEpochMilli(tmMS), ZoneId.systemDefault()).with(LocalTime.MAX);
+        return startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+    /**
+     * 获取当天的结束时间
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:23:59:59.999所对应的时间戳
+     */
+    public static long getTodayEndUTC(){
+        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX)
+                .atZone(ZoneId.systemDefault())
+                .toInstant()
+                .toEpochMilli();
+        /*Calendar todayStart = Calendar.getInstance();
+        todayStart.set(Calendar.HOUR_OF_DAY, 23);
+        todayStart.set(Calendar.MINUTE, 59);
+        todayStart.set(Calendar.SECOND, 59);
+        todayStart.set(Calendar.MILLISECOND, 999);
+        return todayStart.getTime().getTime();*/
+    }
+
+    /**
+     * 获取当前时间所在月份的开始时间戳
+     * @param curTime
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:xxxx-xx-01 00:00:00.000所对应的时间戳
+     */
+    public static long getMonthBeginUTC(long curTime){
+        Calendar c = Calendar.getInstance();
+        if (!isMsUTC(curTime))
+            curTime = curTime*1000;
+        try {
+            c.setTime(new Date(curTime));
+            c.set(Calendar.DAY_OF_MONTH, 1);
+            c.set(Calendar.HOUR_OF_DAY, 0);
+            c.set(Calendar.MINUTE, 0);
+            c.set(Calendar.SECOND,0);
+            c.set(Calendar.MILLISECOND, 0);
+            return c.getTimeInMillis();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    /**
+     * 获取当前时间所在月份的结束时间戳
+     * @param curTime
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:xxxx-xx-31 23:59:59.999所对应的时间戳
+     */
+    public static long getMonthEndUTC(long curTime){
+        Calendar c = Calendar.getInstance();
+        if (!isMsUTC(curTime))
+            curTime = curTime*1000;
+        try {
+            c.setTime(new Date(curTime));
+            c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
+            c.set(Calendar.HOUR_OF_DAY, 23);
+            c.set(Calendar.MINUTE, 59);
+            c.set(Calendar.SECOND,59);
+            c.set(Calendar.MILLISECOND, 999);
+            return c.getTimeInMillis();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始时间,UTC时间格式,秒或毫秒
+     * @param endTime 结束时间,UTC时间格式,秒或毫秒
+     * @return 月份字符串列表
+     * ["2018-01", "2018-02"]
+     */
+    public static List<String> getMonthListBetween(long startTime, long endTime){
+        ArrayList<String> arrMonth = new ArrayList<>();
+        if (!isMsUTC(startTime))
+            startTime = startTime*1000;
+        if (!isMsUTC(endTime))
+            endTime = endTime*1000;
+        try{
+            String strStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(startTime));
+            String strEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(endTime));
+            Date dtStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strStart);
+            Date dtEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strEnd);
+
+            Calendar dPos = Calendar.getInstance();
+            dPos.setTime(dtStart);                  //设置日期起始时间
+            while (dPos.getTime().before(dtEnd)) {
+                arrMonth.add((new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(dPos.getTime()));
+                dPos.add(Calendar.MONTH, 1);//进行当前日期月份加1
+            }
+            arrMonth.add(strEnd);
+        }catch (Exception e){e.printStackTrace();}
+        return arrMonth;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始时间,UTC时间格式,秒或毫秒
+     * @param endTime 结束时间,UTC时间格式,秒或毫秒
+     * @return 月份字符串列表
+     * ["201801", "201802"]
+     */
+    public static List<String> getMonthListBetweenEx(long startTime, long endTime){
+        ArrayList<String> arrMonth = new ArrayList<>();
+        if (!isMsUTC(startTime))
+            startTime = startTime*1000;
+        if (!isMsUTC(endTime))
+            endTime = endTime*1000;
+        try{
+            String strStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).format(new Date(startTime));
+            String strEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).format(new Date(endTime));
+            Date dtStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).parse(strStart);
+            Date dtEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).parse(strEnd);
+
+            Calendar dPos = Calendar.getInstance();
+            dPos.setTime(dtStart);                  //设置日期起始时间
+            while (dPos.getTime().before(dtEnd)) {
+                arrMonth.add((new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).format(dPos.getTime()));
+                dPos.add(Calendar.MONTH, 1);//进行当前日期月份加1
+            }
+            arrMonth.add(strEnd);
+        }catch (Exception e){e.printStackTrace();}
+        return arrMonth;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表UTC
+     * @param startTime 起始时间,UTC时间格式,秒或毫秒
+     * @param endTime 结束时间,UTC时间格式,秒或毫秒
+     * @return 月份UTC时间戳列表(精确到毫秒)
+     * [2018-01-01 00:00:00.000对应的UTC, 2018-02-01 00:00:00.000对应的UTC]
+     */
+    public static List<Long> getMonthUTCListBetween(long startTime, long endTime){
+        ArrayList<Long> arrMonth = new ArrayList<>();
+        if (!isMsUTC(startTime))
+            startTime = startTime*1000;
+        if (!isMsUTC(endTime))
+            endTime = endTime*1000;
+        try{
+            String strStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(startTime));
+            String strEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(endTime));
+            Date dtStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strStart);
+            Date dtEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strEnd);
+
+            Calendar dPos = Calendar.getInstance();
+            dPos.setTime(dtStart);                  //设置日期起始时间
+            while (dPos.getTime().before(dtEnd)) {
+                arrMonth.add(dPos.getTimeInMillis());
+                dPos.add(Calendar.MONTH, 1);//进行当前日期月份加1
+            }
+            arrMonth.add(dtEnd.getTime());
+        }catch (Exception e){e.printStackTrace();}
+        return arrMonth;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始月份,如:2018-01-01 00:00:00
+     * @param endTime 结束月份,如:2018-02-01 00:00:00
+     * @return 月份字符串列表
+     * ["2018-01", "2018-02"]
+     */
+    public static List<String> getMonthListBetween(String startTime, String endTime){
+        try {
+            //Date d1 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(startTime);
+            //Date d2 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(endTime);
+            return getMonthListBetween(convertDateStr2UTC(startTime), convertDateStr2UTC(endTime));
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始月份,如:2018-01-01 00:00:00
+     * @param endTime 结束月份,如:2018-02-01 00:00:00
+     * @return 月份字符串列表
+     * ["201801", "201802"]
+     */
+    public static List<String> getMonthListBetweenEx(String startTime, String endTime){
+        try {
+            //Date d1 = new SimpleDateFormat(YEAR_MONTH_FORMAT_EX).parse(startTime);
+            //Date d2 = new SimpleDateFormat(YEAR_MONTH_FORMAT_EX).parse(endTime);
+            return getMonthListBetweenEx(convertDateStr2UTC(startTime), convertDateStr2UTC(endTime));
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表UTC
+     * @param startTime 起始月份,如:2018-01-01 00:00:00
+     * @param endTime 结束月份,如:2018-02-01 00:00:00
+     * @return 月份UTC时间戳列表(精确到秒)
+     * [2018-01-01 00:00:00.000对应的UTC, 2018-02-01 00:00:00.000对应的UTC]
+     */
+    public static List<Long> getMonthUTCListBetween(String startTime, String endTime){
+        try {
+            Date d1 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(startTime);
+            Date d2 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(endTime);
+            return getMonthUTCListBetween(d1.getTime(), d2.getTime());
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * yyyyMMddhhmmss时间字符串转yyyy-MM-dd HH:mm:ss时间字符串
+     * @param strDateStr
+     * @return
+     */
+    public static String addSplitForDateStr(String strDateStr){
+        if (!StringUtils.isEmpty(strDateStr)){
+            try {
+                return localDateTime2StrTime(strTime2LocalDateTime(strDateStr, TIMESTAMP_FORMAT_EX2), TIMESTAMP_FORMAT);
+            }catch (Exception e){}
+        }
+        return "";
+    }
+
+    /**
+     * yyyyMMddhhmmss时间字符串转yyyy-MM-dd HH:mm:ss时间字符串
+     * @param strDateStr
+     * @param desDateFormat
+     * @return
+     */
+    public static String addSplitForDateStr(String strDateStr, String desDateFormat){
+        if (!StringUtils.isEmpty(strDateStr)){
+            try {
+                return localDateTime2StrTime(utcMsTime2LocalDateTime(convertDateStr2UTC(strDateStr)), desDateFormat);
+            }catch (Exception e){}
+        }
+        return "";
+    }
+
+    /**
+     * 修改指定时间的月份
+     * @param curTime
+     * @param month  > 0 在指定时间上加数个月;< 0 在指定时间上减数个月;
+     * @return
+     */
+    public static long getTimeChgMonth(long curTime, int month){
+        if (month == 0)
+            return curTime;
+        Calendar c = Calendar.getInstance();
+        if (!isMsUTC(curTime))
+            curTime = curTime*1000;
+        try {
+            c.setTime(new Date(curTime));
+            c.add(Calendar.MONTH, month);
+            return c.getTimeInMillis();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    public static String convertDateObj2DateStr(Date dateObj, String strDateFormat){
+        try {
+            int len = strDateFormat.length();
+            if (len >= 21)
+                return new SimpleDateFormat(TIMESTAMP_FORMAT_EX).format(dateObj);
+            else if (len >= 17)
+                return new SimpleDateFormat(TIMESTAMP_FORMAT).format(dateObj);
+            else if (len >= 12)
+                return new SimpleDateFormat(TIMESTAMP_FORMAT_EX2).format(dateObj);
+            else {
+                int splitCounts = CommTool.totalCharCountsInStr(strDateFormat, '-');
+                if (splitCounts <= 0)
+                    splitCounts = CommTool.totalCharCountsInStr(strDateFormat, '/');
+                if (splitCounts >= 2)
+                    return new SimpleDateFormat(YEAR_MONTH_DAY_FORMAT).format(dateObj);
+                else if (splitCounts >= 1)
+                    return new SimpleDateFormat(YEAR_MONTH_FORMAT).format(dateObj);
+                else
+                    return new SimpleDateFormat(YEAR_MONTH_FORMAT_EX).format(dateObj);
+            }
+        }catch (Exception e){}
+        return new SimpleDateFormat(YEAR_MONTH_DAY_FORMAT).format(dateObj);
+    }
+
+    /**
+     * 获取当前时间为星期几,取值范围[1,7]
+     * @param lUTC
+     * @return
+     */
+    public static int getDayIndexOfWeek(long lUTC){
+        LocalDateTime date = utcMsTime2LocalDateTime(lUTC);
+        if (date != null)
+            return date.getDayOfWeek().getValue();
+        return 0;
+    }
+
+    /**
+     * 获取当前时间为本月的第几天,取值范围[1,31]
+     * @param lUTC
+     * @return
+     */
+    public static int getDayIndexOfMonth(long lUTC){
+        LocalDateTime date = utcMsTime2LocalDateTime(lUTC);
+        if (date != null)
+            return date.getDayOfMonth();
+        return 0;
+    }
+
+    /**
+     * 获取当前时间所在月份的最后一天
+     * @param lUTC
+     * @return
+     */
+    public static int getLastDayIndexOfMonth(long lUTC){
+        return getDayIndexOfMonth(getMonthEndUTC(lUTC));
+    }
+
+    /**
+     * 获取当前时间为本年的第几月,取值范围[1,12]
+     * @param lUTC
+     * @return
+     */
+    public static int getCurMonthIndex(long lUTC){
+        LocalDateTime date = utcMsTime2LocalDateTime(lUTC);
+        if (date != null)
+            return date.getMonthValue();
+        return 0;
+    }
+
+    public static int getCurYearValue(long lUTC){
+        LocalDateTime date = utcMsTime2LocalDateTime(lUTC);
+        if (date != null)
+            return date.getYear();
+        return 0;
+    }
+}

+ 16 - 0
src/main/java/com/shkpr/service/aimodelpower/components/TrimStringField.java

@@ -0,0 +1,16 @@
+package com.shkpr.service.aimodelpower.components;
+
+import com.opencsv.bean.AbstractBeanField;
+import com.opencsv.exceptions.CsvConstraintViolationException;
+import com.opencsv.exceptions.CsvDataTypeMismatchException;
+import org.springframework.util.StringUtils;
+
+public class TrimStringField extends AbstractBeanField {
+    @Override
+    protected Object convert(String s) throws CsvDataTypeMismatchException, CsvConstraintViolationException {
+        if (!StringUtils.isEmpty(s))
+            return s.trim();
+        return s;
+    }
+}
+

+ 83 - 0
src/main/java/com/shkpr/service/aimodelpower/components/locks/BaseLockMgr.java

@@ -0,0 +1,83 @@
+package com.shkpr.service.aimodelpower.components.locks;
+
+import com.shkpr.service.aimodelpower.commtools.TimeTool;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+public abstract class BaseLockMgr {
+    private final byte[] LATCH_COMM = new byte[0];
+    private ConcurrentHashMap<String, CountDownLatchEx> COMMKEY2CDLatch = new ConcurrentHashMap<>();
+
+    public BaseLockMgr() {
+    }
+
+    /**
+     * 根据指定key获取单机版同一线程可重入锁(区别与分布式同步排他锁)
+     * @param key
+     * @param waitMsTm:等待响应的时长,单位:毫秒
+     * @return
+     * @throws Exception
+     */
+    public CountDownLatchEx tryLatchForXXX(String key, long waitMsTm) throws Exception{
+        if (StringUtils.isEmpty(key))
+            return null;
+
+        CountDownLatchEx oOldLatch = null;
+        synchronized (LATCH_COMM){
+            oOldLatch = COMMKEY2CDLatch.get(key);
+            if (oOldLatch == null){
+                oOldLatch = new CountDownLatchEx(key, true);
+                COMMKEY2CDLatch.put(key, oOldLatch);
+                return oOldLatch;
+            }
+        }
+
+        if (oOldLatch != null){
+            try {
+                return oOldLatch.tryLock(waitMsTm);
+            }catch (Exception ex){
+                throw ex;
+            }
+        }else
+            return null;
+
+        /*CountDownLatchEx oLatchOld = COMMKEY2CDLatch.get(key);
+        if (oLatchOld != null){
+            try {
+                if (waitMsTm < 0)
+                    oLatchOld.await();
+                else if (!oLatchOld.await(waitMsTm, TimeUnit.MILLISECONDS))
+                    return null;//指定时间内仍未获得信号
+            }catch (Exception ex){
+                throw ex;
+            }
+        }
+
+        synchronized (LATCH_COMM){
+            CountDownLatchEx oLatchNew = COMMKEY2CDLatch.get(key);
+            if (oLatchNew != null && !oLatchNew.equals(oLatchOld))
+                return null;
+
+            oLatchNew = new CountDownLatchEx(key, 1);
+            COMMKEY2CDLatch.put(key, oLatchNew);
+            return oLatchNew;
+        }*/
+    }
+
+    public void timerReleaseLatch(){
+        List<String> keys =  new ArrayList<>(COMMKEY2CDLatch.keySet());
+        long lCurTm = System.currentTimeMillis();
+        for (String key:keys){
+            CountDownLatchEx oOldLatch = COMMKEY2CDLatch.get(key);
+            long lEndTm = oOldLatch!=null?oOldLatch.getEndLockTM():0L;
+            if (lEndTm > 0L && (lCurTm - lEndTm >= TimeTool.MS_ONE_DAY)){
+                synchronized (LATCH_COMM){
+                    COMMKEY2CDLatch.remove(key);
+                }
+            }
+        }
+    }
+}

+ 134 - 0
src/main/java/com/shkpr/service/aimodelpower/components/locks/CountDownLatchEx.java

@@ -0,0 +1,134 @@
+package com.shkpr.service.aimodelpower.components.locks;
+
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 1) 同一线程下可重入锁;但不支持父子线程之间的可重入锁
+ * 2) 不同的线程之间互斥等待
+ */
+public class CountDownLatchEx {
+    private final byte[] LATCH_COMM = new byte[0];
+    private volatile long endLockTM = 0L;
+    private volatile Thread lockedBy = null;
+    private volatile int lockedCount = 0;
+    private boolean isReentrant = true;  //是否定义为可重入锁
+    private String strTag = "";
+    private Map<Thread, CountDownLatch> subThreadId2Wait = new HashMap<>();
+
+    public CountDownLatchEx(String tag, boolean reentrant) {
+        this.lockedCount = 1;
+        this.lockedBy = Thread.currentThread();
+        this.strTag = (StringUtils.isEmpty(tag)?this.getClass().getSimpleName():tag);
+        this.isReentrant = reentrant;
+        subThreadId2Wait.put(lockedBy, new CountDownLatch(1));
+    }
+
+    public void countDown() {
+        synchronized (LATCH_COMM){
+            if (lockedCount > 0 && Thread.currentThread() == lockedBy){
+                List<CountDownLatch> waitLatch = new ArrayList<>(subThreadId2Wait.values());
+                subThreadId2Wait.clear();
+                lockedCount--;
+                if (lockedCount == 0)
+                    endLockTM = System.currentTimeMillis();
+                for (CountDownLatch oLatch:waitLatch)
+                    oLatch.countDown();
+                waitLatch.clear();
+            }
+        }
+    }
+
+    private void removeWaitLatch(Thread thread){
+        synchronized (LATCH_COMM){
+            subThreadId2Wait.remove(thread);
+        }
+    }
+
+    private CountDownLatch getWaitLatch(Thread thread){
+        synchronized (LATCH_COMM){
+            CountDownLatch subThreadWait = subThreadId2Wait.get(thread);
+            if (subThreadWait == null){
+                subThreadWait = new CountDownLatch(1);
+                subThreadId2Wait.put(thread, subThreadWait);
+            }
+            return subThreadWait;
+        }
+    }
+
+    public CountDownLatchEx tryLock(long waitMsTm) throws InterruptedException {
+        Thread thread = Thread.currentThread();
+        if (waitMsTm < 0){
+            while (lockedCount > 0 && (!isReentrant || lockedBy != thread)){
+                CountDownLatch waitLatch = getWaitLatch(thread);
+                if (waitLatch != null){
+                    try {
+                        waitLatch.await();
+                    }catch (InterruptedException ee){
+                        removeWaitLatch(thread);
+                        throw ee;
+                    }
+                }else
+                    return null;
+            }
+        }else {
+            long canWaitMsTm = waitMsTm;
+            while (canWaitMsTm > 0 && lockedCount > 0 && (!isReentrant || lockedBy != thread)){
+                CountDownLatch waitLatch = getWaitLatch(thread);
+                if (waitLatch != null){
+                    long startWait = System.currentTimeMillis();
+                    try {
+                        waitLatch.await(canWaitMsTm, TimeUnit.MILLISECONDS);
+                    }catch (InterruptedException ee){
+                        removeWaitLatch(thread);
+                        throw ee;
+                    }
+                    canWaitMsTm = canWaitMsTm - (System.currentTimeMillis() - startWait);
+                }else
+                    return null;
+            }
+        }
+
+        synchronized (LATCH_COMM){
+            if (lockedCount > 0 && (!isReentrant || lockedBy != thread)){
+                removeWaitLatch(thread);
+                return null;
+            }
+
+            lockedCount++;
+            lockedBy = thread;
+            endLockTM = 0L;
+            return this;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return strTag.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (!(obj instanceof CountDownLatchEx)) {
+            return false;
+        }
+
+        CountDownLatchEx other = (CountDownLatchEx)obj;
+        if (other.strTag.equals(this.strTag))
+            return true;
+        return false;
+    }
+
+    public long getEndLockTM() {
+        synchronized (LATCH_COMM){
+            return endLockTM;
+        }
+    }
+}

+ 26 - 0
src/main/java/com/shkpr/service/aimodelpower/components/validators/IntInitOrRange.java

@@ -0,0 +1,26 @@
+package com.shkpr.service.aimodelpower.components.validators;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+@Documented
+@Constraint(validatedBy = {IntInitOrRangeV.class})
+@Target({ ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IntInitOrRange {
+    String message() default "Filed Or Param Is Invalid";
+    int init() default 0;
+    int min() default 0;
+    int max() default 2147483647;
+
+    Class<?>[] groups() default {};
+    Class<? extends Payload>[] payload() default {};
+
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    @Retention(RetentionPolicy.RUNTIME)
+    @Documented
+    public @interface List {
+        IntInitOrRange[] value();
+    }
+}

+ 30 - 0
src/main/java/com/shkpr/service/aimodelpower/components/validators/IntInitOrRangeV.java

@@ -0,0 +1,30 @@
+package com.shkpr.service.aimodelpower.components.validators;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * (1) 要么为init初始值 (2)要么取值范围在[min, max]之间
+ */
+public class IntInitOrRangeV implements ConstraintValidator<IntInitOrRange, Integer> {
+    int init = 0;
+    int min = 0;
+    int max = 2147483647;
+
+    @Override
+    public void initialize(IntInitOrRange constraintAnnotation) {
+        init = constraintAnnotation.init();
+        min = constraintAnnotation.min();
+        max = constraintAnnotation.max();
+    }
+
+    @Override
+    public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
+        if (integer != null
+                && (integer.intValue() == init
+                    || (integer.intValue() >= min && integer.intValue() <= max))) {
+            return true;
+        }
+        return false;
+    }
+}

+ 25 - 0
src/main/java/com/shkpr/service/aimodelpower/components/validators/ListNullOrSize.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.aimodelpower.components.validators;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+@Documented
+@Constraint(validatedBy = {ListNullOrSizeV.class})
+@Target({ ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ListNullOrSize {
+    String message() default "Filed Or Param Is Invalid";
+    int min() default 0;
+    int max() default 2147483647;
+
+    Class<?>[] groups() default {};
+    Class<? extends Payload>[] payload() default {};
+
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    @Retention(RetentionPolicy.RUNTIME)
+    @Documented
+    public @interface List {
+        ListNullOrSize[] value();
+    }
+}

+ 26 - 0
src/main/java/com/shkpr/service/aimodelpower/components/validators/ListNullOrSizeV.java

@@ -0,0 +1,26 @@
+package com.shkpr.service.aimodelpower.components.validators;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.List;
+
+/**
+ * (1) 为null  (2) 不为null时,要求size在[min, max]之间
+ */
+public class ListNullOrSizeV implements ConstraintValidator<ListNullOrSize, List> {
+    int min = 0;
+    int max = 2147483647;
+
+    @Override
+    public void initialize(ListNullOrSize constraintAnnotation) {
+        min = constraintAnnotation.min();
+        max = constraintAnnotation.max();
+    }
+
+    @Override
+    public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) {
+        if (list == null || (list.size() >= min && list.size() <= max))
+            return true;
+        return false;
+    }
+}

+ 25 - 0
src/main/java/com/shkpr/service/aimodelpower/components/validators/StrNullOrSize.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.aimodelpower.components.validators;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+@Documented
+@Constraint(validatedBy = {StrNullOrSizeV.class})
+@Target({ ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface StrNullOrSize {
+    String message() default "Filed Or Param Is Invalid";
+    int min() default 0;
+    int max() default 2147483647;
+
+    Class<?>[] groups() default {};
+    Class<? extends Payload>[] payload() default {};
+
+    @Target({ElementType.FIELD, ElementType.PARAMETER})
+    @Retention(RetentionPolicy.RUNTIME)
+    @Documented
+    public @interface List {
+        StrNullOrSize[] value();
+    }
+}

+ 25 - 0
src/main/java/com/shkpr/service/aimodelpower/components/validators/StrNullOrSizeV.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.aimodelpower.components.validators;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * (1) 为null  (2) 不为null时,要求size在[min, max]之间
+ */
+public class StrNullOrSizeV implements ConstraintValidator<StrNullOrSize, String> {
+    int min = 0;
+    int max = 2147483647;
+
+    @Override
+    public void initialize(StrNullOrSize constraintAnnotation) {
+        min = constraintAnnotation.min();
+        max = constraintAnnotation.max();
+    }
+
+    @Override
+    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
+        if (s == null || (s.length() >= min && s.length() <= max))
+            return true;
+        return false;
+    }
+}

+ 22 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/CaffeineConfiguration.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.github.benmanes.caffeine.cache.RemovalCause;
+import com.github.benmanes.caffeine.cache.RemovalListener;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+public class CaffeineConfiguration {
+    @Value("${local.cache.max.size.order.seq:1000}")
+    private int orderSeqMaxCacheSize;   //Cache可存储的最大orderSeq数量;
+
+    class CustomRemovalListener implements RemovalListener<Object, Object> {
+        @Override
+        public void onRemoval(Object key, Object value, RemovalCause cause) {
+            //System.out.format("removal listerner called with key [%s], cause [%s], evicted [%S]\n",
+            //        key, cause.toString(), cause.wasEvicted());
+        }
+    }
+}

+ 60 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/DBMgrConfiguration.java

@@ -0,0 +1,60 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.aimodelpower.constants.LogFlagBusiType;
+import com.shkpr.service.aimodelpower.dbdao.DBMgrProxy;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+
+@Configuration
+@EnableAutoConfiguration
+public class DBMgrConfiguration {
+    @Value("${global.log.switch.info:true}")                //所有业务Info级别的日志开关标识
+    private boolean mBAllInfoLogPrintFlag;
+
+    @Value("${global.log.switch.info.user:true}")
+    private boolean mBUserInfoLogPrintFlag;                  //用户业务Info级别的日志开关标识
+
+    @Value("${global.log.switch.info.auth:true}")
+    private boolean mBAuthInfoLogPrintFlag;                  //验证业务Info级别的日志开关标识
+
+    @Value("${global.log.switch.info.db.user:true}")
+    private boolean mBDatabaseUserInfoLogPrintFlag;               //Database中用户业务Info级别的日志开关标识
+
+    @Value("${global.lan.test.log:false}")
+    private boolean mBInnerTest = false;
+
+    public DBMgrConfiguration() {
+    }
+
+    @PostConstruct
+    public void init(){
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogPrintMgr.ALL_BUSI_SWITCH, mBAllInfoLogPrintFlag);
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INIT.toStrValue(), true);
+
+        if (mBInnerTest)
+            return;
+
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_USER.toStrValue(), mBUserInfoLogPrintFlag);
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_AUTH.toStrValue(), mBAuthInfoLogPrintFlag);
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_ROLE_POWER.toStrValue(), true);
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_PARTITION.toStrValue(), true);
+
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_DB_USER.toStrValue(), mBDatabaseUserInfoLogPrintFlag);
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_DB_ROLE_POWER.toStrValue(), true);
+        LogPrintMgr.getInstance().setLogSwitch(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_DB_PARTITION.toStrValue(), true);
+    }
+
+    //使用时可用@Qualifier("startDBMgrProxy")进行识别
+    @Bean
+    public DBMgrProxy startDBMgrProxy(){
+        DBMgrProxy.getInstance().init();
+        return DBMgrProxy.getInstance();
+    }
+}
+

+ 69 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/GlobalParamConfiguration.java

@@ -0,0 +1,69 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.global.base.thread.ThreadPoolProxy;
+import com.global.base.tools.EncryptionUtil;
+import com.global.base.tools.RandomUtil;
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+
+
+@Configuration
+@EnableAutoConfiguration
+public class GlobalParamConfiguration {
+    @Value("${global.http.status.200:true}")
+    private boolean mBHttpStatusAlready200;                       //Http Status是否总是返回200ok,即所有错误码只能在body当中
+
+    @Value("${global.local.cache.switch:true}")                   //是否启用本地缓存策略
+    private boolean mBUseLocalCache;
+
+    @Value("${global.enable.async.subtask.cpucores:8}")         //启动异步子任务的最小cpu核心数
+    private int mNCpuCoresForEnableAsyncSubTask = 8;
+
+    @Value("${global.internal.operator.account:TriCooperation}")
+    private String mStrInternalOperatorAccount = "";
+
+    @Value("${global.internal.operator.password:123@asd}")       //123@asd的BCypte加盐值
+    private String mStrInternalOperatorPassword = "";
+
+    @Value("${global.service.online.time:0}")                      //服务上线的时间
+    private long mTmUTCServiceOnline = 0L;
+
+    @Value("${global.push.slip.period.new.alarm:0}")
+    private int mSlipPeriodPushNewAlarm = 0;
+
+    @Value("${global.push.slip.period.urge.alarm:0}")
+    private int mSlipPeriodPushUrgeAlarm = 0;
+
+    @Value("${global.internal.call.password:}")
+    private String mStrInternalCallPassword = "";
+
+    public GlobalParamConfiguration() {
+    }
+
+    @PostConstruct
+    public void init(){
+        GlobalData.getInstance().setHttpStatusAlready200(mBHttpStatusAlready200);
+        GlobalData.getInstance().setUseLocalCache(mBUseLocalCache);
+        GlobalData.getInstance().setCpuCoresForEnableAsyncSubTask(mNCpuCoresForEnableAsyncSubTask);
+        GlobalData.getInstance().setStrOperatorAccount(mStrInternalOperatorAccount);
+        GlobalData.getInstance().setStrOperatorPassword(mStrInternalOperatorPassword);
+        GlobalData.getInstance().setInternalCallPassword(EncryptionUtil.MD5Hash(StringUtils.isEmpty(mStrInternalCallPassword)? RandomUtil.getRandomStr(8):mStrInternalCallPassword));
+
+        if (mTmUTCServiceOnline > 0L)
+            GlobalData.getInstance().setTmUTCServiceOnline(mTmUTCServiceOnline);
+
+        ThreadPoolProxy.getInstance().getFixedThreadPool("COMM").execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(10000);
+                }catch (Exception e){}
+           }
+        });
+    }
+}

+ 117 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/MainSourceConfiguration.java

@@ -0,0 +1,117 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.shkpr.service.aimodelpower.dbdao.mapper", sqlSessionTemplateRef = "mainSqlSessionTemplate")
+@PropertySource(value = "file:${global.sql.config.path}", ignoreResourceNotFound = true, encoding="utf-8")
+public class MainSourceConfiguration {
+    @Value("${spring.datasource.data.driver-class-name:}")
+    private String driveClass = "org.postgresql.Driver";
+
+    @Value("${spring.datasource.data.jdbc-url:}")
+    private String url = "";
+
+    @Value("${spring.datasource.data.username:}")
+    private String username = "";
+
+    @Value("${spring.datasource.data.password:}")
+    private String password = "";
+
+    @Value("${spring.datasource.data.maximum-pool-size:200}")
+    private Integer maxPoolSize;
+
+    @Value("${spring.datasource.data.minimum-idle:1}")
+    private Integer minIdle;
+
+    @Value("${spring.datasource.data.connection-test-query:}")
+    private String connectionTestQuery;
+
+    @Value("${spring.datasource.data.max-lifetime:120000}")
+    private Long maxLifetime;
+
+    @Value("${spring.datasource.data.idle-timeout:30000}")
+    private Long idleTimeout;
+
+    @Value("${spring.datasource.data.connection-timeout:30000}")
+    private Long connectionTimeout;
+
+    @Value("${spring.datasource.data.validation-timeout:30000}")
+    private Long validTimeout;
+
+    @Value("${spring.datasource.data.init-failed-timeout:-1}")
+    private Long initFailedTimeout;
+
+    @Bean(name = "mainDatasource")
+    //@ConfigurationProperties(prefix = "spring.datasource.data")
+    public DataSource mainDataSource() {
+        HikariDataSource obj = new HikariDataSource(getConfig());
+        try {
+            obj.setLoginTimeout((int)(connectionTimeout/1000));
+        }catch (Exception e){}
+        return obj;
+        //return DataSourceBuilder.create().build();
+        //Spring Boot 2.x默认使用HikariCP
+    }
+
+    private HikariConfig getConfig() {
+        HikariConfig hikariConfig = new HikariConfig();
+        hikariConfig.setDriverClassName(driveClass);
+        hikariConfig.setJdbcUrl(url);
+        hikariConfig.setUsername(username);
+        hikariConfig.setPassword(password);
+
+        hikariConfig.setMaximumPoolSize(maxPoolSize);
+        hikariConfig.setMinimumIdle(minIdle);
+        hikariConfig.setConnectionTestQuery(connectionTestQuery);
+        hikariConfig.setMaxLifetime(maxLifetime);
+        hikariConfig.setIdleTimeout(idleTimeout);
+        hikariConfig.setConnectionTimeout(connectionTimeout);
+        hikariConfig.setValidationTimeout(validTimeout);
+        hikariConfig.setInitializationFailTimeout(initFailedTimeout);
+        return hikariConfig;
+    }
+
+    @Bean("mainSqlSessionFactory")
+    public SqlSessionFactory mainSqlSessionFactoryBean(@Qualifier("mainDatasource") DataSource dataSource) throws Exception {
+        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
+        sessionFactoryBean.setDataSource(dataSource);
+
+        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
+        configuration.setCallSettersOnNulls(true);       //数据库中字段值为null时也要求返回
+        configuration.setMapUnderscoreToCamelCase(true); //开启驼峰映射
+        configuration.setCacheEnabled(false);
+        sessionFactoryBean.setConfiguration(configuration);
+        return sessionFactoryBean.getObject();
+    }
+
+    @Bean("mainSqlSessionTemplate")
+    public SqlSessionTemplate mainSqlSessionTemplate(@Qualifier("mainSqlSessionFactory") SqlSessionFactory sessionFactory) {
+        return new SqlSessionTemplate(sessionFactory);
+    }
+
+    @Bean(name = "mainDbTransactionManager")
+    public DataSourceTransactionManager mainDbTransactionManager(@Qualifier("mainDatasource") DataSource dataSource){
+        return new DataSourceTransactionManager(dataSource);
+    }
+
+    @PostConstruct
+    public void init(){
+        GlobalData.getInstance().setPostGisValid("org.postgis.DriverWrapper".equals(driveClass));
+    }
+}

+ 35 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/RestTemplateConfig.java

@@ -0,0 +1,35 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.shkpr.service.aimodelpower.factorys.SslClientHttpRequestFactory;
+import com.shkpr.service.aimodelpower.services.ServiceMgrProxy;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+@EnableAutoConfiguration
+public class RestTemplateConfig {
+
+    @Bean(name = "RestTemplateEx")
+    public RestTemplate restTemplate(@Qualifier("ClientHttpRequestFactoryEx") ClientHttpRequestFactory factory) {
+        return new RestTemplate(factory);
+    }
+
+    @Bean("ClientHttpRequestFactoryEx")
+    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
+        //SimpleClientHttpRequestFactory factory1 = new SimpleClientHttpRequestFactory();
+        SslClientHttpRequestFactory factory = new SslClientHttpRequestFactory();
+        factory.setReadTimeout(30000);
+        factory.setConnectTimeout(30000);
+        return factory;
+    }
+
+    @Bean
+    public ServiceMgrProxy startServiceMgrProxy(){
+        ServiceMgrProxy.getInstance().init();
+        return ServiceMgrProxy.getInstance();
+    }
+}

+ 45 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/RetryTemplateConfig.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.retry.backoff.ExponentialBackOffPolicy;
+import org.springframework.retry.backoff.FixedBackOffPolicy;
+import org.springframework.retry.policy.SimpleRetryPolicy;
+import org.springframework.retry.support.RetryTemplate;
+
+@Configuration
+@EnableAutoConfiguration
+public class RetryTemplateConfig {
+    @Primary
+    @Bean(name = "Normal3Retry")
+    public RetryTemplate normal3Retry(){
+        RetryTemplate template = new RetryTemplate();
+        SimpleRetryPolicy policy = new SimpleRetryPolicy();//默认最大重试次数为3
+
+        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
+        backOffPolicy.setInitialInterval(200L);
+        backOffPolicy.setMaxInterval(200L);
+        backOffPolicy.setMultiplier(2.0);//第一次间隔为T1=200ms,第二次为T2=2*T1=400ms,第三次为T3=2*T2=800ms
+
+        template.setBackOffPolicy(backOffPolicy);
+        template.setRetryPolicy(policy);
+
+        return template;
+    }
+
+    @Bean(name = "FixedPeriod3Retry")
+    public RetryTemplate fixedPeriod3Retry(){
+        RetryTemplate template = new RetryTemplate();
+        SimpleRetryPolicy policy = new SimpleRetryPolicy();//默认最大重试次数为3
+
+        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
+        fixedBackOffPolicy.setBackOffPeriod(500L); //每次重试固定间隔500ms
+
+        template.setBackOffPolicy(fixedBackOffPolicy);
+        template.setRetryPolicy(policy);
+
+        return template;
+    }
+}

+ 77 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/ScheduleTaskConfiguration.java

@@ -0,0 +1,77 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.aimodelpower.commtools.TimeTool;
+import com.shkpr.service.aimodelpower.constants.LogFlagBusiType;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+import javax.annotation.PostConstruct;
+import java.lang.reflect.Method;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.Executor;
+
+@Configuration
+@EnableScheduling
+public class ScheduleTaskConfiguration implements SchedulingConfigurer, AsyncConfigurer {
+    private String mStrClassName;
+    public ScheduleTaskConfiguration() {
+        mStrClassName = this.getClass().getSimpleName();
+    }
+
+    @Override
+    public Executor getAsyncExecutor() {
+        Executor executor = taskScheduler();
+        return executor;
+    }
+
+    @Override
+    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+        return new AsyncUncaughtExceptionHandler() {
+            @Override
+            public void handleUncaughtException(Throwable ex, Method method, Object... params) {
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, LogFlagBusiType.BUSI_INIT.toStrValue(), mStrClassName
+                        ,String.format("AsyncUncaughtException(method="+method.getName()+", msg="+ex.getMessage()+")..."));
+            }
+        };
+    }
+
+    @Override
+    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
+        TaskScheduler taskScheduler = taskScheduler();
+        scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
+    }
+
+    /** 定时任务多线程处理 */
+    @Bean(destroyMethod = "shutdown")
+    public ThreadPoolTaskScheduler taskScheduler(){
+        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+        scheduler.setPoolSize(5);
+        scheduler.setThreadNamePrefix("Time-Task-");
+        //设置线程池中任务的等待时间,如果超过这个时间还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。
+        //如:kill [PID]后,最大等待时长为5秒钟
+        scheduler.setAwaitTerminationSeconds(5);
+        //设置线程池关闭的时候等待所有任务都完成后,再继续销毁其他的Bean,这样这些异步任务的销毁就会先于数据库连接池对象的销毁
+        scheduler.setWaitForTasksToCompleteOnShutdown(true);
+        return scheduler;
+    }
+
+    @PostConstruct
+    public void init(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                TimeTool.refreshUTCTimeRes();
+            }
+        }, 1000);//延时1秒执行
+    }
+}

+ 116 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/SecondSourceConfiguration.java

@@ -0,0 +1,116 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.shkpr.service.aimodelpower.dbdao.mapper2th", sqlSessionTemplateRef = "secondSqlSessionTemplate")
+@PropertySource(value = "file:${global.sql.config.path}", ignoreResourceNotFound = true, encoding="utf-8")
+public class SecondSourceConfiguration {
+    @Value("${spring.datasource.data2.driver-class-name:}")
+    private String driveClass = "org.postgresql.Driver";
+
+    @Value("${spring.datasource.data2.jdbc-url:}")
+    private String url = "";
+
+    @Value("${spring.datasource.data2.username:}")
+    private String username = "";
+
+    @Value("${spring.datasource.data2.password:}")
+    private String password = "";
+
+    @Value("${spring.datasource.data2.maximum-pool-size:200}")
+    private Integer maxPoolSize;
+
+    @Value("${spring.datasource.data2.minimum-idle:1}")
+    private Integer minIdle;
+
+    @Value("${spring.datasource.data2.connection-test-query:}")
+    private String connectionTestQuery;
+
+    @Value("${spring.datasource.data2.max-lifetime:120000}")
+    private Long maxLifetime;
+
+    @Value("${spring.datasource.data2.idle-timeout:30000}")
+    private Long idleTimeout;
+
+    @Value("${spring.datasource.data2.connection-timeout:30000}")
+    private Long connectionTimeout;
+
+    @Value("${spring.datasource.data2.validation-timeout:30000}")
+    private Long validTimeout;
+
+    @Value("${spring.datasource.data2.init-failed-timeout:-1}")
+    private Long initFailedTimeout;
+
+    @Bean(name = "secondDatasource")
+    //@ConfigurationProperties(prefix = "spring.datasource.data2")
+    public DataSource secondDataSource() {
+        HikariDataSource obj = new HikariDataSource(getConfig());
+        try {
+            obj.setLoginTimeout((int)(connectionTimeout/1000));
+        }catch (Exception e){}
+        return obj;
+        //return DataSourceBuilder.create().build();
+        //Spring Boot 2.x默认使用HikariCP
+    }
+
+    private HikariConfig getConfig() {
+        HikariConfig hikariConfig = new HikariConfig();
+        hikariConfig.setDriverClassName(driveClass);
+        hikariConfig.setJdbcUrl(url);
+        hikariConfig.setUsername(username);
+        hikariConfig.setPassword(password);
+
+        hikariConfig.setMaximumPoolSize(maxPoolSize);
+        hikariConfig.setMinimumIdle(minIdle);
+        hikariConfig.setConnectionTestQuery(connectionTestQuery);
+        hikariConfig.setMaxLifetime(maxLifetime);
+        hikariConfig.setIdleTimeout(idleTimeout);
+        hikariConfig.setConnectionTimeout(connectionTimeout);
+        hikariConfig.setValidationTimeout(validTimeout);
+        hikariConfig.setInitializationFailTimeout(initFailedTimeout);
+        return hikariConfig;
+    }
+
+    @Bean("secondSqlSessionFactory")
+    public SqlSessionFactory secondSqlSessionFactoryBean(@Qualifier("secondDatasource") DataSource dataSource) throws Exception {
+        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
+        sessionFactoryBean.setDataSource(dataSource);
+
+        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
+        configuration.setCallSettersOnNulls(true);       //数据库中字段值为null时也要求返回
+        configuration.setMapUnderscoreToCamelCase(true); //开启驼峰映射
+        configuration.setCacheEnabled(false);
+        sessionFactoryBean.setConfiguration(configuration);
+        return sessionFactoryBean.getObject();
+    }
+
+    @Bean("secondSqlSessionTemplate")
+    public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory") SqlSessionFactory sessionFactory) {
+        return new SqlSessionTemplate(sessionFactory);
+    }
+
+    @Bean(name = "secondDbTransactionManager")
+    public DataSourceTransactionManager secondDbTransactionManager(@Qualifier("secondDatasource") DataSource dataSource){
+        return new DataSourceTransactionManager(dataSource);
+    }
+
+    @PostConstruct
+    public void init(){
+        //GlobalData.getInstance().setPostGisValid("org.postgis.DriverWrapper".equals(driveClass));
+    }
+}

+ 45 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/TaskQueueConfiguration.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.global.base.thread.ThreadPoolProxy;
+import com.shkpr.service.aimodelpower.globalmgr.AsyncTaskQueueMgr;
+import com.shkpr.service.aimodelpower.globalmgr.DelayTaskQueueMgr;
+import com.shkpr.service.aimodelpower.globalmgr.NotifyMsgQueueMgr;
+import com.shkpr.service.aimodelpower.globalmgr.TraceLogMgr;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+
+@Configuration
+@EnableAutoConfiguration
+public class TaskQueueConfiguration {
+    public TaskQueueConfiguration() {
+    }
+
+    @PostConstruct
+    public void init(){
+        ThreadPoolProxy.getInstance().getFixedThreadPool("COMM").execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(5000);
+                }catch (Exception e){}
+
+                TraceLogMgr.setTraceIdByBusinessType("INIT.RECHECK.PUSH.EVENT.DB");
+                TraceLogMgr.removeTraceId();
+            }
+        });
+    }
+
+    //使用时可用@Qualifier("startAsyncTaskQueueMgr")进行识别
+    @Bean
+    public AsyncTaskQueueMgr startAsyncTaskQueueMgr() {return AsyncTaskQueueMgr.getInstance();}
+
+    //使用时可用@Qualifier("startDelayTaskQueueMgr")进行识别
+    @Bean
+    public DelayTaskQueueMgr startDelayTaskQueueMgr() {return DelayTaskQueueMgr.getInstance();}
+
+    @Bean
+    public NotifyMsgQueueMgr startNotifyMsgQueueMgr() {return NotifyMsgQueueMgr.getInstance();}
+}

+ 53 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/ValidatorConfiguration.java

@@ -0,0 +1,53 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import org.hibernate.validator.HibernateValidator;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.executable.ExecutableValidator;
+
+@Configuration
+@EnableAutoConfiguration
+public class ValidatorConfiguration {
+
+    @Bean
+    public MethodValidationPostProcessor selfMethodValidationPostProcessor() {
+        MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
+        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
+                .configure()
+                .addProperty( "hibernate.validator.fail_fast", "true" )
+                .buildValidatorFactory();
+        postProcessor.setValidator(validatorFactory.getValidator()/*selfValidator()*/);//设置validator模式为快速失败返回
+        return postProcessor;
+    }
+
+    //用于校验属性或变量
+    //使用时可用@Qualifier("selfValidator")进行识别
+    @Bean
+    public Validator selfValidator(){
+        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
+                .configure()
+                .addProperty( "hibernate.validator.fail_fast", "true" )
+                .buildValidatorFactory();
+        GlobalData.getInstance().setValidForParam(validatorFactory.getValidator());
+        return GlobalData.getInstance().getValidForParam();
+    }
+
+    //用于校验函数接口
+    //使用时可用@Qualifier("selfExeValidator")进行识别
+    @Bean
+    public ExecutableValidator selfExeValidator(){
+        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
+                .configure()
+                .addProperty( "hibernate.validator.fail_fast", "true" )
+                .buildValidatorFactory();
+        GlobalData.getInstance().setValidForFun(validatorFactory.getValidator().forExecutables());
+        return GlobalData.getInstance().getValidForFun();
+    }
+}

+ 96 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/WebMvcConfiguration.java

@@ -0,0 +1,96 @@
+package com.shkpr.service.aimodelpower.configuration;
+import com.shkpr.service.aimodelpower.SpringContextUtil;
+import com.shkpr.service.aimodelpower.interfaces.URIInterceptorIntef;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.http.HttpMethod;
+import org.springframework.util.StringUtils;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.*;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * 该类主要用来注册各种Controller拦截器
+ * WebSecurityConfig类中注册的过滤器JWTLoginFilter、JWTAuthenticationFilter优先于该类中注册的拦截器URIInterceptorIntef
+ * 过滤拦截顺序: JWTLoginFilter--->JWTAuthenticationFilter--->URIInterceptorIntef
+ */
+@Configuration
+@EnableWebMvc
+public class WebMvcConfiguration implements WebMvcConfigurer{
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        @SuppressWarnings("static-access")
+        Map<String, URIInterceptorIntef> mapURLInterceptorByOrder = new TreeMap<String, URIInterceptorIntef>(); //TreeMap默认按键值升序
+        Map<String, URIInterceptorIntef> mapURLInterceptor = SpringContextUtil.getApplicationContext().getBeansOfType(URIInterceptorIntef.class);  //获取URIInterceptorIntef类型的所有Component组件
+        if (!StringUtils.isEmpty(mapURLInterceptor)){
+            Iterator it = mapURLInterceptor.entrySet().iterator();
+            while (it.hasNext()){
+                Map.Entry entry = (Map.Entry)it.next();
+                URIInterceptorIntef urlInterceptor = (URIInterceptorIntef)entry.getValue();
+                if (urlInterceptor != null){
+                    mapURLInterceptorByOrder.put(String.valueOf(urlInterceptor.order()), urlInterceptor);
+                }
+            }
+        }
+
+        if (!StringUtils.isEmpty(mapURLInterceptorByOrder)){
+            Iterator it = mapURLInterceptorByOrder.entrySet().iterator();
+            while (it.hasNext()){
+                Map.Entry entry = (Map.Entry)it.next();
+                //System.out.println("WebMvcConfig::addInterceptors() key="+(String) entry.getKey());
+                URIInterceptorIntef urlInterceptor = (URIInterceptorIntef)entry.getValue();
+                if (urlInterceptor != null){
+                    String[] arrForbidUrls = urlInterceptor.forbidPathPatterns();
+                    if (arrForbidUrls == null)
+                        arrForbidUrls = new String[]{};
+                    String[] arrExcludeUrls = urlInterceptor.excludePathPatterns();
+                    if (arrExcludeUrls == null){
+                        //多个拦截器将按照链接的顺序依次匹配拦截(注:有可能多个拦截器都匹配成功,则多个拦截器依次执行)
+                        registry.addInterceptor(urlInterceptor).addPathPatterns(arrForbidUrls);
+                    }else{
+                        registry.addInterceptor(urlInterceptor).addPathPatterns(arrForbidUrls).excludePathPatterns(arrExcludeUrls);
+                    }
+                }
+            }
+        }
+        //super.addInterceptors(registry);
+    }
+
+    //解决跨域问题
+    private CorsConfiguration buildConfig() {
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.addAllowedOrigin("*");
+        //corsConfiguration.addAllowedMethod("*");
+        corsConfiguration.addAllowedMethod(HttpMethod.POST);
+        corsConfiguration.addAllowedMethod(HttpMethod.GET);
+        corsConfiguration.addAllowedMethod(HttpMethod.PUT);
+        corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
+        corsConfiguration.addAllowedMethod(HttpMethod.OPTIONS);
+        corsConfiguration.addAllowedMethod(HttpMethod.HEAD);
+        corsConfiguration.addAllowedHeader("x-requested-with,Content-Type,Authorization,user-agent,Timestamp,Sequence,Signature");
+        return corsConfiguration;
+    }
+
+    //解决跨域问题
+    @Bean
+    public CorsFilter corsFilter() {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", buildConfig());
+        return new CorsFilter(source);
+    }
+
+    //配置该服务的默认首页用于阿里云服务SLB的http head健康检查
+    @Override
+    public void addViewControllers(ViewControllerRegistry registry) {
+        registry.addViewController("/").setViewName("index");
+        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
+        //super.addViewControllers(registry);
+    }
+
+}

+ 71 - 0
src/main/java/com/shkpr/service/aimodelpower/configuration/WebSecurityConfiguration.java

@@ -0,0 +1,71 @@
+package com.shkpr.service.aimodelpower.configuration;
+
+import com.shkpr.service.aimodelpower.controllerfilter.CustomAuthenticationProvider;
+import com.shkpr.service.aimodelpower.controllerfilter.third.ThirdJWTBusiFilterMgr;
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * 该类主要用来做权限控制的配置、以及注册各种过滤器
+ * 执行顺序
+ * (1) 注册验证组件 - configure(AuthenticationManagerBuilder auth)方法中注册自定义验证组件
+ * (2) 设置验证规则 - configure(HttpSecurity http)方法中设置了各种路由访问规则
+ * (3) 初始化过滤组件 - JWTLoginFilter 和 JWTAuthenticationFilter 类会初始化
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)                     //@PreAuthorize对权限的注解需要设置prePostEnabled = true
+public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
+    @Value("${global.test.pressure:false}")
+    private boolean mBForPressureTest;
+
+    @Value("${global.ops.lan.ip:127.0.0.1}")
+    private String mStrOpsServerLanIP;
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+        //使用自定义身份验证组件
+        auth.authenticationProvider(new CustomAuthenticationProvider());
+    }
+
+    // 设置 HTTP 验证规则
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        String[] arrOpsServerLanIPs = mStrOpsServerLanIP.split(";");
+        String strAccessFilterForOps = "hasIpAddress('127.0.0.1')";
+        for (String strTmp:arrOpsServerLanIPs){
+            strAccessFilterForOps += " or hasIpAddress('"+ strTmp +"')";
+        }
+
+        http.csrf().disable()                                          // 关闭csrf验证
+                .authorizeRequests()                                   // 对请求进行认证
+                .antMatchers(ApiURI.URI_FILE_BUSI_XXX).permitAll()
+                .antMatchers(ApiURI.URI_INTERNAL_OPS_XXX).access(strAccessFilterForOps)
+                .antMatchers("/").permitAll()
+                .anyRequest().authenticated()                                                                                          //所有其他请求需要身份认证
+                .and()
+                //多个filter将按照链接的顺序依次传递执行
+                .addFilterBefore(new ThirdJWTBusiFilterMgr(ApiURI.URI_ALL_BUSI_XXX, authenticationManager()),
+                        UsernamePasswordAuthenticationFilter.class);
+                /*.addFilterBefore(new ServerStatusMonitorFilter(ThirdApiURI.URI_HGAS_MONITOR_XXX, authenticationManager()),
+                        UsernamePasswordAuthenticationFilter.class);*/
+
+    }
+
+    @Override
+    public void configure(WebSecurity web) throws Exception {
+        /*web.ignoring()
+                .antMatchers("/error")
+                .antMatchers("/static")
+                .antMatchers("/static/**");                                                               // 所有/static下的静态资源请求时都忽略访问规则
+        */
+    }
+}

+ 116 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/ApiURI.java

@@ -0,0 +1,116 @@
+package com.shkpr.service.aimodelpower.constants;
+public class ApiURI {
+    public static final String HEADER_CLIENT_TYPE = "Client-Type";
+    public static final String HEADER_USER_AGENT = "user-agent";
+    public static final String HEADER_AUTH_VERIFY = "Auth-Verify";
+    public static final String HEADER_SIGN_KEY = "tri_coorperation_tech_task";
+    public static final String HEADER_SIGN_KEY_PUSH = "tri_coorperation_tech_push";
+    public static final String HEADER_TIMESTAMP = "Timestamp";
+    public static final String HEADER_SEQUENCE = "Sequence";
+    public static final String HEADER_SIGNATURE = "Signature";
+    public static final String EXCEPTION_FORMAT = "{%s:%s}:%s"; //{(ios/apk/pc):url}:error reason
+
+    public static final String URI_XXX_MM_LISTS = "mm-lists"; //极值查询
+    public static final String URI_XXX_NEW_INFO = "new-info";//新增
+    public static final String URI_XXX_INFO = "info";   //精确查找
+    public static final String URI_XXX_LISTS = "lists"; //分页查询
+    public static final String URI_XXX_FAST_LISTS = "fast-lists"; //分页查询
+    public static final String URI_XXX_DOING_LISTS = "doing-lists";
+    public static final String URI_XXX_TOTAL_LISTS = "total-lists";
+    public static final String URI_XXX_ITEM_LISTS = "item-lists";
+    public static final String URI_XXX_ITEM_DOING = "item-doing";
+    public static final String URI_XXX_RESET = "reset"; //更新(插入或更新)
+    public static final String URI_XXX_IDS = "ids";     //查询id列表
+    public static final String URI_XXX_SK = "sk";       //以key搜索查询
+    public static final String URI_XXX_SS = "ss";       //模糊搜索查询
+    public static final String URI_XXX_DEL = "del";     //删除
+    public static final String URI_XXX_TURN = "turn";   //转派
+    public static final String URI_XXX_TOTALS = "totals";   //数据统计
+    public static final String URI_XXX_ACCEPT = "accept";   //接收
+    public static final String URI_XXX_DEAL = "deal";       //处理
+    public static final String URI_XXX_BATCH_DEAL = "batch-deal";//批量处理
+    public static final String URI_XXX_URGE = "urge";       //催办
+    public static final String URI_XXX_CHECK = "check";     //审核
+    public static final String URI_XXX_EXTENDS = "extends";//扩展数据
+    public static final String URI_XXX_PREPARE = "prepare";
+    public static final String URI_XXX_ZONE_REGIONS_LISTS = "zone-regions-lists";
+    public static final String URI_XXX_ZONE_REGIONS_PAGES_SS = "zone-regions-pages-ss";
+    public static final String URI_XXX_STATUS_GROUP_TOTALS = "status-group-totals";   //状态分组数据统计
+    public static final String URI_XXX_ADD_NOTE = "add-note"; //追加批注
+    public static final String URI_XXX_TYPE_LISTS = "type-lists";
+    public static final String URI_XXX_IGNORE = "ignore";
+    public static final String URI_XXX_TM_SUM_TOTALS = "tm-sum-totals";
+    public static final String URI_XXX_UPLOAD = "upload";
+    public static final String URI_XXX_DOWNLOAD = "download";
+    public static final String URI_XXX_CLOSE = "close";
+    public static final String URI_XXX_REFUSE = "refuse";
+    public static final String URI_XXX_DESTROY = "destroy";
+    public static final String URI_XXX_STATUS_CHG = "status-chg";
+    public static final String URI_XXX_SIGN = "sign";
+    public static final String URI_XXX_DONE_DEGREE = "done-degree";
+    public static final String URI_XXX_DEV_TYPE_LISTS = "dev-type-lists";
+    public static final String URI_XXX_BIND = "bind";
+    public static final String URI_XXX_UNBIND = "unbind";
+    public static final String URI_XXX_TAG_REPORT = "tag-report";
+    public static final String URI_XXX_TAG_REVOKE = "tag-revoke";
+    public static final String URI_XXX_TO_QUEUE = "to-queue";
+    public static final String URI_XXX_TO_ITEM = "to-item";
+    public static final String URI_XXX_TO_FAULT = "to-fault";
+    public static final String URI_XXX_TO_REPAIR = "to-repair";
+    public static final String URI_XXX_FILTER_FIELD_LISTS = "filter-field-lists";
+    public static final String URI_XXX_TAG_LISTS = "tag-lists";
+    public static final String URI_XXX_HISTORY_GIS_TRACK = "history-gis-track";
+    public static final String URI_XXX_USER_HISTORY_GIS_TRACK = "user-history-gis-track";
+    public static final String URI_XXX_ITEM_DETAIL = "item-details";
+    public static final String URI_XXX_SUMS = "sums";   //汇总
+    public static final String URI_XXX_BIND_CHECK = "bind-check";
+    public static final String URI_XXX_RESULT_DETAIL = "result-detail";
+    public static final String URI_XXX_PROBLEM_DETAIL = "problem-detail";
+    public static final String URI_XXX_NOTIFY = "notify";
+    public static final String URI_XXX_NEW_WITH_OBJ = "new-with-obj";
+    public static final String URI_XXX_REPORT_LIST = "report-list";
+    public static final String URI_XXX_DONE_TOTAL = "done-total";
+    public static final String URI_XXX_DONE_LIST = "done-list";
+    public static final String URI_XXX_USER = "user";
+    public static final String URI_XXX_ZONE = "zone";
+    public static final String URI_XXX_DEV = "dev";
+    public static final String URI_XXX_APPEND = "append";
+    public static final String URI_XXX_TO_ORDER = "to-order";
+    public static final String URI_XXX_LIST_WITH_OBJ = "lists-with-obj";
+    public static final String URI_XXX_LIST_WITH_REGION = "lists-with-region";
+    public static final String URI_XXX_UNBIND_DEL = "unbind-del";
+    public static final String URI_XXX_PLAN_LIST = "plan-lists";
+    public static final String URI_XXX_POINT_LIST = "point-lists";
+    public static final String URI_XXX_ASSIGN = "assign";
+    public static final String URI_XXX_ADD_MEMBER = "add-member";
+    public static final String URI_XXX_DEL_MEMBER = "del-member";
+    public static final String URI_XXX_SEIZE_LIST = "seize-list";
+    public static final String URI_XXX_ACCEPT_LIST = "accept-list";
+    public static final String URI_XXX_RESEND = "resend";
+    public static final String URI_XXX_LIST_WITH_TOTAL = "lists-with-total";
+    public static final String URI_XXX_TEAM = "team";
+    public static final String URI_XXX_ORG = "org";
+    public static final String URI_XXX_END_LISTS = "end-lists";
+    public static final String URI_XXX_BATCH_SK = "batch-sk";
+    public static final String URI_XXX_SCORE = "score";
+    public static final String URI_XXX_KIND = "kind";
+    public static final String URI_XXX_EVENT_TEMPLATE_LISTS = "event-template-lists";
+
+    public static final String URI_FILE_BUSI_XXX = "/files/**";
+
+    public static final String URI_ALL_BUSI_XXX = "/ai-model/**";
+
+    public static final String URI_INTERNAL_H = "/ai-model/internal";
+
+    public static final String URI_FILES_H = "/ai-model/files";
+    public static final String URI_FILES_XXX = URI_FILES_H+"/**";
+
+    public static final String URI_CUSTOMIZE_H = "/ai-model/customize";
+    public static final String URI_CUSTOMIZE_XXX = URI_CUSTOMIZE_H+"/**";
+    public static final String URI_CUSTOMIZE_COMPLEX_OPTIONS_H = URI_CUSTOMIZE_H+"/complex-options";
+
+    public static final String URI_COMM_REPORT_FORM_H = "/ai-model/report-form";
+    public static final String URI_COMM_REPORT_FORM_XXX = "/ai-model/report-form/**";
+
+    public static final String URI_INTERNAL_OPS_XXX = "/ops/**";
+}

+ 10 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/CacheHandleType.java

@@ -0,0 +1,10 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public enum CacheHandleType {
+    INIT,
+    ADD,
+    RESET,
+    MODIFY,
+    REMOVE,
+    CLEAR;
+}

+ 13 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/CommDefine.java

@@ -0,0 +1,13 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public interface CommDefine {
+    String REQ_OUTER = "Outer";//外来请求者
+    String REQ_INNER = "Inner";
+    String INTERNAL_OPERATOR_ID = "FFFFFFFF";
+    String INTERNAL_OPERATOR_ROLE = "SelfOperator";
+    String INTERNAL_OPERATOR_ROLE_ID = "FFFFFFFF";
+    String ADMIN_USER_ID = "0";
+    String ADMIN_ROLE_ID = "0";
+    String ADMIN_ACCOUNT = "admin";
+    String INVALID_STR_ID = "-1";
+}

+ 16 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/CommFieldStatus.java

@@ -0,0 +1,16 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface CommFieldStatus {
+    int DESTROY = -1;
+    int DISABLE = 0;
+    int ENABLE = 1;
+
+    List<Integer> ALL_DEFINE = new ArrayList<Integer>(){{
+        add(DESTROY);
+        add(DISABLE);
+        add(ENABLE);
+    }};
+}

+ 12 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/DispatchAnalysisResultNote.java

@@ -0,0 +1,12 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public interface DispatchAnalysisResultNote {
+    String GET_SAMPLE_DATA_ERROR = "采集数据获取失败";
+    String OVERDUE_SAMPLE_DATA = "采集数据(过期或超期)不在监测时段内";
+    String UNCHANGED_SAMPLE_DATA = "采集数据持续未更新";
+    String NO_SAMPLE_DEVICE = "未绑定采集设备";
+    String NO_MATCH_COMPARE_FIELD = "比对字段不匹配";
+    String OTHERS = "其他原因";
+    String YES_TRIGGER = "已触发";
+    String NO_TRIGGER = "未触发";
+}

+ 16 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/DispatchFrequency.java

@@ -0,0 +1,16 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface DispatchFrequency {
+    List<Integer> RANGES = new ArrayList<Integer>(){{
+        add(1);
+        add(5);
+        add(10);
+        add(20);
+        add(30);
+        add(40);
+        add(50);
+    }};
+}

+ 8 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/DispatchPointType.java

@@ -0,0 +1,8 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public interface DispatchPointType {
+    String SITE = "site";
+    String ZONE = "zone";
+    String DEVICE = "device";
+    String OTHER = "other";
+}

+ 9 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/DispatchSource.java

@@ -0,0 +1,9 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public interface DispatchSource {
+    int UN_KNOWN = -1; //未知
+    int AUTO = 0;      //自建
+    int PLAN = 1;     //预案
+    int CS = 2;       //客服
+    int OTHER = 255; //其他
+}

+ 11 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/FaultExtendType.java

@@ -0,0 +1,11 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface FaultExtendType {
+    int ATT = 1;
+    List<Integer> ALL_TYPE = new ArrayList<Integer>(){{
+        add(ATT);
+    }};
+}

+ 13 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/FaultOrderStatus.java

@@ -0,0 +1,13 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public class FaultOrderStatus {
+    public static final int CLOSE = -1;  //关闭结束
+    public static final int PENDING = 0; //待处理
+    public static final int HANDLED = 1; //已处理
+
+    public static boolean isHandled(int nValue){
+        if (nValue > PENDING)
+            return true;
+        return false;
+    }
+}

+ 10 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/LinkMode.java

@@ -0,0 +1,10 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public enum LinkMode {
+    PL_PLAN_2_POINT, //巡检:计划-->点
+    PL_POINT_2_PLAN,//巡检:点-->计划
+    PL_POINT_2_OBJ,//巡检:点-->对象
+    PL_OBJ_2_POINT,//巡检:对象-->点
+    PL_XXX_2_ITEM,
+    PL_ITEM_2_XXX;
+}

+ 162 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/LogFlagBusiType.java

@@ -0,0 +1,162 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public enum  LogFlagBusiType {
+    BUSI_INIT(0,"Init Busi"),
+    BUSI_CONN(1,"Conn Busi"),
+    BUSI_AUTH(2, "Auth Busi"),
+    BUSI_SUB(3, "Subscribe Busi"),
+    BUSI_NOTIFY(4, "Notify Busi"),
+    BUSI_CMD(5,"Command Busi"),
+    BUSI_USER(6,"User Busi"),
+    BUSI_DEV(7,"Dev Busi"),
+    BUSI_APP_APIS(8, "App Apis"),
+    BUSI_USER_APIS_CASE(9,"User Apis Case"),
+    BUSI_ROLE_POWER(10,"Role Power Info"),
+    BUSI_PARTITION(11,"Partition Info"),
+    BUSI_APPS_INFO(12,"Apps Info"),
+    BUSI_ROLE_INFO(13,"Role Info"),
+    BUSI_ALARM_TASK_INFO(14,"Alarm Task Info"),
+    BUSI_WARN_REPORT_INFO(15,"Warn Report Info"),
+    BUSI_PUSH_TASK_INFO(16,"Push Task Info"),
+    BUSI_CALL_BASE_AS(17, "Call Base As Busi"),
+    BUSI_WARN_EVENT_INFO(18, "Warn Event Info"),
+    BUSI_REPAIR_TASK_INFO(19,"Repair Task Info"),
+    BUSI_TASK_FILES(20, "Task Files"),
+    BUSI_FAULT_TASK_INFO(21,"Fault Task Info"),
+    BUSI_ORDER_MAT_TYPE(22, "Order Material Type"),
+    BUSI_PATROL_ITEM_TYPE(23, "Patrol Item Type"),
+    BUSI_ORDER_ITEM_CYCLE(24, "Order Time Cycle"),
+    BUSI_ORDER_PATROL_PLAN(25,"Patrol Plan Info"),
+    BUSI_ORDER_PATROL_PLAN_ROUTE(26,"Patrol Plan Route Info"),
+    BUSI_ORDER_PATROL_POINT(27,"Patrol Point Info"),
+    BUSI_PATROL_PLAN_INFO(28,"Patrol Plan Info"),
+    BUSI_PATROL_JOB_REPORT_TYPE(29,"Patrol Job Report Type"),
+    BUSI_PATROL_JOB_INFO(30,"Patrol Job Info"),
+    BUSI_PATROL_JOB_REAL_GIS(31,"Patrol Job Real Gis"),
+    BUSI_PATROL_JOB_POINT(32,"Patrol Job Point"),
+    BUSI_PATROL_JOB_REPORT(33,"Patrol Job Report"),
+    BUSI_PATROL_ZONE_INFO(34,"Patrol Zone Info"),
+    BUSI_PATROL_POINT_INFO(35,"Patrol Point Info"),
+    BUSI_PATROL_PLAN_POINT_LINK(36,"Patrol Plan Point Link"),
+    BUSI_PATROL_ITEM_OTHER_LINK(37,"Patrol Item Other Link"),
+    BUSI_PATROL_OBJECT_INFO(38,"Patrol Object Info"),
+    BUSI_PATROL_POINT_OBJ_LINK(39,"Patrol Point Object Link"),
+    BUSI_CUSTOM_COMPLEX_OPTIONS(40,"Custom Complex Options"),
+    BUSI_PATROL_PATROL_JOB_OBJECT_INFO(41,"Patrol Job Object Info"),
+    BUSI_PATROL_ADDITION_FEEDBACK(42,"Patrol Addition Feedback Info"),
+    BUSI_PATROL_REPORT_STATS(43,"Patrol Report Stats Data"),
+    BUSI_WWS_DISPATCH_PLAN(44,"WWS Dispatch Plan"),
+    BUSI_WWS_DISPATCH_PLAN_SUG(45,"WWS Dispatch Plan Suggestion"),
+    BUSI_WWS_DISPATCH_PLAN_POINT(46,"WWS Dispatch Plan Point"),
+    BUSI_CALL_DATA_AS(47, "Call STATS DATA As Busi"),
+    BUSI_WWS_DISPATCH_EVENT(48,"WWS Dispatch Event"),
+    BUSI_WWS_DISPATCH_MIXED_EVENT(49,"WWS Dispatch Mixed Event"),
+    BUSI_WWS_DISPATCH_ORDER(50,"WWS Dispatch Order"),
+    BUSI_CALL_PUSH_AS(51, "Call PUSH As Busi"),
+    BUSI_WWS_DISPATCH_CALL(52,"WWS Dispatch Call"),
+    BUSI_CALL_WAN_NET_AS(53, "Call Wan Net As Busi"),
+    BUSI_PATROL_PLAN_BATCH(54,"Patrol Plan Batch"),
+    BUSI_REPAIR_TEAM_BIZ(55,"Repair Team Biz"),
+    BUSI_REPORT_FORM_FOR_USER(56,"Report Form For User"),
+    BUSI_TASK_PUSH_BIZ(57,"Task Push Biz"),
+    BUSI_PATROL_DASHBOARD_BIZ(58,"Patrol Dashboard Biz"),
+    BUSI_REPAIR_DASHBOARD_BIZ(59,"Repair Dashboard Biz"),
+    BUSI_CALL_GW_AS(60, "Call Data GW As Biz"),
+    BUSI_WARN_TYPE_MGR(61, "Warn Type Mgr Biz"),
+    BUSI_CALL_TASK_AS(62, "Call Task As Biz"),
+
+    BUSI_INTERNAL_WARN_EVENT_MAIN_TYPE(96,"Internal Warn Event Main Type Biz"),
+    BUSI_INTERNAL_WARN_SUG_DEFINE(97,"Internal Warn Sug Define Biz"),
+    BUSI_INTERNAL_WARN_EVENT_SUG_LINK(98,"Internal Warn Event Sug Link Biz"),
+    BUSI_INTERNAL(99,"Internal Busi"),
+
+    BUSI_DB_USER(100,"DB User Busi"),
+    BUSI_DB_DEV(101,"DB Dev Busi"),
+    BUSI_DB_DEV_TYPE(102, "DB Dev Type Busi"),
+    BUSI_DB_APP_APIS(103,"DB App Apis"),
+    BUSI_DB_USER_APIS_CASE(104,"DB User Apis Case"),
+    BUSI_DB_ROLE_POWER(105,"DB Role Power Info"),
+    BUSI_DB_PARTITION(106,"DB Partition Info"),
+    BUSI_DB_USER_OWN_ZONE(107,"DB User Own Zone Info"),
+    BUSI_DB_APPS_BASE_INFO(108,"DB Apps Base Info"),
+    BUSI_DB_APPS_EXTRA_INFO(109,"DB Apps Extra Info"),
+    BUSI_DB_ROLE_INFO(110,"DB Role Info"),
+    BUSI_DB_APP_APIS_CASE(111,"DB App Apis Case"),
+    BUSI_DB_ROLE_APIS_CASE(112,"DB Role Apis Case"),
+    BUSI_DB_ALARM_TASK_INFO(113,"DB Alarm Task Info"),
+    BUSI_DB_WARN_REPORT_INFO(114,"DB Warn Report Info"),
+    BUSI_DB_PUBLIC_BIZ_PUSH_REQ(115,"DB Public Biz Push Req"),
+    BUSI_DB_PUBLIC_NOTIFY_EVENT(116,"DB Public Notify Event"),
+    BUSI_DB_WARN_EVENT_INFO(117,"DB Warn Event Info"),
+    BUSI_DB_REPAIR_TASK_ATT(118,"DB Repair Task Attachment"),
+    BUSI_DB_REPAIR_TASK_STATUS_TRACK(119,"DB Repair Task Status Track"),
+    BUSI_DB_REPAIR_TASK_INFO(120,"DB Repair Task Info"),
+    BUSI_DB_REPAIR_TASK_NOTE_RECORD(121,"DB Repair Task Note Record"),
+    BUSI_DB_WARN_EVENT_TYPE_INFO(122,"DB Warn Event Type Info"),
+    BUSI_DB_ORDER_TYPE_INFO(123,"DB Order Type Info"),
+    BUSI_DB_FILE_ATTACHMENT(124,"DB File Attachment Info"),
+    BUSI_DB_REPAIR_TASK_RELEVANT_USER(125,"DB Repair Task Relevant User"),
+    BUSI_DB_FAULT_TASK_ATT(126,"DB Fault Task Attachment"),
+    BUSI_DB_FAULT_TASK_INFO(127,"DB Fault Task Info"),
+    BUSI_DB_ORDER_MATERIAL_TYPE(128,"DB Order Material Type"),
+    BUSI_DB_REPAIR_MATERIAL(129,"DB Repair Task Materials"),
+    BUSI_DB_TYPE_DEFINE(130,"DB Type Define Info"),
+    BUSI_DB_ORDER_TIME_CYCLE(131,"DB Order Time Cycle"),
+    BUSI_DB_PATROL_PLAN(132,"DB Patrol Plan"),
+    BUSI_DB_PATROL_PLAN_POINT(133,"DB Patrol Plan Point"),
+    BUSI_DB_PATROL_PLAN_ROUTE(134,"DB Patrol Plan Route"),
+    BUSI_DB_PATROL_REPORT_TYPE(135,"DB Patrol Report Type"),
+    BUSI_DB_PATROL_JOB(136,"DB Patrol Job"),
+    BUSI_DB_PATROL_JOB_STATUS_TRACK(137,"DB Patrol Job Status Track"),
+    BUSI_DB_PATROL_JOB_REAL_GIS(138,"DB Patrol Job Real Gis"),
+    BUSI_DB_PATROL_JOB_POINT(139,"DB Patrol Job Point"),
+    BUSI_DB_PATROL_JOB_ROUTE(140,"DB Patrol Job Route"),
+    BUSI_DB_PATROL_JOB_POINT_ATT(141,"DB Patrol Job Point Attachment"),
+    BUSI_DB_PATROL_ZONE(142,"DB Patrol Zone"),
+    BUSI_DB_PATROL_POINT(143,"DB Patrol Point"),
+    BUSI_DB_PATROL_POINT_ATT(144,"DB Patrol Point Attachment"),
+    BUSI_DB_PATROL_PLAN_POINT_LINK(145,"DB Patrol Plan Point Link"),
+    BUSI_DB_PATROL_ITEM_TYPE(146,"DB Patrol Item Type"),
+    BUSI_DB_PATROL_ITEM_TYPE_LINK(147,"DB Patrol Item Type Link"),
+    BUSI_DB_PATROL_POINT_OBJECT_LINK(148,"DB Patrol Point Object Link"),
+    BUSI_DB_PATROL_JOB_OBJECT(149,"DB Patrol Job Object"),
+    BUSI_DB_PATROL_JOB_OBJECT_REPORT_ATT(150,"DB Patrol Job Object Report Attachment"),
+    BUSI_DB_PATROL_JOB_OBJECT_REPORT(151,"DB Patrol Job Object Report Info"),
+    BUSI_DB_PATROL_OBJECT_ADDED_FEEDBACK_ATT(152,"DB Patrol Object Added Feedback Attachment"),
+    BUSI_DB_PATROL_OBJECT_ADDED_FEEDBACK(153,"DB Patrol Object Added Feedback Info"),
+    BUSI_DB_PATROL_OBJECT(154,"DB Patrol Object"),
+    BUSI_DB_PATROL_JOB_OBJECT_ATT(155,"DB Patrol Job Object Attachment"),
+    BUSI_DB_PATROL_OBJECT_ATT(156,"DB Patrol Object Attachment"),
+    BUSI_DB_PIPE_GIS_FEATURE_LABEL(157,"DB Pipe Gis Feature Label"),
+    BUSI_DB_WWS_DISPATCH_PLAN(158,"DB WWS Dispatch Plan"),
+    BUSI_DB_WWS_DISPATCH_PLAN_POINT(159,"DB WWS Dispatch Plan Point"),
+    BUSI_DB_WWS_DISPATCH_PLAN_SUG(160,"DB WWS Dispatch Plan Suggestion"),
+    BUSI_DB_WWS_DISPATCH_EVENT(161,"DB WWS Dispatch Event"),
+    BUSI_DB_WWS_DISPATCH_EVENT_TRIGGER_DATA(162,"DB WWS Dispatch Event Trigger Data"),
+    BUSI_DB_WWS_DISPATCH_EVENT_SUG(163,"DB WWS Dispatch Event Suggestion"),
+    BUSI_DB_WWS_DISPATCH_ORDER(164,"DB WWS Dispatch Order"),
+    BUSI_DB_WWS_DISPATCH_ORDER_REPORT(165,"DB WWS Dispatch Order Report"),
+    BUSI_DB_WWS_DISPATCH_ORDER_REPORT_ATT(166,"DB WWS Dispatch Order Report Attachment"),
+    BUSI_DB_WWS_DISPATCH_ORDER_STATUS_TRACK(167,"DB WWS Dispatch Order Status Track"),
+    BUSI_DB_PUSH_CALL(168,"DB Push Call Biz"),
+    BUSI_DB_PATROL_JOB_WITH_BATCH(169,"DB Patrol Job With Batch Biz"),
+    BUSI_DB_REPAIR_TEAM_INFO(170,"DB Repair Team Info Biz"),
+    BUSI_DB_REPAIR_TEAM_USER_LINK(171,"DB Repair Team User Link Biz"),
+    BUSI_DB_COMM_TASK_FORM(172,"DB Comm Task Form Biz"),
+    BUSI_DB_3TH_CS_ORDER_SYNCH(173,"DB 3TH CS Order Synch"),
+    BUSI_DB_WARN_REPORT_PUSH_REQ_LINK(174,"DB Warn Report Push Req Link"),
+    BUSI_DB_WARN_TYPE_DICT_MGR(175,"DB Warn Type Dict Mgr"),
+
+    BUSI_ALL(999,"ALL Busi"),
+    BUSI_REDIS(1000,"Redis Busi");
+
+    private LogFlagBusiType(int index, String name){
+        this.name = name;
+        this.index = index;
+    }
+    private String name;
+    private int index;
+    public int toIntValue(){return index;}
+    public String toStrValue() {return name;}
+}
+

+ 17 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/MsgNotifyDefine.java

@@ -0,0 +1,17 @@
+package com.shkpr.service.aimodelpower.constants;
+
+
+public interface MsgNotifyDefine {
+    public interface Topic{
+        String GIS_FEATURE = "gisFeature";
+        String TYPE_DEFINE = "typeDefine";
+        String GIS_LAYER = "gisLayer";
+        String CS_ORDER = "cs";
+    }
+    public interface Tag{
+        String LABEL = "label";
+        String QCODE = "qcode";
+        String CHANGE = "change";
+        String LAYER = "layer";
+    }
+}

+ 9 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/SampleCompareResult.java

@@ -0,0 +1,9 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public interface SampleCompareResult {
+    int WAIT = -2;//对比时间未到
+    int FAILED = -1;//对比失败
+    int NO = 0;//不满足未触发
+    int YES = 1;//满足已触发
+    int DELAY_TO_NEXT = 255;//进入下一次循环
+}

+ 29 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/SampleFieldDefine.java

@@ -0,0 +1,29 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public interface SampleFieldDefine {
+    Map<String, String> SAMPLE_FIELD_LONG_2_SHORT = new HashMap<String, String>(){{
+        put("press_cur","pres");
+        put("flow_cur","flow");
+        put("flow_total_pos","ft");
+        put("flow_total_rev","ftv");
+        put("flow_total_settleday","ftsd");
+        put("valve_status","valve");
+        put("user_code","userCode");
+        put("consume_id","consumeId");
+        put("end_time","endTime");
+        put("start_flow","startFlow");
+        put("end_flow","endFlow");
+        put("flow_value","flowValue");
+        put("dev_temperature","temp");
+        put("gis_lat","lat");
+        put("gis_long","lon");
+        put("lock_status","lockStatus");
+        put("sensor_status","sensorStatus");
+        put("warn_status","warnStatus");
+        put("water_accum","waterAccum");
+        put("water_out","waterOut");
+    }};
+}

+ 21 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/TDKind.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface TDKind {
+    int DEV_TAG_FIELD = 0; //设备标记字段
+    int ZONE_M_TYPE = 1;   //分区主类型
+    int ZONE_S_TYPE = 2;   //分区子类型
+    int WATER_USE_TYPE = 3;//用水类型
+    int SITE_TYPE = 4;     //站点类型
+    int WATER_NATURE = 5; //用水性质
+    int THRESHOLD_TYPE = 6;//业务阀值类型
+    int PATROL_OBJECT_TYPE = 7;//巡检单元对象类型
+    int SELF_COMPLEX_OPTION = 8;//自定义复合选项类型
+
+    List<Integer> ALL_ITEM = new ArrayList<Integer>(){{
+        add(PATROL_OBJECT_TYPE);
+        add(SELF_COMPLEX_OPTION);
+    }};
+}

+ 27 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/TaskQueueDataTypeEx.java

@@ -0,0 +1,27 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import com.global.base.taskqueue.TaskQueueDataType;
+
+public class TaskQueueDataTypeEx extends TaskQueueDataType {
+    public static final int ASYNC_TASK_BEGIN = 1000;
+    public static final int ASYNC_PUSH_TASK = ASYNC_TASK_BEGIN+1;
+    public static final int ASYNC_PUSH_TASK_RW_DB = ASYNC_PUSH_TASK+1;
+    public static final int ASYNC_PARSE_EVENT_FILE = ASYNC_PUSH_TASK_RW_DB+1;
+    public static final int ASYNC_PRODUCE_PATROL_JOB = ASYNC_PARSE_EVENT_FILE+1;
+    public static final int ASYNC_PRODUCE_FAULT_FOR_JOB = ASYNC_PRODUCE_PATROL_JOB+1;
+    public static final int ASYNC_VERIFY_REPORT_FOR_JOB = ASYNC_PRODUCE_FAULT_FOR_JOB+1;
+    public static final int ASYNC_ANALYSIS_WWS_DISPATCH_PLAN = ASYNC_VERIFY_REPORT_FOR_JOB+1;
+    public static final int ASYNC_REPORT_PATROL_REAL_GIS = ASYNC_ANALYSIS_WWS_DISPATCH_PLAN+1;
+    public static final int ASYNC_TASK_END = 1010;
+
+    public static final int DELAY_TASK_BEGIN = 2000;
+    public static final int DELAY_PUSH_TASK = DELAY_TASK_BEGIN+1;
+    public static final int DELAY_PRODUCE_PATROL_JOB = DELAY_PUSH_TASK+1;
+    public static final int DELAY_NOTIFY_MSG_TO_GW_SERVICE = DELAY_PRODUCE_PATROL_JOB+1;
+    public static final int DELAY_TASK_END = 2010;
+
+    public static final int NOTIFY_MSG_BEGIN = 2020;
+    public static final int NOTIFY_MSG_FROM_OTHER_SERVICE = NOTIFY_MSG_BEGIN+1;
+    public static final int NOTIFY_MSG_TO_GW_SERVICE = NOTIFY_MSG_FROM_OTHER_SERVICE+1;
+    public static final int NOTIFY_MSG_END = 2030;
+}

+ 37 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/UrlMethodType.java

@@ -0,0 +1,37 @@
+package com.shkpr.service.aimodelpower.constants;
+
+import org.springframework.web.bind.annotation.RequestMethod;
+
+public enum UrlMethodType {
+    GET("GET", RequestMethod.GET),
+    HEAD("HEAD", RequestMethod.HEAD),
+    POST("POST", RequestMethod.POST),
+    PUT("PUT", RequestMethod.PUT),
+    PATCH("PATCH", RequestMethod.PATCH),
+    DELETE("DELETE", RequestMethod.DELETE),
+    OPTIONS("OPTIONS", RequestMethod.OPTIONS);
+
+    UrlMethodType(String name, RequestMethod method) {
+        this.name = name;
+        this.method = method;
+    };
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public RequestMethod getMethod() {
+        return method;
+    }
+
+    public void setMethod(RequestMethod method) {
+        this.method = method;
+    }
+
+    private String name;
+    private RequestMethod method;
+}

+ 17 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/UserCurStateType.java

@@ -0,0 +1,17 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public enum UserCurStateType {
+    STATE_REGISTER(0,"Registering"),
+    STATE_ENABLE(1,"Enable"),
+    STATE_DISABLE(2,"Disable"),
+    STATE_LOGOUT(3,"Logout");
+    private String name;
+    private int index;
+
+    private UserCurStateType(int index,String name) {
+        this.name = name;
+        this.index = index;
+    }
+    public int toIntValue(){return index;}
+    public String toStrValue() {return name;}
+}

+ 7 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/UserFlagType.java

@@ -0,0 +1,7 @@
+package com.shkpr.service.aimodelpower.constants;
+
+public interface UserFlagType {
+    String ME = "me";
+    String OTHER = "other";
+    String OUTER = "outer";
+}

+ 57 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerapi/ThirdBaseController.java

@@ -0,0 +1,57 @@
+package com.shkpr.service.aimodelpower.controllerapi;
+
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import com.shkpr.service.aimodelpower.dto.ResponseCode;
+import com.shkpr.service.aimodelpower.exception.SelfException;
+import com.shkpr.service.aimodelpower.subtask.BaseSubTask;
+import org.springframework.util.StringUtils;
+
+public abstract class ThirdBaseController {
+    public abstract BaseSubTask getSubTask();
+    public <T, V> T parseParam(int uriType
+            ,final String strPlatform
+            ,final String strUri
+            ,final String strTime
+            ,final String strSeq
+            ,final String strSignDes
+            ,final String strSignInitData
+            ,final String strParamBody
+            , Class<T> paramType
+            , Class<V> validType) throws Exception{
+        if (!StringUtils.isEmpty(strSignDes)){//签名不为空时表示要求做签名认证
+            int nSignRes = getSubTask().checkRequestSignFun(strSignDes, strSignInitData).intValue();;
+            if (nSignRes == 1){
+                throw new SelfException(ResponseCode.RESULT_ERROR_SIGN.toStrCode()
+                        , String.format(ApiURI.EXCEPTION_FORMAT
+                        , strPlatform
+                        , strUri
+                        , ResponseCode.RESULT_ERROR_SIGN.toStrMsg()));
+            }
+        }
+
+        T oJsonParam = getSubTask().checkRequestParamFun(strParamBody, paramType, validType);
+        if (oJsonParam == null){
+            throw new SelfException(ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , strUri
+                    , ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrMsg()));
+        }
+
+        int nSeqRes = getSubTask().checkRequestSequenceFun(strSeq, strTime, uriType).intValue(); //防重序列号置于检测末尾
+        if (nSeqRes == 1)
+            throw new SelfException(ResponseCode.RESULT_REQUEST_TIMEOUT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , strUri
+                    , ResponseCode.RESULT_REQUEST_TIMEOUT.toStrMsg()+"(srctm:"+strTime+")"));
+        else if (nSeqRes == 2){
+            throw new SelfException(ResponseCode.RESULT_REPEAT_SEQUENCE.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , strUri
+                    , ResponseCode.RESULT_REPEAT_SEQUENCE.toStrMsg()));
+        }
+        return oJsonParam;
+    }
+}

+ 66 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerapi/ThirdFilesTransController.java

@@ -0,0 +1,66 @@
+package com.shkpr.service.aimodelpower.controllerapi;
+
+import com.shkpr.service.aimodelpower.dto.ResponseCode;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@RequestMapping("files")
+@RestController
+public class ThirdFilesTransController {
+    final String MSG_SUCCESS = "success.";
+    final String MSG_FAILED = "failed.";
+    private String mStrClassName;
+
+    public ThirdFilesTransController() {
+        mStrClassName = "ThirdFilesTransController";
+    }
+
+    /**
+     * 要求请求方不能用json方式请求,而是直接用window.location.url="http://xxx.xxx.xxx.xxx:yyyy/files/download?fileid=aaa"的方式请求
+     * @param request
+     * @param response
+     * @param fileid
+     */
+    @GetMapping(value = "download")
+    public void fileDownload(HttpServletRequest request
+            , HttpServletResponse response
+            , @RequestParam(required=false) String fileid){
+        return;
+    }
+
+    /**
+     * 要求请求方的Content-Type为multipart/form-data
+     * 要求请求方的文件组名为files
+     * @param request
+     * @param response
+     * @param files
+     * @return
+     */
+    @RequestMapping(value = "upload/event/"+"{eventType}")
+    public String fileUploadForEvent(HttpServletRequest request
+            , HttpServletResponse response
+            , @PathVariable("eventType") String eventType
+            , @RequestParam(required=false, value = "files") MultipartFile[] files){
+        String code = ResponseCode.RESULT_NORMAL.toStrCode();
+        return code;
+    }
+
+    /**
+     * 要求请求方的Content-Type为multipart/form-data
+     * 要求请求方的文件组名为files
+     * @param request
+     * @param response
+     * @param files
+     * @return
+     */
+    @RequestMapping(value = "upload/image")
+    public String fileUploadForImage(HttpServletRequest request
+            , HttpServletResponse response
+            , @RequestParam(required=false, value = "files") MultipartFile[] files){
+        String code = ResponseCode.RESULT_NORMAL.toStrCode();
+        return code;
+    }
+}

+ 81 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerapi/ThirdInternalController.java

@@ -0,0 +1,81 @@
+package com.shkpr.service.aimodelpower.controllerapi;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.global.base.taskqueue.TaskQueueData;
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.aimodelpower.commtools.CommTool;
+import com.shkpr.service.aimodelpower.commtools.HttpTool;
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import com.shkpr.service.aimodelpower.constants.LogFlagBusiType;
+import com.shkpr.service.aimodelpower.constants.TaskQueueDataTypeEx;
+import com.shkpr.service.aimodelpower.controllerfilter.TokenAuthenticationService;
+import com.shkpr.service.aimodelpower.dto.MsgNotifyBean;
+import com.shkpr.service.aimodelpower.dto.ResponseCode;
+import com.shkpr.service.aimodelpower.dto.ResponseRes;
+import com.shkpr.service.aimodelpower.exception.SelfException;
+import com.shkpr.service.aimodelpower.globalmgr.NotifyMsgQueueMgr;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RequestMapping(ApiURI.URI_INTERNAL_H)
+@RestController
+public class ThirdInternalController {
+    final String MSG_SUCCESS = "success.";
+    final String MSG_FAILED = "failed.";
+    private String mStrClassName;
+    private AtomicInteger mSeqNotify = null;
+
+    public ThirdInternalController() {
+        mStrClassName = "ThirdInternalController";
+        mSeqNotify = new AtomicInteger(0);
+    }
+
+    @PostMapping(value = ApiURI.URI_XXX_NOTIFY)
+    public ResponseRes notifyMsg(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        MsgNotifyBean oJsonParam = FastJsonUtil.fromJSONByGson(HttpTool.getJsonBodyStr(request), MsgNotifyBean.class);
+        if (oJsonParam == null || !oJsonParam.checkValid())
+            throw new SelfException(ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrMsg()));
+
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqNotify.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                ,String.format("%s:%s seq:{%s} param:%s begin====>"
+                        ,strPlatform
+                        ,URI_PATH
+                        ,strRunSeq
+                        ,oJsonParam.toString()));
+
+        ResponseRes<String> resResult = new ResponseRes<String>();
+        resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+        resResult.setResmsg(MSG_SUCCESS);
+        resResult.setResdata("");
+
+        NotifyMsgQueueMgr.getInstance().postTaskData(new TaskQueueData(TaskQueueDataTypeEx.NOTIFY_MSG_FROM_OTHER_SERVICE, oJsonParam));
+
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                ,String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                        ,strPlatform
+                        ,URI_PATH
+                        ,strRunSeq
+                        ,resResult.getRescode()
+                        ,resResult.getResmsg()
+                        ,resResult.getTimestamp()-llReqBefore));
+        return resResult;
+    }
+}

+ 176 - 0
src/main/java/com/shkpr/service/aimodelpower/controllercheck/JWTControllerCheck.java

@@ -0,0 +1,176 @@
+package com.shkpr.service.aimodelpower.controllercheck;
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.aimodelpower.commtools.CommTool;
+import com.shkpr.service.aimodelpower.commtools.HttpTool;
+import com.shkpr.service.aimodelpower.constants.LogFlagBusiType;
+import com.shkpr.service.aimodelpower.controllerfilter.TokenAuthenticationService;
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import com.shkpr.service.aimodelpower.dto.ResponseCode;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 该类主要用来校验Controller的request头和request参数
+ */
+public class JWTControllerCheck {
+    protected Validator mValidator = null;//由于该类不是@Component或@Bean,所以无法对Validator msValidator使用@Autowired
+    protected Map<String, String> mMapURI2Method;
+    protected String mStrThisSampleName = null;
+    private AtomicInteger mTmpIndex = new AtomicInteger(0);
+    public JWTControllerCheck(Map<String, String> mapURI2Method){
+        this.mMapURI2Method = mapURI2Method;
+        this.mValidator = GlobalData.getInstance().getValidForParam();
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+    }
+
+    public boolean checkRequest(HttpServletRequest request, HttpServletResponse response){
+        //解决跨域请求问题
+        response.setHeader("Access-Control-Allow-Origin", "*");
+        response.setHeader("Access-Control-Allow-Methods", "*");
+        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Content-Type,Authorization");
+
+        if (!checkServerInternet(request, response))
+            return false;
+        if (!checkMaxConcurrentRequest(request, response))
+            return false;
+        if (!checkRequestHead(request, response))
+            return false;
+        if (!checkRequestParam(request, response))
+            return false;
+        if (!checkRequestBody(request, response))
+            return false;
+        return true;
+    }
+
+
+
+    protected boolean checkServerInternet(HttpServletRequest request, HttpServletResponse response){
+        /*if (!DataTransferMgr.getInstance().isConnected()){
+            response.setStatus(ResponseCode.STATUS_SERVER_NET_DISCONN_OR_BUSY.toInt());//服务器端网络异常
+            return false;
+        }*/
+        return true;
+    }
+
+    protected boolean checkMaxConcurrentRequest(HttpServletRequest request, HttpServletResponse response){
+        /*if (DataTransferMgr.getInstance().getLiveUnitClient() > GlobalData.getInstance().getMaxConcurrentRequest()){
+            response.setStatus(ResponseCode.STATUS_MAX_CONCURRENT_REQUEST_COUNT.toInt());//超过了最大并发请求数
+            return false;
+        }*/
+        return true;
+    }
+
+    protected boolean checkRequestHead(HttpServletRequest request, HttpServletResponse response){
+        boolean bResult = true;
+        if (mMapURI2Method == null)
+            return bResult;
+
+        String strOldMethod = mMapURI2Method.get(request.getRequestURI());
+        if (strOldMethod == null){
+            for (Map.Entry<String,String> entry:mMapURI2Method.entrySet()){
+                String uri = entry.getKey();
+                String method = entry.getValue();
+                if (CommTool.isTheThisFormatMatch(uri, request.getRequestURI())){
+                    strOldMethod = method;
+                    break;
+                }
+            }
+        }
+        if (strOldMethod != null){
+            String submitMehtod = request.getMethod();
+            submitMehtod = submitMehtod!=null ? submitMehtod.toLowerCase():"xxx";
+
+            if (submitMehtod.equalsIgnoreCase(strOldMethod)){
+                String strContentType = request.getHeader("Content-Type");
+                strContentType = strContentType!=null ? strContentType.toLowerCase():"xxx";
+                String strContent = request.getHeader("Content");                       //经测试发现ios只能设置Content
+                strContent = strContent!=null ? strContent.toLowerCase():"xxx";
+
+                String strAccept = request.getHeader("Accept");
+                strAccept = strAccept!=null ? strAccept.toLowerCase():"xxx";
+
+                String strCompare = TokenAuthenticationService.HEADER_CONTENT_TYPE;
+                strCompare = strCompare.toLowerCase();
+                String strShortCompare = TokenAuthenticationService.HEADER_SHORT_CONTENT_TYPE;
+                strShortCompare = strShortCompare.toLowerCase();
+
+                if (submitMehtod.equals("post")
+                        || submitMehtod.equals("delete")
+                        || submitMehtod.equals("put")){
+                    //boolean b = strAccept.contains(strCompare);
+                    if (!strContentType.contains(strCompare)
+                            && !strContentType.contains(strShortCompare)
+                            && !strContent.contains(strCompare)
+                            && !strContent.contains(strShortCompare)
+                            && !strAccept.contains(strCompare)
+                            && !strAccept.contains(strShortCompare)){
+                        HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_INVALID_CONTENT_TYPE);//POST/DELETE/PUT时Content-Type不对
+                        bResult = false;
+                    }
+                }else if (submitMehtod.equals("get")){
+                    /*String strAuthToken = request.getHeader("authortoken");
+                    String strUserAgent = request.getHeader(ApiURI.HEADER_USER_AGENT);
+                    if (!StringUtils.isEmpty(strAuthToken)
+                            || ("apk".equals(CommTool.getPlatformByAgent(strUserAgent)) && !strContentType.contains(strCompare))){
+                        HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_ACCESS_DENY);
+                        bResult = false;
+                    }*/
+                }
+
+                if (!bResult && mTmpIndex.incrementAndGet()%10==0){
+                    Map<String, String> mapHeads = new HashMap<String, String>();
+                    Enumeration<String> headerNames = request.getHeaderNames();
+                    while (headerNames.hasMoreElements()) {
+                        String key = (String)headerNames.nextElement();
+                        String value = "";
+                        Enumeration<String> headerValues = request.getHeaders(key);
+                        while (headerValues.hasMoreElements()){
+                            value = value + (String)headerValues.nextElement();
+                        }
+                        mapHeads.put(key, value);
+                    }
+
+                    String strAddress = HttpTool.getIpAddress(request);
+                    LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_WARN, LogFlagBusiType.BUSI_AUTH.toStrValue(), mStrThisSampleName, "Inner"
+                            , String.format("uri:{%s %s} remote_address:{%s} illegal request for printing... %s"
+                                    , submitMehtod
+                                    , request.getRequestURI()
+                                    , strAddress
+                                    , FastJsonUtil.toJSON(mapHeads)));
+                }
+            } else{
+                HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_ERROR_REQUEST_METHOD);//URI对应的Method不对
+                bResult = false;
+            }
+        } else{
+            HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_NOT_MATCHED_URI);//找不到对应的URI
+            bResult = false;
+        }
+        return bResult;
+    }
+
+    protected boolean checkRequestParam(HttpServletRequest request, HttpServletResponse response){ return true; }
+
+    protected boolean checkRequestBody(HttpServletRequest request, HttpServletResponse response){
+        return true;
+    }
+
+    public <T> boolean checkObjectByValidator(T object, Class<?>... classForObject){
+        if (mValidator != null){
+            Set<ConstraintViolation<T>> constraintViolations = mValidator.validate(object, classForObject);
+            if (!(constraintViolations == null || constraintViolations.size() <= 0))
+                return false;
+        }
+        return true;
+    }
+}

+ 27 - 0
src/main/java/com/shkpr/service/aimodelpower/controllercheck/ThirdCommReportFormCheck.java

@@ -0,0 +1,27 @@
+package com.shkpr.service.aimodelpower.controllercheck;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+public class ThirdCommReportFormCheck extends JWTControllerCheck {
+    public ThirdCommReportFormCheck(Map<String, String> mapURI2Method) {
+        super(mapURI2Method);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+    }
+
+    @Override
+    protected boolean checkRequestHead(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestHead(request, response);
+    }
+
+    @Override
+    protected boolean checkRequestParam(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestParam(request, response);
+    }
+
+    @Override
+    protected boolean checkRequestBody(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestBody(request, response);
+    }
+}

+ 28 - 0
src/main/java/com/shkpr/service/aimodelpower/controllercheck/ThirdCostomXXXControllerCheck.java

@@ -0,0 +1,28 @@
+package com.shkpr.service.aimodelpower.controllercheck;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+public class ThirdCostomXXXControllerCheck extends JWTControllerCheck {
+    public ThirdCostomXXXControllerCheck(Map<String, String> mapURI2Method) {
+        super(mapURI2Method);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+    }
+
+    @Override
+    protected boolean checkRequestHead(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestHead(request, response);
+    }
+
+    @Override
+    protected boolean checkRequestParam(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestParam(request, response);
+    }
+
+    @Override
+    protected boolean checkRequestBody(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestBody(request, response);
+    }
+}
+

+ 32 - 0
src/main/java/com/shkpr/service/aimodelpower/controllercheck/ThirdTaskFilesControllerCheck.java

@@ -0,0 +1,32 @@
+package com.shkpr.service.aimodelpower.controllercheck;
+
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+public class ThirdTaskFilesControllerCheck extends JWTControllerCheck {
+    public ThirdTaskFilesControllerCheck(Map<String, String> mapURI2Method) {
+        super(mapURI2Method);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+    }
+
+    @Override
+    protected boolean checkRequestHead(HttpServletRequest request, HttpServletResponse response) {
+        String uri = request.getRequestURI();
+        if (uri.startsWith(String.format("%s/%s", ApiURI.URI_FILES_H, ApiURI.URI_XXX_UPLOAD)))
+            return true;
+        return super.checkRequestHead(request, response);
+    }
+
+    @Override
+    protected boolean checkRequestParam(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestParam(request, response);
+    }
+
+    @Override
+    protected boolean checkRequestBody(HttpServletRequest request, HttpServletResponse response) {
+        return super.checkRequestBody(request, response);
+    }
+}

+ 25 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/CustomAuthenticationProvider.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.aimodelpower.controllerfilter;
+
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+public class CustomAuthenticationProvider implements AuthenticationProvider {
+    protected String mStrThisSampleName = null;
+
+    public CustomAuthenticationProvider() {
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+    }
+
+    //在JWTLoginFilter::attemptAuthentication()之后执行
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        return null;
+    }
+
+    @Override
+    public boolean supports(Class<?> aClass) {
+        return aClass.equals(UsernamePasswordAuthenticationToken.class);
+    }
+}

+ 88 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/GrantedAuthorityImpl.java

@@ -0,0 +1,88 @@
+package com.shkpr.service.aimodelpower.controllerfilter;
+
+import com.shkpr.service.aimodelpower.dto.LoginUserRoleType;
+import org.springframework.security.core.GrantedAuthority;
+import java.util.ArrayList;
+import java.util.List;
+
+public class GrantedAuthorityImpl implements GrantedAuthority{
+    private static volatile List<GrantedAuthorityImpl> msArrRootAdmin = null;
+    private static volatile List<GrantedAuthorityImpl> msArrAdmin = null;
+    private static volatile List<GrantedAuthorityImpl> msArrNormalUser = null;
+    private static volatile List<GrantedAuthorityImpl> msArrTempUser = null;
+
+    private String authority;
+    public GrantedAuthorityImpl(String authority) {
+        this.authority = authority;
+    }
+    public void setAuthority(String authority) {
+        this.authority = authority;
+    }
+    @Override
+    public String getAuthority() {
+        return this.authority;
+    }
+
+    public static List<GrantedAuthorityImpl> generateAuthority(LoginUserRoleType emType){
+        switch (emType){
+            case ROOT_ADMIN:{
+                if (msArrRootAdmin == null){
+                    synchronized(GrantedAuthorityImpl.class){
+                        if (msArrRootAdmin == null){
+                            msArrRootAdmin = new ArrayList<GrantedAuthorityImpl>();
+                            msArrRootAdmin.add(new GrantedAuthorityImpl(emType.toStrValue()));
+                        }
+                    }
+                }
+            }
+            return msArrRootAdmin;
+            case GUEST:{
+                if (msArrTempUser == null){
+                    synchronized(GrantedAuthorityImpl.class){
+                        if (msArrTempUser == null){
+                            msArrTempUser = new ArrayList<GrantedAuthorityImpl>();
+                            msArrTempUser.add(new GrantedAuthorityImpl(emType.toStrValue()));
+                        }
+                    }
+                }
+            }
+            return msArrTempUser;
+            case USER:{
+                if (msArrNormalUser == null){
+                    synchronized(GrantedAuthorityImpl.class){
+                        if (msArrNormalUser == null){
+                            msArrNormalUser = new ArrayList<GrantedAuthorityImpl>();
+                            msArrNormalUser.add(new GrantedAuthorityImpl(emType.toStrValue()));
+                        }
+                    }
+                }
+            }
+            return msArrNormalUser;
+            case NORMAL_ADMIN:{
+                if (msArrAdmin == null){
+                    synchronized(GrantedAuthorityImpl.class){
+                        if (msArrAdmin == null){
+                            msArrAdmin = new ArrayList<GrantedAuthorityImpl>();
+                            msArrAdmin.add(new GrantedAuthorityImpl(emType.toStrValue()));
+                        }
+                    }
+                }
+            }
+            return msArrAdmin;
+            default:
+                break;
+        }
+        return null;
+    }
+
+    public static LoginUserRoleType getRoleTypeByAuthority(List<GrantedAuthorityImpl> authorityList){
+        if (authorityList == msArrRootAdmin)
+            return LoginUserRoleType.ROOT_ADMIN;
+        else if (authorityList == msArrAdmin)
+            return LoginUserRoleType.NORMAL_ADMIN;
+        else if (authorityList == msArrNormalUser)
+            return LoginUserRoleType.USER;
+        else
+            return LoginUserRoleType.GUEST;
+    }
+}

+ 126 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/JWTAuthenticationFilter.java

@@ -0,0 +1,126 @@
+package com.shkpr.service.aimodelpower.controllerfilter;
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.aimodelpower.commtools.HttpTool;
+import com.shkpr.service.aimodelpower.constants.LogFlagBusiType;
+import com.shkpr.service.aimodelpower.controllercheck.JWTControllerCheck;
+import com.shkpr.service.aimodelpower.exception.SelfAuthFilterException;
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import com.shkpr.service.aimodelpower.dto.ResponseCode;
+import org.springframework.security.authentication.AccountExpiredException;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.CredentialsExpiredException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Token过滤器,检验所有请求的Token是否合法
+ * 从http头的Authorization 项读取token数据,然后校验token的合法性
+ * 如果校验通过,就认为这是一个取得授权的合法请求
+ */
+public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
+    private RequestMatcher mRequestMatcher = null;
+    protected String mStrThisSampleName = null;
+    protected JWTControllerCheck mControllerCheck = null;
+
+    public JWTAuthenticationFilter(AuthenticationManager authenticationManager){
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+    }
+
+    public JWTAuthenticationFilter(String url, AuthenticationManager authenticationManager){
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        if (url != null && !url.isEmpty())
+            this.mRequestMatcher = new AntPathRequestMatcher(url);
+    }
+
+    public void setControllerCheck(JWTControllerCheck mControllerCheck) {
+        this.mControllerCheck = mControllerCheck;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        if (this.mRequestMatcher != null && !this.mRequestMatcher.matches(request)){
+            //System.out.println(mStrThisSampleName+"::doFilterInternal not matches()...");
+            //response.setStatus(ResponseCode.STATUS_NOT_MATCHED_URI.toInt());
+            //如果response.setStatus()设置成非200值后,将在下一个filter的checkHandle()函数中直接return false,
+            //这样request无法继续向后传递,始终无法得到执行
+            chain.doFilter(request, response); //当前URI没有匹配成功,向后传递继续匹配
+            return;
+        }
+
+        if (mControllerCheck != null && !mControllerCheck.checkRequest(request, response))  //当前URI已匹配成功,但Request请求格式不对,不再向后传递
+            return;
+
+        /*if (GlobalData.getInstance().isForDevPressureTest()
+                && ThirdJWTDevicesAuthFilter.class.getSimpleName().equals(mStrThisSampleName)){
+            chain.doFilter(request, response);                                                   //不验证token直接向后传递
+            return;
+        }*/
+
+        int nStatusCode = HttpServletResponse.SC_OK;
+        Authentication authentication = null;
+        try {
+            authentication = TokenAuthenticationService.getAuthentication(request);
+            if (authentication != null)
+                SecurityContextHolder.getContext().setAuthentication(authentication); //不设置setAuthentication(authentication)将默认返回403,得不到正确结果
+        }
+        /* !!! 注:SecurityContextHolder.getContext().getAuthentication() == null时response.setStatus(xxx)无效,response.status总为403 !!! */
+        catch (BadCredentialsException e){
+            //无Token或者非法的Token
+            nStatusCode = ResponseCode.STATUS_INVALID_TOKEN.toInt();
+            HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_INVALID_TOKEN);
+            //System.out.println(e.getMessage());
+        }catch (CredentialsExpiredException e){
+            //非法Token,或已过期
+            nStatusCode = ResponseCode.STATUS_EXPIRED_TOKEN.toInt();
+            HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_EXPIRED_TOKEN);
+            //System.out.println(e.getMessage());
+        }catch (AccountExpiredException e){
+            //还未注册过,需要注册
+            nStatusCode = ResponseCode.STATUS_NOT_LOGGED_IN.toInt();
+            HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_NOT_LOGGED_IN);
+            //System.out.println(e.getMessage());
+        }catch (SelfAuthFilterException e){
+            nStatusCode = e.getErrorCode();
+            HttpTool.handlerHttpErrorStatus(response, e.getErrorCode(), e.getMessage());
+            //System.out.println(e.getMessage());
+        }catch (Exception e){
+            //其他错误
+            nStatusCode = ResponseCode.STATUS_ACCESS_DENY.toInt();
+            HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_ACCESS_DENY);
+            //System.out.println(e.getMessage());
+        }
+
+        if (authentication == null){
+            //SecurityContextHolder.getContext().setAuthentication(null);           //Token不合法时需要设置setAuthentication(null),不然response仍然返回200并且携带数据结果
+                                                                                   //解决bug:最近一次验证成功过,如此次未验证成功且不设置setAuthentication(null)的话,response.status仍然为200且会携带数据结果
+            if (GlobalData.getInstance().isHttpStatusAlready200()){
+                if (nStatusCode == HttpServletResponse.SC_OK)
+                    HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_ACCESS_DENY);
+            }else{
+                if (response.getStatus() == HttpServletResponse.SC_OK)
+                    HttpTool.handlerHttpErrorStatus(response, ResponseCode.STATUS_ACCESS_DENY);
+            }
+
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_WARN, LogFlagBusiType.BUSI_AUTH.toStrValue(), "JWTAuthenticationFilter"
+                    , String.format("Auth Failed Uri{%s} Remote{%s:%d}"
+                            ,request.getRequestURI()
+                            ,request.getRemoteAddr()
+                            ,request.getRemotePort()));
+            return; //当前URI已匹配成功但未验证成功,不再向后传递
+        }
+        chain.doFilter(request, response);  //当前URI已匹配成功且已验证成功,向后传递,filter链路执行完毕后,进入自己的拦截器
+    }
+}

+ 392 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/TokenAuthenticationService.java

@@ -0,0 +1,392 @@
+package com.shkpr.service.aimodelpower.controllerfilter;
+
+import com.global.base.tools.CastUtil;
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import com.shkpr.service.aimodelpower.constants.CommDefine;
+import com.shkpr.service.aimodelpower.exception.SelfAuthFilterException;
+import com.shkpr.service.aimodelpower.globalcache.GlobalData;
+import com.shkpr.service.aimodelpower.globalcache.UserCacheProxy;
+import com.shkpr.service.aimodelpower.dto.AuthTokenData;
+import com.shkpr.service.aimodelpower.dto.ResponseCode;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.CredentialsExpiredException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TokenAuthenticationService {
+    public static final int MIN_EXPIRATIONTIME = 7*60*24;                              // 默认Token过期时间为7天(单位:分钟)
+    public static final long MS_EXPIRATIONTIME = MIN_EXPIRATIONTIME*60*1000;         // 默认Token过期时间为7天(单位:毫秒)
+    public static final String SECRET = "TRICP_ALAM_DMA";                              // JWT密码
+    public static final String HEADER_STRING = "Authorization";                       // 存放Token的Header Key
+    public static final String HEADER_CONTENT_TYPE = "application/json;charset=UTF-8";
+    public static final String HEADER_SHORT_CONTENT_TYPE = "application/json";
+    public static final String SIGNATURE_KEY = "tri_coorperation_tech";              //签名秘钥
+    public static final String HEADER_SEQUENCE = "Sequence";
+    public static final String HEADER_USERID = "UUID";
+    public static final String HEADER_ROLEID = "RLID";
+    public static final boolean bRoleIsStr = true;
+    //该方法使用HS256算法生成signKey
+    /*private static Key getKeyInstance() {
+        //We will sign our JavaWebToken with our ApiKey secret
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
+        return new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
+    }*/
+
+    /**
+     * 从数据声明中生成令牌
+     * @param claims
+     * @return
+     */
+    public static AuthTokenData generateToken(Map<String, Object> claims){
+        return generateToken(claims, MIN_EXPIRATIONTIME);
+    }
+
+    /**
+     * 从数据声明中生成令牌
+     * @param expired Token过期时间(单位:分钟)
+     * @return
+     */
+    public static AuthTokenData generateToken(Map<String, Object> claims, int expired){
+        long nowMillis   = System.currentTimeMillis();
+        Date dateExpired  = null;
+        String strFlagKey = null;
+        String strToken = null;
+        try {
+            strToken = Jwts.builder()
+                    .setClaims(claims)
+                    .setIssuedAt(new Date(nowMillis))                                         //设置Token的签发时间
+                    .setExpiration(dateExpired = new Date(nowMillis + expired*60*1000))       //设置Token有效期
+                    .signWith(SignatureAlgorithm.HS256, SECRET.getBytes("UTF-8"))          //签名设置
+                    .compact();
+            try {
+                strFlagKey = (String)claims.get("flagkey");
+            } catch (Exception e){}
+        } catch (Exception e){
+            strToken = null;
+            e.printStackTrace();
+        }
+
+        return  StringUtils.isEmpty(strToken) ? null:new AuthTokenData(strToken
+                , dateExpired!=null ? dateExpired.getTime():System.currentTimeMillis()
+                , nowMillis
+                , strFlagKey);
+    }
+
+    /**
+     * @param strFlagKey
+     * @param expired Token过期时间(单位:分钟)
+     * @return
+     */
+    public static AuthTokenData generateToken(String strFlagKey, String strAccount, String roleId, int expired){
+        Map<String, Object> claims = new HashMap<>(16);
+        //claims.put("sub", strUsername);
+        claims.put("flagkey", strFlagKey);
+        claims.put("account", strAccount);
+        claims.put("roleid", bRoleIsStr?roleId:CastUtil.castInt(roleId));
+        return generateToken(claims, expired);
+    }
+
+    /**
+     * 从令牌中获取数据声明
+     * 使用该接口需要同时捕获ExpiredJwtException和Exception异常并处理
+     * @param token 令牌
+     * @return 数据声明
+     */
+    private static Claims getClaimsFromToken(String token) throws ExpiredJwtException, Exception{
+        Claims claims = null;
+        try {
+            claims = Jwts.parser().setSigningKey(SECRET.getBytes("UTF-8")).parseClaimsJws(token).getBody();
+        }catch (ExpiredJwtException e){
+            claims = null;
+            throw e;
+        }catch (Exception e) {
+            claims = null;
+            throw e;
+        }
+        return claims;
+    }
+
+    /**
+     * 从令牌中获取FlagKey
+     * @param token
+     * @return
+     * @throws ExpiredJwtException
+     * @throws Exception
+     */
+    public static String getFlagKeyFromToken(String token) throws ExpiredJwtException, Exception{
+        String strKey = null;
+        try {
+            Claims claims = getClaimsFromToken(token);
+            if (claims != null)
+                strKey = (String)claims.get("flagkey");
+        }catch (ExpiredJwtException e){
+            strKey = null;
+            throw e;
+        }catch (Exception e) {
+            strKey = null;
+            throw e;
+        }
+        return strKey;
+    }
+
+    public static AuthTokenData getAuthDataFromToken(String token) throws ExpiredJwtException, Exception{
+        AuthTokenData data = null;
+        try {
+            Claims claims = getClaimsFromToken(token);
+            if (claims != null){
+                String strKey = (String)claims.get("flagkey");
+                String nRoleId = bRoleIsStr?(String)claims.get("roleid"):String.valueOf((int)claims.get("roleid"));
+                data = new AuthTokenData(token, claims.getExpiration().getTime(), claims.getIssuedAt().getTime(), strKey, nRoleId);
+            }
+        }catch (ExpiredJwtException e){
+            data = null;
+            throw e;
+        }catch (Exception e) {
+            data = null;
+            throw e;
+        }
+        return data;
+    }
+
+    /**
+     * 从令牌中获取用户ID
+     *
+     * @param token 令牌
+     * @return 用户ID
+     */
+    public static String getUserIDFromToken(String token) throws ExpiredJwtException, Exception{
+        String strKey = null;
+        try {
+            strKey = getFlagKeyFromToken(token);
+        }catch (Exception e) {
+            strKey = null;
+            throw e;
+        }
+        int nIndex = (strKey != null) ? strKey.indexOf(":"):-1;
+        if (nIndex >= 0)
+            strKey = strKey.substring(nIndex+1);
+        return strKey;
+    }
+
+    /**
+     * 从令牌中获取权限角色
+     * @param token
+     * @return
+     */
+    /*public static String getStrAuthorityFromToken(String token) throws ExpiredJwtException, Exception{
+        String strAuthority = null;
+        try {
+            Claims claims = getClaimsFromToken(token);
+            if (claims != null)
+                strAuthority = (String)claims.get("authorities");
+        } catch (ExpiredJwtException e){
+            strAuthority = null;
+            throw e;
+        } catch (Exception e) {
+            strAuthority = null;
+            throw e;
+        }
+        return strAuthority;
+    }*/
+
+    /**
+     * 判断令牌是否过期
+     *
+     * @param token 令牌
+     * @return 是否过期
+     */
+    public static Boolean isTokenExpired(String token){
+        try {
+            Claims claims = getClaimsFromToken(token);
+            if (claims != null){
+                Date expiration = claims.getExpiration();
+                return expiration.before(new Date());
+            }
+        } catch (ExpiredJwtException e){
+            return true;
+        } catch (Exception e) {
+            return true;
+        }
+        return true;
+    }
+
+    /**
+     * 判断令牌是否过期
+     *
+     * @return 是否过期
+     */
+    public static Boolean isTokenExpired(long lExpired){
+        return lExpired <= new Date().getTime();
+    }
+
+    /**
+     * 刷新令牌
+     * @param token 原令牌
+     * @param nExpired Token过期时间(单位:分钟)
+     * @return
+     */
+    public static AuthTokenData refreshToken(String token, int nExpired) throws ExpiredJwtException, Exception{
+        AuthTokenData tokenData = null;
+        try {
+            Claims claims = getClaimsFromToken(token);
+            if (claims != null){
+                tokenData = generateToken(claims, nExpired);
+            }
+        } catch (ExpiredJwtException e){
+            tokenData = null;
+            throw e;
+        } catch (Exception e) {
+            tokenData = null;
+            throw e;
+        }
+        return tokenData;
+    }
+
+    /**
+     * 验证令牌
+     *
+     * @param token 令牌
+     * @return 是否有效
+     */
+    public static Boolean validateToken(String token) {
+        return !isTokenExpired(token);
+    }
+
+    public static Authentication getAuthentication(HttpServletRequest request) throws Exception{
+        final String strAuthVerify = request.getHeader(ApiURI.HEADER_AUTH_VERIFY);
+        if (GlobalData.getInstance().getInternalCallPassword().equalsIgnoreCase(strAuthVerify)){
+            try {
+                request.setAttribute(HEADER_USERID, CommDefine.INTERNAL_OPERATOR_ID);
+                request.setAttribute(HEADER_ROLEID, CommDefine.INTERNAL_OPERATOR_ROLE_ID);
+            }catch (Exception e){}
+
+            return new UsernamePasswordAuthenticationToken(CommDefine.INTERNAL_OPERATOR_ID,
+                    null,
+                    new ArrayList<GrantedAuthorityImpl>());
+        }
+
+        // 从Header中拿到token
+        String strUri = request.getRequestURI();
+        String authHeader = request.getHeader(HEADER_STRING);
+        if (authHeader != null && authHeader.length() > 0 /*&& authHeader.startsWith(TOKEN_PREFIX)*/){
+            String authToken = authHeader/*authHeader.substring(TOKEN_PREFIX.length())*/;
+            AuthTokenData authData = null;
+            try {
+                authData = getAuthDataFromToken(authToken);
+            } catch (ExpiredJwtException e){
+                throw new CredentialsExpiredException("Invalidate token, token is expired.");
+            } catch (Exception e){
+                throw new BadCredentialsException("Invalidate Token, has no user.");
+            }
+
+            boolean bEasy = true;
+            if (bEasy && authData != null){
+                long lTimeLogout = UserCacheProxy.getInstance().getLogoutAccountTime(authData.getStrFlagKey());
+                if (lTimeLogout == -1){//此账号未被注销过
+                    if (isTokenExpired(authData.getExpired()))
+                        throw new CredentialsExpiredException("Invalidate token, token is expired.");
+                }else {
+                    //此账号被注销过,判断token的签发时间和注销时间
+                    if (authData.getIssueAt() <= lTimeLogout)        //签发时间早于注销时间
+                        throw new BadCredentialsException("Invalidate Token, has no user.");
+                    else if (isTokenExpired(authData.getExpired())) //签发时间晚于注销时间,但已过期
+                        throw new CredentialsExpiredException("Invalidate token, token is expired.");
+                }
+
+                /*LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_AUTH.toStrValue(), TokenAuthenticationService.class.getSimpleName()
+                        , String.format("%s User(%s) Remote{%s:%d}"
+                                ,request.getRequestURI()
+                                ,authData.getStrFlagKey()
+                                ,request.getRemoteAddr()
+                                ,request.getRemotePort()));*/
+
+                if (strUri.startsWith(ApiURI.URI_INTERNAL_H)){
+                    if (!CommDefine.INTERNAL_OPERATOR_ID.equals(authData.getStrFlagKey())){
+                        throw new SelfAuthFilterException(ResponseCode.STATUS_DENY_OPERATE_USER.toInt()
+                                ,ResponseCode.STATUS_DENY_OPERATE_USER.toStrMsg());
+                    }
+                }
+
+                try {
+                    request.setAttribute(HEADER_USERID, authData.getStrFlagKey());
+                    request.setAttribute(HEADER_ROLEID, authData.getRoleid());
+                }catch (Exception e){}
+
+                return new UsernamePasswordAuthenticationToken(authData.getStrFlagKey(),
+                        null,
+                        new ArrayList<GrantedAuthorityImpl>());
+            }else{
+                /*JwtLoginUserEx oUser = null;
+                try {
+                    strFlagKey = getFlagKeyFromToken(authToken);
+                    oUser = UserCacheProxy.getInstance().getJwtUser(strFlagKey);
+                } catch (ExpiredJwtException e){
+                    throw new CredentialsExpiredException("Invalidate token, token is expired.");
+                } catch (Exception e){
+                    throw new BadCredentialsException("Invalidate Token, has no user.");
+                }
+
+                if (oUser == null){
+                    throw new AccountExpiredException("Current user has not login.");
+                }
+
+                if (GlobalData.getInstance().isTokenMustUnique()
+                        && oUser.getTokenData().getStrToken() != null
+                        && !oUser.getTokenData().getStrToken().equals(authToken)){
+                    throw new SelfAuthFilterException(ResponseCode.STATUS_TOO_OLD_TOKEN.toInt(), ResponseCode.STATUS_TOO_OLD_TOKEN.toStrMsg());
+                }
+
+                if (isTokenExpired(oUser.getTokenData().getExpired())){
+                    throw new CredentialsExpiredException("Invalidate token, token is expired.");
+                }
+
+                if (oUser.getAuthToken() == null){                                                     // 用户的AuthToken必须在登录的时候进行设置,不登录的用户直接使用Token默认为不合法
+                    throw new AccountExpiredException("Current user has not login.");
+                }
+
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_AUTH.toStrValue(), TokenAuthenticationService.class.getSimpleName()
+                        , String.format("%s %s Remote{%s:%d}"
+                                ,request.getRequestURI()
+                                ,oUser.toString()
+                                ,request.getRemoteAddr()
+                                ,request.getRemotePort()));
+                return oUser.getAuthToken();
+                */
+                throw new BadCredentialsException("Invalidate Token, has no user.");
+            }
+        }else {
+            throw new SelfAuthFilterException(ResponseCode.STATUS_EMPTY_TOKEN.toInt(), ResponseCode.STATUS_EMPTY_TOKEN.toStrMsg());
+        }
+    }
+
+    /**
+     * Token 中的userid是否为给定的userid
+     * @param strAuthToken
+     * @param strUserId
+     * @return
+     */
+    public static boolean isTheSelfUser(String strAuthToken, String strUserId){
+        if (StringUtils.isEmpty(strUserId))
+            return false;
+
+        String strFlagKey = null;
+        try {
+            strFlagKey = TokenAuthenticationService.getFlagKeyFromToken(strAuthToken);
+        }catch (Exception e){
+            return false;
+        }
+        return strUserId.equals(strFlagKey);
+    }
+}

+ 72 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTBusiFilterMgr.java

@@ -0,0 +1,72 @@
+package com.shkpr.service.aimodelpower.controllerfilter.third;
+
+import com.shkpr.service.aimodelpower.controllerfilter.JWTAuthenticationFilter;
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import com.shkpr.service.aimodelpower.globalmgr.TraceLogMgr;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class ThirdJWTBusiFilterMgr extends JWTAuthenticationFilter {
+    private RequestMatcher mRequestMatcherForTaskFiles = null;
+    private RequestMatcher mRequestMatcherForCustomXXX = null;
+    private RequestMatcher mRequestMatcherForReportForm = null;
+    private ThirdJWTTaskFilesBusiFilter mFilterForTaskFiles = null;
+    private ThirdJWTCustomXXXFilter mFilterForCustomXXX = null;
+    private ThirdJWTCommReportFormFilter mFilterForReportForm = null;
+
+    public ThirdJWTBusiFilterMgr(AuthenticationManager authenticationManager)
+    {
+        this(null, authenticationManager);
+    }
+
+    public ThirdJWTBusiFilterMgr(String url, AuthenticationManager authenticationManager) {
+        super(url,  authenticationManager);
+        this.mStrThisSampleName  = this.getClass().getSimpleName();
+
+        mRequestMatcherForCustomXXX = new AntPathRequestMatcher(ApiURI.URI_CUSTOMIZE_XXX);
+        mRequestMatcherForReportForm = new AntPathRequestMatcher(ApiURI.URI_COMM_REPORT_FORM_XXX);
+        mFilterForTaskFiles = new ThirdJWTTaskFilesBusiFilter(ApiURI.URI_FILES_XXX, authenticationManager);
+        mFilterForCustomXXX = new ThirdJWTCustomXXXFilter(ApiURI.URI_CUSTOMIZE_XXX, authenticationManager);
+        mFilterForReportForm = new ThirdJWTCommReportFormFilter(ApiURI.URI_COMM_REPORT_FORM_XXX, authenticationManager);
+        setControllerCheck(null);
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        //System.out.println(this.mStrThisSampleName+"::doFilterInternal()..."+request.getContextPath()+" " + request.getRequestURI());
+        try {
+             if (mRequestMatcherForTaskFiles != null && mRequestMatcherForTaskFiles.matches(request)){
+                TraceLogMgr.setTraceIdByBusinessType("TASK.FILES");
+                mFilterForTaskFiles.doFilterInternal(request, response, chain);
+            }  else if (mRequestMatcherForCustomXXX != null && mRequestMatcherForCustomXXX.matches(request)){
+                TraceLogMgr.setTraceIdByBusinessType("CUSTOMIZE.XXX");
+                mFilterForCustomXXX.doFilterInternal(request, response, chain);
+            } else if (mRequestMatcherForReportForm != null && mRequestMatcherForReportForm.matches(request)){
+                TraceLogMgr.setTraceIdByBusinessType("REPORT.FORM");
+                mFilterForReportForm.doFilterInternal(request, response, chain);
+            }
+            else {
+                TraceLogMgr.setTraceIdByBusinessType("OTH");
+                //System.out.println(mStrThisSampleName+"::doFilterInternal not matches()...");
+                //response.setStatus(ResponseCode.STATUS_NOT_MATCHED_URI.toInt());
+                //如果response.setStatus()设置成非200值后,将在下一个filter的checkHandle()函数中直接return false,
+                //这样request无法继续向后传递,始终无法得到执行
+                chain.doFilter(request, response); //当前URI没有匹配成功,向后传递继续匹配
+                //return;
+            }
+        }catch (ServletException e1){
+            throw e1;
+        }catch (IOException e2){
+            throw e2;
+        }finally {
+            TraceLogMgr.removeTraceId();
+        }
+    }
+}

+ 45 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTCommReportFormFilter.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.aimodelpower.controllerfilter.third;
+
+import com.shkpr.service.aimodelpower.controllercheck.ThirdCostomXXXControllerCheck;
+import com.shkpr.service.aimodelpower.controllerfilter.JWTAuthenticationFilter;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ThirdJWTCommReportFormFilter extends JWTAuthenticationFilter {
+    private RequestMatcher mRequestMatcher = null;
+    private ThirdCostomXXXControllerCheck mControllerCheck = null;
+    private static final Map<String, String> msMapURI2Method;
+    static {
+        msMapURI2Method = new HashMap<String, String>();
+    }
+
+    public ThirdJWTCommReportFormFilter(AuthenticationManager authenticationManager) {
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ThirdCostomXXXControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    public ThirdJWTCommReportFormFilter(String url, AuthenticationManager authenticationManager) {
+        super(url, authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ThirdCostomXXXControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    @Override
+    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        //System.out.println(this.mStrThisSampleName+"::doFilterInternal()...");
+        super.doFilterInternal(request, response, chain);
+    }
+}
+
+

+ 46 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTCustomXXXFilter.java

@@ -0,0 +1,46 @@
+package com.shkpr.service.aimodelpower.controllerfilter.third;
+
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import com.shkpr.service.aimodelpower.controllercheck.ThirdCostomXXXControllerCheck;
+import com.shkpr.service.aimodelpower.controllerfilter.JWTAuthenticationFilter;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ThirdJWTCustomXXXFilter extends JWTAuthenticationFilter {
+    private RequestMatcher mRequestMatcher = null;
+    private ThirdCostomXXXControllerCheck mControllerCheck = null;
+    private static final Map<String, String> msMapURI2Method;
+    static {
+        msMapURI2Method = new HashMap<String, String>();
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_CUSTOMIZE_COMPLEX_OPTIONS_H, ApiURI.URI_XXX_LISTS), "GET");
+    }
+
+    public ThirdJWTCustomXXXFilter(AuthenticationManager authenticationManager) {
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ThirdCostomXXXControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    public ThirdJWTCustomXXXFilter(String url, AuthenticationManager authenticationManager) {
+        super(url, authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ThirdCostomXXXControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    @Override
+    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        //System.out.println(this.mStrThisSampleName+"::doFilterInternal()...");
+        super.doFilterInternal(request, response, chain);
+    }
+}
+

+ 46 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTTaskFilesBusiFilter.java

@@ -0,0 +1,46 @@
+package com.shkpr.service.aimodelpower.controllerfilter.third;
+
+import com.shkpr.service.aimodelpower.constants.ApiURI;
+import com.shkpr.service.aimodelpower.controllercheck.ThirdTaskFilesControllerCheck;
+import com.shkpr.service.aimodelpower.controllerfilter.JWTAuthenticationFilter;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ThirdJWTTaskFilesBusiFilter extends JWTAuthenticationFilter {
+    private RequestMatcher mRequestMatcher = null;
+    private ThirdTaskFilesControllerCheck mControllerCheck = null;
+    private static final Map<String, String> msMapURI2Method;
+    static {
+        msMapURI2Method = new HashMap<String, String>();
+        msMapURI2Method.put(String.format("%s/%s/(.*)", ApiURI.URI_FILES_H, ApiURI.URI_XXX_UPLOAD), "Request");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_FILES_H, ApiURI.URI_XXX_DOWNLOAD), "Get");
+    }
+
+    public ThirdJWTTaskFilesBusiFilter(AuthenticationManager authenticationManager) {
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ThirdTaskFilesControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    public ThirdJWTTaskFilesBusiFilter(String url, AuthenticationManager authenticationManager) {
+        super(url, authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ThirdTaskFilesControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    @Override
+    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        //System.out.println(this.mStrThisSampleName+"::doFilterInternal()...");
+        super.doFilterInternal(request, response, chain);
+    }
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidAccept.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidAccept {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidAddNote.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidAddNote {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidCheck.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidCheck {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidClose.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidClose {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidDeal.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidDeal {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidDel.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidDel {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidList.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidList {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidNew.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidNew {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidRefuse.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidRefuse {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidResend.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidResend {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidReset.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidReset {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidSK.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidSK {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidSS.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidSS {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidTurn.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidTurn {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/CommonParamValidUrge.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface CommonParamValidUrge {
+}

+ 4 - 0
src/main/java/com/shkpr/service/aimodelpower/controllervalid/OrderParamValidTotal.java

@@ -0,0 +1,4 @@
+package com.shkpr.service.aimodelpower.controllervalid;
+
+public interface OrderParamValidTotal {
+}

+ 56 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/DBMgrProxy.java

@@ -0,0 +1,56 @@
+package com.shkpr.service.aimodelpower.dbdao;
+
+import com.shkpr.service.aimodelpower.SpringContextUtil;
+import com.shkpr.service.aimodelpower.dbdao.services.intef.*;
+
+public class DBMgrProxy {
+    private volatile RolePowerDBService rolePowerDBService = null;
+    private volatile PartitionInfoDBService partitionInfoDBService = null;
+    private volatile RoleInfoDBService roleInfoDBService = null;
+    private volatile UserDBService userDBService = null;
+    private volatile FileAttachmentDBService fileAttachmentDBService = null;
+    private volatile TypeDefineDBService typeDefineDBService = null;
+    private volatile TestGeomInfoDBService testGeomInfoDBService = null;
+    private static volatile DBMgrProxy msInstance = null;
+    public static DBMgrProxy getInstance(){
+        if (msInstance == null){
+            synchronized (DBMgrProxy.class){
+                if (msInstance == null)
+                    msInstance = new DBMgrProxy();
+            }
+        }
+        return msInstance;
+    }
+
+    private DBMgrProxy() {
+    }
+
+    public void init(){
+        if (rolePowerDBService == null)
+            rolePowerDBService = (RolePowerDBService)SpringContextUtil.getBean(RolePowerDBService.class);
+        if (partitionInfoDBService == null)
+            partitionInfoDBService = (PartitionInfoDBService)SpringContextUtil.getBean(PartitionInfoDBService.class);
+        if (roleInfoDBService == null)
+            roleInfoDBService = (RoleInfoDBService)SpringContextUtil.getBean(RoleInfoDBService.class);
+        if (userDBService == null)
+            userDBService = (UserDBService)SpringContextUtil.getBean(UserDBService.class);
+        if (fileAttachmentDBService == null)
+            fileAttachmentDBService = (FileAttachmentDBService)SpringContextUtil.getBean(FileAttachmentDBService.class);
+        if (typeDefineDBService == null)
+            typeDefineDBService = (TypeDefineDBService)SpringContextUtil.getBean(TypeDefineDBService.class);
+    }
+
+    public RolePowerDBService applyRolePowerApi() {return rolePowerDBService;}
+
+    public PartitionInfoDBService applyPartitionApi() {return partitionInfoDBService;}
+
+    public RoleInfoDBService applyRoleInfoApi() {return roleInfoDBService;}
+
+    public UserDBService applyUserInfoApi() {return userDBService;}
+
+    public FileAttachmentDBService applyFileAttachmentApi() {return fileAttachmentDBService;}
+
+    public TypeDefineDBService applyTypeDefineApi() { return typeDefineDBService; }
+
+    public TestGeomInfoDBService applyTestGeomApi() {return  testGeomInfoDBService;}
+}

+ 14 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/FileAttachmentMapper.java

@@ -0,0 +1,14 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+
+import com.shkpr.service.aimodelpower.dbdao.providers.FileAttachmentSqlProvider;
+import com.shkpr.service.aimodelpower.dbdao.tables.FileAttachmentTable;
+import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface FileAttachmentMapper extends FileAttachmentTable {
+    @InsertProvider(type = FileAttachmentSqlProvider.class, method = "batchInserts")
+    int batchInserts(@Param("inserts") List<Map<String, Object>> inserts);
+}

+ 45 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/PartitionInfoMapper.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+import com.shkpr.service.aimodelpower.dbdao.providers.PartitionInfoSqlProvider;
+import com.shkpr.service.aimodelpower.dbdao.tables.PartitionInfoTable;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.apache.ibatis.type.JdbcType;
+
+import java.util.List;
+import java.util.Map;
+
+public interface PartitionInfoMapper extends PartitionInfoTable {
+    @SelectProvider(type = PartitionInfoSqlProvider.class, method = "totalCounts")
+    int totalCounts(@Param("andWheres") Map<String, Object> andWheres, @Param("orWheres") Map<String, Object> orWheres, @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "type", column = "type", javaType = Integer.class , jdbcType = JdbcType.VARCHAR)
+    })
+    @SelectProvider(type = PartitionInfoSqlProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "type", column = "type", javaType = Integer.class , jdbcType = JdbcType.VARCHAR)
+    })
+    @SelectProvider(type = PartitionInfoSqlProvider.class, method = "batchQueryIn")
+    List<Map<String, Object>> batchQueryIn(@Param("ids") List<? extends Object> ids
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+
+    @Results({
+            @Result(property = "type", column = "type", javaType = Integer.class , jdbcType = JdbcType.VARCHAR)
+    })
+    @SelectProvider(type = PartitionInfoSqlProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+}

+ 45 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/RoleInfoMapper.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+
+import com.shkpr.service.aimodelpower.dbdao.providers.RoleInfoSqlProvider;
+import com.shkpr.service.aimodelpower.dbdao.tables.RoleInfoTable;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.apache.ibatis.type.JdbcType;
+
+import java.util.List;
+import java.util.Map;
+
+public interface RoleInfoMapper extends RoleInfoTable {
+    @SelectProvider(type = RoleInfoSqlProvider.class, method = "totalCounts")
+    int totalCounts(@Param("andWheres") Map<String, Object> andWheres, @Param("orWheres") Map<String, Object> orWheres, @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "parentid", column = "parent_id", javaType = Integer.class ,jdbcType = JdbcType.INTEGER)
+    })
+    @SelectProvider(type = RoleInfoSqlProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "parentid", column = "parent_id", javaType = Integer.class ,jdbcType = JdbcType.INTEGER)
+    })
+    @SelectProvider(type = RoleInfoSqlProvider.class, method = "getBySerialId")
+    Map<String, Object> getOne(@Param("table") String table, @Param("filed") String filed, @Param("id") int id);
+
+    @Results({
+            @Result(property = "parentid", column = "parent_id", javaType = Integer.class ,jdbcType = JdbcType.INTEGER)
+    })
+    @SelectProvider(type = RoleInfoSqlProvider.class, method = "queryChildOrParentWiths")
+    List<Map<String, Object>> queryChildOrParentWiths(@Param("selfId") int id
+            , @Param("childOrParent") boolean bQueryChildOrParent
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+}

+ 24 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/RolePowerMapper.java

@@ -0,0 +1,24 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+
+import com.shkpr.service.aimodelpower.dbdao.providers.RolePowerSqlProvider;
+import com.shkpr.service.aimodelpower.dbdao.tables.RolePowerTable;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.SelectProvider;
+
+import java.util.List;
+import java.util.Map;
+
+public interface RolePowerMapper extends RolePowerTable {
+
+    @Results({
+            @Result(property = "roleid", column = "role_id"),
+            @Result(property = "appid", column = "app_id")
+    })
+    @SelectProvider(type = RolePowerSqlProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+}

+ 92 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/TestGeomInfoMapper.java

@@ -0,0 +1,92 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+
+import com.shkpr.service.aimodelpower.dbdao.pgtype.GisPointTypeHandlePg;
+import com.shkpr.service.aimodelpower.dbdao.providers.TestGeomInfoSqlProvider;
+import com.shkpr.service.aimodelpower.dto.SelfGis;
+import org.apache.ibatis.annotations.*;
+import org.apache.ibatis.type.JdbcType;
+
+import java.util.List;
+import java.util.Map;
+
+public interface TestGeomInfoMapper {
+    @SelectProvider(type = TestGeomInfoSqlProvider.class, method = "totalCounts")
+    int totalCounts(@Param("table") String table
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "gis_xy", column = "gis_xy", javaType = SelfGis.class ,jdbcType = JdbcType.OTHER, typeHandler = GisPointTypeHandlePg.class)
+    })
+    @SelectProvider(type = TestGeomInfoSqlProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("table") String table, @Param("filed") String file
+            , @Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "gis_xy", column = "gis_xy", javaType = SelfGis.class ,jdbcType = JdbcType.OTHER, typeHandler = GisPointTypeHandlePg.class)
+    })
+    @SelectProvider(type = TestGeomInfoSqlProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table, @Param("filed") String filed, @Param("id") Object id);
+
+    @Results({
+            @Result(property = "gis_xy", column = "gis_xy", javaType = SelfGis.class ,jdbcType = JdbcType.OTHER, typeHandler = GisPointTypeHandlePg.class)
+    })
+    @SelectProvider(type = TestGeomInfoSqlProvider.class, method = "batchQueryIn")
+    List<Map<String, Object>> batchQueryIn(@Param("table") String table, @Param("filed") String file
+            , @Param("ids") List<? extends Object> ids
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @Results({
+            @Result(property = "gis_xy", column = "gis_xy", javaType = SelfGis.class ,jdbcType = JdbcType.OTHER, typeHandler = GisPointTypeHandlePg.class)
+    })
+    @SelectProvider(type = TestGeomInfoSqlProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("table") String table, @Param("filed") String filed
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @InsertProvider(type = TestGeomInfoSqlProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = TestGeomInfoSqlProvider.class, method = "updateWiths")
+    int updateWiths(@Param("datas") Map<String, Object> datas
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @UpdateProvider(type = TestGeomInfoSqlProvider.class, method = "updateWiths")
+    int updateWithsEx(@Param("datas") Map<String, Object> datas
+            , @Param("datasEx") Map<String, Object> datasEx
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = TestGeomInfoSqlProvider.class, method = "existsLine")
+    boolean existLine(@Param("table") String table
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @DeleteProvider(type = TestGeomInfoSqlProvider.class, method = "deleteWiths")
+    int deleteWithsEx(@Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @UpdateProvider(type = TestGeomInfoSqlProvider.class, method = "batchUpdateWiths")
+    int batchUpdateWiths( @Param("andWheres") List<Map<String, Object>> andWheres
+            , @Param("datas") List<Map<String, Object>> datas);
+}

+ 63 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/TypeDefineMapper.java

@@ -0,0 +1,63 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+import com.shkpr.service.aimodelpower.dbdao.providers.TypeDefineSqlProvider;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+import java.util.Map;
+
+public interface TypeDefineMapper {
+    @SelectProvider(type = TypeDefineSqlProvider.class, method = "totalCounts")
+    int totalCounts(@Param("andWheres") Map<String, Object> andWheres, @Param("orWheres") Map<String, Object> orWheres, @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineSqlProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("table") String table
+            , @Param("filed") String file
+            , @Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineSqlProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @InsertProvider(type = TypeDefineSqlProvider.class, method = "insertOrUpdate")
+    int insertOrUpdate(@Param("inserts") Map<String, Object> inserts, @Param("updates") Map<String, Object> updates);
+
+    @InsertProvider(type = TypeDefineSqlProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = TypeDefineSqlProvider.class, method = "updateWiths")
+    int updateWiths(@Param("datas") Map<String, Object> datas
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineSqlProvider.class, method = "existsLine")
+    boolean existLine(@Param("table") String table
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @DeleteProvider(type = TypeDefineSqlProvider.class, method = "deleteWiths")
+    int deleteWith(@Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @DeleteProvider(type = TypeDefineSqlProvider.class, method = "deleteInIds")
+    int batchDeleteIn(@Param("ids") List<? extends Object> ids, @Param("extend") String extend);
+
+    @UpdateProvider(type = TypeDefineSqlProvider.class, method = "batchUpdateWiths")
+    int batchUpdateWiths( @Param("andWheres") List<Map<String, Object>> andWheres
+            , @Param("datas") List<Map<String, Object>> datas);
+}

+ 20 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper/UserMapper.java

@@ -0,0 +1,20 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper;
+
+import com.shkpr.service.aimodelpower.dbdao.providers.UserSqlProvider;
+import com.shkpr.service.aimodelpower.dbdao.tables.UserTable;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.SelectProvider;
+
+import java.util.List;
+import java.util.Map;
+
+public interface UserMapper extends UserTable {
+    @SelectProvider(type = UserSqlProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOneByUniqueId(@Param("table") String table, @Param("filed") String filed, @Param("id") Object id);
+
+    @SelectProvider(type = UserSqlProvider.class, method = "batchQueryIn")
+    List<Map<String, Object>> batchQueryIn(@Param("table") String table, @Param("filed") String filed
+            , @Param("ids") List<? extends Object> ids
+            , @Param("order") String order
+            , @Param("extend") String extend);
+}

+ 67 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/mapper2th/PatrolObjectAttMapper.java

@@ -0,0 +1,67 @@
+package com.shkpr.service.aimodelpower.dbdao.mapper2th;
+
+import com.shkpr.service.aimodelpower.dbdao.providers.PatrolObjectAttSqlProvider;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+import java.util.Map;
+
+public interface PatrolObjectAttMapper {
+    @SelectProvider(type = PatrolObjectAttSqlProvider.class, method = "totalCounts")
+    int totalCounts(@Param("andWheres") Map<String, Object> andWheres, @Param("orWheres") Map<String, Object> orWheres, @Param("extend") String extend);
+
+    @SelectProvider(type = PatrolObjectAttSqlProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("table") String table, @Param("filed") String filed
+            , @Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = PatrolObjectAttSqlProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table, @Param("filed") String filed, @Param("id") Object id);
+
+    @SelectProvider(type = PatrolObjectAttSqlProvider.class, method = "batchQueryIn")
+    List<Map<String, Object>> batchQueryIn(@Param("table") String table, @Param("filed") String filed
+            , @Param("ids") List<? extends Object> ids
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = PatrolObjectAttSqlProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("table") String table, @Param("filed") String filed
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @InsertProvider(type = PatrolObjectAttSqlProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    @InsertProvider(type = PatrolObjectAttSqlProvider.class, method = "batchInserts")
+    int batchInserts(@Param("inserts") List<Map<String, Object>> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = PatrolObjectAttSqlProvider.class, method = "updateWiths")
+    int updateWiths(@Param("datas") Map<String, Object> datas
+            , @Param("datasEx") Map<String, Object> datasEx
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = PatrolObjectAttSqlProvider.class, method = "existsLine")
+    boolean existLine(@Param("table") String table
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @DeleteProvider(type = PatrolObjectAttSqlProvider.class, method = "deleteWiths")
+    int deleteWithsEx(@Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+}

+ 48 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/AbstractGeometryTypeHandlerPg.java

@@ -0,0 +1,48 @@
+package com.shkpr.service.aimodelpower.dbdao.pgtype;
+
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.postgis.Geometry;
+import org.postgis.PGgeometry;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+@SuppressWarnings("unchecked")
+public abstract class AbstractGeometryTypeHandlerPg<T extends Geometry> extends BaseTypeHandler<T> {
+
+    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
+        PGgeometry geometry = new PGgeometry();
+        geometry.setGeometry(parameter);
+        ps.setObject(i, geometry);
+    }
+
+    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnName);
+        if (pGgeometry == null) {
+            return null;
+        }
+        return (T) pGgeometry.getGeometry();
+    }
+
+    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnIndex);
+        if (pGgeometry == null) {
+            return null;
+        }
+        return (T) pGgeometry.getGeometry();
+    }
+
+    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        PGgeometry pGgeometry = (PGgeometry) cs.getObject(columnIndex);
+        if (pGgeometry == null) {
+            return null;
+        }
+        return (T) pGgeometry.getGeometry();
+    }
+
+}
+
+

+ 41 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/BoolTypeHandlerPg.java

@@ -0,0 +1,41 @@
+package com.shkpr.service.aimodelpower.dbdao.pgtype;
+
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.MappedJdbcTypes;
+import org.apache.ibatis.type.MappedTypes;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * 读取时,将数据库中int值转换为boolean值并返回
+ *          使用:@Results({@Result(property = "字段", column = "字段", javaType = Boolean.class ,jdbcType = JdbcType.INTEGER, typeHandler = BoolTypeHandlerPg.class)})
+ * 写入时,将boolean值转换为int值并写入
+ *          使用:#{字段,javaType=Boolean,jdbcType=INTEGER,typeHandler=com.sqlmybatis.test.pgtype.BoolTypeHandlerPg}
+ */
+@MappedTypes({Boolean.class})
+@MappedJdbcTypes(JdbcType.INTEGER)
+public class BoolTypeHandlerPg extends BaseTypeHandler<Boolean>{
+    @Override
+    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Boolean aBoolean, JdbcType jdbcType) throws SQLException {
+        preparedStatement.setInt(i, aBoolean?1:0);
+    }
+
+    @Override
+    public Boolean getNullableResult(ResultSet resultSet, String s) throws SQLException {
+        return resultSet.getInt(s)==0?false:true;
+    }
+
+    @Override
+    public Boolean getNullableResult(ResultSet resultSet, int i) throws SQLException {
+        return resultSet.getInt(i)==0?false:true;
+    }
+
+    @Override
+    public Boolean getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
+        return callableStatement.getInt(i)==0?false:true;
+    }
+}

+ 54 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/DateTypeHandlerPg.java

@@ -0,0 +1,54 @@
+package com.shkpr.service.aimodelpower.dbdao.pgtype;
+
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.MappedJdbcTypes;
+import org.apache.ibatis.type.MappedTypes;
+
+import java.sql.*;
+import java.util.Date;
+
+/**
+ * 读取时,将数据库中以varchar形式存储的毫秒转换为Date时间类型并返回
+ *          使用:@Results({@Result(property = "字段", column = "字段", javaType = Date.class ,jdbcType = JdbcType.VARCHAR, typeHandler = DateTypeHandlerPg.class)})
+ * 写入时,将Date时间转换为varchar毫秒并写入
+ *          使用:#{字段,javaType=Date,jdbcType=VARCHAR,typeHandler=com.sqlmybatis.test.pgtype.DateTypeHandlerPg}
+ */
+@MappedTypes({Date.class})
+@MappedJdbcTypes(JdbcType.VARCHAR)
+public class DateTypeHandlerPg extends BaseTypeHandler<Date> {
+    /**
+     * 将时间戳字符串存入数据库
+     */
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
+        if (parameter == null)
+            ps.setString(i, String.valueOf(System.currentTimeMillis()));
+        else
+            ps.setString(i, String.valueOf(parameter.getTime()));
+    }
+
+    /**
+     * 把时间戳类型的字符串取出转换为Date
+     */
+    @Override
+    public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        return new Date(rs.getLong(columnName));
+    }
+
+    /**
+     * 把时间戳类型的字符串取出转换为Date
+     */
+    @Override
+    public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        return new Date(rs.getLong(columnIndex));
+    }
+
+    /**
+     * 把时间戳类型的字符串取出转换为Date
+     */
+    @Override
+    public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        return cs.getDate(columnIndex);
+    }
+}

+ 172 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/GisPointTypeHandlePg.java

@@ -0,0 +1,172 @@
+package com.shkpr.service.aimodelpower.dbdao.pgtype;
+
+import com.shkpr.service.aimodelpower.dto.LatLngBean;
+import com.shkpr.service.aimodelpower.dto.SelfGis;
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.MappedJdbcTypes;
+import org.apache.ibatis.type.MappedTypes;
+import org.postgis.*;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 特别注意:使用PGgeometry要求数据库配置文件sql.properties中两个参数如下填写
+ *         spring.datasource.data.jdbc-url=jdbc:postgresql_postGIS://127.0.0.1.......
+ *         spring.datasource.data.driver-class-name=org.postgis.DriverWrapper
+ *
+ * 读取时,将数据库中的geometry转换为SelfGis并返回
+ *         使用: @Results({@Result(property = "字段", column = "字段", javaType = SelfGis.class ,jdbcType = JdbcType.OTHER, typeHandler = GisPointTypeHandlePg.class)})
+ * 写入时,将SelfGis转换为geometry并写入
+ *         使用:#{字段,javaType=Object,jdbcType=OTHER,typeHandler=com.shkpr.service.aimodelpower.dbdao.pgtype.GisPointTypeHandlePg}
+ *
+ *  1.@MappedJdbcTypes定义的是JdbcType类型,这里的类型不可自己随意定义,
+ *      必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型。
+ *  2.@MappedTypes定义的是JavaType的数据类型,描述了哪些Java类型可被拦截
+ */
+
+@MappedJdbcTypes(JdbcType.OTHER)
+@MappedTypes(SelfGis.class)
+public class GisPointTypeHandlePg extends BaseTypeHandler<SelfGis> {
+    public void setNonNullParameter(PreparedStatement ps, int i, SelfGis parameter, JdbcType jdbcType) throws SQLException {
+        PGgeometry geometry = new PGgeometry();
+        List<Point> arrPoints = new ArrayList<>();
+        if (parameter != null){
+            for (int n=0;n<parameter.getPoints().size();n++){
+                Point geomPoint = new Point();
+                geomPoint.x = parameter.getPoints().get(n).getLng();
+                geomPoint.y = parameter.getPoints().get(n).getLat();
+                geomPoint.dimension = 2;
+                geomPoint.srid = 4326;
+                arrPoints.add(geomPoint);
+            }
+        }
+
+        if (arrPoints.size() > 0){
+            switch (arrPoints.size()){
+                case 1:{
+                    geometry.setGeometry(arrPoints.get(0));
+                }
+                break;
+                case 2:{
+                    geometry.setGeometry(new LineString(arrPoints.toArray(new Point[0])));
+                }
+                break;
+                default:{
+                    if (!parameter.getPoints().get(0).equals(parameter.getPoints().get(parameter.getPoints().size()-1))){//封闭图形收尾相连
+                        Point geomPoint = new Point();
+                        geomPoint.x = parameter.getPoints().get(0).getLng();
+                        geomPoint.y = parameter.getPoints().get(0).getLat();
+                        geomPoint.dimension = 2;
+                        geomPoint.srid = 4326;
+                        arrPoints.add(geomPoint);
+                    }
+                    geometry.setGeometry(new Polygon(new LinearRing[]{new LinearRing(arrPoints.toArray(new Point[0]))}));
+                }
+                break;
+            }
+        }
+        ps.setObject(i, geometry);
+    }
+
+    public SelfGis getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnName);
+        if (pGgeometry == null || pGgeometry.getGeometry() == null) {
+            return null;
+        }
+        switch (pGgeometry.getGeometry().getType()){
+            case 1:{//point
+                final Point point = (Point)pGgeometry.getGeometry();
+                final LatLngBean gis = new LatLngBean(point.getY(), point.getX());
+                return new SelfGis(new ArrayList<LatLngBean>(){{add(gis);}});
+            }
+            case 2:{//line
+                final LineString line = (LineString)pGgeometry.getGeometry();
+                List<LatLngBean> arrGis = new ArrayList<>();
+                for (Point pTmp:line.getPoints())
+                    arrGis.add(new LatLngBean(pTmp.getY(), pTmp.getX()));
+                return new SelfGis(arrGis);
+            }
+            case 3:{//area
+                final Polygon polygon = (Polygon)pGgeometry.getGeometry();
+                final LinearRing linearRing = polygon.getRing(0);
+                List<LatLngBean> arrGis = new ArrayList<>();
+                for (Point pTmp:linearRing.getPoints())
+                    arrGis.add(new LatLngBean(pTmp.getY(), pTmp.getX()));
+                return new SelfGis(arrGis);
+            }
+            default:
+                return null;
+        }
+    }
+
+    public SelfGis getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        PGgeometry pGgeometry = (PGgeometry) rs.getObject(columnIndex);
+        if (pGgeometry == null || pGgeometry.getGeometry() == null) {
+            return null;
+        }
+        switch (pGgeometry.getGeometry().getType()){
+            case 1:{//point
+                final Point point = (Point)pGgeometry.getGeometry();
+                final LatLngBean gis = new LatLngBean(point.getY(), point.getX());
+                return new SelfGis(new ArrayList<LatLngBean>(){{add(gis);}});
+            }
+            case 2:{//line
+                final LineString line = (LineString)pGgeometry.getGeometry();
+                List<LatLngBean> arrGis = new ArrayList<>();
+                for (Point pTmp:line.getPoints())
+                    arrGis.add(new LatLngBean(pTmp.getY(), pTmp.getX()));
+                return new SelfGis(arrGis);
+            }
+            case 3:{//area
+                final Polygon polygon = (Polygon)pGgeometry.getGeometry();
+                final LinearRing linearRing = polygon.getRing(0);
+                List<LatLngBean> arrGis = new ArrayList<>();
+                for (Point pTmp:linearRing.getPoints())
+                    arrGis.add(new LatLngBean(pTmp.getY(), pTmp.getX()));
+                return new SelfGis(arrGis);
+            }
+            default:
+                return null;
+        }
+    }
+
+    public SelfGis getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        PGgeometry pGgeometry = (PGgeometry) cs.getObject(columnIndex);
+        if (pGgeometry == null || pGgeometry.getGeometry() == null) {
+            return null;
+        }
+        switch (pGgeometry.getGeometry().getType()){
+            case 1:{//point
+                final Point point = (Point)pGgeometry.getGeometry();
+                final LatLngBean gis = new LatLngBean(point.getY(), point.getX());
+                return new SelfGis(new ArrayList<LatLngBean>(){{add(gis);}});
+            }
+            case 2:{//line
+                final LineString line = (LineString)pGgeometry.getGeometry();
+                List<LatLngBean> arrGis = new ArrayList<>();
+                for (Point pTmp:line.getPoints())
+                    arrGis.add(new LatLngBean(pTmp.getY(), pTmp.getX()));
+                return new SelfGis(arrGis);
+            }
+            case 3:{//area
+                final Polygon polygon = (Polygon)pGgeometry.getGeometry();
+                final LinearRing linearRing = polygon.getRing(0);
+                List<LatLngBean> arrGis = new ArrayList<>();
+                for (Point pTmp:linearRing.getPoints())
+                    arrGis.add(new LatLngBean(pTmp.getY(), pTmp.getX()));
+                return new SelfGis(arrGis);
+            }
+            default:
+                return null;
+        }
+    }
+}
+
+
+

+ 0 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/pgtype/JSONTypeHandlerPg.java


Некоторые файлы не были показаны из-за большого количества измененных файлов