andyliu 3 hónapja
commit
cfb5706e37
100 módosított fájl, 6890 hozzáadás és 0 törlés
  1. 32 0
      .gitignore
  2. 24 0
      HELP.md
  3. BIN
      libs/gbase.1.0.4.jar
  4. 259 0
      mvnw
  5. 149 0
      mvnw.cmd
  6. 396 0
      pom.xml
  7. 43 0
      sql.properties
  8. 136 0
      src/main/java/com/shkpr/service/alambizplugin/AlamBizPluginApplication.java
  9. 52 0
      src/main/java/com/shkpr/service/alambizplugin/SpringContextUtil.java
  10. 28 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPAccessToken.java
  11. 35 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPDelOne.java
  12. 35 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPGetOne.java
  13. 18 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIds.java
  14. 38 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIdsDel.java
  15. 40 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIdsSK.java
  16. 13 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIntIdsDel.java
  17. 11 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIntIdsSK.java
  18. 53 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPPageLO.java
  19. 12 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPStrIdsDel.java
  20. 12 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPStrIdsSK.java
  21. 42 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPToken.java
  22. 15 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPUserBase.java
  23. 67 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPUserDetail.java
  24. 46 0
      src/main/java/com/shkpr/service/alambizplugin/apiparam/JPUserUnit.java
  25. 79 0
      src/main/java/com/shkpr/service/alambizplugin/bizservice/UserBizService.java
  26. 518 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/CommTool.java
  27. 260 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/ExcelUtils.java
  28. 205 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/HttpTool.java
  29. 511 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/TimeTool.java
  30. 98 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/UZipUtils.java
  31. 45 0
      src/main/java/com/shkpr/service/alambizplugin/commtools/XMLTool.java
  32. 29 0
      src/main/java/com/shkpr/service/alambizplugin/components/FastDFSProxyServlet.java
  33. 145 0
      src/main/java/com/shkpr/service/alambizplugin/components/GisDynamicDataSource.java
  34. 15 0
      src/main/java/com/shkpr/service/alambizplugin/components/TrimStringField.java
  35. 25 0
      src/main/java/com/shkpr/service/alambizplugin/components/locks/AlarmOrderLockMgr.java
  36. 61 0
      src/main/java/com/shkpr/service/alambizplugin/components/locks/BaseLockMgr.java
  37. 133 0
      src/main/java/com/shkpr/service/alambizplugin/components/locks/CountDownLatchEx.java
  38. 30 0
      src/main/java/com/shkpr/service/alambizplugin/components/locks/SurveyBizLockMgr.java
  39. 26 0
      src/main/java/com/shkpr/service/alambizplugin/components/validators/IntInitOrRange.java
  40. 30 0
      src/main/java/com/shkpr/service/alambizplugin/components/validators/IntInitOrRangeV.java
  41. 25 0
      src/main/java/com/shkpr/service/alambizplugin/components/validators/ListNullOrSize.java
  42. 26 0
      src/main/java/com/shkpr/service/alambizplugin/components/validators/ListNullOrSizeV.java
  43. 25 0
      src/main/java/com/shkpr/service/alambizplugin/components/validators/StrNullOrSize.java
  44. 25 0
      src/main/java/com/shkpr/service/alambizplugin/components/validators/StrNullOrSizeV.java
  45. 45 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/CaffeineConfiguration.java
  46. 60 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/DBMgrConfiguration.java
  47. 14 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/FastDfsClientConfiguration.java
  48. 22 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/FilesTransportConfiguration.java
  49. 64 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/GlobalParamConfiguration.java
  50. 106 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/MainSourceConfiguration.java
  51. 188 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/OkHttpClientConfig.java
  52. 44 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/RestTemplateConfig.java
  53. 45 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/RetryTemplateConfig.java
  54. 74 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/ScheduleTaskConfiguration.java
  55. 106 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/SecondSourceConfiguration.java
  56. 45 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/TaskQueueConfiguration.java
  57. 53 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/ValidatorConfiguration.java
  58. 96 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/WebMvcConfiguration.java
  59. 70 0
      src/main/java/com/shkpr/service/alambizplugin/configuration/WebSecurityConfiguration.java
  60. 50 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ApiURI.java
  61. 16 0
      src/main/java/com/shkpr/service/alambizplugin/constants/AttachmentPurpose.java
  62. 8 0
      src/main/java/com/shkpr/service/alambizplugin/constants/AttachmentType.java
  63. 22 0
      src/main/java/com/shkpr/service/alambizplugin/constants/CommAction.java
  64. 15 0
      src/main/java/com/shkpr/service/alambizplugin/constants/CommDefine.java
  65. 7 0
      src/main/java/com/shkpr/service/alambizplugin/constants/CommProgress.java
  66. 10 0
      src/main/java/com/shkpr/service/alambizplugin/constants/CommStatus.java
  67. 37 0
      src/main/java/com/shkpr/service/alambizplugin/constants/DownLoadEventFileType.java
  68. 26 0
      src/main/java/com/shkpr/service/alambizplugin/constants/GisMetadataDefine.java
  69. 86 0
      src/main/java/com/shkpr/service/alambizplugin/constants/LogFlagBusiType.java
  70. 50 0
      src/main/java/com/shkpr/service/alambizplugin/constants/LoginUserRoleType.java
  71. 16 0
      src/main/java/com/shkpr/service/alambizplugin/constants/MsgNotifyDefine.java
  72. 12 0
      src/main/java/com/shkpr/service/alambizplugin/constants/OrderAction.java
  73. 8 0
      src/main/java/com/shkpr/service/alambizplugin/constants/OrderAttRange.java
  74. 16 0
      src/main/java/com/shkpr/service/alambizplugin/constants/OrderExtendType.java
  75. 121 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ResponseCode.java
  76. 15 0
      src/main/java/com/shkpr/service/alambizplugin/constants/StorageGroupType.java
  77. 37 0
      src/main/java/com/shkpr/service/alambizplugin/constants/TaskQueueDataTypeEx.java
  78. 80 0
      src/main/java/com/shkpr/service/alambizplugin/constants/UploadEventFileType.java
  79. 37 0
      src/main/java/com/shkpr/service/alambizplugin/constants/UrlMethodType.java
  80. 17 0
      src/main/java/com/shkpr/service/alambizplugin/constants/UserCurStateType.java
  81. 53 0
      src/main/java/com/shkpr/service/alambizplugin/constants/ViewContentType.java
  82. 57 0
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiBaseController.java
  83. 134 0
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiCommonController.java
  84. 151 0
      src/main/java/com/shkpr/service/alambizplugin/controller/ApiUserController.java
  85. 32 0
      src/main/java/com/shkpr/service/alambizplugin/controllercheck/ApiCommonControllerCheck.java
  86. 27 0
      src/main/java/com/shkpr/service/alambizplugin/controllercheck/ApiUserControllerCheck.java
  87. 181 0
      src/main/java/com/shkpr/service/alambizplugin/controllercheck/JWTControllerCheck.java
  88. 26 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/CustomAuthenticationProvider.java
  89. 90 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/GrantedAuthorityImpl.java
  90. 116 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/JWTAuthenticationFilter.java
  91. 263 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/TokenAuthenticationService.java
  92. 62 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTBizFilterMgr.java
  93. 47 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTCommonBizFilter.java
  94. 46 0
      src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTUserBizFilter.java
  95. 4 0
      src/main/java/com/shkpr/service/alambizplugin/controllervalid/CommonParamValidAccept.java
  96. 4 0
      src/main/java/com/shkpr/service/alambizplugin/controllervalid/CommonParamValidAddNote.java
  97. 4 0
      src/main/java/com/shkpr/service/alambizplugin/controllervalid/CommonParamValidCheck.java
  98. 4 0
      src/main/java/com/shkpr/service/alambizplugin/controllervalid/CommonParamValidDeal.java
  99. 4 0
      src/main/java/com/shkpr/service/alambizplugin/controllervalid/CommonParamValidDel.java
  100. 0 0
      src/main/java/com/shkpr/service/alambizplugin/controllervalid/CommonParamValidList.java

+ 32 - 0
.gitignore

@@ -0,0 +1,32 @@
+target/
+trilog/
+.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
+
+.mvn
+.mvn/
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/

+ 24 - 0
HELP.md

@@ -0,0 +1,24 @@
+# Getting Started
+
+### Reference Documentation
+For further reference, please consider the following sections:
+
+* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
+* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/3.3.9.RELEASE/maven-plugin)
+* [Create an OCI image](https://docs.spring.io/spring-boot/3.3.9.RELEASE/maven-plugin/build-image.html)
+* [Spring Web](https://docs.spring.io/spring-boot/3.3.9.RELEASE/reference/web/servlet.html)
+
+### Guides
+The following guides illustrate how to use some features concretely:
+
+* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
+* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
+* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
+
+### Maven Parent overrides
+
+Due to Maven's design, elements are inherited from the parent POM to the project POM.
+While most of the inheritance is fine, it also inherits unwanted elements like `<license>` and `<developers>` from the parent.
+To prevent this, the project POM contains empty overrides for these elements.
+If you manually switch to a different parent and actually want the inheritance, you need to remove those overrides.
+

BIN
libs/gbase.1.0.4.jar


+ 259 - 0
mvnw

@@ -0,0 +1,259 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.2
+#
+# Optional ENV vars
+# -----------------
+#   JAVA_HOME - location of a JDK home dir, required when download maven via java source
+#   MVNW_REPOURL - repo url base for downloading maven distribution
+#   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+#   MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+  [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+  native_path() { cygpath --path --windows "$1"; }
+  ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+  # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+  if [ -n "${JAVA_HOME-}" ]; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+      JAVACCMD="$JAVA_HOME/jre/sh/javac"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+      JAVACCMD="$JAVA_HOME/bin/javac"
+
+      if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+        echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+        echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+        return 1
+      fi
+    fi
+  else
+    JAVACMD="$(
+      'set' +e
+      'unset' -f command 2>/dev/null
+      'command' -v java
+    )" || :
+    JAVACCMD="$(
+      'set' +e
+      'unset' -f command 2>/dev/null
+      'command' -v javac
+    )" || :
+
+    if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+      echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+      return 1
+    fi
+  fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+  str="${1:-}" h=0
+  while [ -n "$str" ]; do
+    char="${str%"${str#?}"}"
+    h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+    str="${str#?}"
+  done
+  printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+  printf %s\\n "$1" >&2
+  exit 1
+}
+
+trim() {
+  # MWRAPPER-139:
+  #   Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+  #   Needed for removing poorly interpreted newline sequences when running in more
+  #   exotic environments such as mingw bash on Windows.
+  printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+  case "${key-}" in
+  distributionUrl) distributionUrl=$(trim "${value-}") ;;
+  distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+  esac
+done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+  MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+  case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+  *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+  :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+  :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+  :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+  *)
+    echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+    distributionPlatform=linux-amd64
+    ;;
+  esac
+  distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+  ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+  unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+  exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+  verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+  exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+  clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+  trap clean HUP INT TERM EXIT
+else
+  die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+  distributionUrl="${distributionUrl%.zip}.tar.gz"
+  distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+  verbose "Found wget ... using wget"
+  wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+  verbose "Found curl ... using curl"
+  curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+  verbose "Falling back to use Java to download"
+  javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+  targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+  cat >"$javaSource" <<-END
+	public class Downloader extends java.net.Authenticator
+	{
+	  protected java.net.PasswordAuthentication getPasswordAuthentication()
+	  {
+	    return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+	  }
+	  public static void main( String[] args ) throws Exception
+	  {
+	    setDefault( new Downloader() );
+	    java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+	  }
+	}
+	END
+  # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+  verbose " - Compiling Downloader.java ..."
+  "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+  verbose " - Running Downloader.java ..."
+  "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+  distributionSha256Result=false
+  if [ "$MVN_CMD" = mvnd.sh ]; then
+    echo "Checksum validation is not supported for maven-mvnd." >&2
+    echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+    exit 1
+  elif command -v sha256sum >/dev/null; then
+    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
+      distributionSha256Result=true
+    fi
+  elif command -v shasum >/dev/null; then
+    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+      distributionSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+    echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+    exit 1
+  fi
+  if [ $distributionSha256Result = false ]; then
+    echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+    echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+  unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+  tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"

+ 149 - 0
mvnw.cmd

@@ -0,0 +1,149 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.2
+@REM
+@REM Optional ENV vars
+@REM   MVNW_REPOURL - repo url base for downloading maven distribution
+@REM   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM   MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+  IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+  $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+  Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+  "maven-mvnd-*" {
+    $USE_MVND = $true
+    $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+    $MVN_CMD = "mvnd.cmd"
+    break
+  }
+  default {
+    $USE_MVND = $false
+    $MVN_CMD = $script -replace '^mvnw','mvn'
+    break
+  }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
+if ($env:MVNW_REPOURL) {
+  $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+  $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
+if ($env:MAVEN_USER_HOME) {
+  $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
+}
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+  Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+  Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+  exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+  Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+  if ($TMP_DOWNLOAD_DIR.Exists) {
+    try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+    catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+  }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+  $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+  if ($USE_MVND) {
+    Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+  }
+  Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+  if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+    Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+  }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+  Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+  if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+    Write-Error "fail to move MAVEN_HOME"
+  }
+} finally {
+  try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+  catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

+ 396 - 0
pom.xml

@@ -0,0 +1,396 @@
+<?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>v1-alam-biz-plugin</artifactId>
+    <version>1.0.0</version>
+    <name>v1-alam-biz-plugin</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>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.60</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>com.opencsv</groupId>
+            <artifactId>opencsv</artifactId>
+            <version>4.6</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>3.17</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-collections4</artifactId>
+                    <groupId>org.apache.commons</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.tobato</groupId>
+            <artifactId>fastdfs-client</artifactId>
+            <version>1.27.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mitre.dsmiley.httpproxy</groupId>
+            <artifactId>smiley-http-proxy-servlet</artifactId>
+            <version>1.11</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>18.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>7.1.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>it.geosolutions</groupId>
+            <artifactId>geoserver-manager</artifactId>
+            <version>1.7.0</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>commons-io</artifactId>
+                    <groupId>commons-io</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jasypt</groupId>
+            <artifactId>jasypt</artifactId>
+            <version>1.9.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>3.14.9</version>
+        </dependency>
+
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <id>GeoSolutions</id>
+            <url>http://maven.geo-solutions.it/</url>
+            <name>geoserver-manager repository</name>
+        </repository>
+    </repositories>
+
+    <build>
+        <!-- 打成jar包的名称 -->
+        <finalName>v1-alam-biz-plugin-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://140.246.183.164:5432/water_smart_develop_branch?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.postgresql.Driver
+
+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
+
+
+spring.datasource.data2.jdbc-url=jdbc:postgresql://140.246.183.164: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=120000
+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

+ 136 - 0
src/main/java/com/shkpr/service/alambizplugin/AlamBizPluginApplication.java

@@ -0,0 +1,136 @@
+package com.shkpr.service.alambizplugin;
+
+import com.global.base.component.SnowFlakeEx;
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import com.shkpr.service.alambizplugin.globalmgr.ThreadTaskMgr;
+import com.shkpr.service.alambizplugin.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 AlamBizPluginApplication {
+	@Value("${global.server.apr:false}")
+	private boolean mBUseApr = false;
+
+	@Value("${server.port:9010}")
+	private int mNPort;
+
+	@Value("${global.server.id:tri.gispg.v100}")
+	private String mStrServerId;           //本服务的ID
+
+	@Value("${global.machine.index:0}")
+	private int mOwnerMachineIndex;      //本服务所在的部署机器的索引编号
+
+	@Value("${global.bizservice.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记录
+
+	@Value("${des.proxy.fdfs:127.0.0.1}")
+	private String mStrDesProxyFdfs;
+
+	public static void main(String[] args) {
+		GlobalData.getInstance().setCpuCores(Runtime.getRuntime().availableProcessors());
+		LogPrintMgr.getInstance().initResWithDisruptor(/*GlobalData.getInstance().getCpuCores()*/2, 2, new LogPrintSink());
+		SpringApplication.run(AlamBizPluginApplication.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);
+		GlobalData.getInstance().setStrDesProxyFdfs(mStrDesProxyFdfs);
+		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/alambizplugin/SpringContextUtil.java

@@ -0,0 +1,52 @@
+package com.shkpr.service.alambizplugin;
+
+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);
+    }
+}

+ 28 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPAccessToken.java

@@ -0,0 +1,28 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidNew;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class JPAccessToken {
+    @NotBlank(groups = { CommonParamValidNew.class})
+    @Size(min = 1, max = 1024, groups = { CommonParamValidNew.class})
+    private String token = "";
+
+    public JPAccessToken() {
+    }
+
+    public boolean checkValid(){
+        return true;
+    }
+
+    public String toJsonStr() {
+        return FastJsonUtil.toJSON(this);
+    }
+}

+ 35 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPDelOne.java

@@ -0,0 +1,35 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidDel;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class JPDelOne {
+    @NotBlank(groups = { CommonParamValidDel.class})
+    @Size(min = 1, max = 64, groups = { CommonParamValidDel.class})
+    private String selfUser = "";
+
+    @NotBlank(groups = { CommonParamValidDel.class})
+    @Size(min = 1, max = 64, groups = { CommonParamValidDel.class})
+    private String uid = "";
+
+    public JPDelOne() {
+    }
+
+    public boolean checkValid(){
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "selfUser='" + selfUser + '\'' +
+                ", uid='" + uid + '\'' +
+                '}';
+    }
+}

+ 35 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPGetOne.java

@@ -0,0 +1,35 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidSK;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.validator.constraints.Range;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class JPGetOne {
+    @NotBlank(groups = { CommonParamValidSK.class})
+    @Size(min = 1, max = 64, groups = { CommonParamValidSK.class})
+    private String uid = "";
+
+    @Range(min = 0, max = 1, groups = {CommonParamValidSK.class})
+    private int base = 0;
+
+    public JPGetOne() {
+    }
+
+    public boolean checkValid(){
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "uid='" + uid + '\'' +
+                ", base=" + base +
+                '}';
+    }
+}

+ 18 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIds.java

@@ -0,0 +1,18 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import java.util.ArrayList;
+
+public class JPIds<T> {
+    protected ArrayList<T> ids = null;
+
+    public JPIds() {
+    }
+
+    public ArrayList<T> getIds() {
+        return ids;
+    }
+
+    public void setIds(ArrayList<T> ids) {
+        this.ids = ids;
+    }
+}

+ 38 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIdsDel.java

@@ -0,0 +1,38 @@
+package com.shkpr.service.alambizplugin.apiparam;
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidDel;
+import org.hibernate.validator.constraints.Range;
+
+public class JPIdsDel<T> extends JPIds<T> {
+    @Range(min = 0, max = 200, groups = {CommonParamValidDel.class})
+    private int total = -1;        //取值范围[0,200]
+
+    public JPIdsDel() {
+        super();
+    }
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public void clearData(){
+        if (ids != null)
+            ids.clear();
+        ids = null;
+    }
+
+    public boolean checkValid(){
+        if (!(total >= 0 && total <= 200))
+            return false;
+
+        if (total >= 0){
+            if (ids == null || total != ids.size()){
+                return false;
+            }
+        }
+        return true;
+    }
+}

+ 40 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIdsSK.java

@@ -0,0 +1,40 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidDel;
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidSK;
+import org.hibernate.validator.constraints.Range;
+
+public class JPIdsSK<T> extends JPIds<T> {
+    @Range(min = 0, max = 65535, groups = {CommonParamValidSK.class, CommonParamValidDel.class})
+    private int total = -1;        //取值范围[0,65535]
+
+    public JPIdsSK() {
+        super();
+    }
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public void clearData(){
+        if (ids != null)
+            ids.clear();
+        ids = null;
+    }
+
+    public boolean checkValid(){
+        if (!(total >= 0 && total <= 65535))
+            return false;
+
+        if (total >= 0){
+            if (ids == null || total != ids.size()){
+                return false;
+            }
+        }
+        return true;
+    }
+}

+ 13 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIntIdsDel.java

@@ -0,0 +1,13 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.global.base.tools.FastJsonUtil;
+
+public class JPIntIdsDel extends JPIdsDel<Integer> {
+    public JPIntIdsDel() {
+        super();
+    }
+
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+}

+ 11 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPIntIdsSK.java

@@ -0,0 +1,11 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.global.base.tools.FastJsonUtil;
+
+public class JPIntIdsSK extends JPIdsSK<Integer> {
+    public JPIntIdsSK() {
+    }
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+}

+ 53 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPPageLO.java

@@ -0,0 +1,53 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidList;
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidSS;
+import com.shkpr.service.alambizplugin.dto.TRecordRes;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.validator.constraints.Range;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+@Getter
+@Setter
+public class JPPageLO {
+    @Range(min = 0, max = 200, groups = {CommonParamValidList.class, CommonParamValidSS.class})
+    protected int limit = 20;
+
+    @Range(min = 0, max = Integer.MAX_VALUE, groups = {CommonParamValidList.class, CommonParamValidSS.class})
+    protected int offset = 0;
+
+    public JPPageLO() {
+    }
+
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+
+    public boolean checkValid(){
+        return true;
+    }
+
+    public String genJsonStrForResponse(TRecordRes<? extends Object> oRes){
+        String strResult = "";
+        Map<String, Object> mapData = new HashMap<>(16);
+        if (oRes != null && oRes.getCode() == 0){
+            mapData.put("total", oRes.getTotal());
+            mapData.put("limit", oRes.getData()!=null?oRes.getData().size():0);
+            mapData.put("data", oRes.getData()!=null?oRes.getData():(new ArrayList<Object>()));
+        }else{
+            mapData.put("total", 0);
+            mapData.put("limit", 0);
+            mapData.put("data", new ArrayList<Object>());
+        }
+
+        mapData.put("offset", offset);
+        strResult = FastJsonUtil.toJSON(mapData);
+        mapData.clear();
+        return strResult;
+    }
+}

+ 12 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPStrIdsDel.java

@@ -0,0 +1,12 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.global.base.tools.FastJsonUtil;
+
+public class JPStrIdsDel extends JPIdsDel<String> {
+    public JPStrIdsDel() {
+        super();
+    }
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+}

+ 12 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPStrIdsSK.java

@@ -0,0 +1,12 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.global.base.tools.FastJsonUtil;
+
+public class JPStrIdsSK extends JPIdsSK<String> {
+    public JPStrIdsSK() {
+        super();
+    }
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+}

+ 42 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPToken.java

@@ -0,0 +1,42 @@
+package com.shkpr.service.alambizplugin.apiparam;
+import com.global.base.tools.EncryptionUtil;
+import com.shkpr.service.alambizplugin.commtools.TimeTool;
+import com.shkpr.service.alambizplugin.controllerfilter.TokenAuthenticationService;
+import com.shkpr.service.alambizplugin.controllervalid.TokenParamRefresh;
+import lombok.Getter;
+import lombok.Setter;
+import javax.validation.constraints.NotBlank;
+import org.hibernate.validator.constraints.Range;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class JPToken {
+    @Range(min = 1, max = TokenAuthenticationService.MIN_EXPIRATIONTIME, groups = {TokenParamRefresh.class})
+    private int expired = TokenAuthenticationService.MIN_EXPIRATIONTIME; //Token刷新后的有效时长(单位:分钟),默认为7天
+
+    @NotBlank(groups = { TokenParamRefresh.class})
+    @Size(min = 1, max = 64, groups = {TokenParamRefresh.class})
+    private String signature;     //md5("tri_coorperation_tech"+$timestamp)
+
+    private long timestamp = 0L; //请求发起时的时间戳
+
+    public JPToken() {
+    }
+
+    public boolean checkReqTime(){
+        long lTime = 0;
+        try {
+            lTime = System.currentTimeMillis()-timestamp;
+        }catch (Exception e){}
+        if (lTime> TimeTool.MS_ONE_HALF_MIN || lTime<(-TimeTool.MS_ONE_HALF_MIN)){
+            return false;
+        }
+        return true;
+    }
+
+    public boolean checkValid(){
+        String strSig = EncryptionUtil.MD5Hash(TokenAuthenticationService.SIGNATURE_KEY+timestamp);
+        return signature.equalsIgnoreCase(strSig);
+    }
+}

+ 15 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPUserBase.java

@@ -0,0 +1,15 @@
+package com.shkpr.service.alambizplugin.apiparam;
+
+import com.shkpr.service.alambizplugin.constants.UserCurStateType;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class JPUserBase extends JPUserUnit {
+    protected int status = UserCurStateType.STATE_ENABLE.toIntValue();
+    protected long createTime = 0;        //创建时间,UTC时间格式,单位:毫秒
+
+    public JPUserBase() {
+    }
+}

+ 67 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPUserDetail.java

@@ -0,0 +1,67 @@
+package com.shkpr.service.alambizplugin.apiparam;
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.constants.CommDefine;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Setter
+@Getter
+public class JPUserDetail extends JPUserBase {
+    protected String roleid = "";
+    //protected String role = "";
+    protected String roleName = "";
+    protected String userid = "";
+    protected String org = "";
+    protected String orgName = "";
+
+    public JPUserDetail() {
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "roleid='" + roleid + '\'' +
+                ", userid='" + userid + '\'' +
+                ", status=" + status +
+                ", account='" + account + '\'' +
+                ", realName='" + realName + '\'' +
+                '}';
+    }
+
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+
+    public Map<String, Object> toMapObjForLoginBack(){
+        Map<String, Object> map = new HashMap<>();
+        map.put("userid",userid);
+        map.put("roleid",roleid);
+        //map.put("role",role);
+        map.put("account",account);
+        map.put("phone",phone);
+        map.put("realName",realName);
+        map.put("roleName",roleName);
+        map.put("avatar",avatar);
+        map.put("sex",sex);
+        map.put("org",org);
+        map.put("orgName",orgName);
+        return map;
+    }
+
+    public static JPUserDetail genForInternalOperator(String account){
+        JPUserDetail oUserDetail = new JPUserDetail();
+        oUserDetail.setRoleid(CommDefine.INTERNAL_OPERATOR_ROLE_ID);
+        //oUserDetail.setRole(CommDefine.INTERNAL_OPERATOR_ROLE);
+        oUserDetail.setUserid(CommDefine.INTERNAL_OPERATOR_ID);
+        oUserDetail.setAccount(account);
+        oUserDetail.setRealName(account);
+        oUserDetail.setRoleName(CommDefine.INTERNAL_OPERATOR_ROLE);
+        oUserDetail.setAvatar("");
+        oUserDetail.setSex(1);
+        oUserDetail.setOrg("group");
+        return oUserDetail;
+    }
+}

+ 46 - 0
src/main/java/com/shkpr/service/alambizplugin/apiparam/JPUserUnit.java

@@ -0,0 +1,46 @@
+package com.shkpr.service.alambizplugin.apiparam;
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.controllervalid.UserParamValidLogin;
+import com.shkpr.service.alambizplugin.controllervalid.UserParamValidReg;
+import lombok.Getter;
+import lombok.Setter;
+import javax.validation.constraints.NotBlank;
+import org.hibernate.validator.constraints.Range;
+import javax.validation.constraints.Size;
+
+@Setter
+@Getter
+public class JPUserUnit {
+    @NotBlank(groups = { UserParamValidLogin.class, UserParamValidReg.class})
+    @Size(min = 1, max = 32, groups = { UserParamValidLogin.class, UserParamValidReg.class})
+    protected String account = "";
+
+    @NotBlank(groups = { UserParamValidReg.class, UserParamValidLogin.class})
+    @Size(min = 1, max = 256, groups = {UserParamValidReg.class, UserParamValidLogin.class})
+    protected String password = "";
+
+    @Size(min = 0, max = 32, groups = {UserParamValidReg.class})
+    protected String realName = "";
+
+    @Size(min = 0, max = 255, groups = {UserParamValidReg.class})
+    protected String avatar = "";
+
+    @Size(min = 0, max = 128, groups = {UserParamValidReg.class})
+    protected String email = "";
+
+    @Size(min = 0, max = 128, groups = {UserParamValidReg.class})
+    protected String address = "";
+
+    @Range(min = 0, max = 1, groups = {UserParamValidReg.class})
+    protected int sex = 0; //0:女,1:男
+
+    @Size(min = 1, max = 32, groups = {UserParamValidReg.class})
+    protected String phone = "";
+
+    public JPUserUnit() {
+    }
+
+    public String toJsonStr(){
+        return FastJsonUtil.toJSON(this);
+    }
+}

+ 79 - 0
src/main/java/com/shkpr/service/alambizplugin/bizservice/UserBizService.java

@@ -0,0 +1,79 @@
+package com.shkpr.service.alambizplugin.bizservice;
+
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.apiparam.JPGetOne;
+import com.shkpr.service.alambizplugin.apiparam.JPPageLO;
+import com.shkpr.service.alambizplugin.commtools.CommTool;
+import com.shkpr.service.alambizplugin.constants.ResponseCode;
+import com.shkpr.service.alambizplugin.dbdao.DBMgrProxy;
+import com.shkpr.service.alambizplugin.dbdao.services.intef.UserDBService;
+import com.shkpr.service.alambizplugin.dbdao.tables.UserTable;
+import com.shkpr.service.alambizplugin.dto.CommPageRecord;
+import com.shkpr.service.alambizplugin.dto.TObjectRes;
+import com.shkpr.service.alambizplugin.dto.UserInfoBean;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class UserBizService {
+    private final static String mStrClassName = "UserDataHelper";
+    private final static String EMPTY_NULL = "NULL";
+
+    private static UserDBService getThisDBService(){
+        return DBMgrProxy.getInstance().applyXXXApi(UserDBService.class);
+    }
+
+    public static CommPageRecord<? extends Object> pageLines(JPPageLO jsonParam){
+        CommPageRecord<UserInfoBean> oRes = new CommPageRecord<>();
+        if (jsonParam == null){
+            oRes.setCode(ResponseCode.RESULT_BAD.toInt());
+            oRes.checkRes();
+            return oRes;
+        }
+
+        int totalLine = getThisDBService().totalCountsEx(""
+                , new HashMap<String, Object>(){{put(UserTable.R_INFO.STATUS, 1);}}, null, "");
+        if (totalLine > 0){
+            List<Map<String, Object>> arrTmpDbs = getThisDBService().listAllWithsEx("", ""
+                    , jsonParam.getLimit()
+                    , jsonParam.getOffset()
+                    , new HashMap<String, Object>(){{put(UserTable.R_INFO.STATUS, 1);}}
+                    ,null
+                    , UserTable.R_INFO.DEFAULT_ORDER
+                    , "");
+            if (arrTmpDbs != null){
+                oRes.setCode(ResponseCode.RESULT_NORMAL.toInt());
+                oRes.setTotal(totalLine);
+                oRes.setData(FastJsonUtil.batchMap2Obj(arrTmpDbs, UserInfoBean.class, true));
+                if (arrTmpDbs != null)
+                    arrTmpDbs.clear();
+            }else
+                oRes.setCode(ResponseCode.BUSINESS_DB_REQ_FAILED.toInt());
+        }
+        oRes.checkRes();
+        return oRes;
+    }
+
+    public static TObjectRes<? extends Object> queryLineById(JPGetOne jsonParam){
+        TObjectRes<UserInfoBean> oRes = new TObjectRes<>();
+        if (jsonParam == null)
+            return oRes;
+
+        Map<String, Object> mapDbs = getThisDBService().getOne(jsonParam.getUid());
+        if (mapDbs != null){
+            if (CommTool.mapSize(mapDbs) <= 0){
+                oRes.setCode(ResponseCode.RESULT_BAD.toInt());
+            }else {
+                if (jsonParam.getBase()==1){
+                    oRes.setData(FastJsonUtil.map2Obj(mapDbs, UserInfoBean.class, true));
+                }else{
+                    oRes.setData(FastJsonUtil.map2Obj(mapDbs, UserInfoBean.class, true));
+                }
+            }
+            mapDbs.clear();
+        }else
+            oRes.setCode(ResponseCode.BUSINESS_DB_REQ_FAILED.toInt());
+        return oRes;
+    }
+}

+ 518 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/CommTool.java

@@ -0,0 +1,518 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import com.global.base.component.SnowFlakeEx;
+import com.global.base.tools.*;
+import com.shkpr.service.alambizplugin.constants.CommDefine;
+import com.shkpr.service.alambizplugin.dto.LatLngBean;
+import org.springframework.util.StringUtils;
+
+import java.awt.geom.Path2D;
+import java.math.BigDecimal;
+import java.security.MessageDigest;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CommTool {
+    public static final char[] HEX_DIGITS;
+    static {
+        HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+    }
+
+    public static String getPlatformByAgent(String strClientType, String strUserAgent){
+        return getPlatformByAgent(!StringUtils.isEmpty(strClientType)?strClientType:strUserAgent);
+    }
+
+    public static String getPlatformByAgent(String strUserAgent){
+        String type = "pc";
+        if (StringUtils.isEmpty(strUserAgent))
+            return type;
+
+        String lowerAgent = strUserAgent.toLowerCase();
+        if(lowerAgent.contains("android") || lowerAgent.contains("linux")) {
+            type = "apk";
+        } else if (lowerAgent.contains("iphone") || lowerAgent.contains("ios") || lowerAgent.contains("ipad")){
+            type = "ios";
+        } else if (lowerAgent.indexOf("micromessenger") > -1){
+            type = "wx";
+        } else if (lowerAgent.indexOf("cs") > -1){
+            type = "cs";
+        } else if (lowerAgent.indexOf("windows") > -1){
+            type = "pc";
+        } else if (lowerAgent.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 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 String genNotifyEventID(){
+        return (new StringBuilder("PNE")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genGisTotalTempID(){
+        return (new StringBuilder("PGT")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genElementApplyID(){
+        return (new StringBuilder("EPY")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genPublishBatchNo(){
+        return (new StringBuilder("PN")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genDeviceSN(){
+        StringBuilder tmp = new StringBuilder("GSM");
+        tmp.append(TimeTool.convertUTC2DateStr(System.currentTimeMillis(), TimeTool.TIMESTAMP_FORMAT_EX2).substring(2));
+        tmp.append(EncryptionUtil.MD5Hash(UUID.randomUUID().toString()).toUpperCase().substring(10, 21));
+        return tmp.toString();
+    }
+
+    public static String list2QueryIn(List<? 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 int forceConvertToInt(Object oldObj, int defaultV){
+        if (oldObj != null){
+            if (oldObj.getClass().getSimpleName().equals("Double"))
+                return Double.valueOf((double)oldObj).intValue();
+            else if (oldObj.getClass().getSimpleName().equals("Float"))
+                return Float.valueOf((float)oldObj).intValue();
+            else
+                return CastUtil.castInt(oldObj, defaultV);
+        }
+        return defaultV;
+    }
+
+    public static String escapeInHex(final String src) {
+        StringBuilder tmp = new StringBuilder("");
+        if (StringUtils.isEmpty(src))
+            return tmp.toString();
+
+        int i;
+        char j;
+        tmp.ensureCapacity(src.length() * 6);
+        for (i = 0; i < src.length(); i++) {
+            j = src.charAt(i);
+            if (Character.isDigit(j) || Character.isLowerCase(j) || Character.isUpperCase(j))
+                tmp.append(j);
+            else if (j < 256) {
+                tmp.append(j);
+                /*tmp.append("%");
+                if (j < 16)
+                    tmp.append("0");
+                tmp.append(Integer.toString(j, 16));
+                */
+            } else {
+                //tmp.append("%u");
+                //tmp.append(Integer.toString(j, 16));
+                tmp.append("&#x");
+                tmp.append(Integer.toString(j, 16));
+                tmp.append(";");
+            }
+        }
+        return tmp.toString();
+    }
+
+    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 "";
+    }
+
+    private 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 String genUserUid(String account, String extend){
+        return "UUD" + exchangeMD5(EncryptionUtil.MD5Hash(account+extend));
+    }
+
+    public static String likeMap2LikeStr(Map<String, String> mapLikes, Set<String> filterKey){
+        StringBuilder strLikes = new StringBuilder("");
+        if (mapLikes != null && mapLikes.size() > 0){
+            int nStart = 0;
+            for(Map.Entry<String, String> entry:mapLikes.entrySet()){
+                String key = entry.getKey();
+                String data = entry.getValue();
+
+                if (StringUtils.isEmpty(data) || !filterKey.contains(key))  //likes条件暂时只支持有限字段
+                    continue;
+
+                if (nStart++ > 0)
+                    strLikes.append(" or ");
+                strLikes.append(StringUtil.lower2UnLine(key)+" like '%"+data+"%' ");
+            }
+        }
+        return strLikes.toString();
+    }
+
+    /**
+     * 获取不规则多边形重心点
+     * @param mPoints
+     * @return
+     */
+    public static LatLngBean getCenterOfGravityPoint(List<LatLngBean> mPoints) {
+        double area = 0.0;        //多边形面积
+        double Gx = 0.0, Gy = 0.0;// 重心的x、y
+        int pointSize = CommTool.listSize(mPoints);
+        if (pointSize >= 2){
+            for (int i = 1; i <= mPoints.size(); i++) {
+                double iLat = mPoints.get(i % pointSize).lat;
+                double iLng = mPoints.get(i % pointSize).lng;
+                double nextLat = mPoints.get(i - 1).lat;
+                double nextLng = mPoints.get(i - 1).lng;
+                double temp = (iLat * nextLng - iLng * nextLat) / 2.0;
+                area += temp;
+                Gx += temp * (iLat + nextLat) / 3.0;
+                Gy += temp * (iLng + nextLng) / 3.0;
+            }
+            Gx = Gx / area;
+            Gy = Gy / area;
+        }else if (pointSize == 1)
+            return mPoints.get(0);
+        return new LatLngBean(Gx, Gy);
+    }
+
+    /**
+     * 指定gis点是否在指定区域内
+     * @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);
+    }
+
+    /**
+     * 指定的点是否在线所属的bbox区域内
+     * @param lineBegin
+     * @param lineEnd
+     * @param lng
+     * @param lat
+     * @return
+     */
+    public static boolean isGisPointInLineArea(LatLngBean lineBegin, LatLngBean lineEnd, double lng, double lat){
+        List<LatLngBean> areaGis = new ArrayList<>();
+        double mixBoxLng = Double.min(lineBegin.getLng(), lineEnd.getLng());
+        double mixBoxLat = Double.min(lineBegin.getLat(), lineEnd.getLat());
+        double maxBoxLng = Double.max(lineBegin.getLng(), lineEnd.getLng());
+        double maxBoxLat = Double.max(lineBegin.getLat(), lineEnd.getLat());
+
+        if ((new BigDecimal(mixBoxLng).compareTo(new BigDecimal(lineBegin.getLng())) == 0
+                && new BigDecimal(mixBoxLat).compareTo(new BigDecimal(lineBegin.getLat())) == 0)
+                || (new BigDecimal(mixBoxLng).compareTo(new BigDecimal(lineEnd.getLng())) == 0
+                    && new BigDecimal(mixBoxLat).compareTo(new BigDecimal(lineEnd.getLat())) == 0)){
+            areaGis.add(new LatLngBean(mixBoxLat, mixBoxLng));
+            areaGis.add(new LatLngBean(maxBoxLat, mixBoxLng));
+            areaGis.add(new LatLngBean(maxBoxLat, maxBoxLng));
+            areaGis.add(new LatLngBean(mixBoxLat, maxBoxLng));
+        }else {
+            areaGis.add(new LatLngBean(mixBoxLat, mixBoxLng));
+            areaGis.add(new LatLngBean(lineBegin.getLat(), lineBegin.getLng()));
+            areaGis.add(new LatLngBean(maxBoxLat, maxBoxLng));
+            areaGis.add(new LatLngBean(lineEnd.getLat(), lineEnd.getLng()));
+        }
+        return isGisPointInArea(areaGis, lng, lat);
+    }
+
+    //WGS84标准参考椭球中的地球长半径(单位:米)
+    private static final double EARTH_RADIUS = 6378137; //地球半径:米
+    /**
+     * 根据经纬度,计算两点间的距离
+     *
+     * @param lng1 第一个点的经度
+     * @param lat1  第一个点的纬度
+     * @param lng2 第二个点的经度
+     * @param lat2  第二个点的纬度
+     * @return 返回距离 单位:米
+     */
+    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 double getGisDistanceEx(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 s;
+    }
+
+    /**
+     * 指定两个gis点是否在指定的距离内
+     * @param from 起始点
+     * @param to 终止点
+     * @param maxDistance 指定的最大距离(单位:米)
+     * @return
+     */
+    public static boolean isGisPointNearPoint(LatLngBean from, LatLngBean to, long maxDistance){
+        return getGisDistance(from.getLng(), from.getLat(), to.getLng(), to.getLat()) <= maxDistance;
+    }
+
+    /**
+     * gis点到gis线是否在指定的距离内
+     * @param fromPoint 起始gis点
+     * @param toLineGis 终止gis线
+     * @param maxDistance 指定的最大距离(单位:米)
+     * @return
+     */
+    public static boolean isGisPointNearLine(LatLngBean fromPoint, List<LatLngBean> toLineGis, long maxDistance){
+        int nPointSize = CommTool.listSize(toLineGis);
+        if (nPointSize <= 0)
+            return false;
+        if (nPointSize <= 1)
+            return isGisPointNearPoint(fromPoint, toLineGis.get(0), maxDistance);
+        else {//直线或折线,注:是折线时需将其拆分成多条直线
+            for (int i=0;i<=toLineGis.size()-2;i++){
+                LatLngBean pointA = fromPoint;
+                LatLngBean pointB = toLineGis.get(i);
+                LatLngBean pointC = toLineGis.get(i+1);
+
+                long b = getGisDistance(pointA.getLng(), pointA.getLat(), pointC.getLng(), pointC.getLat());
+                if (b <= 0 || b <= maxDistance)
+                    return true;
+
+                long c = getGisDistance(pointA.getLng(), pointA.getLat(), pointB.getLng(), pointB.getLat());
+                if (c <= 0 || c <= maxDistance)
+                    return true;
+
+                long a = getGisDistance(pointB.getLng(), pointB.getLat(), pointC.getLng(), pointC.getLat());
+                if (a <= 0)
+                    continue;
+
+                long cosABC = (a*a + c*c - b*b)/(2*a*c);
+                if (cosABC <= 0){//直角或钝角
+                    if (c <= maxDistance)
+                        return true;
+                    continue;
+                }
+
+                long cosACB = (a*a + b*b - c*c)/(2*a*b);
+                if (cosACB <= 0){//直角或钝角
+                    if (b <= maxDistance)
+                        return true;
+                    continue;
+                }
+
+                long pp = (a+b+c)/2;
+                long ss = Math.round(10000*Math.sqrt(pp*(pp-a)*(pp-b)*(pp-c)))/10000;
+                long shortA2BC = 2*ss/a;
+                if (shortA2BC <= maxDistance)
+                    return true;
+            }
+            return false;
+        }/*else if (nPointSize == 2){
+            if (isGisPointNearPoint(fromPoint, toLineGis.get(0), maxDistance))//指定点到直线一端的距离
+                return true;
+            if (isGisPointNearPoint(fromPoint, toLineGis.get(1), maxDistance))//指定点到直线另一端的距离
+                return true;
+            return getGisDistance(fromPoint.getLng()//指定点到直线中心点的距离
+                    , fromPoint.getLat()
+                    , (toLineGis.get(0).getLng()+toLineGis.get(1).getLng())/2
+                    , (toLineGis.get(0).getLat()+toLineGis.get(1).getLat())/2) <= maxDistance;
+        }else {//折线
+            if (isGisPointInArea(toLineGis, fromPoint.getLng(), fromPoint.getLat()))//是否在折线的封闭区域内
+                return true;
+            return isGisPointNearPoint(fromPoint, getCenterOfGravityPoint(toLineGis), maxDistance);//指定点到折线封闭区域的重心距离
+        }*/
+    }
+
+    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();
+    }
+
+    public static List safeList(List<? extends Object> listSrc){
+        if (listSrc == null)
+            return new ArrayList();
+        else
+            return listSrc;
+    }
+
+    public static boolean isRootAdminID(String userId){
+        return CommDefine.ADMIN_USER_ID.equals(userId)
+                || CommDefine.INTERNAL_OPERATOR_ID.equals(userId);
+    }
+
+    //84坐标系转2000坐标系
+    public static double[] convert84To2000(double latitude, double longitude) {
+        double x = 0.0, y = 0.0, z = 0.0;
+        double a = EARTH_RADIUS;
+        double f = 1.0 / 298.257223563;
+        double b = (1 - f) * a;
+        double e = Math.sqrt((a * a - b * b) / (a * a));
+        double E = Math.atan2(z, Math.sqrt(x * x + y * y));
+        double r = Math.sqrt(x * x + y * y + z * z);
+        double latitude1 = Math.atan2(z + e * e * b * Math.pow(Math.sin(E), 3), r - a * Math.pow(e, 2) * Math.pow(Math.cos(E), 3));
+        double longitude1 = Math.atan2(y, x);
+        double N = a / Math.sqrt(1 - Math.pow(e * Math.sin(latitude1), 2));
+        double h = r / Math.cos(latitude1) - N;
+        double X = (N + h) * Math.cos(latitude1) * Math.cos(longitude1);
+        double Y = (N + h) * Math.cos(latitude1) * Math.sin(longitude1);
+        double Z = (N * (1 - Math.pow(e, 2)) + h) * Math.sin(latitude1);
+        double k = 1.0000648438897;
+        double dx = -24.9;
+        double dy = 140.8;
+        double dz = 76.3;
+        double X1 = k * (X + dx);
+        double Y1 = k * (Y + dy);
+        double Z1 = k * (Z + dz);
+        return new double[]{X1, Y1, Z1};
+    }
+
+    //已知点A、B、C,求夹角<ABC
+    public static double angleBFromGis(LatLngBean pointA, LatLngBean pointB, LatLngBean pointC){
+        double side_c = getGisDistanceEx(pointA.getLng(), pointA.getLat(), pointB.getLng(), pointB.getLat());
+        double side_a = getGisDistanceEx(pointB.getLng(), pointB.getLat(), pointC.getLng(), pointC.getLat());
+        double side_b = getGisDistanceEx(pointA.getLng(), pointA.getLat(), pointC.getLng(), pointC.getLat());
+        return angleBFromSide(side_a, side_b, side_c);
+    }
+
+    public static double angleBFromSide(double a, double b, double c){
+        if (c + a < b)
+            return -1.0;
+        if (c + a == b)
+            return 180.0;
+        return Math.toDegrees(Math.acos((a*a + c*c - b*b) / (2*a*c)));
+    }
+
+    public static String genSurveyProjID(){
+        return (new StringBuilder("GSP")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+
+    public static String genSurveyJobID(){
+        return (new StringBuilder("GJB")).append(SnowFlakeEx.getInstance().nextHexStrId(4)).toString();
+    }
+}

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

@@ -0,0 +1,260 @@
+package com.shkpr.service.alambizplugin.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();
+        }
+    }
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 205 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/HttpTool.java


+ 511 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/TimeTool.java

@@ -0,0 +1,511 @@
+package com.shkpr.service.alambizplugin.commtools;
+import org.springframework.util.StringUtils;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+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_FORMAT_SLASH = "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 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 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);
+            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 >= 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 "";
+    }
+
+    /**
+     * 修改指定时间的月份
+     * @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);
+    }
+
+    public static boolean checkValidDate(String dateStr) {
+        try {
+            DateTimeFormatter formatter = DateTimeFormatter
+                    .ofPattern("uuuu-MM-dd")//使用 "uuuu" 避免年份解析歧义
+                    .withResolverStyle(ResolverStyle.STRICT);
+            LocalDate.parse(dateStr, formatter);
+            return true;
+        } catch (DateTimeParseException e) {
+            return false;
+        }
+    }
+}

+ 98 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/UZipUtils.java

@@ -0,0 +1,98 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class UZipUtils {
+    /**
+     * 压缩文件列表中包含中文名时,必须使用GBK编码格式
+     * @param zipFile
+     * @return
+     * @throws Exception
+     */
+    private static ZipFile getZipFile(File zipFile) throws Exception {
+        ZipFile zip = new ZipFile(zipFile, Charset.forName("UTF-8"));
+        Enumeration<?> entries = zip.entries();
+        while (entries.hasMoreElements()) {
+            try {
+                ZipEntry entry = (ZipEntry)entries.nextElement();
+            } catch (Exception e) {
+                try {
+                    zip.close();
+                }catch (Exception ee){}
+                return new ZipFile(zipFile, Charset.forName("GBK"));
+            }
+        }
+        try {
+            zip.close();
+        }catch (Exception ee){}
+        return new ZipFile(zipFile, Charset.forName("UTF-8"));
+    }
+
+    public static List<String> unZip(String zipFilePath, String desDirPath) throws RuntimeException{
+        return unZip(new File(zipFilePath), desDirPath);
+    }
+
+    public static List<String> unZip(File zipFile, String desDirPath) throws RuntimeException{
+        List<String> desFilePaths = null;
+        if (zipFile == null || !zipFile.exists())
+            throw new RuntimeException(zipFile.getPath() + "->the source file not exist");
+
+        File desDirFile = new File(desDirPath);
+        if (!desDirFile.exists())
+            desDirFile.mkdirs();
+
+        ZipFile zip = null;
+        try {
+            zip = getZipFile(zipFile);
+            Enumeration<?> entries = zip.entries();
+            desFilePaths = new ArrayList<>();
+            while (entries.hasMoreElements()) {
+                ZipEntry entry = (ZipEntry)entries.nextElement();
+                String desFilePath = (desDirPath.endsWith("/"))?
+                        (desDirPath + entry.getName()):(desDirPath + "/" + entry.getName());
+                desFilePath = desFilePath.replaceAll("\\*", "/");
+
+                if (entry.isDirectory()) {
+                    File dir = new File(desFilePath);
+                    dir.mkdirs();
+                } else {
+                    desFilePaths.add(desFilePath);
+                    File targetFile = new File(desFilePath);
+                    if (!targetFile.getParentFile().exists())
+                        targetFile.getParentFile().mkdirs();
+                    targetFile.createNewFile();
+
+                    InputStream is = zip.getInputStream(entry);
+                    FileOutputStream fos = new FileOutputStream(targetFile);
+                    int len = -1;
+                    byte []buf = new byte[1024];
+                    while ((len = is.read(buf)) != -1) {
+                        fos.write(buf, 0, len);
+                    }
+                    fos.close();
+                    is.close();
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("unzip error from UZipUtils", e);
+        } finally {
+            if (zip != null) {
+                try {
+                    zip.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return desFilePaths==null?new ArrayList<>():desFilePaths;
+    }
+}

+ 45 - 0
src/main/java/com/shkpr/service/alambizplugin/commtools/XMLTool.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.alambizplugin.commtools;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+public class XMLTool {
+    public static String objToXml(Object obj){
+        return objToXml(obj, "UTF-8");
+    }
+
+    public static String objToXml(Object obj, String encoding) {
+        StringWriter sw = new StringWriter();
+        sw.append("<?xml version=\"1.0\" encoding=\""+encoding+"\"?>\n");
+        try {
+            JAXBContext context = JAXBContext.newInstance(obj.getClass());
+            Marshaller marshaller = context.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);//去掉生成xml的默认报文头
+            //marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
+            marshaller.marshal(obj, sw);
+        } catch (JAXBException e) {
+            e.printStackTrace();
+        }
+        return sw.toString();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Object xmlToObj(Class objClazz, String xmlStr) {
+        Object xmlObject = null;
+        try {
+            JAXBContext context = JAXBContext.newInstance(objClazz);
+            Unmarshaller unmarshaller = context.createUnmarshaller();
+            StringReader sr = new StringReader(xmlStr);
+            xmlObject = unmarshaller.unmarshal(sr);
+        } catch (JAXBException e) {
+            e.printStackTrace();
+        }
+        return xmlObject;
+    }
+
+}

+ 29 - 0
src/main/java/com/shkpr/service/alambizplugin/components/FastDFSProxyServlet.java

@@ -0,0 +1,29 @@
+package com.shkpr.service.alambizplugin.components;
+
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import org.apache.http.client.utils.URIUtils;
+import org.mitre.dsmiley.httpproxy.ProxyServlet;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class FastDFSProxyServlet extends ProxyServlet {
+    @Override
+    protected void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException {
+        String desServer = GlobalData.getInstance().getStrDesProxyFdfs();
+        servletRequest.setAttribute(ATTR_TARGET_URI, null);
+        super.targetUri = desServer;
+        URI uri = null;
+        try {
+            uri = new URI(desServer);
+        } catch (URISyntaxException e) {
+        }
+        servletRequest.setAttribute(ATTR_TARGET_HOST, null);
+        super.targetHost = URIUtils.extractHost(uri);
+        super.service(servletRequest, servletResponse);
+    }
+}

+ 145 - 0
src/main/java/com/shkpr/service/alambizplugin/components/GisDynamicDataSource.java

@@ -0,0 +1,145 @@
+package com.shkpr.service.alambizplugin.components;
+
+import com.global.base.tools.CastUtil;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+import org.springframework.util.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 注:多数据源动态切换模式,不支持多数据源的事务操作,即:只支持指定单个数据源后的事务操作
+ */
+public class GisDynamicDataSource extends AbstractRoutingDataSource {
+    private static final ThreadLocal<String> DATA_SOURCE_KEY = new ThreadLocal<>();
+    private static final ConcurrentHashMap<Object, Object> TARGET_DATA_SOURCE = new ConcurrentHashMap<>();
+    private final Map<String, String> DEFAULT_CONN_CONFIG = new HashMap<>();
+    private static final byte[] LATCH_COMM = new byte[0];
+
+    @Override
+    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
+        TARGET_DATA_SOURCE.putAll(targetDataSources);
+        super.setTargetDataSources(TARGET_DATA_SOURCE);
+    }
+
+    @Override
+    public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
+        super.setDefaultTargetDataSource(defaultTargetDataSource);
+    }
+
+    @Override
+    protected Object determineCurrentLookupKey() {
+        String origin = getDataSource();
+        if (StringUtils.isEmpty(origin))
+            return origin;
+
+        String mixArr[] = origin.split("\\|");
+        if (mixArr == null || mixArr.length < 1)
+            return origin;
+        String database = mixArr[0];
+        String address = mixArr.length>=2?mixArr[1]:"";
+        String user = mixArr.length>=3?mixArr[2]:"";
+        String password = mixArr.length>=4?mixArr[3]:"";
+        String key = String.format("%s_%s",address,database);
+        if (StringUtils.isEmpty(address) || address.startsWith("localhost")){
+            if (DEFAULT_CONN_CONFIG.size() > 0)
+                address = DEFAULT_CONN_CONFIG.getOrDefault("address", "127.0.0.1:5432");
+        }
+        if (StringUtils.isEmpty(user)){
+            if (DEFAULT_CONN_CONFIG.size() > 0)
+                user = DEFAULT_CONN_CONFIG.getOrDefault("username", "postgres");
+            else
+                user = "postgres";
+        }
+        if (StringUtils.isEmpty(password)){
+            if (DEFAULT_CONN_CONFIG.size() > 0)
+                password = DEFAULT_CONN_CONFIG.getOrDefault("password", "kpr.23417.postgres");
+            else
+                password = "kpr.23417.postgres";
+        }
+
+        if (!TARGET_DATA_SOURCE.containsKey(key)){
+            synchronized (LATCH_COMM){
+                if (!TARGET_DATA_SOURCE.containsKey(key)){
+                    HikariDataSource oData = appendNewDataSource(database, address, user, password);
+                    if (oData != null){
+                        TARGET_DATA_SOURCE.put(key, oData);
+                        setTargetDataSources(TARGET_DATA_SOURCE);
+                        super.afterPropertiesSet();
+                    }
+                }
+            }
+        }else{
+            synchronized (LATCH_COMM){
+                HikariDataSource oData = (HikariDataSource)TARGET_DATA_SOURCE.get(key);
+                if (oData == null
+                        || !oData.getJdbcUrl().contains(address)
+                        || !user.equals(oData.getUsername())
+                        || !password.equals(oData.getPassword())){
+                    HikariDataSource oNewData = appendNewDataSource(database, address, user, password);
+                    if (oNewData != null){
+                        TARGET_DATA_SOURCE.put(key, oNewData);
+                        setTargetDataSources(TARGET_DATA_SOURCE);
+                        super.afterPropertiesSet();
+
+                        if (oData != null)
+                            oData.close();
+                    }
+                }
+            }
+        }
+        return key;
+    }
+
+    public void initConnConfig(Map<String, String> config){
+        DEFAULT_CONN_CONFIG.clear();
+        DEFAULT_CONN_CONFIG.putAll(config);
+    }
+
+    private HikariDataSource appendNewDataSource(String dataKey, String dataAddress, String user, String password){
+        if (DEFAULT_CONN_CONFIG.size() <= 0 || StringUtils.isEmpty(dataKey))
+            return null;
+
+        HikariConfig hikariConfig = new HikariConfig();
+
+        hikariConfig.setDriverClassName(DEFAULT_CONN_CONFIG.getOrDefault("driverClassName", "org.postgresql.Driver"));
+        if (StringUtils.isEmpty(dataAddress) || dataAddress.startsWith("localhost"))
+            hikariConfig.setJdbcUrl(String.format(DEFAULT_CONN_CONFIG.get("jdbcUrl"), DEFAULT_CONN_CONFIG.getOrDefault("address", "127.0.0.1:5432"), dataKey));
+        else
+            hikariConfig.setJdbcUrl(String.format(DEFAULT_CONN_CONFIG.get("jdbcUrl"), dataAddress, dataKey));
+
+        hikariConfig.setUsername(StringUtils.isEmpty(user)?DEFAULT_CONN_CONFIG.getOrDefault("username", "postgres"):user);
+        hikariConfig.setPassword(StringUtils.isEmpty(password)?DEFAULT_CONN_CONFIG.getOrDefault("password", "kpr.23417.postgres"):password);
+
+        hikariConfig.setMaximumPoolSize(CastUtil.castInt(DEFAULT_CONN_CONFIG.get("maximumPoolSize"), 200));
+        hikariConfig.setMinimumIdle(CastUtil.castInt(DEFAULT_CONN_CONFIG.get("minimumIdle"), 1));
+        hikariConfig.setConnectionTestQuery(DEFAULT_CONN_CONFIG.get("connectionTestQuery"));
+        hikariConfig.setMaxLifetime(CastUtil.castLong(DEFAULT_CONN_CONFIG.get("maxLifetime"), 120000));
+        hikariConfig.setIdleTimeout(CastUtil.castLong(DEFAULT_CONN_CONFIG.get("idleTimeout"), 30000));
+        hikariConfig.setConnectionTimeout(CastUtil.castLong(DEFAULT_CONN_CONFIG.get("connectionTimeout"), 30000));
+        hikariConfig.setValidationTimeout(CastUtil.castLong(DEFAULT_CONN_CONFIG.get("validationTimeout"), 30000));
+        hikariConfig.setInitializationFailTimeout(CastUtil.castLong(DEFAULT_CONN_CONFIG.get("initFailedTimeout"), -1));
+        HikariDataSource obj = new HikariDataSource(hikariConfig);
+        try {
+            obj.setLoginTimeout((int)hikariConfig.getConnectionTimeout()/1000);
+        }catch (Exception e){}
+        return obj;
+    }
+
+    public static void changeDataSource(String dataSourceKey, String dataAddress, String user, String password) {
+        DATA_SOURCE_KEY.set(String.format("%s|%s|%s|%s", dataSourceKey, dataAddress, user, password));
+    }
+
+    public static String getDataSource() { return DATA_SOURCE_KEY.get(); }
+
+    public static void clearDataSource() {
+        DATA_SOURCE_KEY.remove();
+    }
+
+    public static Map<Object, Object> listTargetDataSource(){
+        return TARGET_DATA_SOURCE;
+    }
+}

+ 15 - 0
src/main/java/com/shkpr/service/alambizplugin/components/TrimStringField.java

@@ -0,0 +1,15 @@
+package com.shkpr.service.alambizplugin.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;
+    }
+}

+ 25 - 0
src/main/java/com/shkpr/service/alambizplugin/components/locks/AlarmOrderLockMgr.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.alambizplugin.components.locks;
+
+public class AlarmOrderLockMgr extends BaseLockMgr{
+    private static volatile AlarmOrderLockMgr msInstance = null;
+    private static AlarmOrderLockMgr getInstance(){
+        if (msInstance == null){
+            synchronized (AlarmOrderLockMgr.class){
+                if (msInstance == null)
+                    msInstance = new AlarmOrderLockMgr();
+            }
+        }
+        return msInstance;
+    }
+
+    private AlarmOrderLockMgr() {
+    }
+
+    public static void releaseResource(){
+        getInstance().timerReleaseLatch();
+    }
+
+    public static CountDownLatchEx tryLatchForUser(String userId, long waitMsTm) throws Exception{
+        return getInstance().tryLatchForXXX("AM_U_"+userId, waitMsTm);
+    }
+}

+ 61 - 0
src/main/java/com/shkpr/service/alambizplugin/components/locks/BaseLockMgr.java

@@ -0,0 +1,61 @@
+package com.shkpr.service.alambizplugin.components.locks;
+
+import com.shkpr.service.alambizplugin.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;
+    }
+
+    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);
+                }
+            }
+        }
+    }
+}

+ 133 - 0
src/main/java/com/shkpr/service/alambizplugin/components/locks/CountDownLatchEx.java

@@ -0,0 +1,133 @@
+package com.shkpr.service.alambizplugin.components.locks;
+
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+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;
+        }
+    }
+}

+ 30 - 0
src/main/java/com/shkpr/service/alambizplugin/components/locks/SurveyBizLockMgr.java

@@ -0,0 +1,30 @@
+package com.shkpr.service.alambizplugin.components.locks;
+
+public class SurveyBizLockMgr extends BaseLockMgr{
+    private static volatile SurveyBizLockMgr msInstance = null;
+    private static SurveyBizLockMgr getInstance(){
+        if (msInstance == null){
+            synchronized (SurveyBizLockMgr.class){
+                if (msInstance == null)
+                    msInstance = new SurveyBizLockMgr();
+            }
+        }
+        return msInstance;
+    }
+
+    private SurveyBizLockMgr() {
+    }
+
+    public static void releaseResource(){
+        getInstance().timerReleaseLatch();
+    }
+
+    public static CountDownLatchEx tryLatchForJob(String uid, long waitMsTm) throws Exception{
+        return getInstance().tryLatchForXXX("SB_J_"+uid, waitMsTm);
+    }
+
+    public static CountDownLatchEx tryLatchForProject(String uid, long waitMsTm) throws Exception{
+        return getInstance().tryLatchForXXX("SB_P_"+uid, waitMsTm);
+    }
+}
+

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

@@ -0,0 +1,26 @@
+package com.shkpr.service.alambizplugin.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/alambizplugin/components/validators/IntInitOrRangeV.java

@@ -0,0 +1,30 @@
+package com.shkpr.service.alambizplugin.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/alambizplugin/components/validators/ListNullOrSize.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.alambizplugin.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/alambizplugin/components/validators/ListNullOrSizeV.java

@@ -0,0 +1,26 @@
+package com.shkpr.service.alambizplugin.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/alambizplugin/components/validators/StrNullOrSize.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.alambizplugin.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/alambizplugin/components/validators/StrNullOrSizeV.java

@@ -0,0 +1,25 @@
+package com.shkpr.service.alambizplugin.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;
+    }
+}

+ 45 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/CaffeineConfiguration.java

@@ -0,0 +1,45 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.RemovalCause;
+import com.github.benmanes.caffeine.cache.RemovalListener;
+import com.shkpr.service.alambizplugin.globalcache.interf.PushCacheBase;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.caffeine.CaffeineCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableAutoConfiguration
+public class CaffeineConfiguration {
+    @Value("${local.cache.max.size.push.task:1000}")
+    private int pushTaskMaxCacheSize;   //Cache可存储的最大pushTask数量;
+
+    @Value("${local.cache.expired.push.task:1440}")
+    private int pushTaskCacheExpiredTm;//Cache存储pushTask的有效时长(单位:分钟)
+
+    @Bean(name = PushCacheBase.PUSH_CACHE_MGR_NAME)
+    public CacheManager cachePushTaskManager(){
+        CaffeineCacheManager cacheManager = new CaffeineCacheManager(PushCacheBase.PUSH_CACHE_NAME, PushCacheBase.PUSH_CACHE_NAME_EX);
+        cacheManager.setAllowNullValues(false);
+        cacheManager.setCaffeine(Caffeine.newBuilder()
+                .initialCapacity(pushTaskMaxCacheSize/10)
+                .maximumSize(pushTaskMaxCacheSize)
+                .expireAfterWrite(pushTaskCacheExpiredTm, TimeUnit.MINUTES)
+                .removalListener(new CustomRemovalListener())
+                .recordStats());
+        return cacheManager;
+    }
+
+    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/alambizplugin/configuration/DBMgrConfiguration.java

@@ -0,0 +1,60 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.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();
+    }
+}
+

+ 14 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/FastDfsClientConfiguration.java

@@ -0,0 +1,14 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.github.tobato.fastdfs.FdfsClientConfig;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableMBeanExport;
+import org.springframework.context.annotation.Import;
+import org.springframework.jmx.support.RegistrationPolicy;
+
+@Configuration
+@Import(FdfsClientConfig.class)
+// 解决jmx重复注册bean的问题
+@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
+public class FastDfsClientConfiguration {
+}

+ 22 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/FilesTransportConfiguration.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.web.servlet.MultipartConfigFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.unit.DataSize;
+import org.springframework.util.unit.DataUnit;
+
+import javax.servlet.MultipartConfigElement;
+
+@Configuration
+@EnableAutoConfiguration
+public class FilesTransportConfiguration {
+    @Bean
+    public MultipartConfigElement multipartConfigElement() {
+        MultipartConfigFactory factory = new MultipartConfigFactory();
+        factory.setMaxFileSize(DataSize.of(50, DataUnit.MEGABYTES));
+        factory.setMaxRequestSize(DataSize.of(50, DataUnit.MEGABYTES));
+        return factory.createMultipartConfig();
+    }
+}

+ 64 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/GlobalParamConfiguration.java

@@ -0,0 +1,64 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.global.base.tools.EncryptionUtil;
+import com.global.base.tools.RandomUtil;
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import com.shkpr.service.alambizplugin.globalmgr.ThreadTaskMgr;
+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}")
+    private int mNCpuCoresForEnableAsyncSubTask = 8;
+
+    @Value("${global.internal.operator.account:TriCooperation}")
+    private String mStrInternalOperatorAccount = "";
+
+    @Value("${global.internal.operator.password:123@asd}")
+    private String mStrInternalOperatorPassword = "";
+
+    @Value("${global.bizservice.online.time:0}")
+    private long mTmUTCServiceOnline = 0L;
+
+    @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);
+
+        ThreadTaskMgr.runTask(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(5000);
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+           }
+        });
+    }
+}

+ 106 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/MainSourceConfiguration.java

@@ -0,0 +1,106 @@
+package com.shkpr.service.alambizplugin.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.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.shkpr.service.alambizplugin.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() {
+        return new HikariDataSource(getConfig());
+        //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);
+    }
+}

+ 188 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/OkHttpClientConfig.java

@@ -0,0 +1,188 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import com.shkpr.service.alambizplugin.rpc.RPCMgrProxy;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.springframework.beans.factory.annotation.Qualifier;
+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 org.springframework.context.annotation.Primary;
+import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * OkHttp3特别注意:1) 所有的header不能设置null
+ *                  2) 需要显示的设置user-agent请求头
+ *                  3) 需要关闭人工的Accept-Encoding:gzip压缩解压机制,OkHttp3会默认启用自身的压缩解压机制
+ */
+@Configuration
+@EnableAutoConfiguration
+public class OkHttpClientConfig {
+    @Value("${global.www.proxy.address:}")
+    private String strWWWProxyAddress = "";
+
+    @Primary
+    @Bean(name = "RestTemplateEx")
+    public RestTemplate restTemplate(@Qualifier("OkHttpClient") OkHttpClient okHttpClient) {
+        OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
+        RestTemplate restTemplate = new RestTemplate(factory);
+        // 可以添加消息转换
+        //restTemplate.setMessageConverters(...);
+        // 可以增加拦截器
+        //restTemplate.setInterceptors(...);
+        return restTemplate;
+    }
+
+    @Primary
+    @Bean(name = "RestTemplateUTF8")//解决body无法进行UTF-8编码时的中文乱码问题,如:APPLICATION_XML默认无法指定UTF-8编码;而APPLICATION_JSON_UTF8默认就对body进行了UTF-8编码
+    public RestTemplate restTemplateUTF8(@Qualifier("OkHttpClient") OkHttpClient okHttpClient) {
+        OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
+        RestTemplate restTemplate = new RestTemplate(factory);
+        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
+        if (messageConverters != null){
+            for (int i = 0; i < messageConverters.size(); i++) {
+                HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
+                if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
+                    messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+                }
+            }
+        }
+        return restTemplate;
+    }
+
+    @Bean(name = "RestTemplateProxy")
+    public RestTemplate restTemplateProxy(@Qualifier("OkHttpClientProxy") OkHttpClient okHttpClient) {
+        OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
+        RestTemplate restTemplate = new RestTemplate(factory);
+        // 可以添加消息转换
+        //restTemplate.setMessageConverters(...);
+        // 可以增加拦截器
+        //restTemplate.setInterceptors(...);
+        return restTemplate;
+    }
+
+    @Bean(name = "OkHttpClient")
+    public OkHttpClient okHttpClient(@Qualifier("SSLSocketFactory") SSLSocketFactory sslSocketFactory, @Qualifier("X509TrustManager") X509TrustManager x509TrustManager){
+        return new OkHttpClient.Builder()
+                .sslSocketFactory(sslSocketFactory, x509TrustManager)
+                .hostnameVerifier(new SkipHostnameVerifier())
+                .retryOnConnectionFailure(true)//当使用连接池时该参数设置true才有意义
+                .connectionPool(new okhttp3.ConnectionPool(200, 5, TimeUnit.MINUTES))
+                .connectTimeout(30, TimeUnit.SECONDS)
+                .readTimeout(30, TimeUnit.SECONDS)
+                .writeTimeout(30,TimeUnit.SECONDS)
+                .addNetworkInterceptor(new Interceptor() {//添加网络拦截器
+                    @Override
+                    public Response intercept(Chain chain) throws IOException {
+                        Request oldRequest = chain.request();
+                        //在这里可以添加或修改请求的header,比如添加User-Agent
+                        //Request newRequest = oldRequest.newBuilder()
+                        //        .header("User-Agent", "Linux")
+                        //        .build();
+                        //Response oldResponse =  chain.proceed(newRequest);
+                        //重写Response
+                        //return oldResponse.newBuilder()
+                        //        .header("Cache-Control", "max-age=60")
+                        //        .build();
+                        return chain.proceed(oldRequest);
+                    }
+                })
+                //.addInterceptor(new Interceptor() {//添加应用拦截器
+                //    @Override
+                //    public Response intercept(Chain chain) throws IOException {
+                //        return null;
+                //    }
+                //})
+                .build();
+    }
+
+    @Bean(name = "OkHttpClientProxy")
+    public OkHttpClient okHttpClientProxy(@Qualifier("SSLSocketFactory") SSLSocketFactory sslSocketFactory, @Qualifier("X509TrustManager") X509TrustManager x509TrustManager){
+        if (!StringUtils.isEmpty(strWWWProxyAddress)){
+            String ipAndPort[] = strWWWProxyAddress.split(":");
+            if (ipAndPort != null && ipAndPort.length >= 2){
+                return new OkHttpClient.Builder()
+                        .sslSocketFactory(sslSocketFactory, x509TrustManager)
+                        .hostnameVerifier(new SkipHostnameVerifier())
+                        .retryOnConnectionFailure(true)//当使用连接池时该参数设置true才有意义
+                        .connectionPool(new okhttp3.ConnectionPool(200, 5, TimeUnit.MINUTES))
+                        .connectTimeout(30, TimeUnit.SECONDS)
+                        .readTimeout(30, TimeUnit.SECONDS)
+                        .writeTimeout(30,TimeUnit.SECONDS)
+                        .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipAndPort[0], Integer.valueOf(ipAndPort[1]))))
+                        .build();
+            }
+        }
+        return new OkHttpClient.Builder()
+                .sslSocketFactory(sslSocketFactory, x509TrustManager)
+                .hostnameVerifier(new SkipHostnameVerifier())
+                .retryOnConnectionFailure(true)//当使用连接池时该参数设置true才有意义
+                .connectionPool(new okhttp3.ConnectionPool(200, 5, TimeUnit.MINUTES))
+                .connectTimeout(30, TimeUnit.SECONDS)
+                .readTimeout(30, TimeUnit.SECONDS)
+                .writeTimeout(30,TimeUnit.SECONDS)
+                .build();
+    }
+
+    @Bean(name = "X509TrustManager")
+    public X509TrustManager x509TrustManager() {
+        return new X509TrustManager() {
+            @Override
+            public void checkClientTrusted(X509Certificate[] x509Certificates, String s){
+            }
+            @Override
+            public void checkServerTrusted(X509Certificate[] x509Certificates, String s){
+            }
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return new X509Certificate[0];
+            }
+        };
+    }
+
+    @Bean(name = "SSLSocketFactory")
+    public SSLSocketFactory sslSocketFactory(@Qualifier("X509TrustManager") X509TrustManager x509TrustManager) {
+        try {
+            SSLContext context = SSLContext.getInstance("TLS");
+            context.init(null, new TrustManager[] {x509TrustManager}, new SecureRandom());
+            return context.getSocketFactory();
+        } catch (NoSuchAlgorithmException | KeyManagementException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private static class SkipHostnameVerifier implements HostnameVerifier {
+        @Override
+        public boolean verify(String s, SSLSession sslSession) {
+            return true;
+        }
+    }
+
+    @Bean
+    public RPCMgrProxy startServiceMgrProxy(){
+        GlobalData.getInstance().setSwitchManualHttpGiz(false);
+        RPCMgrProxy.getInstance().init();
+        return RPCMgrProxy.getInstance();
+    }
+}

+ 44 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/RestTemplateConfig.java

@@ -0,0 +1,44 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+public class RestTemplateConfig {
+
+    /*@Bean(name = "RestTemplateEx")
+    public RestTemplate restTemplate(@Qualifier("ClientHttpRequestFactoryEx") ClientHttpRequestFactory factory) {
+        return new RestTemplate(factory);
+    }
+
+    @Bean(name = "RestTemplateUTF8") //解决body无法进行UTF-8编码时的中文乱码问题,如:APPLICATION_XML默认无法指定UTF-8编码;而APPLICATION_JSON_UTF8默认就对body进行了UTF-8编码
+    public RestTemplate restTemplateUTF8(@Qualifier("ClientHttpRequestFactoryEx") ClientHttpRequestFactory factory) {
+        RestTemplate template = new RestTemplate(factory);
+        List<HttpMessageConverter<?>> messageConverters = template.getMessageConverters();
+        if (messageConverters != null){
+            for (int i = 0; i < messageConverters.size(); i++) {
+                HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
+                if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
+                    messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+                }
+            }
+        }
+        return template;
+    }
+
+    @Bean("ClientHttpRequestFactoryEx")
+    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
+        //SimpleClientHttpRequestFactory factory1 = new SimpleClientHttpRequestFactory();
+        SslClientHttpRequestFactory factory = new SslClientHttpRequestFactory();
+        factory.setReadTimeout(30000);
+        factory.setConnectTimeout(30000);
+        return factory;
+    }
+
+    @Bean
+    public RPCMgrProxy startServiceMgrProxy(){
+        RPCMgrProxy.getInstance().init();
+        return RPCMgrProxy.getInstance();
+    }*/
+}

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

@@ -0,0 +1,45 @@
+package com.shkpr.service.alambizplugin.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;
+    }
+}

+ 74 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/ScheduleTaskConfiguration.java

@@ -0,0 +1,74 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.commtools.TimeTool;
+import com.shkpr.service.alambizplugin.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-");
+        scheduler.setAwaitTerminationSeconds(5);
+        scheduler.setWaitForTasksToCompleteOnShutdown(true);
+        return scheduler;
+    }
+
+    @PostConstruct
+    public void init(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                TimeTool.refreshUTCTimeRes();
+            }
+        }, 10000);
+    }
+}

+ 106 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/SecondSourceConfiguration.java

@@ -0,0 +1,106 @@
+package com.shkpr.service.alambizplugin.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.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.shkpr.service.alambizplugin.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() {
+        return new HikariDataSource(getConfig());
+        //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);
+    }
+}

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

@@ -0,0 +1,45 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.global.base.thread.ThreadPoolProxy;
+import com.shkpr.service.alambizplugin.globalmgr.AsyncTaskQueueMgr;
+import com.shkpr.service.alambizplugin.globalmgr.DelayTaskQueueMgr;
+import com.shkpr.service.alambizplugin.globalmgr.NotifyMsgQueueMgr;
+import com.shkpr.service.alambizplugin.globalmgr.SingleTaskQueueMgr;
+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(3000);
+                }catch (Exception e){}
+            }
+        });
+    }
+
+    //使用时可用@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();}
+
+    @Bean
+    public SingleTaskQueueMgr startSingleTaskQueueMgr() {return SingleTaskQueueMgr.getInstance();}
+}

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

@@ -0,0 +1,53 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.shkpr.service.alambizplugin.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/alambizplugin/configuration/WebMvcConfiguration.java

@@ -0,0 +1,96 @@
+package com.shkpr.service.alambizplugin.configuration;
+import com.shkpr.service.alambizplugin.SpringContextUtil;
+import com.shkpr.service.alambizplugin.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);
+    }
+
+}

+ 70 - 0
src/main/java/com/shkpr/service/alambizplugin/configuration/WebSecurityConfiguration.java

@@ -0,0 +1,70 @@
+package com.shkpr.service.alambizplugin.configuration;
+
+import com.shkpr.service.alambizplugin.controllerfilter.CustomAuthenticationProvider;
+import com.shkpr.service.alambizplugin.controllerfilter.third.ApiJWTBizFilterMgr;
+import com.shkpr.service.alambizplugin.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_ACCESS_TOKEN_CHECK).permitAll()
+                .antMatchers(ApiURI.URI_FILE_BUSI_XXX).permitAll()
+                .antMatchers("/").permitAll()
+                .anyRequest().authenticated()                                                                                          //所有其他请求需要身份认证
+                .and()
+                .addFilterBefore(new ApiJWTBizFilterMgr(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下的静态资源请求时都忽略访问规则
+        */
+    }
+}

+ 50 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/ApiURI.java

@@ -0,0 +1,50 @@
+package com.shkpr.service.alambizplugin.constants;
+public class ApiURI {
+    public static final String HEADER_X_SOURCE_IP = "X-Source-IP";
+    public static final String HEADER_BIZ_TYPE = "Biz-Type";
+    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_TIMESTAMP = "Timestamp";
+    public static final String HEADER_SEQUENCE = "Sequence";
+    public static final String HEADER_SIGNATURE = "Signature";
+    public static final String HEADER_AUTHORIZATION = "Authorization";
+    public static final String EXCEPTION_FORMAT = "{%s:%s}:%s"; //{(ios/apk/pc):url}:error reason
+    public static final String WORKSPACE = "Workspace";
+
+    public static final String URI_XXX_NEW_INFO = "new-info";//新增
+    public static final String URI_XXX_LISTS = "lists"; //分页查询
+    public static final String URI_XXX_RESET = "reset"; //更新(插入或更新)
+    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_UPLOAD = "upload";
+    public static final String URI_XXX_DOWNLOAD = "download";
+    public static final String URI_XXX_RESET_PWD = "pwd-reset";
+    public static final String URI_XXX_CHG_PWD = "pwd-chg";
+    public static final String URI_XXX_IMAGES = "images";
+
+    public static final String URI_ACCESS_TOKEN_CHECK = "/gis-plugin/apply/access-token-check";
+    public static final String URI_FILE_BUSI_XXX = "/files/**";
+    public static final String URI_IMAGE_SHOW_XXX = "/imageShow/**";
+
+    public static final String URI_ALL_BUSI_XXX = "/kpr-plugin/**";
+
+    public static final String URI_GIS_SURVEY_H = "/kpr-plugin/gis-survey";
+    public static final String URI_GIS_SURVEY_XXX = URI_GIS_SURVEY_H+"/**";
+
+    public static final String URI_USERS_H = "/kpr-plugin/users";
+    public static final String URI_USERS_XXX = URI_USERS_H+"/**";
+
+    public static final String URI_COMMON_H = "/kpr-plugin/common";
+    public static final String URI_COMMON_XXX = URI_COMMON_H+"/**";
+
+    public static final String URI_FILES_H = "/kpr-plugin/files";
+    public static final String URI_FILES_XXX = URI_FILES_H+"/**";
+
+    public static final String URI_INTERNAL_H = "/kpr-plugin/internal";
+    public static final String URI_INTERNAL_XXX = URI_INTERNAL_H+"/**";
+
+    public static final String URI_INTERNAL_OPS_XXX = "/ops/**";
+}

+ 16 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/AttachmentPurpose.java

@@ -0,0 +1,16 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface AttachmentPurpose {
+    String GUIDE = "guide";
+    String PROPERTY = "property";
+    String OTHER = "other";
+
+    List<String> ALL_PURPOSE = new ArrayList<String>(){{
+        add(GUIDE);
+        add(PROPERTY);
+        add(OTHER);
+    }};
+}

+ 8 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/AttachmentType.java

@@ -0,0 +1,8 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public interface AttachmentType {
+    int UN_KNOWN = -1;
+    int IMAGE = 1;
+    int VIDEO = 2;
+    int OTHER = 3;
+}

+ 22 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/CommAction.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public interface CommAction {
+    String ADD = "add";
+    String DELETE = "delete";
+    String UPDATE = "update";
+    String PREPARE = "prepare";//预处理
+    String COMMIT = "commit";//处理提交
+    String CHECK = "check";//预审
+
+    Map<String,String> PROMOTE = new HashMap<String,String>(){{
+        put(ADD, "新增");
+        put(DELETE, "删除");
+        put(UPDATE, "修改");
+        put(PREPARE, "预处理");
+        put(COMMIT, "处理提交");
+        put(CHECK, "预审");
+    }};
+}

+ 15 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/CommDefine.java

@@ -0,0 +1,15 @@
+package com.shkpr.service.alambizplugin.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";
+    String SUPER_USER_ID = "UUDA12395CB8B325F16";
+    int LIMIT_MAX = 2000;
+}

+ 7 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/CommProgress.java

@@ -0,0 +1,7 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public interface CommProgress {
+    int INIT = 0;
+    int HALF = 50;
+    int DONE = 100;
+}

+ 10 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/CommStatus.java

@@ -0,0 +1,10 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public interface CommStatus {
+    int UNKNOWN = -1;//未知
+    int READY = 0;//准备就绪(待预审)
+    int PROGRESS = 1;//处理中(预审通过处理中)
+    int SUCCESS = 2;//处理成功
+    int FAILED = 4;//处理失败
+    int OTHER = 255;//其他或取消
+}

+ 37 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/DownLoadEventFileType.java

@@ -0,0 +1,37 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class DownLoadEventFileType {
+    public static final List<String> CUSTOMER_COLUMN_HEADER = new ArrayList<>();
+    public static final HashMap<String, String> CUSTOMER_COLUMN = new HashMap<>();
+
+    static {
+        CUSTOMER_COLUMN_HEADER.add("user_code");
+        CUSTOMER_COLUMN_HEADER.add("user_name");
+        CUSTOMER_COLUMN_HEADER.add("address");
+        CUSTOMER_COLUMN_HEADER.add("caliber");
+        CUSTOMER_COLUMN_HEADER.add("phone");
+        CUSTOMER_COLUMN_HEADER.add("meter_no");
+        CUSTOMER_COLUMN_HEADER.add("meter_use");
+        CUSTOMER_COLUMN_HEADER.add("use_nature");
+        CUSTOMER_COLUMN_HEADER.add("press_level");
+        CUSTOMER_COLUMN_HEADER.add("status_code");
+        CUSTOMER_COLUMN_HEADER.add("status_name");
+
+        CUSTOMER_COLUMN.put("user_code","用户编号");
+        CUSTOMER_COLUMN.put("user_name","用户名称");
+        CUSTOMER_COLUMN.put("address","用户地址");
+        CUSTOMER_COLUMN.put("caliber","口径(DN)");
+        CUSTOMER_COLUMN.put("phone","联系电话");
+        CUSTOMER_COLUMN.put("meter_no","水表表号");
+        CUSTOMER_COLUMN.put("meter_use","水表用途");
+        CUSTOMER_COLUMN.put("use_nature","用水性质");
+        CUSTOMER_COLUMN.put("press_level","加压级别");
+        CUSTOMER_COLUMN.put("status_code","状态标识");
+        CUSTOMER_COLUMN.put("status_name","状态");
+    }
+
+}

+ 26 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisMetadataDefine.java

@@ -0,0 +1,26 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface GisMetadataDefine {
+    interface WATER_NATURE{
+        String SUPPLY = "supply";
+        String DRAIN = "drain";
+        List<String> DEFINES = new ArrayList<String>(){{
+            add(SUPPLY);
+            add(DRAIN);
+        }};
+    }
+
+    interface TYPE_KINE{
+        String POINT = "point";
+        String LINE = "line";
+        String FACE = "face";
+        List<String> DEFINES = new ArrayList<String>(){{
+            add(POINT);
+            add(LINE);
+            add(FACE);
+        }};
+    }
+}

+ 86 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/LogFlagBusiType.java

@@ -0,0 +1,86 @@
+package com.shkpr.service.alambizplugin.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_MAINT_RECORDS(12,"Maintenance Records"),
+    BUSI_CALL_BASE_AS(13, "Call Base As Busi"),
+    BUSI_CALL_GEO_SERVER(14, "Call GeoServer As Busi"),
+    BUSI_LINKED_PATH(15, "Linked Path Busi"),
+    BUSI_NNS_PATH(16, "NNS Path Busi"),
+    BUSI_WFS_FEATURE(17, "WFS Feature Busi"),
+    BUSI_CUSTOMER(18, "Customer Busi"),
+    BUSI_FILES(19, "Files Busi"),
+    BUSI_FEATURES(20, "Features Busi"),
+    BUSI_FEATURES_TOTALS(21, "Features Totals Busi"),
+    BUSI_CALL_TDT_MAP_SERVER(22, "Call TDTMap Server As Busi"),
+    BUSI_TDT_MAP_BUSI(23, "TDTMap Busi"),
+    BUSI_COMMON(24, "Common Busi"),
+    BUSI_EXTEND_DIRECT_TABLE(25,"Extend Power Direct Table"),
+    BUSI_CALL_TASK_AS(26, "Call Task As Busi"),
+    BUSI_PIPELINE(27, "PipeLine Busi"),
+    BUSI_GIS_TOTAL_TEMPLATE(28, "Gis Super Template Busi"),
+    BUSI_GIS_ELEMENT_ACTION(29, "Gis Element Action Busi"),
+    BUSI_FEATURES_LAYER_TEMPLATE(30, "Features Layer Template Biz"),
+    BUSI_GEO_PUBLISH(31, "Geo Publish Biz"),
+    BUSI_GIS_METADATA_LAYER_TT(32, "Gis Metadata Layer Template"),
+    BUSI_GIS_METADATA_PROPERTY_TT(33, "Gis Metadata Property Template"),
+    BUSI_NO_JWT_BIZ(34, "No JWT Biz"),
+    BUSI_GIS_ANALY_STATS_REPORT(35, "Gis Analy Stats Report Biz"),
+    BUSI_GIS_SURVEY_PROJECT_BIZ(36,"Gis Survey Project Biz"),
+    BUSI_GIS_SURVEY_JOB_BIZ(37,"Gis Survey Job 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_MT_RECORD(107,"DB Maintenance Records"),
+    BUSI_DB_ROLE_INFO(108,"DB Role Info"),
+    BUSI_DB_MEDIA_INFO(109,"DB Media Info"),
+    BUSI_DB_CUSTOMER_DEVICE_LINK(110,"DB Customer Device Link"),
+    BUSI_DB_TILE_MAP_INFO(111,"DB Tile Map Info"),
+    BUSI_DB_FILE_ATTACHMENT(112,"DB File Attachment Info"),
+    BUSI_DB_DEVICE_ATTACHMENT_LINK(113,"DB Device Attachment Link"),
+    BUSI_DB_DIRECT_READ_TABLE_INFO(114,"DB Direct Read Table Info"),
+    BUSI_DB_DEVICE_LABEL_INFO(115,"DB Device Label Info"),
+    BUSI_DB_GIS_TOTAL_TEMPLATE(116,"DB Gis Super Template"),
+    BUSI_DB_ELEMENT_CHANGE_APPLY(117,"DB Element Change Apply"),
+    BUSI_DB_PIPE_LAYER_TYPE_KIND_LINK(118,"DB Pipe Layer Type Kind Link"),
+    BUSI_DB_GIS_DYNAMIC_BIZ(119,"DB Gis Dynamic Biz"),
+    BUSI_DB_GIS_PUBLISH_APPLY(120,"DB Gis Publish Apply"),
+    BUSI_DB_GIS_METADATA_LAYER(121,"DB Gis Metadata Layer Template"),
+    BUSI_DB_GIS_METADATA_PROPERTY(122,"DB Gis Metadata Property Template"),
+    BUSI_DB_GIS_LAYER_DAILY_ANALYSIS(124,"DB Gis Layer Daily Analysis"),
+    BUSI_DB_SURVEY_PROJECT_BIZ(125,"DB Gis Survey Project"),
+    BUSI_DB_SURVEY_JOB_BIZ(126,"DB Gis Survey Job"),
+    BUSI_DB_SURVEY_JOB_FOCUS(127,"DB Gis Survey Job Focus"),
+    BUSI_DB_SURVEY_JOB_STATUS_TRACK(128,"DB Gis Survey Job Status Track"),
+
+    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;}
+}
+

+ 50 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/LoginUserRoleType.java

@@ -0,0 +1,50 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public enum LoginUserRoleType {
+    ROOT_ADMIN(0,"admin"),
+    NORMAL_ADMIN(1,"normal_admin"),
+    USER(2,"user"),
+    GUEST(3,"guest");
+
+    private LoginUserRoleType(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;}
+
+    @Override
+    public String toString() {
+        return "LoginUserRoleType{" +
+                "name='" + name + '\'' +
+                ", index=" + index +
+                '}';
+    }
+
+    public static LoginUserRoleType valueFromInt(int nRole){
+        switch (nRole){
+            case 0:
+                return ROOT_ADMIN;
+            case 1:
+                return NORMAL_ADMIN;
+            case 2:
+                return USER;
+            case 3:
+                return GUEST;
+            default:
+                break;
+        }
+        return GUEST;
+    }
+
+    public static boolean isRootAdmin(String roleId){
+        return CommDefine.ADMIN_ROLE_ID.equals(roleId)
+                || CommDefine.INTERNAL_OPERATOR_ROLE_ID.equals(roleId);
+    }
+
+    public static String getRootAdminRoleId(){
+        return String.valueOf(ROOT_ADMIN.toIntValue());
+    }
+}

+ 16 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/MsgNotifyDefine.java

@@ -0,0 +1,16 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public class MsgNotifyDefine {
+    public interface Topic{
+        String GIS_FEATURE = "gisFeature";
+        String GIS_LAYER = "gisLayer";
+        String GIS_WS = "gisWS";
+    }
+    public interface Tag{
+        String LABEL = "label";
+        String QCODE = "qcode";
+        String CHANGE = "change";
+        String RELOAD = "reload";
+        String ANALYZE = "analyze";
+    }
+}

+ 12 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/OrderAction.java

@@ -0,0 +1,12 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public interface OrderAction {
+    int UN_KNOWN = -1;
+    int NORMAL = 1; //正常流转
+    int TURN = 2;   //指向转派
+    int REJECT = 4;//审核驳回
+    int FINISH = 8;//审核完结
+    int RETURN = 16;//拒接退回
+    int CLOSING = 32;//忽略关闭
+    int EXPIRED = 255;//过期作废
+}

+ 8 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/OrderAttRange.java

@@ -0,0 +1,8 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public interface OrderAttRange {
+    int UN_KNOWN = -1;
+    int ORIGINAL = 1;      //原始附件
+    int BEFORE_HANDLE = 2; //处理前附件
+    int AFTER_HANDLE = 3;  //处理后附件
+}

+ 16 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/OrderExtendType.java

@@ -0,0 +1,16 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface OrderExtendType {
+    int TRACK = 1;
+    int ATTACH = 2;
+    int FOCUS = 3;
+
+    List<Integer> ALL_TYPE = new ArrayList<Integer>(){{
+        add(TRACK);
+        add(ATTACH);
+        add(FOCUS);
+    }};
+}

+ 121 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/ResponseCode.java

@@ -0,0 +1,121 @@
+package com.shkpr.service.alambizplugin.constants;
+
+/**
+ * RESULT_开头的为响应体中的结果码rescode
+ * STATUS_开头的为HTTP Status响应码
+ */
+public enum ResponseCode {
+    RESULT_NORMAL(0, "Normal result."),
+    RESULT_BAD(1, "Bad result,see the message/data for reason."),
+
+    STATUS_SUCCESS(200, "Success"),
+    STATUS_BAD_REQUEST(600, "Bad Request,see the message/data for reason."),
+    STATUS_ACCESS_DENY(603, "Access denied."),
+    STATUS_NOT_FOUND_URI(604, "No mapping found for HTTP request with URI."),
+    STATUS_METHOD_NOT_ALLOWED(605, "Method Not Allowed."),
+    STATUS_HTTP_TYPE_NOT_ACCEPTABLE(606, "Http media type not acceptable."),
+    STATUS_HTTP_TYPE_NOT_SUPPORTED(615, "Http media type not supported."),
+    STATUS_INTERNAL_SERVER_ERROR(700, "Internal Server Error."),
+    STATUS_SERVER_RUN_ERROR(1000,"The server is abnormal."),
+    STATUS_NULL_POINT_EXCEPTION(1001, "Empty param or param is null."),
+    STATUS_ERROR_DATA_TYPE(1002, "The data type is wrong."),
+    STATUS_IO_EXCEPTION(1003, "IO exception."),
+    STATUS_NO_SUCH_METHOD(1004, "No such method."),
+    STATUS_INDEX_OUT_OF_BOUNDS(1005, "Index out of bounds."),
+    STATUS_ERROR_JSON_FORMAT(1006, "Error JSON data format."),
+    STATUS_NOT_POST_REQUEST(1007, "Not post request."),
+    STATUS_NOT_DELETE_REQUEST(1008, "Not delete request."),
+    STATUS_ERROR_PARAM_FORMAT(1009, "Error parameter format."),
+    STATUS_INVALID_CONTENT_TYPE(1010, "Error Content-Type."),
+    STATUS_NOT_MATCHED_URI(1011, "No mapping found for HTTP request with URI."),
+    STATUS_ERROR_REQUEST_METHOD(1012, "Error request method."),
+    STATUS_NO_USER_ACCOUNT(1013, "No such user or has not login."),
+    STATUS_SERVER_NET_DISCONN_OR_BUSY(1014, "The network of server is down or busy. Please try again later."),
+    STATUS_MAX_CONCURRENT_REQUEST_COUNT(1015, "Exceeded the maximum number of concurrent requests. Please try again later."),
+    STATUS_INVALID_HEADER(1016, "Invalid headers, please check the headers of request."),
+
+    STATUS_EMPTY_TOKEN(2000,"Empty token."),
+    STATUS_INVALID_TOKEN(2001, "Invalidate Token, please re-login."),
+    STATUS_EXPIRED_TOKEN(2002, "Expired Token, please re-login."),
+    STATUS_NOT_LOGGED_IN(2003, "Not logged in."),
+    STATUS_DENY_OPERATE_USER(2004, "No permission to operate."),
+    STATUS_TOO_OLD_TOKEN(2005, "The token is too old, please use your new token."),
+    STATUS_INVALID_OLD_PWD(2006, "The original password is wrong."),
+    STATUS_INVALID_KEY(2007, "Invalidate Key"),
+    STATUS_INVALID_NAME(2008, "Invalidate Name"),
+
+    RESULT_ERROR_SIGN(3000, "Illegal signature"),
+    RESULT_REPEAT_SEQUENCE(3001, "Repeat the request, please check the request sequence number."),
+    RESULT_REQUEST_TIMEOUT(3002, "Request timed out."),
+    RESULT_REQUEST_TOO_BUSY(3003, "Request too busy, please try again later."),
+    RESULT_REPEAT_RECORDS(3004, "Repeat the records, please check the request."),
+    RESULT_REFERENCE_RECORDS(3005, "Reference the records, please check the request."),
+    RESULT_REFERENCE_NOT_EXIST(3006, "Reference the not exist, please check the request."),
+    RESULT_INVALID_MULTI_TYPE_BIND(3007, "Multi type binding, please check the request."),
+    RESULT_ILLEGAL_LOGIN(3998, "Illegal login."),
+    RESULT_ACCOUNT_LOCKED(3999, "Account has been locked, please try again later."),
+
+    RESULT_INVALID_ORDER(4000, "The order number is inconsistent."),//错误或不合法的工单号
+    RESULT_DUPLICATE_ORDER(4001,"The order is already exists."), //指定工单已存在
+    RESULT_ORDER_ACCEPTED(4002, "The order is already accepted."),//指定工单已被接收
+    RESULT_ORDER_DEALED(4003, "The order is already deal."),//指定工单已被处理
+    RESULT_ORDER_ODD_STATUS(4004, "The order status is incorrect.No permission to operation."),//指定工单状态错误,暂无权限做次操作
+    RESULT_ORDER_OWN_CHANGED(4005, "The owner of order is changed.No permission to operation."),//指定工单归属已变更,暂无限操作
+
+    RESULT_USER_ALREADY_REG(8000, "This phone is already registered."),
+    RESULT_DENY_FOR_SAME_PASS(8001, "Two passwords cannot be the same."),
+    RESULT_REFRESH_TOKEN_FAILED(8002, "Refresh token failed, please login again."),
+    RESULT_TOKEN_INVALID_SIGN(8003, "Refresh token failed, invalid signature"),
+    RESULT_INVALID_USER_INFO(8004, "User information verification failed."),
+    RESULT_EXISTS_USER_NAME(8005, "Username already exists."),
+    RESULT_USER_NOT_REG(8006, "This phone is not registered."),
+    RESULT_INNER_JS_SERVER_AUTH_FAILED(8007, "Inner js bizservice verify failed."),
+
+    RESULT_SERVER_NET_DISCONN_OR_BUSY(9000, "The network of server is down or busy. Please try again later."),
+
+    RESULT_INVALID_PUSH_TASK(9100, "The push task is inconsistent."),
+    RESULT_PUSH_TASK_CLOSE(9101, "The push task will be closed."),
+    RESULT_PUSH_TASK_RETRY(9102, "The push task will be next push in the queue."),
+    RESULT_PUSH_FAILED_ERROR_RECEIVER(9103, "Push task failed because of error receiver."),
+    RESULT_PUSH_FAILED_ERROR_OTHERS(9104, "Push task failed because of other errors."),
+    RESULT_PUSH_FAILED_NO_WAY(9105, "Push task failed because of no support the push way."),
+
+    RESULT_FILE_INVALID_TYPE(10000, "Illegal file type."),
+    RESULT_FILE_RW_FILED(10001, "File read/write error."),
+    RESULT_FILE_SIZE_EXCEED(10002, "File size limit exceeded."),
+    RESULT_FILE_PARSE_FAILED(10003, "File parse failed."),
+    RESULT_FILE_EMPTY_ROWS(10004, "File is empty rows."),
+
+    RESULT_NOT_SUPPORT_GEO_WFS_TYPE(20000, "The operation for this geo wfs type is not supported."),
+    RESULT_NOT_SUPPORT_GEO_WFS_WS(20001, "The operation for this geo wfs workspace is not supported."),
+    RESULT_GEO_WFS_TYPE_EMPTY_DATA(20002, "The empty data for this geo wfs type."),
+    RESULT_LABEL_ALREADY_USED(20003, "The Label is already in use."),
+    RESULT_REQ_TO_GEO_SERVER_FAILED(20004, "The request to GeoServer Failed."),
+    RESULT_GEO_WFS_ELEMENT_IS_NOT_EXIST(20005, "The geo wfs element is not exist."),
+
+    RESULT_FAST_DFS_UPLOAD_FAILED(30000, "Upload File To FastDfs Failed."),
+
+    BUSINESS_SYNC_FUN_FAILED(65529,"The Synch operation failed."),
+    BUSINESS_DB_REQ_FAILED(65530,"The DB operation failed."),
+    BUSINESS_API_ABOLISH(65531,"The Api has been abolished."),
+    BUSINESS_BUSY(65532,"Business is busy, please try again."),
+    SERVICE_OFFLINE(65533, "Service offline, please turn off offline mode"),
+    STATUS_UNKNOWN(65534,"Unknown reason,see the message/data for reason."),
+    RESULT_UNKNOWN(65535,"Unknown reason,see the message/data for reason.");
+
+    private String name;
+    private int index;
+    private ResponseCode(int indexC, String strN){
+        index = indexC;
+        name = strN;
+    }
+
+    public int toInt() {return index;}
+    public String toStrCode() {return String.valueOf(index);}
+    public String toStrMsg() {return name;}
+
+    @Override
+    public String toString() {
+        return "StatusCode: " + index + " Message: " + name;
+    }
+}

+ 15 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/StorageGroupType.java

@@ -0,0 +1,15 @@
+package com.shkpr.service.alambizplugin.constants;
+
+public enum StorageGroupType {
+    BIZ(1,"gis-element"),
+    MAP(2,"maps");
+
+    private StorageGroupType(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;}
+}

+ 37 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/TaskQueueDataTypeEx.java

@@ -0,0 +1,37 @@
+package com.shkpr.service.alambizplugin.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_NOTIFY_PWD_RESET = ASYNC_PARSE_EVENT_FILE+1;
+    public static final int ASYNC_REFRESH_GEO_WFS_FEATURE_TYPE = ASYNC_NOTIFY_PWD_RESET+1;
+    public static final int ASYNC_FLUSH_TILE_MAP_TO_FASTDFS = ASYNC_REFRESH_GEO_WFS_FEATURE_TYPE+1;
+    public static final int ASYNC_BATCH_SYNC_TILE_MAP_FROM_REMOTE = ASYNC_FLUSH_TILE_MAP_TO_FASTDFS+1;
+    public static final int ASYNC_REFRESH_GEO_WFS_FEATURE_DATA = ASYNC_BATCH_SYNC_TILE_MAP_FROM_REMOTE+1;
+    public static final int ASYNC_RELOAD_GEO_WORKSPACE = ASYNC_REFRESH_GEO_WFS_FEATURE_DATA+1;
+    public static final int ASYNC_TASK_END = 1100;
+
+    public static final int DELAY_TASK_BEGIN = 2000;
+    public static final int DELAY_PUSH_TASK = DELAY_TASK_BEGIN+1;
+    public static final int DELAY_BATCH_SYNC_TILE_MAP_FROM_REMOTE = DELAY_PUSH_TASK+1;
+    public static final int DELAY_BATCH_SYNC_DEV_LABEL_TO_GEO_SERVER = DELAY_BATCH_SYNC_TILE_MAP_FROM_REMOTE+1;
+    public static final int DELAY_CHECK_GEO_PUBLISH_STEP = DELAY_BATCH_SYNC_DEV_LABEL_TO_GEO_SERVER+1;
+    public static final int DELAY_HANDLE_LAYER_CHANGED = DELAY_CHECK_GEO_PUBLISH_STEP+1;
+    public static final int DELAY_HANDLE_WS_CHANGED = DELAY_HANDLE_LAYER_CHANGED+1;
+    public static final int DELAY_RELOAD_GEO_WORKSPACE = DELAY_HANDLE_WS_CHANGED+1;
+    public static final int DELAY_REDO_LAYER_DAILY = DELAY_RELOAD_GEO_WORKSPACE+1;
+    public static final int DELAY_TASK_END = 2010;
+
+    public static final int NOTIFY_MSG_BEGIN = 2020;
+    public static final int NOTIFY_MSG_TO_OTHER_SERVICE = NOTIFY_MSG_BEGIN+1;
+    public static final int NOTIFY_MSG_FROM_OTHER_SERVICE  = NOTIFY_MSG_TO_OTHER_SERVICE+1;
+    public static final int NOTIFY_MSG_END = 2030;
+
+    public static final int SINGLE_TASK_BEGIN = 2040;
+    public static final int SINGLE_PUBLISH_LAYER = SINGLE_TASK_BEGIN+1;
+    public static final int SINGLE_TASK_END = 2050;
+}

+ 80 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/UploadEventFileType.java

@@ -0,0 +1,80 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import com.shkpr.service.alambizplugin.commtools.CommTool;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class UploadEventFileType {
+    public static final HashMap<String, String> FILES_TYPE = new HashMap<>();
+    public static final HashMap<String, String> CUSTOMER_REQUIRED = new HashMap<>();
+    public static final HashMap<String, String> CUSTOMER_OPTIONAL = new HashMap<>();
+    static {
+        // images
+        FILES_TYPE.put("jpg","FFD8FF");
+        FILES_TYPE.put("png","89504E47");
+        FILES_TYPE.put("gif","47494638");
+        FILES_TYPE.put("tif","49492A00");
+        FILES_TYPE.put("bmp","424D");
+
+        FILES_TYPE.put("xml","3C3F786D6C");
+        FILES_TYPE.put("html","68746D6C3E");
+        //FILES_TYPE.put("doc","D0CF11E0");
+        FILES_TYPE.put("xls","D0CF11E0");//excel2003版本文件
+        //FILES_TYPE.put("docx","504B0304");
+        FILES_TYPE.put("xlsx","504B0304");//excel2007以上版本文件
+
+        CUSTOMER_REQUIRED.put("用户编号","user_code");
+        /*CUSTOMER_OPTIONAL.put("用户名称","user_name");
+        CUSTOMER_OPTIONAL.put("用户地址","address");
+        CUSTOMER_OPTIONAL.put("口径(DN)","caliber");
+        CUSTOMER_OPTIONAL.put("联系电话","phone");
+        CUSTOMER_OPTIONAL.put("水表表号","meter_no");
+        CUSTOMER_OPTIONAL.put("水表用途","meter_use");
+        CUSTOMER_OPTIONAL.put("用水性质","use_nature");
+        CUSTOMER_OPTIONAL.put("加压级别","press_level");*/
+    }
+
+
+    public static final int CUSTOMER_EVENT = 0;
+    public static boolean isSupportFileType(String typeHex, int eventType){
+        switch (eventType){
+            case CUSTOMER_EVENT:{
+                return FILES_TYPE.get("xls").startsWith(typeHex) || FILES_TYPE.get("xlsx").startsWith(typeHex);
+            }
+        }
+        return false;
+    }
+
+    public static String getFileExtByFileType(String typeHex){
+        if (!StringUtils.isEmpty(typeHex)){
+            for (Map.Entry<String, String> entry:FILES_TYPE.entrySet()){
+                String ext = entry.getKey();
+                String type = entry.getValue();
+                if (type.startsWith(typeHex))
+                    return ext;
+            }
+        }
+        return "";
+    }
+
+    public static String getImageFileType(String typeHex){
+        if (CommTool.lenString(typeHex) > 0){
+            if (typeHex.startsWith(FILES_TYPE.get("jpg")))
+                return "jpg";
+            else if (FILES_TYPE.get("png").startsWith(typeHex))
+                return "png";
+            else if (FILES_TYPE.get("gif").startsWith(typeHex))
+                return "gif";
+            return "jpeg";
+        }
+        return "";
+    }
+
+    public static boolean isSupportImageFile(String typeHex){
+        return !StringUtils.isEmpty(getImageFileType(typeHex));
+    }
+}

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

@@ -0,0 +1,37 @@
+package com.shkpr.service.alambizplugin.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/alambizplugin/constants/UserCurStateType.java

@@ -0,0 +1,17 @@
+package com.shkpr.service.alambizplugin.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;}
+}

+ 53 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/ViewContentType.java

@@ -0,0 +1,53 @@
+package com.shkpr.service.alambizplugin.constants;
+
+import org.apache.commons.lang3.StringUtils;
+
+public enum ViewContentType {
+    DEFAULT("default","application/octet-stream"),
+    JPG("jpg", "image/jpeg"),
+    TIFF("tiff", "image/tiff"),
+    GIF("gif", "image/gif"),
+    JFIF("jfif", "image/jpeg"),
+    PNG("png", "image/png"),
+    TIF("tif", "image/tiff"),
+    ICO("ico", "image/x-icon"),
+    JPEG("jpeg", "image/jpeg"),
+    WBMP("wbmp", "image/vnd.wap.wbmp"),
+    FAX("fax", "image/fax"),
+    NET("net", "image/pnetvue"),
+    JPE("jpe", "image/jpeg"),
+    RP("rp", "image/vnd.rn-realpix");
+
+    private String prefix;
+    private String type;
+
+    public static String getContentType(String prefix){
+        if(StringUtils.isEmpty(prefix))
+            return DEFAULT.getType();
+
+        int tmpIndex = prefix.lastIndexOf(".");
+        if (tmpIndex < 0)
+            return DEFAULT.getType();
+
+        prefix = prefix.substring(tmpIndex+1);
+        for (ViewContentType value:ViewContentType.values()) {
+            if (value.getPrefix().equalsIgnoreCase(prefix)){
+                return value.getType();
+            }
+        }
+        return DEFAULT.getType();
+    }
+
+    ViewContentType(String prefix, String type) {
+        this.prefix = prefix;
+        this.type = type;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public String getType() {
+        return type;
+    }
+}

+ 57 - 0
src/main/java/com/shkpr/service/alambizplugin/controller/ApiBaseController.java

@@ -0,0 +1,57 @@
+package com.shkpr.service.alambizplugin.controller;
+
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.constants.ResponseCode;
+import com.shkpr.service.alambizplugin.exception.SelfException;
+import com.shkpr.service.alambizplugin.subtask.BaseSubTask;
+import org.springframework.util.StringUtils;
+
+public abstract class ApiBaseController {
+    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;
+    }
+}

+ 134 - 0
src/main/java/com/shkpr/service/alambizplugin/controller/ApiCommonController.java

@@ -0,0 +1,134 @@
+package com.shkpr.service.alambizplugin.controller;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.commtools.CommTool;
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.controllerfilter.TokenAuthenticationService;
+import com.shkpr.service.alambizplugin.controllervalid.CommonParamValidDel;
+import com.shkpr.service.alambizplugin.constants.ResponseCode;
+import com.shkpr.service.alambizplugin.dto.ResponseRes;
+import com.shkpr.service.alambizplugin.exception.SelfException;
+import com.shkpr.service.alambizplugin.apiparam.JPStrIdsDel;
+import com.shkpr.service.alambizplugin.subtask.BaseSubTask;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RequestMapping(ApiURI.URI_COMMON_H)
+@RestController
+public class ApiCommonController extends ApiBaseController {
+    final String MSG_SUCCESS = "success.";
+    final String MSG_FAILED = "failed.";
+    private String mStrClassName;
+    private String mBizType = "";
+    private AtomicInteger mSeqUpload = null
+            , mSeqBatchDel = null;
+
+    public ApiCommonController() {
+        mStrClassName = "ApiCommonController";
+        mBizType = LogFlagBusiType.BUSI_COMMON.toStrValue();
+        mSeqUpload = new AtomicInteger(0);
+        mSeqBatchDel = new AtomicInteger(0);
+    }
+
+    @Override
+    public BaseSubTask getSubTask() {
+        return null;
+    }
+
+    @RequestMapping(value = ApiURI.URI_XXX_IMAGES+"/"+ApiURI.URI_XXX_UPLOAD)
+    public ResponseRes uploadImages(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent
+            , @RequestParam(required=false, value = "file") MultipartFile[] files) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        ResponseCode paramCheck = ResponseCode.RESULT_NORMAL;
+        if (files == null || files.length <= 0)
+            paramCheck = ResponseCode.STATUS_ERROR_JSON_FORMAT;
+        if (paramCheck != ResponseCode.RESULT_NORMAL)
+            throw new SelfException(paramCheck.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , paramCheck.toStrMsg()));
+
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqUpload.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                ,String.format("%s:%s seq:{%s} begin====>"
+                        ,strPlatform
+                        ,URI_PATH
+                        ,strRunSeq));
+
+        ResponseRes<String> resResult = new ResponseRes<String>();
+        resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+        resResult.setResdata("");
+        resResult.setResmsg(MSG_SUCCESS);
+
+        //do......
+
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, 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;
+    }
+
+    @DeleteMapping(value = ApiURI.URI_XXX_IMAGES+"/"+ApiURI.URI_XXX_DEL)
+    public ResponseRes delImages(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent
+            , @RequestBody(required=false) @Validated(value={CommonParamValidDel.class}) JPStrIdsDel oJsonParam
+            , BindingResult bindRes) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (oJsonParam == null || bindRes.hasErrors() || !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, mSeqBatchDel.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                ,String.format("%s:%s seq:{%s} param.Size:{%d} begin====>"
+                        ,strPlatform
+                        ,URI_PATH
+                        ,strRunSeq
+                        ,oJsonParam.getTotal()));
+
+        ResponseRes<String> resResult = new ResponseRes<String>();
+        resResult.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+        resResult.setResdata("");
+        resResult.setResmsg(MSG_FAILED);
+
+        //do.......
+
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, 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;
+    }
+}

+ 151 - 0
src/main/java/com/shkpr/service/alambizplugin/controller/ApiUserController.java

@@ -0,0 +1,151 @@
+package com.shkpr.service.alambizplugin.controller;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.bizservice.UserBizService;
+import com.shkpr.service.alambizplugin.commtools.CommTool;
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.constants.ResponseCode;
+import com.shkpr.service.alambizplugin.controllerfilter.TokenAuthenticationService;
+import com.shkpr.service.alambizplugin.controllervalid.*;
+import com.shkpr.service.alambizplugin.dto.*;
+import com.shkpr.service.alambizplugin.exception.SelfException;
+import com.shkpr.service.alambizplugin.apiparam.*;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RequestMapping(ApiURI.URI_USERS_H)
+@RestController
+public class ApiUserController {
+    final String MSG_SUCCESS = "success.";
+    final String MSG_FAILED = "failed.";
+    private String mStrClassName = "", mBizType = "";
+    private AtomicInteger mSeqApisSearchReq = null,
+            mSeqBatchAddReq = null, mSeqResetReq = null,
+            mSeqPwdChg = null, mSeqPwdReset = null,
+            mSeqBatchListReq = null, mSeqBatchDel = null;
+
+    public ApiUserController() {
+        mStrClassName = "ApiUserController";
+        mBizType = LogFlagBusiType.BUSI_USER.toStrValue();
+        mSeqApisSearchReq = new AtomicInteger(0);
+        mSeqBatchAddReq = new AtomicInteger(0);
+        mSeqResetReq = new AtomicInteger(0);
+        mSeqPwdChg = new AtomicInteger(0);
+        mSeqPwdReset = new AtomicInteger(0);
+        mSeqBatchListReq = new AtomicInteger(0);
+        mSeqBatchDel = new AtomicInteger(0);
+    }
+
+    @PostMapping(value = ApiURI.URI_XXX_SK)
+    public ResponseRes searchByIds(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent
+            , @RequestBody(required=false) @Validated(value={CommonParamValidSK.class}) JPGetOne oJsonParam
+            , BindingResult bindRes) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (oJsonParam == null || bindRes.hasErrors() || !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, mSeqApisSearchReq.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, 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_BAD.toStrCode());
+        resResult.setResmsg(MSG_FAILED);
+        resResult.setResdata("");
+
+        TObjectRes<? extends Object> oRes = UserBizService.queryLineById(oJsonParam);
+        if (oRes != null){
+            if (oRes.getCode() == 0){
+                resResult.setResmsg(MSG_SUCCESS);
+                if (oRes.getData() != null)
+                    resResult.setResdata(FastJsonUtil.toJSON(oRes.getData()));
+            }
+            resResult.setRescode(String.valueOf(oRes.getCode()));
+        }
+
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, 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;
+    }
+
+    @PostMapping(value = ApiURI.URI_XXX_LISTS)
+    public ResponseRes batchLists(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent
+            , @RequestBody(required=false) @Validated(value={CommonParamValidList.class}) JPPageLO oJsonParam
+            , BindingResult bindRes) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        if (oJsonParam == null)
+            oJsonParam = new JPPageLO();
+        if (oJsonParam == null || bindRes.hasErrors() || !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, mSeqBatchListReq.incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, strUserId
+                ,String.format("%s:%s seq:{%s} param:%s begin====>"
+                        ,strPlatform
+                        ,URI_PATH
+                        ,strRunSeq
+                        ,oJsonParam.toJsonStr()));
+
+        ResponseRes<String> resResult = new ResponseRes<String>();
+        resResult.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+        resResult.setResmsg(MSG_FAILED);
+        resResult.setResdata("");
+
+        CommPageRecord<? extends Object> arrRes = UserBizService.pageLines(oJsonParam);
+        if (arrRes != null && arrRes.getCode() == 0){
+            resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+            resResult.setResmsg(MSG_SUCCESS);
+            resResult.setResdata(oJsonParam.genJsonStrForResponse(arrRes));
+            arrRes.clearData();
+        }
+
+        resResult.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, 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;
+    }
+}

+ 32 - 0
src/main/java/com/shkpr/service/alambizplugin/controllercheck/ApiCommonControllerCheck.java

@@ -0,0 +1,32 @@
+package com.shkpr.service.alambizplugin.controllercheck;
+
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+public class ApiCommonControllerCheck extends JWTControllerCheck {
+    public ApiCommonControllerCheck(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/%s", ApiURI.URI_COMMON_H, ApiURI.URI_XXX_IMAGES, 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);
+    }
+}

+ 27 - 0
src/main/java/com/shkpr/service/alambizplugin/controllercheck/ApiUserControllerCheck.java

@@ -0,0 +1,27 @@
+package com.shkpr.service.alambizplugin.controllercheck;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+public class ApiUserControllerCheck extends JWTControllerCheck {
+    public ApiUserControllerCheck(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);
+    }
+}

+ 181 - 0
src/main/java/com/shkpr/service/alambizplugin/controllercheck/JWTControllerCheck.java

@@ -0,0 +1,181 @@
+package com.shkpr.service.alambizplugin.controllercheck;
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.global.base.tools.FastJsonUtil;
+import com.shkpr.service.alambizplugin.commtools.CommTool;
+import com.shkpr.service.alambizplugin.commtools.HttpTool;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.controllerfilter.TokenAuthenticationService;
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import com.shkpr.service.alambizplugin.constants.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", "GET,POST,DELETE,PUT");
+        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Content-Type,Authorization");
+        response.setHeader("X-Content-Type-Options", "nosniff");
+        //response.setHeader("X-Frame-Options", "DENY");
+        response.setHeader("X-XSS-Protection", "1; mode=block");
+
+        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;
+    }
+
+    public boolean skipCheckAuthToPermit(HttpServletRequest request, HttpServletResponse response){return false;}
+}

+ 26 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/CustomAuthenticationProvider.java

@@ -0,0 +1,26 @@
+package com.shkpr.service.alambizplugin.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;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+public class CustomAuthenticationProvider implements AuthenticationProvider{
+    protected String mStrThisSampleName = null;
+    public CustomAuthenticationProvider() {
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        //innerJsService = SpringContextUtil.getBean(InnerJsService.class);
+    }
+
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        throw new UsernameNotFoundException(String.format("No account or password error."));
+    }
+
+    @Override
+    public boolean supports(Class<?> aClass) {
+        return aClass.equals(UsernamePasswordAuthenticationToken.class);
+    }
+}
+

+ 90 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/GrantedAuthorityImpl.java

@@ -0,0 +1,90 @@
+package com.shkpr.service.alambizplugin.controllerfilter;
+
+import com.shkpr.service.alambizplugin.constants.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;
+    }
+}
+

+ 116 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/JWTAuthenticationFilter.java

@@ -0,0 +1,116 @@
+package com.shkpr.service.alambizplugin.controllerfilter;
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.commtools.HttpTool;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.controllercheck.JWTControllerCheck;
+import com.shkpr.service.alambizplugin.exception.SelfAuthFilterException;
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import com.shkpr.service.alambizplugin.constants.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)){
+            chain.doFilter(request, response);
+            return;
+        }
+
+        if (mControllerCheck != null && !mControllerCheck.checkRequest(request, response))  //当前URI已匹配成功,但Request请求格式不对,不再向后传递
+            return;
+
+        int nStatusCode = HttpServletResponse.SC_OK;
+        Authentication authentication = null;
+        try {
+            authentication = TokenAuthenticationService.getAuthentication(request, mControllerCheck.skipCheckAuthToPermit(request, response));
+            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;
+        }
+        chain.doFilter(request, response);
+    }
+}

+ 263 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/TokenAuthenticationService.java

@@ -0,0 +1,263 @@
+package com.shkpr.service.alambizplugin.controllerfilter;
+
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.constants.CommDefine;
+import com.shkpr.service.alambizplugin.dto.AuthTokenData;
+import com.shkpr.service.alambizplugin.constants.ResponseCode;
+import com.shkpr.service.alambizplugin.exception.SelfAuthFilterException;
+import com.shkpr.service.alambizplugin.globalcache.GlobalData;
+import com.shkpr.service.alambizplugin.globalcache.UserCacheProxy;
+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.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";
+
+    private static AuthTokenData generateToken(Map<String, Object> claims){
+        return generateToken(claims, MIN_EXPIRATIONTIME);
+    }
+
+    private static AuthTokenData generateToken(Map<String, Object> claims, int expired){
+        String strFlagKey = "";
+        String strAccount = "";
+        String roleId = "";
+        try {
+            strFlagKey = (String)claims.get("flagkey");
+        } catch (Exception e){}
+        try {
+            strAccount = (String)claims.get("account");
+        } catch (Exception e){}
+        try {
+            roleId = (String)claims.get("roleid");
+        } catch (Exception e){}
+        return generateToken(strFlagKey, strAccount, roleId, expired);
+    }
+
+    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", roleId);
+        return generateToken(claims, expired);*/
+        long nowMillis = System.currentTimeMillis();
+        Date dateExpired  = null;
+        String strToken = null;
+        try {
+            strToken = Jwts.builder()
+                    .setHeaderParam("typ", "JWT")
+                    .setHeaderParam("alg", "HS256")
+                    //.setAudience("APP")
+                    //.setIssuer("SERVICE")
+                    //.setId(UUID.randomUUID().toString())
+                    .setIssuedAt(new Date(nowMillis))
+                    .setExpiration(dateExpired = new Date(nowMillis + expired*60*1000))
+                    .signWith(SignatureAlgorithm.HS256, SECRET.getBytes("UTF-8"))
+                    .claim("flagkey", strFlagKey)
+                    .claim("account", strAccount)
+                    .claim("roleid", roleId)
+                    .compact();
+        } catch (Exception e){
+            strToken = null;
+            e.printStackTrace();
+        }
+
+        return  StringUtils.isEmpty(strToken) ? null:new AuthTokenData(strToken
+                , dateExpired!=null ? dateExpired.getTime():System.currentTimeMillis()
+                , nowMillis
+                , strFlagKey);
+    }
+
+    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;
+    }
+
+    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 strRoleId = (String)claims.get("roleid");
+                data = new AuthTokenData(token, claims.getExpiration().getTime(), claims.getIssuedAt().getTime(), strKey, strRoleId);
+            }
+        }catch (ExpiredJwtException e){
+            data = null;
+            throw e;
+        }catch (Exception e) {
+            data = null;
+            throw e;
+        }
+        return data;
+    }
+
+    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;
+    }
+
+    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;
+    }
+
+    public static Boolean isTokenExpired(long lExpired){
+        return lExpired <= new Date().getTime();
+    }
+
+    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;
+    }
+
+    public static Boolean validateToken(String token) {
+        return !isTokenExpired(token);
+    }
+
+    public static Authentication getAuthentication(HttpServletRequest request, boolean isSkipAuthToPermit) throws Exception{
+        final String strAuthVerify = request.getHeader(ApiURI.HEADER_AUTH_VERIFY);
+        if (GlobalData.getInstance().getInternalCallPassword().equalsIgnoreCase(strAuthVerify)
+                || isSkipAuthToPermit){
+            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>());
+        }
+
+        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 {
+                    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.");
+                }
+
+                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{
+                throw new BadCredentialsException("Invalidate Token, has no user.");
+            }
+        }else {
+            throw new SelfAuthFilterException(ResponseCode.STATUS_EMPTY_TOKEN.toInt(), ResponseCode.STATUS_EMPTY_TOKEN.toStrMsg());
+        }
+    }
+
+    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);
+    }
+}

+ 62 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTBizFilterMgr.java

@@ -0,0 +1,62 @@
+package com.shkpr.service.alambizplugin.controllerfilter.third;
+
+import com.shkpr.service.alambizplugin.controllerfilter.JWTAuthenticationFilter;
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.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 ApiJWTBizFilterMgr extends JWTAuthenticationFilter {
+    private RequestMatcher mRequestMatcherForUser = null;
+    private RequestMatcher mRequestMatcherForCommon = null;
+
+    private ApiJWTUserBizFilter mFilterForUser = null;
+    private ApiJWTCommonBizFilter mFilterForCommon = null;
+
+    public ApiJWTBizFilterMgr(AuthenticationManager authenticationManager) {
+        this(null, authenticationManager);
+    }
+
+    public ApiJWTBizFilterMgr(String url, AuthenticationManager authenticationManager) {
+        super(url,  authenticationManager);
+        this.mStrThisSampleName  = this.getClass().getSimpleName();
+
+        mRequestMatcherForUser = new AntPathRequestMatcher(ApiURI.URI_USERS_XXX);
+        mRequestMatcherForCommon = new AntPathRequestMatcher(ApiURI.URI_COMMON_XXX);
+
+        mFilterForUser = new ApiJWTUserBizFilter(ApiURI.URI_USERS_XXX, authenticationManager);
+        mFilterForCommon = new ApiJWTCommonBizFilter(ApiURI.URI_COMMON_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 (mRequestMatcherForUser != null && mRequestMatcherForUser.matches(request)){
+                TraceLogMgr.setTraceIdByBusinessType("USER");
+                mFilterForUser.doFilterInternal(request, response, chain);
+            }else if (mRequestMatcherForCommon != null && mRequestMatcherForCommon.matches(request)){
+                TraceLogMgr.setTraceIdByBusinessType("COMMON");
+                mFilterForCommon.doFilterInternal(request, response, chain);
+            }
+            else {
+                TraceLogMgr.setTraceIdByBusinessType("OTH");
+                chain.doFilter(request, response);
+            }
+        }catch (ServletException e1){
+            throw e1;
+        }catch (IOException e2){
+            throw e2;
+        }finally {
+            TraceLogMgr.removeTraceId();
+        }
+    }
+}

+ 47 - 0
src/main/java/com/shkpr/service/alambizplugin/controllerfilter/third/ApiJWTCommonBizFilter.java

@@ -0,0 +1,47 @@
+package com.shkpr.service.alambizplugin.controllerfilter.third;
+
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.controllercheck.ApiCommonControllerCheck;
+import com.shkpr.service.alambizplugin.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 ApiJWTCommonBizFilter extends JWTAuthenticationFilter {
+    private RequestMatcher mRequestMatcher = null;
+    private ApiCommonControllerCheck mControllerCheck = null;
+    private static final Map<String, String> msMapURI2Method;
+    static {
+        msMapURI2Method = new HashMap<String, String>();
+
+        msMapURI2Method.put(String.format("%s/%s/%s", ApiURI.URI_COMMON_H, ApiURI.URI_XXX_IMAGES, ApiURI.URI_XXX_UPLOAD), "Request");
+        msMapURI2Method.put(String.format("%s/%s/%s", ApiURI.URI_COMMON_H, ApiURI.URI_XXX_IMAGES, ApiURI.URI_XXX_DEL), "POST");
+    }
+
+    public ApiJWTCommonBizFilter(AuthenticationManager authenticationManager) {
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ApiCommonControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    public ApiJWTCommonBizFilter(String url, AuthenticationManager authenticationManager) {
+        super(url, authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ApiCommonControllerCheck(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/alambizplugin/controllerfilter/third/ApiJWTUserBizFilter.java

@@ -0,0 +1,46 @@
+package com.shkpr.service.alambizplugin.controllerfilter.third;
+
+import com.shkpr.service.alambizplugin.constants.ApiURI;
+import com.shkpr.service.alambizplugin.controllercheck.ApiUserControllerCheck;
+import com.shkpr.service.alambizplugin.controllerfilter.JWTAuthenticationFilter;
+import org.springframework.security.authentication.AuthenticationManager;
+
+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;
+
+/**
+ * Controller过滤器处理类
+ */
+public class ApiJWTUserBizFilter extends JWTAuthenticationFilter {
+    private ApiUserControllerCheck mControllerCheck = null;
+    private static final Map<String, String> msMapURI2Method;
+    static {
+        msMapURI2Method = new HashMap<String, String>();
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_USERS_H, ApiURI.URI_XXX_LISTS), "POST");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_USERS_H, ApiURI.URI_XXX_SK), "POST");
+    }
+
+    public ApiJWTUserBizFilter(String url, AuthenticationManager authenticationManager){
+        super(url, authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ApiUserControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    public ApiJWTUserBizFilter(AuthenticationManager authenticationManager){
+        super(authenticationManager);
+        this.mStrThisSampleName = this.getClass().getSimpleName();
+        this.mControllerCheck = new ApiUserControllerCheck(msMapURI2Method);
+        setControllerCheck(this.mControllerCheck);
+    }
+
+    @Override
+    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        super.doFilterInternal(request, response, chain);
+    }
+}

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

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

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

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

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

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

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

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

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

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

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


Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott