TRX 1 жил өмнө
commit
84de8a626f
100 өөрчлөгдсөн 5570 нэмэгдсэн , 0 устгасан
  1. 35 0
      .gitignore
  2. BIN
      .mvn/wrapper/maven-wrapper.jar
  3. 2 0
      .mvn/wrapper/maven-wrapper.properties
  4. 308 0
      mvnw
  5. 205 0
      mvnw.cmd
  6. 466 0
      pom.xml
  7. 23 0
      src/main/java/com/zswl/dataservice/DataServiceApplication.java
  8. 28 0
      src/main/java/com/zswl/dataservice/auth/AuthSettings.java
  9. 205 0
      src/main/java/com/zswl/dataservice/auth/JWTManager.java
  10. 104 0
      src/main/java/com/zswl/dataservice/auth/UserAuthUtil.java
  11. 19 0
      src/main/java/com/zswl/dataservice/auth/UserContext.java
  12. 120 0
      src/main/java/com/zswl/dataservice/auth/UserContextInterceptor.java
  13. 67 0
      src/main/java/com/zswl/dataservice/components/DataRecord.java
  14. 28 0
      src/main/java/com/zswl/dataservice/config/GlobalResponseAdvice.java
  15. 26 0
      src/main/java/com/zswl/dataservice/config/JpaDataConfiguration.java
  16. 99 0
      src/main/java/com/zswl/dataservice/config/MongoConfiguration.java
  17. 27 0
      src/main/java/com/zswl/dataservice/config/PageableDefaultConfig.java
  18. 26 0
      src/main/java/com/zswl/dataservice/config/PaginationConfiguration.java
  19. 46 0
      src/main/java/com/zswl/dataservice/config/PostProcessorConfig.java
  20. 103 0
      src/main/java/com/zswl/dataservice/config/RestExceptionHandler.java
  21. 41 0
      src/main/java/com/zswl/dataservice/config/SwaggerConfig.java
  22. 73 0
      src/main/java/com/zswl/dataservice/config/SwaggerProperties.java
  23. 28 0
      src/main/java/com/zswl/dataservice/config/SystemDefaultConfig.java
  24. 63 0
      src/main/java/com/zswl/dataservice/config/WebMvcConfig.java
  25. 18 0
      src/main/java/com/zswl/dataservice/config/converts/BigDecimalToDecimal128Converter.java
  26. 20 0
      src/main/java/com/zswl/dataservice/config/converts/Decimal128ToBigDecimalConverter.java
  27. 26 0
      src/main/java/com/zswl/dataservice/config/result/InvokerExceptionResolver.java
  28. 81 0
      src/main/java/com/zswl/dataservice/config/result/InvokerResult.java
  29. 41 0
      src/main/java/com/zswl/dataservice/config/result/InvokerState.java
  30. 33 0
      src/main/java/com/zswl/dataservice/config/result/ResultException.java
  31. 57 0
      src/main/java/com/zswl/dataservice/config/result/ServiceResult.java
  32. 21 0
      src/main/java/com/zswl/dataservice/config/result/SuperEndpoints.java
  33. 68 0
      src/main/java/com/zswl/dataservice/controller/DeviceController.java
  34. 69 0
      src/main/java/com/zswl/dataservice/controller/GateWayController.java
  35. 71 0
      src/main/java/com/zswl/dataservice/controller/GateWayUserInfoController.java
  36. 67 0
      src/main/java/com/zswl/dataservice/controller/MqttInfoController.java
  37. 56 0
      src/main/java/com/zswl/dataservice/controller/OauthController.java
  38. 40 0
      src/main/java/com/zswl/dataservice/controller/OperationLogsController.java
  39. 51 0
      src/main/java/com/zswl/dataservice/controller/OperationMessageController.java
  40. 61 0
      src/main/java/com/zswl/dataservice/controller/ProjectInfoController.java
  41. 47 0
      src/main/java/com/zswl/dataservice/controller/TestController.java
  42. 18 0
      src/main/java/com/zswl/dataservice/dao/AppInfoDao.java
  43. 12 0
      src/main/java/com/zswl/dataservice/dao/MongoDao.java
  44. 8 0
      src/main/java/com/zswl/dataservice/dao/TokenLoginDao.java
  45. 14 0
      src/main/java/com/zswl/dataservice/dao/UserDao.java
  46. 15 0
      src/main/java/com/zswl/dataservice/dao/extend/UserDaoExtend.java
  47. 73 0
      src/main/java/com/zswl/dataservice/dao/impl/UserDaoImpl.java
  48. 17 0
      src/main/java/com/zswl/dataservice/dao/mqtt/DeviceInfoDao.java
  49. 13 0
      src/main/java/com/zswl/dataservice/dao/mqtt/GateWay2DeviceDao.java
  50. 16 0
      src/main/java/com/zswl/dataservice/dao/mqtt/GateWay2UserDao.java
  51. 18 0
      src/main/java/com/zswl/dataservice/dao/mqtt/GateWayInfoDao.java
  52. 18 0
      src/main/java/com/zswl/dataservice/dao/mqtt/GateWayUserInfoDao.java
  53. 25 0
      src/main/java/com/zswl/dataservice/dao/mqtt/Mqtt2UserDao.java
  54. 16 0
      src/main/java/com/zswl/dataservice/dao/mqtt/MqttInfoDao.java
  55. 17 0
      src/main/java/com/zswl/dataservice/dao/mqtt/OperationLogsDao.java
  56. 18 0
      src/main/java/com/zswl/dataservice/dao/mqtt/OperationMessageDao.java
  57. 18 0
      src/main/java/com/zswl/dataservice/dao/mqtt/ProjectInfoDao.java
  58. 15 0
      src/main/java/com/zswl/dataservice/dao/mqtt/extend/DeviceInfoDaoExtend.java
  59. 15 0
      src/main/java/com/zswl/dataservice/dao/mqtt/extend/GateWayInfoDaoExtend.java
  60. 15 0
      src/main/java/com/zswl/dataservice/dao/mqtt/extend/GateWayUserInfoDaoExtend.java
  61. 15 0
      src/main/java/com/zswl/dataservice/dao/mqtt/extend/OperationLogsDaoExtend.java
  62. 17 0
      src/main/java/com/zswl/dataservice/dao/mqtt/extend/OperationMessageDaoExtend.java
  63. 17 0
      src/main/java/com/zswl/dataservice/dao/mqtt/extend/ProjectInfoDaoExtend.java
  64. 74 0
      src/main/java/com/zswl/dataservice/dao/mqtt/impl/DeviceInfoDaoImpl.java
  65. 67 0
      src/main/java/com/zswl/dataservice/dao/mqtt/impl/GateWayInfoDaoImpl.java
  66. 74 0
      src/main/java/com/zswl/dataservice/dao/mqtt/impl/GateWayUserInfoDaoImpl.java
  67. 75 0
      src/main/java/com/zswl/dataservice/dao/mqtt/impl/OperationLogsDaoImpl.java
  68. 84 0
      src/main/java/com/zswl/dataservice/dao/mqtt/impl/OperationMessageDaoImpl.java
  69. 70 0
      src/main/java/com/zswl/dataservice/dao/mqtt/impl/ProjectInfoDaoImpl.java
  70. 36 0
      src/main/java/com/zswl/dataservice/domain/AppInfo.java
  71. 50 0
      src/main/java/com/zswl/dataservice/domain/SuperEntity.java
  72. 40 0
      src/main/java/com/zswl/dataservice/domain/TokenLogin.java
  73. 63 0
      src/main/java/com/zswl/dataservice/domain/User.java
  74. 28 0
      src/main/java/com/zswl/dataservice/domain/mqtt/DeviceInfo.java
  75. 36 0
      src/main/java/com/zswl/dataservice/domain/mqtt/GateWay2Device.java
  76. 36 0
      src/main/java/com/zswl/dataservice/domain/mqtt/GateWay2User.java
  77. 31 0
      src/main/java/com/zswl/dataservice/domain/mqtt/GateWayInfo.java
  78. 32 0
      src/main/java/com/zswl/dataservice/domain/mqtt/GateWayUserInfo.java
  79. 38 0
      src/main/java/com/zswl/dataservice/domain/mqtt/Mqtt2User.java
  80. 47 0
      src/main/java/com/zswl/dataservice/domain/mqtt/MqttInfo.java
  81. 51 0
      src/main/java/com/zswl/dataservice/domain/mqtt/OperationLogs.java
  82. 56 0
      src/main/java/com/zswl/dataservice/domain/mqtt/OperationMessage.java
  83. 28 0
      src/main/java/com/zswl/dataservice/domain/mqtt/ProjectInfo.java
  84. 18 0
      src/main/java/com/zswl/dataservice/helper/ApplicationContextHolder.java
  85. 37 0
      src/main/java/com/zswl/dataservice/helper/BatchQueryHelper.java
  86. 273 0
      src/main/java/com/zswl/dataservice/helper/DBHelper.java
  87. 59 0
      src/main/java/com/zswl/dataservice/helper/JsonHelper.java
  88. 179 0
      src/main/java/com/zswl/dataservice/helper/MongoQueryLanguageHelper.java
  89. 30 0
      src/main/java/com/zswl/dataservice/helper/MongoTemplateNearest.java
  90. 284 0
      src/main/java/com/zswl/dataservice/helper/ReIndexHelper.java
  91. 103 0
      src/main/java/com/zswl/dataservice/helper/jpa/TransactionHelper.java
  92. 32 0
      src/main/java/com/zswl/dataservice/model/AppInfoModel.java
  93. 26 0
      src/main/java/com/zswl/dataservice/model/QueryModel.java
  94. 22 0
      src/main/java/com/zswl/dataservice/model/TokenModel.java
  95. 12 0
      src/main/java/com/zswl/dataservice/model/baseParam/IDParam.java
  96. 18 0
      src/main/java/com/zswl/dataservice/model/mqtt/DeviceInfoAddParam.java
  97. 18 0
      src/main/java/com/zswl/dataservice/model/mqtt/DeviceInfoModel.java
  98. 18 0
      src/main/java/com/zswl/dataservice/model/mqtt/DeviceInfoSearchParam.java
  99. 25 0
      src/main/java/com/zswl/dataservice/model/mqtt/GateWayBindDeviceParam.java
  100. 21 0
      src/main/java/com/zswl/dataservice/model/mqtt/GateWayInfoAddParam.java

+ 35 - 0
.gitignore

@@ -0,0 +1,35 @@
+HELP.md
+target/
+logs/
+logss/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

BIN
.mvn/wrapper/maven-wrapper.jar


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

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

+ 308 - 0
mvnw

@@ -0,0 +1,308 @@
+#!/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
+#
+#    https://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.2.0
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+      else
+        JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+    JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+      if $darwin ; then
+        javaHome="$(dirname "\"$javaExecutable\"")"
+        javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+      fi
+      javaHome="$(dirname "\"$javaExecutable\"")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(cd "$wdir/.." || exit 1; pwd)
+    fi
+    # end of workaround
+  done
+  printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    # Remove \r in case we run on Windows within Git Bash
+    # and check out the repository with auto CRLF management
+    # enabled. Otherwise, we may read lines that are delimited with
+    # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+    # splitting rules.
+    tr -s '\r\n' ' ' < "$1"
+  fi
+}
+
+log() {
+  if [ "$MVNW_VERBOSE" = true ]; then
+    printf '%s\n' "$1"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+    log "Found $wrapperJarPath"
+else
+    log "Couldn't find $wrapperJarPath, downloading it ..."
+
+    if [ -n "$MVNW_REPOURL" ]; then
+      wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    else
+      wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    fi
+    while IFS="=" read -r key value; do
+      # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+      safeValue=$(echo "$value" | tr -d '\r')
+      case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+      esac
+    done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+    log "Downloading from: $wrapperUrl"
+
+    if $cygwin; then
+      wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+    fi
+
+    if command -v wget > /dev/null; then
+        log "Found wget ... using wget"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        else
+            wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        log "Found curl ... using curl"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        else
+            curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        fi
+    else
+        log "Falling back to using Java to download"
+        javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaSource=$(cygpath --path --windows "$javaSource")
+          javaClass=$(cygpath --path --windows "$javaClass")
+        fi
+        if [ -e "$javaSource" ]; then
+            if [ ! -e "$javaClass" ]; then
+                log " - Compiling MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/javac" "$javaSource")
+            fi
+            if [ -e "$javaClass" ]; then
+                log " - Running MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+  case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+  esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+  wrapperSha256Result=false
+  if command -v sha256sum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  elif command -v shasum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+    echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+    exit 1
+  fi
+  if [ $wrapperSha256Result = false ]; then
+    echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+    echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+    echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 205 - 0
mvnw.cmd

@@ -0,0 +1,205 @@
+@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    https://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.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %WRAPPER_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+    powershell -Command "&{"^
+       "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+       "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+       "  Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+       "  Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+       "  Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+       "  exit 1;"^
+       "}"^
+       "}"
+    if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%

+ 466 - 0
pom.xml

@@ -0,0 +1,466 @@
+<?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>3.2.3</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.zswl</groupId>
+    <artifactId>DataService</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>DataService</name>
+    <description>DataService</description>
+
+    <properties>
+        <java.version>17</java.version>
+
+        <mongo-java-driver.version>3.12.13</mongo-java-driver.version>
+        <!--        <mongodb-driver-sync.version>4.9.1</mongodb-driver-sync.version>-->
+        <mongodb-driver-sync.version>5.0.0</mongodb-driver-sync.version>
+        <spring-data-mongodb.version>3.4.12</spring-data-mongodb.version>
+
+        <spring-mvc.version>6.1.5</spring-mvc.version>
+        <jstl.version>1.2</jstl.version>
+        <commons-fileupload.version>1.5</commons-fileupload.version>
+        <javax.servlet-api.version>4.0.1</javax.servlet-api.version>
+        <servlets-ssi.version>5.0.16</servlets-ssi.version>
+        <javax.servlet.jsp-api.version>2.3.3</javax.servlet.jsp-api.version>
+        <junit.version>4.13.2</junit.version>
+        <commons-lang3.version>3.12.0</commons-lang3.version>
+        <httpclient.version>4.5.14</httpclient.version>
+        <javax.annotation-api.version>1.3.2</javax.annotation-api.version>
+
+        <spring-boot-starter-security.version>3.0.5</spring-boot-starter-security.version>
+    </properties>
+
+    <dependencies>
+        <!-- spring boot -->
+        <!--tomcat运行环境-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+        </dependency>
+        <!--自带web容器-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!--日志-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!--测试-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+            <version>${spring-boot-starter-security.version}</version>
+        </dependency>
+
+        <!-- gson -->
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.10.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <version>3.2.3</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.data</groupId>
+                    <artifactId>spring-data-jpa</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-jpa</artifactId>
+            <version>3.2.3</version>
+        </dependency>
+
+
+        <!--Spring mvc-->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-orm</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-tx</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aspects</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-expression</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-oxm</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-messaging</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring-mvc.version}</version>
+        </dependency>
+
+        <!-- 依赖包 -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>jstl</artifactId>
+            <version>${jstl.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>${commons-fileupload.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>${javax.servlet-api.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>tomcat</groupId>
+            <artifactId>servlets-ssi</artifactId>
+            <version>${servlets-ssi.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet.jsp</groupId>
+            <artifactId>javax.servlet.jsp-api</artifactId>
+            <version>${javax.servlet.jsp-api.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons-lang3.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>${javax.annotation-api.version}</version>
+        </dependency>
+
+
+        <!-- 添加 JavaParser 依赖 -->
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+            <version>3.23.1</version>
+        </dependency>
+
+        <!-- db -->
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-mongodb</artifactId>
+            <version>4.2.4</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-data-commons</artifactId>
+                    <groupId>org.springframework.data</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-mongodb</artifactId>
+            <!--            <version>4.2.4</version>-->
+            <exclusions>
+                <exclusion>
+                    <groupId>org.mongodb</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!--    驱动   -->
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongodb-driver-sync</artifactId>
+            <version>${mongodb-driver-sync.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongodb-driver-core</artifactId>
+            <version>${mongodb-driver-sync.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!--    redis    -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>2.0.39</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.7.0</version>
+        </dependency>
+
+        <!--        <dependency>-->
+        <!--            <groupId>org.springframework.boot</groupId>-->
+        <!--            <artifactId>spring-boot-starter-security</artifactId>-->
+        <!--        </dependency>-->
+
+
+        <!--    swagger  start   -->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
+            <version>4.5.0</version>
+        </dependency>
+        <!--    swagger  end    -->
+
+        <!--         工具类       -->
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.4</version>
+        </dependency>
+
+        <!--    工具类    -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.20</version>
+        </dependency>
+
+        <!--    阿里云短信    -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dysmsapi20170525</artifactId>
+            <version>2.0.24</version>
+        </dependency>
+
+        <!--阿里云 oss-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.6.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-sts</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.14.0</version>
+        </dependency>
+
+        <!--    excel导出    -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml-schemas</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+
+        <!--二维码-->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+
+        <!--    mqtt    -->
+        <!--        <dependency>-->
+        <!--            <groupId>org.apache.activemq</groupId>-->
+        <!--            <artifactId>activemq-broker</artifactId>-->
+        <!--        </dependency>-->
+
+        <!--        <dependency>-->
+        <!--            <groupId>org.apache.activemq</groupId>-->
+        <!--            <artifactId>activemq-client</artifactId>-->
+        <!--        </dependency>-->
+
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-artemis</artifactId>
+            <version>3.2.4</version>
+        </dependency>
+
+    </dependencies>
+
+
+    <repositories>
+        <!-- 阿里-->
+        <repository>
+            <id>nexus</id>
+            <name>nexus</name>
+            <url>https://maven.aliyun.com/nexus/content/groups/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
+        </repository>
+
+
+        <repository>
+            <id>spring-snapshots</id>
+            <name>Spring Snapshots</name>
+            <url>https://repo.spring.io/snapshot</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+
+        <repository>
+            <id>spring-milestones</id>
+            <name>Spring Milestones</name>
+            <url>https://repo.spring.io/milestone</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+
+
+    </repositories>
+
+
+    <pluginRepositories>
+
+        <pluginRepository>
+            <id>groovy-plugins-release</id>
+            <url>https://groovy.jfrog.io/artifactory/plugins-release</url>
+        </pluginRepository>
+
+    </pluginRepositories>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 23 - 0
src/main/java/com/zswl/dataservice/DataServiceApplication.java

@@ -0,0 +1,23 @@
+package com.zswl.dataservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class})
+@EnableAsync
+@EnableCaching
+@Configuration
+@EnableWebMvc
+public class DataServiceApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(DataServiceApplication.class, args);
+    }
+
+}

+ 28 - 0
src/main/java/com/zswl/dataservice/auth/AuthSettings.java

@@ -0,0 +1,28 @@
+package com.zswl.dataservice.auth;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+@Component
+@Data
+@ConfigurationProperties(prefix = "authsettings")
+public class AuthSettings {
+
+    private List<Map<String, String>> freeUrls;
+
+    private List<Map<String, String>> codeValidateUrls;
+
+    private String validateSsoSessionURL;
+
+    private long tokenExpirePeriod = 8 * 60 * 60 * 1000; //8小时
+
+    private String privateKey;
+
+    private String publicKey;
+
+    private String tokenHeaderName = "accessToken";
+}

+ 205 - 0
src/main/java/com/zswl/dataservice/auth/JWTManager.java

@@ -0,0 +1,205 @@
+package com.zswl.dataservice.auth;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.auth0.jwt.interfaces.Claim;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.auth0.jwt.interfaces.JWTVerifier;
+import com.auth0.jwt.interfaces.RSAKeyProvider;
+import com.zswl.dataservice.config.SystemDefaultConfig;
+import com.zswl.dataservice.model.user.LoginUser;
+import com.zswl.dataservice.service.RedisService;
+import com.zswl.dataservice.utils.ConfigDict;
+import com.zswl.dataservice.utils.exception.UnauthorizedException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.text.SimpleDateFormat;
+import java.util.Base64;
+import java.util.Date;
+import java.util.Map;
+
+@Slf4j
+@Component
+public class JWTManager {
+
+    public static final String ISSUER = "miss-dx-train";
+
+    @Autowired
+    private AuthSettings authSettings;
+
+    @Autowired
+    private RedisService redisService;
+
+    private RSAKeyProvider keyProvider;
+
+    @PostConstruct
+    public void init() {
+
+        /*
+         * KeyStore store = KeyStore.getInstance(sslSettings.getKeyStoreType());
+         * InputStream ksInputStream = new FileInputStream(sslSettings.getKeyStore());
+         * store.load(ksInputStream, sslSettings.getKeyStorePassword().toCharArray());
+         * RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey)
+         * store.getKey(sslSettings.getKeyAlias(),
+         * sslSettings.getKeyPassword().toCharArray()); RSAPublicKeySpec spec = new
+         * RSAPublicKeySpec(privateKey.getModulus(), privateKey.getPublicExponent());
+         * RSAPublicKey publicKey = (RSAPublicKey)
+         * KeyFactory.getInstance("RSA").generatePublic(spec);
+         */
+        String priKey = // "-----BEGIN PRIVATE KEY-----" +
+                this.authSettings.getPrivateKey();
+        // "-----END PRIVATE KEY-----" +
+        String pubKey = // "-----BEGIN PUBLIC KEY-----" +
+                this.authSettings.getPublicKey();
+        // "-----END PUBLIC KEY-----" +
+
+        // 获取KeyFactory,指定RSA算法
+        KeyFactory keyFactory;
+        try {
+            keyFactory = KeyFactory.getInstance("RSA");
+            // 将BASE64编码的私钥字符串进行解码
+            byte[] priKeyEncodeByte = Base64.getDecoder().decode(priKey);
+            // 将BASE64解码后的字节数组,构造成PKCS8EncodedKeySpec对象,生成私钥对象
+
+            PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(priKeyEncodeByte));
+            // 将BASE64编码的公钥字符串进行解码
+            byte[] pubKeyEncodeByte = Base64.getDecoder().decode(pubKey);
+            // 将BASE64解码后的字节数组,构造成X509EncodedKeySpec对象,生成公钥对象
+            PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(pubKeyEncodeByte));
+
+            this.keyProvider = new RSAKeyProvider() {
+
+                @Override
+                public RSAPublicKey getPublicKeyById(String kid) {
+                    // Received 'kid' value might be null if it wasn't defined in the Token's header
+                    // RSAPublicKey publicKey = jwkStore.get(kid);
+                    return (RSAPublicKey) publicKey;
+                }
+
+                @Override
+                public RSAPrivateKey getPrivateKey() {
+                    return (RSAPrivateKey) privateKey;
+                }
+
+                @Override
+                public String getPrivateKeyId() {
+                    return null;
+                }
+            };
+        } catch (NoSuchAlgorithmException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            log.error(e.getMessage(), e);
+        } catch (InvalidKeySpecException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    public LoginUser verifyToken(String token) {
+
+        // String token =
+        // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE";
+        // RSAPublicKey publicKey = //Get the key instance
+        // RSAPrivateKey privateKey = //Get the key instance
+        try {
+
+            Algorithm algorithm = Algorithm.RSA256(this.keyProvider.getPublicKeyById(null), null);
+            JWTVerifier verifier = JWT.require(algorithm).withIssuer(ConfigDict.redis_issuer)
+                    //.acceptExpiresAt(4)
+                    .build(); // Reusable verifier // instance
+
+            DecodedJWT jwt = verifier.verify(token);
+
+            Map<String, Claim> claims = jwt.getClaims();
+
+            String loginName = getClaimValue(claims, "loginName");
+
+            if (redisService.verifyExpireJwtToken(loginName, token)) {
+                LoginUser user = new LoginUser();
+                user.setLoginName(loginName);
+                user.setId(getClaimValue(claims, "uid"));
+                user.setUserName(getClaimValue(claims, "userName"));
+                user.setHeadUrl(getClaimValue(claims, "headUrl"));
+                user.setPhone(getClaimValue(claims, "phone"));
+                user.setCreateTokenTime(claims.get("createTokenTime").asString());
+                user.setTokenExpirePeriod(claims.get("tokenExpirePeriod").asLong());
+                user.setToken(token);
+                return user;
+            } else {
+                throw new UnauthorizedException("用户登录失效,请重新登录");
+            }
+
+        } catch (TokenExpiredException e0) {
+            log.error("用户登录过期,请重新登录", e0);
+            throw new UnauthorizedException("用户登录过期,请重新登录");
+        } catch (JWTVerificationException exception) {
+
+            log.error("用户登录验证出错,请重新登录", exception);
+            throw new UnauthorizedException("用户登录验证出错,请重新登录");
+        } catch (UnauthorizedException e4) {
+            log.error(e4.getMessage(), e4);
+            throw e4;
+        } catch (Exception e3) {
+            log.error("用户登录验证出错,请稍候重试", e3);
+            throw new UnauthorizedException("用户登录验证出错,请稍候重试");
+        }
+    }
+
+    public String createToken(LoginUser user) {
+        try {
+
+            Algorithm algorithm = Algorithm.RSA256(null, this.keyProvider.getPrivateKey());
+            long currentTime = System.currentTimeMillis();
+            Date expires = new Date(currentTime + SystemDefaultConfig.tokenExecTime);
+            // 创建Token的时间
+            user.setCreateTokenTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentTime));
+            // Token过期时间
+            user.setTokenExpirePeriod(this.authSettings.getTokenExpirePeriod());
+
+//			user.setTokenHeaderName(this.authSettings.getTokenHeaderName());
+
+            String token = JWT.create()
+                    .withClaim("createTokenTime", user.getCreateTokenTime())
+                    .withClaim("tokenExpirePeriod", user.getTokenExpirePeriod())
+                    .withClaim("uid", user.getId())
+                    .withClaim("loginName", user.getLoginName())
+                    .withClaim("userName", user.getUserName())
+                    .withClaim("headUrl", user.getHeadUrl())
+                    .withClaim("phone", user.getPhone())
+                    .withClaim("isAdmin", user.getIsAdmin())
+                    .withExpiresAt(expires)
+                    .withIssuer(ConfigDict.redis_issuer).sign(algorithm);
+
+            return token;
+
+        } catch (JWTCreationException exception) {
+            log.error(exception.getMessage(), exception);
+            return null;
+        }
+    }
+
+    private static String getClaimValue(Map<String, Claim> claims, String key) {
+        Claim claim = claims.get(key);
+        if (claim == null)
+            return null;
+        return claim.asString();
+    }
+
+}

+ 104 - 0
src/main/java/com/zswl/dataservice/auth/UserAuthUtil.java

@@ -0,0 +1,104 @@
+package com.zswl.dataservice.auth;
+
+import com.zswl.dataservice.model.user.LoginUser;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class UserAuthUtil {
+
+    private static PathMatcher pathMatcher = new AntPathMatcher();
+
+    public static boolean isFree(AuthSettings authSettings, HttpServletRequest request) {
+        String path = request.getRequestURI();
+        String method = request.getMethod();
+
+        List<Map<String, String>> freeUrls = authSettings.getFreeUrls();
+
+        if (freeUrls != null) {
+            for (Map<String, String> kv : freeUrls) {
+                String path0 = kv.get("path");
+                String method0 = kv.get("method");
+
+                if (pathMatcher.match(path0, path)) {
+                    if (method0.indexOf(method) >= 0) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public static boolean isCodeValidate(AuthSettings authSettings, HttpServletRequest request) {
+        String path = request.getRequestURI();
+        String method = request.getMethod();
+
+        List<Map<String, String>> codeValidateUrls = authSettings.getCodeValidateUrls();
+
+        if (codeValidateUrls != null) {
+            for (Map<String, String> kv : codeValidateUrls) {
+                String path0 = kv.get("path");
+                String method0 = kv.get("method");
+
+                if (pathMatcher.match(path0, path)) {
+                    if (method0.indexOf(method) >= 0) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
+     * 模拟权限校验, 可以根据自己项目需要定制不同的策略,如查询数据库获取具体的菜单url或者角色等等.
+     *
+     * @param user
+     */
+    public static boolean verify(LoginUser user, HttpServletRequest request) {
+
+        String url = request.getHeader("x-user-serviceName");
+        if (StringUtils.isEmpty(user)) {
+            return false;
+        } else {
+            List<String> str = new ArrayList<String>();//user.getAllowPermissionService();
+            for (String permissionService : str) {
+                if (url.equalsIgnoreCase(permissionService)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 模拟权限赋值, 可以根据自己项目需要定制不同的策略,如查询数据库获取具体的菜单url或者角色等等.
+     *
+     * @param user
+     */
+    public static void permission(LoginUser user) {
+        if (user.getLoginName().equals("admin")) {
+            List allowPermissionService = new ArrayList();
+            allowPermissionService.add("client-service");
+            allowPermissionService.add("provider-service");
+            //user.setAllowPermissionService(allowPermissionService);
+        } else if (user.getLoginName().equals("spring")) {
+            List allowPermissionService = new ArrayList();
+            allowPermissionService.add("client-service");
+            //user.setAllowPermissionService(allowPermissionService);
+        } else {
+            List allowPermissionService = new ArrayList();
+            //user.setAllowPermissionService(allowPermissionService);
+        }
+    }
+
+}

+ 19 - 0
src/main/java/com/zswl/dataservice/auth/UserContext.java

@@ -0,0 +1,19 @@
+package com.zswl.dataservice.auth;
+
+import com.zswl.dataservice.model.user.LoginUser;
+
+public class UserContext {
+    public static ThreadLocal<LoginUser> context = new ThreadLocal<LoginUser>();
+
+    public static LoginUser currentUser() {
+        return context.get();
+    }
+
+    public static void set(LoginUser user) {
+        context.set(user);
+    }
+
+    public static void shutdown() {
+        context.remove();
+    }
+}

+ 120 - 0
src/main/java/com/zswl/dataservice/auth/UserContextInterceptor.java

@@ -0,0 +1,120 @@
+package com.zswl.dataservice.auth;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.zswl.dataservice.model.user.LoginUser;
+import com.zswl.dataservice.service.RedisService;
+import com.zswl.dataservice.utils.exception.UnauthorizedException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.StringUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
+
+//@Slf4j
+public class UserContextInterceptor implements HandlerInterceptor {
+
+    private JWTManager jwtManager;
+
+    private AuthSettings authSettings;
+
+    private RedisService redisService;
+
+    public UserContextInterceptor(AuthSettings authSettings, JWTManager jwtManager, RedisService redisService) {
+        this.authSettings = authSettings;
+        this.jwtManager = jwtManager;
+        this.redisService = redisService;
+    }
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
+        String method = request.getMethod();
+        if (method != null && "OPTIONS".equals(method)) {
+            return true;
+        }
+
+        String token = request.getHeader(authSettings.getTokenHeaderName());
+
+        if (token != null && token.length() > 0) {
+            try {
+                LoginUser user = verifyUser(token);
+                UserContext.set(user);
+                return true;
+            } catch (UnauthorizedException ue) {
+
+                if (UserAuthUtil.isFree(authSettings, request)) {
+                    return true;
+                }
+
+                response.setCharacterEncoding("UTF-8");
+                response.setHeader("Content-Type", "application/json");
+                response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                JSONObject data = new JSONObject();
+                data.put("message", ue.getMessage());
+                response.getWriter().write(data.toString());
+                response.getWriter().flush();
+                response.getWriter().close();
+                return false;
+            }
+        } else if (UserAuthUtil.isCodeValidate(authSettings, request)) {
+            String code = request.getParameter("_validate_code");
+
+            if (code != null && code.length() > 0 && redisService.verifyExpireCode(code)) {
+                String payloadJson = StringUtils.newStringUtf8(Base64.decodeBase64(code));
+                JSONObject jo = JSON.parseObject(payloadJson);
+                if (jo != null) {
+                    LoginUser user = new LoginUser();
+                    user.setLoginName(jo.getString("loginName"));
+                    user.setId(jo.getString("userId"));
+                    UserContext.set(user);
+                }
+                return true;
+            } else {
+                response.setCharacterEncoding("UTF-8");
+                response.setHeader("Content-Type", "application/json");
+                response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                JSONObject data = new JSONObject();
+                data.put("message", "您访问资源(图片,文件,音频等)时,提供的验证code无效");
+                response.getWriter().write(data.toJSONString());
+                response.getWriter().flush();
+                response.getWriter().close();
+                return false;
+            }
+        } else {
+            if (UserAuthUtil.isFree(authSettings, request)) {
+                return true;
+            } else {
+
+                // throw new UnauthorizedUserException("用户没有登录,请登录");
+
+                response.setCharacterEncoding("UTF-8");
+                response.setHeader("Content-Type", "application/json");
+                response.setStatus(HttpStatus.UNAUTHORIZED.value());
+                JSONObject data = new JSONObject();
+                data.put("message", "用户没有登录,请登录");
+                response.getWriter().write(data.toJSONString());
+                response.getWriter().flush();
+                response.getWriter().close();
+                return false;
+            }
+        }
+    }
+
+    @Override
+    public void postHandle(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+
+    }
+
+    @Override
+    public void afterCompletion(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        UserContext.shutdown();
+    }
+
+    private LoginUser verifyUser(String token) throws UnauthorizedException {
+        return jwtManager.verifyToken(token);
+    }
+
+}

+ 67 - 0
src/main/java/com/zswl/dataservice/components/DataRecord.java

@@ -0,0 +1,67 @@
+package com.zswl.dataservice.components;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import lombok.*;
+import lombok.experimental.Delegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * 数据记录集,可用于还原,适合完成业务补偿部分,建议配合事务使用
+ */
+@Component
+@NoArgsConstructor
+public class DataRecord {
+
+    @Getter
+    @Setter
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+
+    private interface ProxyMethod {
+        boolean add(RevertData data);
+
+        boolean addAll(Collection<? extends RevertData> datas);
+
+        void clear();
+
+        int size();
+    }
+
+
+    @Delegate(types = ProxyMethod.class)
+    private Collection<RevertData> list = new ArrayList<>();
+
+
+    @Data
+    @Builder
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class RevertData {
+        private Class<? extends SuperEntity> entityClass;
+        private Query query;
+        private Update update;
+    }
+
+    public Collection<RevertData> list() {
+        return this.list;
+    }
+
+
+    /**
+     * 恢复数据
+     */
+    public void revert() {
+        for (RevertData data : this.list) {
+            this.mongoTemplate.updateFirst(data.query, data.update, data.entityClass);
+        }
+    }
+
+}

+ 28 - 0
src/main/java/com/zswl/dataservice/config/GlobalResponseAdvice.java

@@ -0,0 +1,28 @@
+package com.zswl.dataservice.config;
+
+import org.springframework.core.MethodParameter;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
+
+/**
+ * 暂时没用
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+//@RestControllerAdvice(basePackages = "com.zswl.dataservice.controller")
+public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
+    @Override
+    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
+        return true;
+    }
+
+    @Override
+    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
+        return "11";
+    }
+}

+ 26 - 0
src/main/java/com/zswl/dataservice/config/JpaDataConfiguration.java

@@ -0,0 +1,26 @@
+package com.zswl.dataservice.config;
+
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * JPA 配置
+ */
+
+//允许自动装载数据源
+@Import({DataSourceAutoConfiguration.class, PaginationConfiguration.class})
+
+//允许使用jpa注解
+@EnableJpaAuditing
+
+//允许事务管理
+@EnableTransactionManagement
+
+@ComponentScan("com.zswl.dataservice.helper.jpa")
+public class JpaDataConfiguration {
+
+
+}

+ 99 - 0
src/main/java/com/zswl/dataservice/config/MongoConfiguration.java

@@ -0,0 +1,99 @@
+package com.zswl.dataservice.config;
+
+import com.mongodb.ReadPreference;
+import com.zswl.dataservice.config.converts.BigDecimalToDecimal128Converter;
+import com.zswl.dataservice.config.converts.Decimal128ToBigDecimalConverter;
+import org.bson.codecs.DocumentCodec;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.mongodb.MongoDatabaseFactory;
+import org.springframework.data.mongodb.MongoTransactionManager;
+import org.springframework.data.mongodb.config.EnableMongoAuditing;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
+import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
+import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
+import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 集成自动配置
+ */
+@Configuration
+@EnableMongoAuditing
+@ComponentScan({"com.zswl.dataservice", "com.zswl.dataservice.helper"})
+@EnableMongoRepositories("com.zswl.dataservice")
+@Import(PaginationConfiguration.class)
+public class MongoConfiguration {
+
+
+    static {
+        //jdk 11 以上,强制使用 TLSv1.3 ,  mongo 驱动目前兼容 TLSv1.2
+        System.setProperty("jdk.tls.client.protocols", "TLSv1.2");
+    }
+
+    /**
+     * 自定义转换器
+     *
+     * @param mongoDbFactory
+     * @param mongoMappingContext
+     * @return
+     * @throws Exception
+     */
+    @Bean
+    @ConditionalOnMissingBean
+    public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory mongoDbFactory, MongoMappingContext mongoMappingContext) throws Exception {
+        DefaultDbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
+        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
+        List<Object> list = new ArrayList<>();
+        list.add(new BigDecimalToDecimal128Converter());//自定义的类型转换器
+        list.add(new Decimal128ToBigDecimalConverter());//自定义的类型转换器
+        converter.setCustomConversions(new MongoCustomConversions(list));
+        return converter;
+    }
+
+    /**
+     * 事务
+     *
+     * @param dbFactory
+     * @return
+     */
+    @Bean
+    MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
+        return new MongoTransactionManager(dbFactory);
+    }
+
+    /**
+     * 配置读写分离
+     *
+     * @return
+     */
+    @Bean
+    public ReadPreference readPreference(MongoTemplate mongoTemplate) {
+//        首选主节点,大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点。
+        ReadPreference readPreference = ReadPreference.primaryPreferred();
+        mongoTemplate.setReadPreference(readPreference);
+        return readPreference;
+    }
+
+    @Bean
+    public DocumentCodec documentCodec(MongoDatabaseFactory dbFactory) {
+        return new DocumentCodec(dbFactory.getCodecRegistry());
+    }
+
+
+// 	 @EventListener(ApplicationReadyEvent.class)
+//	 public void initIndicesAfterStartup() {
+//
+//	    IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);
+//
+//	     IndexResolver resolver = new MongoPersistentEntityIndexResolver(mongoMappingContext);
+//	     resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);
+//	 }
+}

+ 27 - 0
src/main/java/com/zswl/dataservice/config/PageableDefaultConfig.java

@@ -0,0 +1,27 @@
+package com.zswl.dataservice.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import java.util.List;
+
+// 加起的话swigger看不到
+//@Configuration
+public class PageableDefaultConfig extends WebMvcConfigurationSupport {
+
+    /**
+     * 设置分页时默认的每一页数据量
+     *
+     * @param argumentResolvers
+     */
+    @Override
+    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
+        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
+        resolver.setFallbackPageable(PageRequest.of(0, 20));
+        argumentResolvers.add(resolver);
+        super.addArgumentResolvers(argumentResolvers);
+    }
+}

+ 26 - 0
src/main/java/com/zswl/dataservice/config/PaginationConfiguration.java

@@ -0,0 +1,26 @@
+package com.zswl.dataservice.config;
+
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
+import org.springframework.data.web.config.SpringDataWebConfiguration;
+
+@Configuration
+public class PaginationConfiguration extends SpringDataWebConfiguration {
+
+    public PaginationConfiguration(ApplicationContext context, ObjectFactory<ConversionService> conversionService) {
+        super(context, conversionService);
+    }
+
+    @Bean
+    @Override
+    public PageableHandlerMethodArgumentResolver pageableResolver() {
+        PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver = new PageableHandlerMethodArgumentResolver(sortResolver());
+        pageableHandlerMethodArgumentResolver.setMaxPageSize(Integer.MAX_VALUE);
+        return pageableHandlerMethodArgumentResolver;
+    }
+
+}

+ 46 - 0
src/main/java/com/zswl/dataservice/config/PostProcessorConfig.java

@@ -0,0 +1,46 @@
+package com.zswl.dataservice.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Slf4j
+//@Configuration
+public class PostProcessorConfig {
+
+//    @Bean
+//    public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
+//        return new BeanPostProcessor() {
+//            @Override
+//            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+//                if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
+//                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
+//                }
+//                return bean;
+//            }
+//
+//            private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
+//                List<T> copy = mappings.stream()
+//                        .filter(mapping -> mapping.getPatternParser() == null)
+//                        .collect(Collectors.toList());
+//                mappings.clear();
+//                mappings.addAll(copy);
+//            }
+//
+//            @SuppressWarnings("unchecked")
+//            private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
+//                try {
+//                    Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
+//                    field.setAccessible(true);
+//                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
+//                } catch (IllegalArgumentException | IllegalAccessException e) {
+//                    throw new IllegalStateException(e);
+//                }
+//            }
+//        };
+//    }
+
+}

+ 103 - 0
src/main/java/com/zswl/dataservice/config/RestExceptionHandler.java

@@ -0,0 +1,103 @@
+package com.zswl.dataservice.config;
+
+import com.zswl.dataservice.config.result.InvokerState;
+import com.zswl.dataservice.config.result.ResultException;
+import com.zswl.dataservice.type.ResultState;
+import com.zswl.dataservice.utils.result.ResultContent;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.lang.Nullable;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
+import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RestControllerAdvice
+@ResponseBody
+public class RestExceptionHandler extends DefaultHandlerExceptionResolver {
+
+    @ExceptionHandler(Exception.class)
+    @ResponseStatus(HttpStatus.OK)
+    public ResultContent<String> exception(Exception exception) {
+        String msg = exception.getMessage();
+        log.error("绑定异常信息 ex={}", exception.getMessage(), exception);
+        return ResultContent.buildFail(msg);
+    }
+
+    @ExceptionHandler(BindException.class)
+    @ResponseStatus(HttpStatus.OK)
+    public ResultContent<String> bindException(BindException exception) {
+        String msg = exception.getMessage();
+        try {
+            if (exception.getBindingResult() != null) {
+                List<ObjectError> list = exception.getBindingResult().getAllErrors();
+                if (ObjectUtils.isNotEmpty(list) && list.size() > 0) {
+                    ObjectError objectError = list.get(0);
+                    if (objectError instanceof FieldError) {
+                        FieldError fieldError = (FieldError) objectError;
+                        msg = String.format("【%s】 %s", fieldError.getField(), fieldError.getDefaultMessage());
+                    } else {
+                        msg = String.format("%s", objectError.getDefaultMessage());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        log.error("绑定异常信息 ex1={}", exception.getMessage(), exception);
+        return ResultContent.buildFail(msg);
+    }
+
+    @Override
+    protected ModelAndView handleBindException(
+            BindException ex,
+            HttpServletRequest request,
+            HttpServletResponse response, @Nullable Object handler) throws IOException {
+        ModelAndView mv = new ModelAndView();
+        mv.addObject("state", ResultState.Fail);
+        mv.addObject("success", false);
+        mv.addObject("failed", true);
+        mv.setView(new MappingJackson2JsonView());
+        List<String> errors = ex.getBindingResult().getAllErrors().stream().map(error -> error.getDefaultMessage()).collect(Collectors.toList());
+        mv.addObject("msg", String.join(",", errors));
+        return mv;
+    }
+
+    protected ModelAndView handleMissingServletRequestParameter(
+            MissingServletRequestParameterException ex,
+            HttpServletRequest request,
+            HttpServletResponse response,
+            @Nullable Object handler) throws IOException {
+
+        log.error("missing param exception,uri:{},url:{}", request.getRequestURI(), request.getRequestURL());
+        return super.handleMissingServletRequestParameter(ex, request, response, handler);
+    }
+
+
+//    @Override
+    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
+        e.printStackTrace();
+        log.error("exception : {}", e);
+        ModelAndView mv = new ModelAndView();
+        mv.addObject("state", InvokerState.Exception);
+        mv.setView(new MappingJackson2JsonView());
+        mv.addObject("exception", ResultException.build(e));
+        return mv;
+    }
+
+}

+ 41 - 0
src/main/java/com/zswl/dataservice/config/SwaggerConfig.java

@@ -0,0 +1,41 @@
+package com.zswl.dataservice.config;
+
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import io.swagger.v3.oas.models.ExternalDocumentation;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import lombok.extern.java.Log;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ *
+ */
+@Log
+@Configuration
+@EnableKnife4j
+public class SwaggerConfig {
+
+    @Value("${spring.application.name}")
+    private String applicationName;
+
+    @Bean
+    public OpenAPI springShopOpenAPI() {
+        return new OpenAPI()
+                // 接口文档标题
+                .info(new Info().title("物联网平台API接口文档")
+                        // 接口文档简介
+                        .description("物联网平台接口文档")
+                        // 接口文档版本
+                        .version("v1.0")
+                        // 开发者联系方式
+                        .contact(new Contact().url("").name("RTX").email("315146153@qq.com")))
+                .externalDocs(new ExternalDocumentation()
+                        .description("物联网平台")
+                        .url("http://127.0.0.1:8081"));
+
+    }
+
+}

+ 73 - 0
src/main/java/com/zswl/dataservice/config/SwaggerProperties.java

@@ -0,0 +1,73 @@
+package com.zswl.dataservice.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties("swagger")
+public class SwaggerProperties {
+    /**
+     * 是否开启swagger,生产环境一般关闭,所以这里定义一个变量
+     */
+    private Boolean enable;
+
+    /**
+     * 项目应用名
+     */
+    private String applicationName;
+
+    /**
+     * 项目版本信息
+     */
+    private String applicationVersion;
+
+    /**
+     * 项目描述信息
+     */
+    private String applicationDescription;
+
+    /**
+     * 接口调试地址
+     */
+    private String tryHost;
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public String getApplicationName() {
+        return applicationName;
+    }
+
+    public void setApplicationName(String applicationName) {
+        this.applicationName = applicationName;
+    }
+
+    public String getApplicationVersion() {
+        return applicationVersion;
+    }
+
+    public void setApplicationVersion(String applicationVersion) {
+        this.applicationVersion = applicationVersion;
+    }
+
+    public String getApplicationDescription() {
+        return applicationDescription;
+    }
+
+    public void setApplicationDescription(String applicationDescription) {
+        this.applicationDescription = applicationDescription;
+    }
+
+    public String getTryHost() {
+        return tryHost;
+    }
+
+    public void setTryHost(String tryHost) {
+        this.tryHost = tryHost;
+    }
+}

+ 28 - 0
src/main/java/com/zswl/dataservice/config/SystemDefaultConfig.java

@@ -0,0 +1,28 @@
+package com.zswl.dataservice.config;
+
+/**
+ * @author TRX
+ * @date 2024/4/7
+ */
+public class SystemDefaultConfig {
+    /**
+     * token过期时间 7天过期
+     */
+    public static final long tokenExecTime = 7 * 24 * 60 * 60 * 1000L;
+
+    /**
+     * 密码最大错误 3次, 超过会被锁定
+     */
+    public static final int maxPassWordErrorCount = 3;
+
+    /**
+     * 如果密码错误,,则锁定 10 分钟
+     */
+    public static final long loginLockTime = 10 * 60 * 1000L;
+
+    /**
+     * 默认密码
+     */
+    public static final String defaultPassWord = "123abc";
+
+}

+ 63 - 0
src/main/java/com/zswl/dataservice/config/WebMvcConfig.java

@@ -0,0 +1,63 @@
+package com.zswl.dataservice.config;
+
+import com.zswl.dataservice.auth.AuthSettings;
+import com.zswl.dataservice.auth.JWTManager;
+import com.zswl.dataservice.auth.UserContextInterceptor;
+import com.zswl.dataservice.service.RedisService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ReflectionUtils;
+import org.springframework.web.servlet.config.annotation.*;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+@Slf4j
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+    @Autowired
+    private AuthSettings authSettings;
+
+    @Autowired
+    private JWTManager jwtManager;
+
+    @Autowired
+    private RedisService redisService;
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+
+//        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
+//        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+
+    }
+
+    /**
+     * 请求拦截器
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(new UserContextInterceptor(authSettings, jwtManager, redisService));
+    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        log.info("addCorsMappings...");
+        registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
+//        registry.addMapping("/**")
+//                .allowedOriginPatterns("*")
+//                .allowCredentials(false)
+//                .allowedOrigins("*")
+//                .allowedHeaders("*")
+//                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+//                .maxAge(3600);
+    }
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/config/converts/BigDecimalToDecimal128Converter.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.config.converts;
+
+import org.bson.types.Decimal128;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+import org.springframework.data.convert.WritingConverter;
+
+import java.math.BigDecimal;
+
+@ReadingConverter
+@WritingConverter
+public class BigDecimalToDecimal128Converter implements Converter<BigDecimal, Decimal128> {
+
+    public Decimal128 convert(BigDecimal bigDecimal) {
+        return new Decimal128(bigDecimal);
+    }
+
+}

+ 20 - 0
src/main/java/com/zswl/dataservice/config/converts/Decimal128ToBigDecimalConverter.java

@@ -0,0 +1,20 @@
+package com.zswl.dataservice.config.converts;
+
+import org.bson.types.Decimal128;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+import org.springframework.data.convert.WritingConverter;
+
+import java.math.BigDecimal;
+
+@ReadingConverter
+@WritingConverter
+public class Decimal128ToBigDecimalConverter implements Converter<Decimal128, BigDecimal> {
+
+    public BigDecimal convert(Decimal128 decimal128) {
+        return decimal128.bigDecimalValue();
+    }
+
+
+
+}

+ 26 - 0
src/main/java/com/zswl/dataservice/config/result/InvokerExceptionResolver.java

@@ -0,0 +1,26 @@
+package com.zswl.dataservice.config.result;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
+
+/**
+ * 处理统一用的系统异常
+ */
+@Slf4j
+public class InvokerExceptionResolver implements HandlerExceptionResolver {
+
+    @Override
+    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
+        e.printStackTrace();
+        ModelAndView mv = new ModelAndView();
+        mv.addObject("state", InvokerState.Exception);
+        mv.setView(new MappingJackson2JsonView());
+        mv.addObject("exception", ResultException.build(e));
+        return mv;
+    }
+
+}

+ 81 - 0
src/main/java/com/zswl/dataservice/config/result/InvokerResult.java

@@ -0,0 +1,81 @@
+package com.zswl.dataservice.config.result;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+
+/**
+ * 调用结果
+ */
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class InvokerResult<T> implements Serializable {
+
+
+    //状态
+    private InvokerState state;
+
+    //内容
+    private T content;
+
+
+    /**
+     * 是否成功
+     *
+     * @param content
+     * @return
+     */
+    public static InvokerResult isTrue(Boolean content) {
+        return new InvokerResult(content ? InvokerState.Success : InvokerState.Error, content);
+    }
+
+
+    /**
+     * 设置对象不能为空,如果为空状态则为error
+     *
+     * @param content
+     * @return
+     */
+    public static InvokerResult notNull(Object content) {
+        return new InvokerResult(content == null ? InvokerState.Error : InvokerState.Success, content);
+    }
+
+
+    /**
+     * 实例化并设置当前状态为Success
+     *
+     * @return
+     */
+    public static InvokerResult success(Object content) {
+        return new InvokerResult(InvokerState.Success, content);
+    }
+
+    /**
+     * 错误
+     *
+     * @param content
+     * @return
+     */
+    public static InvokerResult error(Object content) {
+        return new InvokerResult(InvokerState.Error, content);
+    }
+
+    /**
+     * 异常
+     *
+     * @param content
+     * @return
+     */
+    public static InvokerResult exception(Object content) {
+        return new InvokerResult(InvokerState.Exception, content);
+    }
+
+
+}

+ 41 - 0
src/main/java/com/zswl/dataservice/config/result/InvokerState.java

@@ -0,0 +1,41 @@
+package com.zswl.dataservice.config.result;
+
+public enum InvokerState {
+
+    /**
+     * 成功
+     */
+    Success("成功"),
+
+    /**
+     * 失败
+     */
+    Error("失败"),
+
+
+    /**
+     * 异常情况
+     */
+    Exception("异常"),
+
+
+    /**
+     * 机器人验证
+     */
+    Robot("机器验证"),
+
+
+    ;
+
+
+    private String remark;
+
+
+    InvokerState(String remark) {
+        this.remark = remark;
+    }
+
+    public String getInfo() {
+        return remark;
+    }
+}

+ 33 - 0
src/main/java/com/zswl/dataservice/config/result/ResultException.java

@@ -0,0 +1,33 @@
+package com.zswl.dataservice.config.result;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 结果集异常
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ResultException {
+
+    private String type;
+    private String cls;
+    private String message;
+
+
+    /**
+     * 创建异常对象
+     *
+     * @param e
+     * @return
+     */
+    public static ResultException build(Exception e) {
+        ResultException exception = new ResultException();
+        exception.type = e.getClass().getSimpleName();
+        exception.cls = e.getClass().getName();
+        exception.message = e.getMessage();
+        return exception;
+    }
+}

+ 57 - 0
src/main/java/com/zswl/dataservice/config/result/ServiceResult.java

@@ -0,0 +1,57 @@
+package com.zswl.dataservice.config.result;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.BeanUtils;
+
+/**
+ * 业务结果集
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public abstract class ServiceResult {
+
+    /**
+     * 状态
+     */
+    private Object state;
+
+    /**
+     * 创建实例对象
+     *
+     * @param cls
+     * @param state
+     * @param <T>
+     * @return
+     */
+    public static <T> T build(Class<? extends T> cls, Object state) {
+        try {
+            ServiceResult serviceResult = (ServiceResult) cls.newInstance();
+            serviceResult.setState(state);
+            return (T) serviceResult;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 创建实例并复制
+     *
+     * @param cls
+     * @param state
+     * @param copySource
+     * @param <T>
+     * @return
+     */
+    public static <T> T build(Class<? extends T> cls, Object state, Object copySource) {
+        T t = build(cls, state);
+        BeanUtils.copyProperties(copySource, t);
+        return t;
+    }
+
+
+}

+ 21 - 0
src/main/java/com/zswl/dataservice/config/result/SuperEndpoints.java

@@ -0,0 +1,21 @@
+package com.zswl.dataservice.config.result;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 所有终端的父类
+ */
+@RequestMapping(SuperEndpoints.DefaultEndPointName)
+public abstract class SuperEndpoints {
+
+    /**
+     * 默认的端点名称
+     */
+    public final static  String DefaultEndPointName = "endpoints";
+
+
+
+
+
+}

+ 68 - 0
src/main/java/com/zswl/dataservice/controller/DeviceController.java

@@ -0,0 +1,68 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.TokenModel;
+import com.zswl.dataservice.model.mqtt.DeviceInfoAddParam;
+import com.zswl.dataservice.model.mqtt.DeviceInfoModel;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import com.zswl.dataservice.model.params.TokenParam;
+import com.zswl.dataservice.service.AppInfoService;
+import com.zswl.dataservice.service.mqtt.DeviceInfoService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 设备管理 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/device/free")
+@RestController
+@Validated
+@Tag(name = "设备管理")
+public class DeviceController {
+
+    @Autowired
+    DeviceInfoService deviceInfoService;
+
+    @Operation(summary = "添加设备")
+    @RequestMapping(value = "addDeviceInfo", method = {RequestMethod.POST})
+    public ResultContent addDeviceInfo(@RequestBody DeviceInfoAddParam param) {
+        Assert.hasText(param.getDeviceId(), "设备ID不能为空");
+        Assert.hasText(param.getDeviceName(), "设备名称不能为空");
+        return deviceInfoService.addDeviceInfo(param);
+    }
+
+    @Operation(summary = "设备列表-分页查询")
+    @RequestMapping(value = {"pageActivity"}, method = {RequestMethod.POST})
+    public ResultContent<Page<DeviceInfoModel>> pageActivity(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, @Parameter(required = false) DeviceInfoSearchParam param) {
+        return deviceInfoService.pageDevice(pageable, param);
+    }
+
+    @Operation(summary = "删除设备")
+    @RequestMapping(value = "deleteDeviceInfo", method = {RequestMethod.GET})
+    public ResultContent deleteDeviceInfo(String deviceId) {
+        return deviceInfoService.deleteDeviceInfo(deviceId);
+    }
+
+    @Operation(summary = "查询设备")
+    @RequestMapping(value = "getDeviceById", method = {RequestMethod.GET})
+    public ResultContent<DeviceInfoModel> getDeviceById(String deviceId) {
+        return deviceInfoService.getDeviceById(deviceId);
+    }
+}

+ 69 - 0
src/main/java/com/zswl/dataservice/controller/GateWayController.java

@@ -0,0 +1,69 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.mqtt.*;
+import com.zswl.dataservice.service.mqtt.GateWayInfoService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 网关管理 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/gateWay/free")
+@RestController
+@Validated
+@Tag(name = "网关管理")
+public class GateWayController {
+
+    @Autowired
+    GateWayInfoService gateWayInfoService;
+
+    @Operation(summary = "添加网关")
+    @RequestMapping(value = "addDeviceInfo", method = {RequestMethod.POST})
+    public ResultContent addDeviceInfo(@RequestBody GateWayInfoAddParam param) {
+        Assert.hasText(param.getGateWayId(), "网关ID不能为空");
+        Assert.hasText(param.getGateWayName(), "网关名称不能为空");
+        return gateWayInfoService.addGateWayInfo(param);
+    }
+
+    @Operation(summary = "网关列表-分页查询")
+    @RequestMapping(value = {"pageGateWay"}, method = {RequestMethod.POST})
+    public ResultContent<Page<GateWayInfoModel>> pageGateWay(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, GateWayInfoSearchParam param) {
+        return gateWayInfoService.pageGateWay(pageable, param);
+    }
+
+    @Operation(summary = "删除网关")
+    @RequestMapping(value = "deleteGateWayInfo", method = {RequestMethod.GET})
+    public ResultContent deleteGateWayInfo(String gateWayId) {
+        return gateWayInfoService.deleteGateWayInfo(gateWayId);
+    }
+
+    @Operation(summary = "查询网关")
+    @RequestMapping(value = "getGateWayById", method = {RequestMethod.GET})
+    public ResultContent<GateWayInfoModel> getGateWayById(String deviceId) {
+        return gateWayInfoService.getById(deviceId);
+    }
+
+
+    @Operation(summary = "网关绑定设备、连接账号")
+    @RequestMapping(value = "gateWayBindDevice", method = {RequestMethod.POST})
+    public ResultContent gateWayBindDevice(@RequestBody GateWayBindDeviceParam param) {
+        Assert.hasText(param.getGateWayId(), "网关ID不能为空");
+        Assert.hasText(param.getUserName(), "连接账号不能为空");
+        return gateWayInfoService.gateWayBindDevice(param);
+    }
+}

+ 71 - 0
src/main/java/com/zswl/dataservice/controller/GateWayUserInfoController.java

@@ -0,0 +1,71 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.mqtt.*;
+import com.zswl.dataservice.service.mqtt.DeviceInfoService;
+import com.zswl.dataservice.service.mqtt.GateWayUserInfoService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 连接用户管理 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/gateWayUserInfo/free")
+@RestController
+@Validated
+@Tag(name = "连接用户管理")
+public class GateWayUserInfoController {
+
+    @Autowired
+    GateWayUserInfoService gateWayUserInfoService;
+
+    @Operation(summary = "添加连接用户")
+    @RequestMapping(value = "addDeviceInfo", method = {RequestMethod.POST})
+    public ResultContent addDeviceInfo(@RequestBody GateWayUserInfoAddParam param) {
+        Assert.hasText(param.getUserName(), "连接账号不能为空");
+        Assert.hasText(param.getPassWord(), "连接密码不能为空");
+        return gateWayUserInfoService.addGateWayUser(param);
+    }
+
+    @Operation(summary = "连接用户列表-分页查询")
+    @RequestMapping(value = {"pageGateWayUser"}, method = {RequestMethod.POST})
+    public ResultContent<Page<GateWayUserInfoModel>> pageGateWayUser(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10, sort = "") Pageable pageable, @Parameter(required = false) GateWayUserInfoSearchParam param) {
+        return gateWayUserInfoService.pageGateWayUser(pageable, param);
+    }
+
+    @Operation(summary = "删除连接用户")
+    @RequestMapping(value = "deleteMqttUser", method = {RequestMethod.POST})
+    public ResultContent deleteMqttUser(GateWayUserInfoNameParam param) {
+        Assert.hasText(param.getUserName(), "连接账号不能为空");
+        return gateWayUserInfoService.deleteMqttUser(param);
+    }
+
+    @Operation(summary = "启动-停用连接账号")
+    @RequestMapping(value = "updateState", method = {RequestMethod.POST})
+    public ResultContent updateState(GateWayUserInfoNameParam param) {
+        Assert.hasText(param.getUserName(), "连接账号不能为空");
+        return gateWayUserInfoService.updateState(param);
+    }
+
+    @Operation(summary = "查询连接账号")
+    @RequestMapping(value = "getUserByUserName", method = {RequestMethod.POST})
+    public ResultContent<GateWayUserInfoModel> getUserByUserName(GateWayUserInfoNameParam param) {
+        Assert.hasText(param.getUserName(), "连接账号不能为空");
+        return gateWayUserInfoService.getUserByUserName(param.getUserName());
+    }
+
+}

+ 67 - 0
src/main/java/com/zswl/dataservice/controller/MqttInfoController.java

@@ -0,0 +1,67 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.mqtt.*;
+import com.zswl.dataservice.service.mqtt.DeviceInfoService;
+import com.zswl.dataservice.service.mqtt.MqttInfoService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * mqtt连接地址管理 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/mqttInfo/free")
+@RestController
+@Validated
+@Tag(name = "MQTT连接地址管理")
+public class MqttInfoController {
+
+    @Autowired
+    MqttInfoService mqttInfoService;
+
+    @Operation(summary = "添加地址")
+    @RequestMapping(value = "addMqttInfo", method = {RequestMethod.POST})
+    public ResultContent addMqttInfo(@RequestBody MqttInfoAddParam param) {
+        return mqttInfoService.addMqttInfo(param);
+    }
+
+    @Operation(summary = "所有地址列表")
+    @RequestMapping(value = {"findAllMqttInfo"}, method = {RequestMethod.POST})
+    public ResultContent<List<MqttInfoModel>> findAllMqttInfo() {
+        return mqttInfoService.findAllMqttInfo();
+    }
+
+    @Operation(summary = "所有地址列表(简单信息)")
+    @RequestMapping(value = {"findAllMqttInfoSimple"}, method = {RequestMethod.POST})
+    public ResultContent<List<MqttInfoSimpleModel>> findAllMqttInfoSimple() {
+        return mqttInfoService.findAllMqttInfoSimple();
+    }
+
+    @Operation(summary = "删除地址")
+    @RequestMapping(value = "deleteMqttInfo", method = {RequestMethod.GET})
+    public ResultContent deleteMqttInfo(String id) {
+        return mqttInfoService.deleteMqttInfo(id);
+    }
+
+    @Operation(summary = "查询地址详情")
+    @RequestMapping(value = "getMqttInfoById", method = {RequestMethod.GET})
+    public ResultContent<MqttInfoModel> getMqttInfoById(String id) {
+        return mqttInfoService.getMqttInfoById(id);
+    }
+}

+ 56 - 0
src/main/java/com/zswl/dataservice/controller/OauthController.java

@@ -0,0 +1,56 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.TokenModel;
+import com.zswl.dataservice.model.params.LoginModel;
+import com.zswl.dataservice.model.params.TokenParam;
+import com.zswl.dataservice.service.AppInfoService;
+import com.zswl.dataservice.service.AuthService;
+import com.zswl.dataservice.service.UserService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 访问令牌 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/oauth")
+@RestController
+@Validated
+public class OauthController {
+
+    @Autowired
+    AuthService authService;
+
+    @Autowired
+    UserService userService;
+
+    @Operation(summary = "初始管理员账号")
+    @RequestMapping(value = "free/initAdmin", method = {RequestMethod.GET})
+    public ResultContent initAdmin() {
+        return userService.initAdmin();
+    }
+
+    @Operation(summary = "创建Token,需要提供登录名和密码!")
+    @RequestMapping(value = "/free/token", method = {RequestMethod.POST})
+    public ResultContent createToken(LoginModel data) {
+        if (StringUtils.isEmpty(data.getLoginName())) {
+            return ResultContent.buildFail("登录名不能为空");
+        }
+        if (StringUtils.isEmpty(data.getPassWord())) {
+            return ResultContent.buildFail("密码名不能为空");
+        }
+        return authService.createToken(data);
+    }
+
+}

+ 40 - 0
src/main/java/com/zswl/dataservice/controller/OperationLogsController.java

@@ -0,0 +1,40 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.operLogs.OperationLogsModel;
+import com.zswl.dataservice.model.operLogs.OperationLogsSearchParam;
+import com.zswl.dataservice.service.mqtt.OperationLogsService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 日志管理 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/operationLogs/free")
+@RestController
+@Validated
+@Tag(name = "日志管理")
+public class OperationLogsController {
+
+    @Autowired
+    OperationLogsService operationLogsService;
+
+    @Operation(summary = "设备列表-分页查询")
+    @RequestMapping(value = {"page"}, method = {RequestMethod.POST})
+    public ResultContent<Page<OperationLogsModel>> page(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable,
+            @Parameter(required = false) OperationLogsSearchParam param) {
+        return operationLogsService.pageLogs(pageable, param);
+    }
+}

+ 51 - 0
src/main/java/com/zswl/dataservice/controller/OperationMessageController.java

@@ -0,0 +1,51 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.mqtt.*;
+import com.zswl.dataservice.service.mqtt.DeviceInfoService;
+import com.zswl.dataservice.service.mqtt.OperationMessageService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 指令信息 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/operationMessage/free")
+@RestController
+@Validated
+@Tag(name = "指令信息管理")
+public class OperationMessageController {
+
+    @Autowired
+    DeviceInfoService deviceInfoService;
+
+    @Autowired
+    OperationMessageService operationMessageService;
+
+    @Operation(summary = "标准指令已响应")
+    @RequestMapping(value = "receiveMessage", method = {RequestMethod.GET})
+    @Parameter(name = "messageId", description = "指令ID")
+    public ResultContent receiveMessage(String messageId) {
+        return operationMessageService.receiveMessage(messageId);
+    }
+
+    @Operation(summary = "指令列表-分页查询")
+    @RequestMapping(value = {"page"}, method = {RequestMethod.POST})
+    public ResultContent<Page<OperationMessageModel>> page(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, @Parameter(required = false) OperationMessageSearchParam param) {
+        return operationMessageService.page(pageable, param);
+    }
+}

+ 61 - 0
src/main/java/com/zswl/dataservice/controller/ProjectInfoController.java

@@ -0,0 +1,61 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.mqtt.*;
+import com.zswl.dataservice.service.mqtt.DeviceInfoService;
+import com.zswl.dataservice.service.mqtt.ProjectInfoService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.http.MediaType;
+import org.springframework.util.Assert;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 项目 服务
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@RequestMapping("/project/free")
+@RestController
+@Validated
+@Tag(name = "项目管理")
+public class ProjectInfoController {
+
+    @Autowired
+    DeviceInfoService deviceInfoService;
+
+    @Autowired
+    ProjectInfoService projectInfoService;
+
+    @Operation(summary = "添加-编辑项目")
+    @RequestMapping(value = "addProjectInfo", method = {RequestMethod.POST})
+    public ResultContent addProjectInfo(@RequestBody ProjectInfoAddParam param) {
+        return projectInfoService.addProjectInfo(param);
+    }
+
+    @Operation(summary = "项目列表-分页查询")
+    @RequestMapping(value = {"pageProject"}, method = {RequestMethod.POST})
+    public ResultContent<Page<ProjectInfoModel>> pageProject(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, ProjectInfoSearchParam param) {
+        return projectInfoService.page(pageable, param);
+    }
+
+    @Operation(summary = "删除项目")
+    @RequestMapping(value = "deleteProjectInfo", method = {RequestMethod.GET})
+    public ResultContent deleteProjectInfo(String id) {
+        return projectInfoService.deleteProjectInfo(id);
+    }
+
+    @Operation(summary = "查询项目详情")
+    @RequestMapping(value = "getProjectInfo", method = {RequestMethod.GET})
+    @Parameter(name = "id", description = "数据ID")
+    public ResultContent<ProjectInfoModel> getProjectInfo(String id) {
+        return projectInfoService.getProjectInfo(id);
+    }
+}

+ 47 - 0
src/main/java/com/zswl/dataservice/controller/TestController.java

@@ -0,0 +1,47 @@
+package com.zswl.dataservice.controller;
+
+import com.zswl.dataservice.model.mqtt.SendMessageModel;
+import com.zswl.dataservice.service.UserService;
+import com.zswl.dataservice.utils.result.ResultContent;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+@RequestMapping("/test")
+@RestController
+@Validated
+@Tag(name = "测试接口")
+public class TestController {
+
+    @Autowired
+    UserService userService;
+
+    @Operation(summary = "测试添加用户接口")
+    @RequestMapping(value = "free/test", method = {RequestMethod.GET})
+    public ResultContent test(@Parameter(name = "name", description = "名称") String name) {
+        Map map = new HashMap();
+        map.put("obj", name);
+        map.put("time", System.currentTimeMillis());
+        return userService.addUser(name);
+    }
+
+    @Operation(summary = "发送指令")
+    @RequestMapping(value = "free/sendMessage", method = {RequestMethod.POST})
+    public ResultContent sendMessage(@RequestBody SendMessageModel param) {
+        return userService.sendMessage(param);
+    }
+
+}
+

+ 18 - 0
src/main/java/com/zswl/dataservice/dao/AppInfoDao.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.dao;
+
+import com.zswl.dataservice.domain.AppInfo;
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.domain.User;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface AppInfoDao extends MongoDao<AppInfo> {
+
+    AppInfo findTopByEntIdAndAppSecret(String entId, String appSecret);
+
+}

+ 12 - 0
src/main/java/com/zswl/dataservice/dao/MongoDao.java

@@ -0,0 +1,12 @@
+package com.zswl.dataservice.dao;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+/**
+ * Mongodb的一些通用方法
+ */
+public interface MongoDao<T extends SuperEntity> extends MongoRepository<T, String> {
+
+
+}

+ 8 - 0
src/main/java/com/zswl/dataservice/dao/TokenLoginDao.java

@@ -0,0 +1,8 @@
+package com.zswl.dataservice.dao;
+
+import com.zswl.dataservice.domain.TokenLogin;
+import com.zswl.dataservice.domain.User;
+
+public interface TokenLoginDao extends MongoDao<TokenLogin> {
+    TokenLogin findTopByUser(User user);
+}

+ 14 - 0
src/main/java/com/zswl/dataservice/dao/UserDao.java

@@ -0,0 +1,14 @@
+package com.zswl.dataservice.dao;
+
+import com.zswl.dataservice.dao.extend.UserDaoExtend;
+import com.zswl.dataservice.domain.User;
+
+import java.util.List;
+
+public interface UserDao extends MongoDao<User>, UserDaoExtend {
+
+    User findByLoginName(String loginName);
+
+    User findTopById(String id);
+
+}

+ 15 - 0
src/main/java/com/zswl/dataservice/dao/extend/UserDaoExtend.java

@@ -0,0 +1,15 @@
+package com.zswl.dataservice.dao.extend;
+
+import com.zswl.dataservice.domain.User;
+import com.zswl.dataservice.model.user.UserSearchParams;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface UserDaoExtend {
+    Page<User> page(Pageable pageable, UserSearchParams param);
+}

+ 73 - 0
src/main/java/com/zswl/dataservice/dao/impl/UserDaoImpl.java

@@ -0,0 +1,73 @@
+package com.zswl.dataservice.dao.impl;
+
+import com.zswl.dataservice.dao.extend.UserDaoExtend;
+import com.zswl.dataservice.domain.User;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.user.UserSearchParams;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/6
+ * @Version: 1.0
+ */
+public class UserDaoImpl implements UserDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<User> page(Pageable pageable, UserSearchParams param) {
+        Criteria criteria = new Criteria();
+
+        if (param.getUserType() != null) {
+            criteria.and("userType").is(param.getUserType());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getLoginName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getLoginName() + ".*$");
+            criterias.add(Criteria.where("loginName").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getUserName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getUserName() + ".*$");
+            criterias.add(Criteria.where("userName").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getPhone())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getPhone() + ".*$");
+            criterias.add(Criteria.where("phone").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        criteria.and("loginName").ne("admin");
+        criteria.and("isDelete").ne(Boolean.TRUE);
+
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, User.class);
+    }
+
+}

+ 17 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/DeviceInfoDao.java

@@ -0,0 +1,17 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.domain.AppInfo;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface DeviceInfoDao extends MongoDao<DeviceInfo>, DeviceInfoDaoExtend {
+
+    DeviceInfo findTopById(String id);
+
+    DeviceInfo findTopByDeviceId(String deviceId);
+}

+ 13 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/GateWay2DeviceDao.java

@@ -0,0 +1,13 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.domain.mqtt.*;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface GateWay2DeviceDao extends MongoDao<GateWay2Device> {
+
+    GateWay2Device findTopByGateWayInfoAndDeviceInfo(GateWayInfo gateWayInfo, DeviceInfo deviceInfo);
+}

+ 16 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/GateWay2UserDao.java

@@ -0,0 +1,16 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.GateWay2User;
+import com.zswl.dataservice.domain.mqtt.GateWayUserInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface GateWay2UserDao extends MongoDao<GateWay2User> {
+
+    GateWay2User findTopByGateWayUserInfo(GateWayUserInfo gateWayUserInfo);
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/GateWayInfoDao.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.GateWayInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.GateWayInfo;
+import com.zswl.dataservice.domain.mqtt.GateWayUserInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface GateWayInfoDao extends MongoDao<GateWayInfo>, GateWayInfoDaoExtend {
+
+    GateWayInfo findTopById(String id);
+
+    GateWayInfo findTopByGateWayId(String gateWayId);
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/GateWayUserInfoDao.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.GateWayUserInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.GateWayUserInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface GateWayUserInfoDao extends MongoDao<GateWayUserInfo>, GateWayUserInfoDaoExtend {
+
+    GateWayUserInfo findTopById(String id);
+
+    GateWayUserInfo findTopByUserName(String userName);
+}

+ 25 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/Mqtt2UserDao.java

@@ -0,0 +1,25 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.domain.mqtt.GateWayUserInfo;
+import com.zswl.dataservice.domain.mqtt.Mqtt2User;
+import com.zswl.dataservice.domain.mqtt.MqttInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface Mqtt2UserDao extends MongoDao<Mqtt2User> {
+
+    Mqtt2User findTopByMqttInfoAndGateWayUserInfo(MqttInfo mqttInfo, GateWayUserInfo gateWayUserInfo);
+
+    /**
+     * 删除网关和角色的关系
+     *
+     * @param mqttInfo
+     * @param gateWayUserInfo
+     */
+    void deleteByMqttInfoAndGateWayUserInfo(MqttInfo mqttInfo, GateWayUserInfo gateWayUserInfo);
+
+    void deleteByMqttInfo(MqttInfo mqttInfo);
+}

+ 16 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/MqttInfoDao.java

@@ -0,0 +1,16 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.MqttInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface MqttInfoDao extends MongoDao<MqttInfo> {
+    MqttInfo findTopByBrokerHost(String brokerHost);
+
+    MqttInfo findTopById(String id);
+}

+ 17 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/OperationLogsDao.java

@@ -0,0 +1,17 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.OperationLogsDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.OperationLogs;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface OperationLogsDao extends MongoDao<OperationLogs>, OperationLogsDaoExtend {
+
+    OperationLogs findTopById(String id);
+
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/OperationMessageDao.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.OperationMessageDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.OperationMessage;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface OperationMessageDao extends MongoDao<OperationMessage>, OperationMessageDaoExtend {
+
+    OperationMessage findTopByMessageId(String messageId);
+
+    OperationMessage findTopById(String id);
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/ProjectInfoDao.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.dao.mqtt;
+
+import com.zswl.dataservice.dao.MongoDao;
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.ProjectInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.ProjectInfo;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+public interface ProjectInfoDao extends MongoDao<ProjectInfo>, ProjectInfoDaoExtend {
+
+    ProjectInfo findTopById(String id);
+
+    ProjectInfo findTopByCode(String code);
+}

+ 15 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/extend/DeviceInfoDaoExtend.java

@@ -0,0 +1,15 @@
+package com.zswl.dataservice.dao.mqtt.extend;
+
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface DeviceInfoDaoExtend {
+    Page<DeviceInfo> page(Pageable pageable, DeviceInfoSearchParam param);
+}

+ 15 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/extend/GateWayInfoDaoExtend.java

@@ -0,0 +1,15 @@
+package com.zswl.dataservice.dao.mqtt.extend;
+
+import com.zswl.dataservice.domain.mqtt.GateWayInfo;
+import com.zswl.dataservice.model.mqtt.GateWayInfoSearchParam;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface GateWayInfoDaoExtend {
+    Page<GateWayInfo> page(Pageable pageable, GateWayInfoSearchParam param);
+}

+ 15 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/extend/GateWayUserInfoDaoExtend.java

@@ -0,0 +1,15 @@
+package com.zswl.dataservice.dao.mqtt.extend;
+
+import com.zswl.dataservice.domain.mqtt.GateWayUserInfo;
+import com.zswl.dataservice.model.mqtt.GateWayUserInfoSearchParam;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface GateWayUserInfoDaoExtend {
+    Page<GateWayUserInfo> page(Pageable pageable, GateWayUserInfoSearchParam param);
+}

+ 15 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/extend/OperationLogsDaoExtend.java

@@ -0,0 +1,15 @@
+package com.zswl.dataservice.dao.mqtt.extend;
+
+import com.zswl.dataservice.domain.mqtt.OperationLogs;
+import com.zswl.dataservice.model.operLogs.OperationLogsSearchParam;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface OperationLogsDaoExtend {
+    Page<OperationLogs> page(Pageable pageable, OperationLogsSearchParam param);
+}

+ 17 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/extend/OperationMessageDaoExtend.java

@@ -0,0 +1,17 @@
+package com.zswl.dataservice.dao.mqtt.extend;
+
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.OperationMessage;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import com.zswl.dataservice.model.mqtt.OperationMessageSearchParam;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface OperationMessageDaoExtend {
+    Page<OperationMessage> page(Pageable pageable, OperationMessageSearchParam param);
+}

+ 17 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/extend/ProjectInfoDaoExtend.java

@@ -0,0 +1,17 @@
+package com.zswl.dataservice.dao.mqtt.extend;
+
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.ProjectInfo;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import com.zswl.dataservice.model.mqtt.ProjectInfoSearchParam;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/7/7
+ * @Version: 1.0
+ */
+public interface ProjectInfoDaoExtend {
+    Page<ProjectInfo> page(Pageable pageable, ProjectInfoSearchParam param);
+}

+ 74 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/impl/DeviceInfoDaoImpl.java

@@ -0,0 +1,74 @@
+package com.zswl.dataservice.dao.mqtt.impl;
+
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class DeviceInfoDaoImpl implements DeviceInfoDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<DeviceInfo> page(Pageable pageable, DeviceInfoSearchParam param) {
+        Criteria criteria = new Criteria();
+
+        if (StringUtils.isNotEmpty(param.getDeviceId())) {
+            criteria.and("deviceId").is(param.getDeviceId());
+        }
+
+        if (StringUtils.isNotEmpty(param.getEpId())) {
+            criteria.and("epId").is(param.getEpId());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getDeviceName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getDeviceName() + ".*$");
+            criterias.add(Criteria.where("deviceName").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+//        if (StringUtils.isNotEmpty(param.getTitle())) {
+//            Pattern pattern = Pattern.compile("^.*" + param.getTitle() + ".*$");
+//            criteria.orOperator(
+//                    Criteria.where("name").regex(pattern),
+//                    Criteria.where("content").regex(pattern)
+//            );
+//        }
+
+        criteria.and("isDelete").is(Boolean.FALSE);
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, DeviceInfo.class);
+    }
+
+}

+ 67 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/impl/GateWayInfoDaoImpl.java

@@ -0,0 +1,67 @@
+package com.zswl.dataservice.dao.mqtt.impl;
+
+import com.zswl.dataservice.dao.mqtt.extend.GateWayInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.GateWayInfo;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.mqtt.GateWayInfoSearchParam;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class GateWayInfoDaoImpl implements GateWayInfoDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<GateWayInfo> page(Pageable pageable, GateWayInfoSearchParam param) {
+        Criteria criteria = new Criteria();
+
+        if (StringUtils.isNotEmpty(param.getGateWayId())) {
+            criteria.and("gateWayId").is(param.getGateWayId());
+        }
+
+        if (StringUtils.isNotEmpty(param.getEpId())) {
+            criteria.and("epId").is(param.getEpId());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getGateWayName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getGateWayName() + ".*$");
+            criterias.add(Criteria.where("gateWayName").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        criteria.and("isDelete").is(Boolean.FALSE);
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, GateWayInfo.class);
+    }
+
+}

+ 74 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/impl/GateWayUserInfoDaoImpl.java

@@ -0,0 +1,74 @@
+package com.zswl.dataservice.dao.mqtt.impl;
+
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.GateWayUserInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.GateWayUserInfo;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import com.zswl.dataservice.model.mqtt.GateWayUserInfoSearchParam;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class GateWayUserInfoDaoImpl implements GateWayUserInfoDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<GateWayUserInfo> page(Pageable pageable, GateWayUserInfoSearchParam param) {
+        Criteria criteria = new Criteria();
+
+        if (StringUtils.isNotEmpty(param.getId())) {
+            criteria.and("id").is(param.getId());
+        }
+
+        if (param.getState() != null) {
+            criteria.and("state").is(param.getState());
+        }
+
+        if (StringUtils.isNotEmpty(param.getEpId())) {
+            criteria.and("epId").is(param.getEpId());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getUserName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getUserName() + ".*$");
+            criterias.add(Criteria.where("userName").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        criteria.and("isDelete").is(Boolean.FALSE);
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, GateWayUserInfo.class);
+    }
+
+}

+ 75 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/impl/OperationLogsDaoImpl.java

@@ -0,0 +1,75 @@
+package com.zswl.dataservice.dao.mqtt.impl;
+
+import com.zswl.dataservice.dao.mqtt.extend.OperationLogsDaoExtend;
+import com.zswl.dataservice.domain.mqtt.OperationLogs;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.operLogs.OperationLogsSearchParam;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class OperationLogsDaoImpl implements OperationLogsDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<OperationLogs> page(Pageable pageable, OperationLogsSearchParam param) {
+        Criteria criteria = new Criteria();
+
+        if (StringUtils.isNotEmpty(param.getUid())) {
+            criteria.and("uid").is(param.getUid());
+        }
+
+        if (StringUtils.isNotEmpty(param.getEpId())) {
+            criteria.and("epId").is(param.getEpId());
+        }
+
+        if (param.getLevel() != null) {
+            criteria.and("level").is(param.getLevel());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getContent())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getContent() + ".*$");
+            criterias.add(Criteria.where("content").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getIp())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getIp() + ".*$");
+            criterias.add(Criteria.where("ip").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        criteria.and("isDelete").is(Boolean.FALSE);
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, OperationLogs.class);
+    }
+
+}

+ 84 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/impl/OperationMessageDaoImpl.java

@@ -0,0 +1,84 @@
+package com.zswl.dataservice.dao.mqtt.impl;
+
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.OperationMessageDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.OperationMessage;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import com.zswl.dataservice.model.mqtt.OperationMessageSearchParam;
+import com.zswl.dataservice.utils.CommonUtil;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class OperationMessageDaoImpl implements OperationMessageDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<OperationMessage> page(Pageable pageable, OperationMessageSearchParam param) {
+        Criteria criteria = new Criteria();
+
+        if (StringUtils.isNotEmpty(param.getDeviceId())) {
+            criteria.and("deviceId").is(param.getDeviceId());
+        }
+
+        if (StringUtils.isNotEmpty(param.getEpId())) {
+            criteria.and("epId").is(param.getEpId());
+        }
+
+        if (StringUtils.isNotEmpty(param.getGateWayId())) {
+            criteria.and("gateWayId").is(param.getGateWayId());
+        }
+
+        if (param.getIsReceive() != null && param.getIsReceive()) {
+            criteria.and("isReceive").is(param.getIsReceive());
+        }
+
+        // 时间范围
+        if (!CommonUtil.longIsEmpty(param.getStartTime()) && !CommonUtil.longIsEmpty(param.getEndTime())) {
+            criteria.and("createTime").gte(param.getStartTime()).lte(param.getEndTime());
+        }
+
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getTopic())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getTopic() + ".*$");
+            criterias.add(Criteria.where("topic").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        criteria.and("isDelete").is(Boolean.FALSE);
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, OperationMessage.class);
+    }
+
+}

+ 70 - 0
src/main/java/com/zswl/dataservice/dao/mqtt/impl/ProjectInfoDaoImpl.java

@@ -0,0 +1,70 @@
+package com.zswl.dataservice.dao.mqtt.impl;
+
+import com.zswl.dataservice.dao.mqtt.extend.DeviceInfoDaoExtend;
+import com.zswl.dataservice.dao.mqtt.extend.ProjectInfoDaoExtend;
+import com.zswl.dataservice.domain.mqtt.DeviceInfo;
+import com.zswl.dataservice.domain.mqtt.ProjectInfo;
+import com.zswl.dataservice.helper.DBHelper;
+import com.zswl.dataservice.model.mqtt.DeviceInfoSearchParam;
+import com.zswl.dataservice.model.mqtt.ProjectInfoSearchParam;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @Author TRX
+ * @CreateDate: 2023/4/12
+ * @Version: 1.0
+ */
+public class ProjectInfoDaoImpl implements ProjectInfoDaoExtend {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    @Override
+    public Page<ProjectInfo> page(Pageable pageable, ProjectInfoSearchParam param) {
+        Criteria criteria = new Criteria();
+
+        if (param.getState() != null) {
+            criteria.and("state").is(param.getState());
+        }
+        
+        // 模糊搜索
+        List<Criteria> criterias = new ArrayList<>();
+        if (StringUtils.isNotEmpty(param.getName())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getName() + ".*$");
+            criterias.add(Criteria.where("name").is(pattern));
+        }
+        if (StringUtils.isNotEmpty(param.getCode())) {
+            Pattern pattern = Pattern.compile("^.*" + param.getCode() + ".*$");
+            criterias.add(Criteria.where("code").is(pattern));
+        }
+        if (!CollectionUtils.isEmpty(criterias)) {
+            criteria.andOperator(criterias.toArray(new Criteria[]{}));
+        }
+
+        criteria.and("isDelete").is(Boolean.FALSE);
+        Sort sort = param.getSort();
+        if (ObjectUtils.isEmpty(sort)) {
+            sort = Sort.by(Sort.Order.desc("createTime"));
+        }
+        Query query = Query.query(criteria);
+        query.with(sort);
+        return dbHelper.pages(query, pageable, ProjectInfo.class);
+    }
+
+}

+ 36 - 0
src/main/java/com/zswl/dataservice/domain/AppInfo.java

@@ -0,0 +1,36 @@
+package com.zswl.dataservice.domain;
+
+import com.zswl.dataservice.type.AppState;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 用户认证账户信息
+ *
+ * @author TRX
+ * @date 2024/3/21
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class AppInfo extends SuperEntity {
+    /**
+     * 渠道ID
+     */
+    private String entId;
+    /**
+     * appSecret
+     */
+    private String appSecret;
+    /**
+     * 应用ID
+     */
+    private String appId;
+    /**
+     * 账户状态
+     */
+    private AppState appState;
+}

+ 50 - 0
src/main/java/com/zswl/dataservice/domain/SuperEntity.java

@@ -0,0 +1,50 @@
+package com.zswl.dataservice.domain;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.MappedSuperclass;
+import lombok.Data;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.AbstractPersistable;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import org.springframework.data.mongodb.core.index.Indexed;
+
+import java.io.Serializable;
+
+@Data
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+public abstract class SuperEntity extends AbstractPersistable<String> implements Serializable {
+
+
+    @Id
+    private String id;
+
+    /**
+     * 创建时间
+     */
+
+    @Indexed
+    @CreatedDate
+    private Long createTime;
+
+    /**
+     * 修改时间
+     */
+    @Indexed
+    @LastModifiedDate
+    private Long updateTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    @Schema(name = "isDelete", description = "是否删除")
+    private Boolean isDelete = Boolean.FALSE;
+
+    @Schema(description = "所属项目ID")
+    private String epId;
+}

+ 40 - 0
src/main/java/com/zswl/dataservice/domain/TokenLogin.java

@@ -0,0 +1,40 @@
+package com.zswl.dataservice.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.util.Date;
+
+/**
+ * 令牌登陆
+ */
+@Data
+@Builder
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class TokenLogin extends SuperEntity {
+
+    //用户
+    @Indexed
+    @DBRef(lazy = true)
+    private User user;
+
+    private String loginName;
+
+    private String userName;
+
+    //现在的校验次数
+    @Indexed
+    private int errorCount;
+
+    //过期时间
+    @Indexed(expireAfterSeconds = 0)
+    private Date TTL;
+
+}

+ 63 - 0
src/main/java/com/zswl/dataservice/domain/User.java

@@ -0,0 +1,63 @@
+package com.zswl.dataservice.domain;
+
+import com.zswl.dataservice.type.UserState;
+import com.zswl.dataservice.type.UserType;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * @author TRX
+ * @date 2024/3/20
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class User extends SuperEntity {
+    /**
+     * 登录名
+     */
+    @Indexed
+    private String loginName;
+    /**
+     * 用户名
+     */
+    private String userName;
+
+    /**
+     * 头像
+     */
+    private String headUrl;
+
+    /**
+     * 密码
+     */
+    private String passWord;
+
+    /**
+     * 电话号码
+     */
+    private String phone;
+
+    /**
+     * 是否是超级管理员
+     */
+    private Boolean isAdmin;
+
+    /**
+     * 用户类型:
+     */
+    private UserType userType;
+
+    /**
+     * 用户状态:是否可用
+     */
+    private UserState userState;
+
+    @Schema(description = "最后登录时间")
+    private Long lastLoginTime;
+}

+ 28 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/DeviceInfo.java

@@ -0,0 +1,28 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 物联网设备信息
+ *
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class DeviceInfo extends SuperEntity {
+
+    @Schema(description = "设备ID")
+    private String deviceId;
+
+    @Schema(description = "设备名称")
+    private String deviceName;
+
+}

+ 36 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/GateWay2Device.java

@@ -0,0 +1,36 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.mqtt.type.OnLineState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 网关和设备的绑定关系 可能一个设备绑定多个网关 一个网关多个设备 (多对多的关系)
+ *
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class GateWay2Device extends SuperEntity {
+
+    @DBRef(lazy = true)
+    @Schema(description = "硬件设备网关信息")
+    private GateWayInfo gateWayInfo;
+
+    @DBRef(lazy = true)
+    @Schema(description = "关联的设备信息")
+    private DeviceInfo deviceInfo;
+
+    @Schema(description = "设备在线状态")
+    OnLineState state;
+
+    private String bindTimeStr;
+}

+ 36 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/GateWay2User.java

@@ -0,0 +1,36 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 硬件网关和他使用的用户绑定关系 (一个用户只能绑定一个网关)
+ *
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class GateWay2User extends SuperEntity {
+
+    @DBRef(lazy = true)
+    @Schema(description = "硬件设备网关信息")
+    private GateWayInfo gateWayInfo;
+
+    @DBRef(lazy = true)
+    @Schema(description = "用户信息")
+    private GateWayUserInfo gateWayUserInfo;
+
+    @Schema(description = "绑定的时间")
+    private Long bindTime;
+
+    @Schema(description = "绑定时间显示字段")
+    private String bindTimeStr;
+}

+ 31 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/GateWayInfo.java

@@ -0,0 +1,31 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.mqtt.type.OnLineState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 物联网 硬件设备  网关信息
+ *
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class GateWayInfo extends SuperEntity {
+
+    @Schema(description = "网关ID")
+    private String gateWayId;
+
+    @Schema(description = "网关名称")
+    private String gateWayName;
+
+    @Schema(description = "网关在线状态")
+    OnLineState state;
+}

+ 32 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/GateWayUserInfo.java

@@ -0,0 +1,32 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.mqtt.type.MqttUserState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class GateWayUserInfo extends SuperEntity {
+
+    @Schema(description = "mqtt连接账号")
+    private String userName;
+
+    @Schema(description = "mqtt连接密码")
+    private String passWord;
+
+    @Schema(description = "用户权限角色名称,一般和 userName 相同")
+    private String roleName;
+
+    @Schema(description = "用户状态:可用不可用")
+    private MqttUserState state;
+}

+ 38 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/Mqtt2User.java

@@ -0,0 +1,38 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * mqtt服务和账号关系信息 (是否在mqtt服务商添加账号)
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class Mqtt2User extends SuperEntity {
+
+    @Schema(description = "mqtt服务信息")
+    @DBRef(lazy = true)
+    private MqttInfo mqttInfo;
+
+    @Schema(description = "网关用户信息")
+    @DBRef(lazy = true)
+    private GateWayUserInfo gateWayUserInfo;
+
+    @Schema(description = "是否已同步")
+    private Boolean isSync = Boolean.FALSE;
+
+    @Schema(description = "同步时间")
+    private Long syncTime;
+
+    @Schema(description = "同步时间")
+    private String syncTimeStr;
+}

+ 47 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/MqttInfo.java

@@ -0,0 +1,47 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.mqtt.type.AddressType;
+import com.zswl.dataservice.utils.mqtt.type.CommonState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * MQTT 服务地址
+ *
+ * @author TRX
+ * @date 2024/5/14
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class MqttInfo extends SuperEntity {
+
+    @Schema(description = "MQTT服务的自定义名称")
+    private String name;
+
+    @Schema(description = "mqtt地址")
+    private String brokerHost;
+
+    @Schema(description = "mqtt端口")
+    private String brokerPort;
+
+    @Schema(description = "标记这个服务器的地址的名称,如:重庆、贵阳、成都")
+    private AddressType address;
+
+    @Schema(description = "jmx连接的地址,一般是内网地址")
+    private String jmxHost;
+
+    @Schema(description = "jmx连接的端口")
+    private String jmxPort;
+
+    @Schema(description = "MQTT服务的broker名称")
+    private String brokerName;
+
+    @Schema(description = "状态")
+    private CommonState state;
+}

+ 51 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/OperationLogs.java

@@ -0,0 +1,51 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.domain.User;
+import com.zswl.dataservice.utils.mqtt.type.LoginType;
+import com.zswl.dataservice.utils.mqtt.type.LogsLevel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/5/27
+ */
+@Data
+public class OperationLogs extends SuperEntity {
+
+    @Schema(description = "用户ID")
+    private String uid;
+
+    @Schema(description = "登录名")
+    private String loginName;
+
+    @Schema(description = "用户名称")
+    private String userName;
+
+    @Schema(description = "IP地址")
+    private String ip;
+
+    @Schema(description = "浏览器")
+    private String ua;
+
+    @Schema(description = "日志操作端类型")
+    private LoginType loginType;
+
+    @Schema(description = "日志内容")
+    private String content;
+
+    @Schema(description = "日志级别,重要程度")
+    private LogsLevel level;
+
+    @Schema(description = "时间")
+    private String time;
+
+    @Schema(description = "管理数据ID")
+    private String dataId;
+
+    @Schema(description = "关联保存关联信息")
+    private Object backObj;
+
+
+}

+ 56 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/OperationMessage.java

@@ -0,0 +1,56 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 指令数据
+ *
+ * @author TRX
+ * @date 2024/5/21
+ */
+@Data
+@Document
+@NoArgsConstructor
+@AllArgsConstructor
+public class OperationMessage extends SuperEntity {
+    @Schema(description = "消息ID")
+    private String messageId;
+
+    @Schema(description = "topic")
+    private String topic;
+
+    @Schema(description = "消息内容")
+    private Object data;
+
+    @Schema(description = "ttl时间(毫秒数)")
+    private Long ttlTime;
+
+    @Schema(description = "关于的设备信息")
+    private DeviceInfo deviceInfo;
+
+    @Schema(description = "设备ID")
+    private String deviceId;
+
+    @Schema(description = "关于的网关信息")
+    private GateWayInfo gateWayInfo;
+
+    @Schema(description = "网关ID")
+    private String gateWayId;
+
+    @Schema(description = "消息创建时间")
+    private String time;
+
+    @Schema(description = "是否收到信息")
+    private Boolean isReceive;
+
+    @Schema(description = "接收到的时间")
+    private Long receiveTime;
+
+    @Schema(description = "接收到的时间可阅读的")
+    private String receiveTimeStr;
+}

+ 28 - 0
src/main/java/com/zswl/dataservice/domain/mqtt/ProjectInfo.java

@@ -0,0 +1,28 @@
+package com.zswl.dataservice.domain.mqtt;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.mqtt.type.CommonState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 项目数据
+ *
+ * @author TRX
+ * @date 2024/5/21
+ */
+@Data
+@Document
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProjectInfo extends SuperEntity {
+    @Schema(description = "名称")
+    private String name;
+    @Schema(description = "code")
+    private String code;
+    @Schema(description = "状态")
+    private CommonState state;
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/helper/ApplicationContextHolder.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.helper;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+public class ApplicationContextHolder implements ApplicationContextAware {
+    private static ApplicationContext context;
+
+    @Override
+    public void setApplicationContext(ApplicationContext context) throws BeansException {
+        ApplicationContextHolder.context = context;
+    }
+
+    public static ApplicationContext getContext() {
+        return context;
+    }
+}

+ 37 - 0
src/main/java/com/zswl/dataservice/helper/BatchQueryHelper.java

@@ -0,0 +1,37 @@
+package com.zswl.dataservice.helper;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.bean.EntityObjectUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 批量查询
+ */
+@Component
+public class BatchQueryHelper {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+
+    /**
+     * 批量查询
+     *
+     * @param entityCls
+     * @param items
+     * @param <T>
+     * @return
+     */
+    public <T extends SuperEntity> List<T> batchQuery(Class<T> entityCls, Collection<Map<String, Object>> items) {
+        return this.mongoTemplate.find(Query.query(EntityObjectUtil.createQueryBatch(items)), entityCls);
+    }
+
+
+}

+ 273 - 0
src/main/java/com/zswl/dataservice/helper/DBHelper.java

@@ -0,0 +1,273 @@
+package com.zswl.dataservice.helper;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.helper.jpa.TransactionHelper;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Delegate;
+import org.bson.Document;
+import org.bson.codecs.DocumentCodec;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.aggregation.Aggregation;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class DBHelper {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DocumentCodec documentCodec;
+
+    //引用事务助手
+    @Autowired
+    @Delegate(types = TransactionHelper.class)
+    private TransactionHelper transactionHelper;
+
+
+    //引用mql查询助手
+    @Autowired
+    @Delegate(types = MongoQueryLanguageHelper.class)
+    private MongoQueryLanguageHelper mongoQueryLanguageHelper;
+
+
+    //引用批量查询
+    @Autowired
+    @Delegate(types = BatchQueryHelper.class)
+    private BatchQueryHelper batchQueryHelper;
+
+
+    //偏移数据
+    @Setter
+    @Getter
+    private long offsetTime = 0L;
+
+
+    // 缓存集合与类名
+    private Map<Class, String> collectionCache = new ConcurrentHashMap();
+
+
+    /**
+     * 设置更新时间
+     *
+     * @param entity
+     */
+    public void updateTime(SuperEntity entity) {
+        entity.setUpdateTime(getTime());
+    }
+
+    /**
+     * 设置创建时间
+     *
+     * @param entity
+     */
+    public void saveTime(SuperEntity entity) {
+        entity.setCreateTime(getTime());
+        updateTime(entity);
+    }
+
+
+    /**
+     * 设置更新时间
+     */
+    public void updateTime(Update update) {
+        update.set("updateTime", getTime());
+    }
+
+    /**
+     * 构建一个 update
+     *
+     * @return
+     */
+    public Update buildUpdate() {
+        Update update = new Update();
+        updateTime(update);
+        return update;
+    }
+
+
+    /**
+     * 设置创建时间
+     */
+    public void saveTime(Update update) {
+        update.setOnInsert("createTime", getTime());
+        updateTime(update);
+    }
+
+
+    /**
+     * 取时间
+     *
+     * @return
+     */
+    public long getTime() {
+        return this.offsetTime + System.currentTimeMillis();
+    }
+
+
+    /**
+     * 分页查询
+     *
+     * @param query
+     * @param pageable
+     * @param cls
+     * @param <T>
+     * @return
+     */
+    public <T> Page<T> pages(Query query, Pageable pageable, Class<T> cls) {
+        long total = this.mongoTemplate.count(query, cls);
+        query.with(pageable);
+        return new PageImpl<T>(this.mongoTemplate.find(query, cls), pageable, total);
+    }
+
+
+    /**
+     * 分页查询
+     *
+     * @param query
+     * @param pageable
+     * @param cls
+     * @param collectionName
+     * @param <T>
+     * @return
+     */
+    public <T> Page<T> pages(Query query, Pageable pageable, Class cls, String collectionName) {
+        long total = this.mongoTemplate.count(query, collectionName);
+        query.with(pageable);
+        return new PageImpl<T>(this.mongoTemplate.find(query, cls, collectionName), pageable, total);
+    }
+
+
+    /**
+     * 支持 aggregate 的分页查询语法
+     *
+     * @param pageable
+     * @param cls
+     * @return
+     */
+    public Page<Document> pages(Criteria criteria, Pageable pageable, Class<? extends SuperEntity> cls, AggregationOperation... aggregationOperations) {
+        //分页
+        AggregationOperation skip = Aggregation.skip(pageable.getOffset());
+        AggregationOperation limit = Aggregation.limit(pageable.getPageSize());
+
+
+        //排序
+        AggregationOperation sort = Aggregation.sort(pageable.getSort());
+        //分页模型
+        List<AggregationOperation> pageAggregationOperation = new ArrayList<AggregationOperation>() {{
+            //分页
+            add(skip);
+            add(limit);
+        }};
+
+
+        //总量
+        AggregationOperation count = Aggregation.count().as("count");
+
+
+        //构建分页查询条件
+        List<AggregationOperation> aggregations = new ArrayList<AggregationOperation>() {{
+
+            //查询条件
+            if (criteria != null) {
+                add(Aggregation.match(criteria));
+            }
+
+            //其他聚合业务
+            addAll(Arrays.asList(aggregationOperations));
+
+            //排序,必须放在分页模型外面,负责排序是分页排序
+            if (pageable.getSort() != null && !pageable.getSort().isEmpty()) {
+                add(sort);
+            }
+
+            //分页模型
+            add(Aggregation.facet().and(pageAggregationOperation.toArray(new AggregationOperation[0])).as("items").and(count).as("count"));
+        }};
+
+
+        //总量,用于分页, 移除外部的分页统计接口,用 facet 进行分页统计
+        Document result = this.mongoTemplate.aggregate(Aggregation.newAggregation(aggregations), this.getCollectionName(cls), Document.class).getMappedResults().get(0);
+
+        //转换输出类型
+        List items = result.getList("items", Document.class);
+
+        long total = 0;
+        List<Document> rets = result.getList("count", Document.class);
+        if (rets == null || rets.size() == 0) {
+            total = 0;
+        } else {
+            total = Long.parseLong(String.valueOf(rets.get(0).get("count")));
+        }
+
+
+        //记录的总数
+
+
+        //转换为分页模型
+        return new PageImpl<Document>(items, pageable, total);
+    }
+
+
+    /**
+     * 获取实体的名称
+     *
+     * @param cls
+     * @return
+     */
+    public String getCollectionName(Class cls) {
+        String name = this.collectionCache.get(cls);
+        if (name == null) {
+            name = this.mongoTemplate.getCollectionName(cls);
+            this.collectionCache.put(cls, name);
+        }
+        return name;
+    }
+
+
+    /**
+     * Document 转 json 对象
+     *
+     * @return
+     */
+    public String toJson(Document document) {
+        return document.toJson(documentCodec);
+    }
+
+
+    /**
+     * 支持查询对象转Json
+     *
+     * @param query
+     * @return
+     */
+    public String toJson(Query query) {
+        return toJson(query.getQueryObject());
+    }
+
+    /**
+     * 支持查询对象转Json
+     *
+     * @param update
+     * @return
+     */
+    public String toJson(Update update) {
+        return toJson(update.getUpdateObject());
+    }
+
+}

+ 59 - 0
src/main/java/com/zswl/dataservice/helper/JsonHelper.java

@@ -0,0 +1,59 @@
+package com.zswl.dataservice.helper;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JsonHelper {
+
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+
+    /**
+     * 转换到json字符串
+     *
+     * @param object
+     * @return
+     * @throws Exception
+     */
+    public String toJson(Object object, boolean format) {
+        try {
+            if (format) {
+                return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
+            } else {
+                return objectMapper.writeValueAsString(object);
+            }
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 转换到json字符串
+     *
+     * @param object
+     * @return
+     */
+    public String toJson(Object object) {
+        return toJson(object, false);
+    }
+
+
+    /**
+     * 转换为对象
+     *
+     * @param json
+     * @param cls
+     * @return
+     * @throws Exception
+     */
+    public <T> T toObject(String json, Class<T> cls) throws Exception {
+        return objectMapper.readValue(json, cls);
+    }
+}

+ 179 - 0
src/main/java/com/zswl/dataservice/helper/MongoQueryLanguageHelper.java

@@ -0,0 +1,179 @@
+package com.zswl.dataservice.helper;
+
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.zswl.dataservice.model.QueryModel;
+import lombok.SneakyThrows;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Component
+public class MongoQueryLanguageHelper {
+
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    @Autowired
+    private DBHelper dbHelper;
+
+
+    @SneakyThrows
+    public Criteria from(Document document) {
+        Criteria c = new Criteria();
+        Field _criteria = c.getClass().getDeclaredField("criteria");
+        _criteria.setAccessible(true);
+        LinkedHashMap<String, Object> criteria = (LinkedHashMap<String, Object>) _criteria.get(c);
+        for (Map.Entry<String, Object> set : document.entrySet()) {
+            criteria.put(set.getKey(), set.getValue());
+        }
+        Field _criteriaChain = c.getClass().getDeclaredField("criteriaChain");
+        _criteriaChain.setAccessible(true);
+        List<Criteria> criteriaChain = (List<Criteria>) _criteriaChain.get(c);
+        criteriaChain.add(c);
+        return c;
+    }
+
+    /**
+     * 通过 mongo的分页条件查询
+     *
+     * @param queryModel
+     * @param pageable
+     * @param entityClass
+     * @param <T>
+     * @return
+     */
+    @SneakyThrows
+    public <T> Page<T> queryByMql(QueryModel queryModel, Pageable pageable, Class<T> entityClass) {
+        Page<Document> page = this.queryByMql(queryModel, pageable, this.dbHelper.getCollectionName(entityClass));
+        //转换为数据库实体
+        List<T> resultSet = page.getContent().parallelStream().map((it) -> {
+            return (T) mongoTemplate.getConverter().read(entityClass, it);
+        }).collect(Collectors.toList());
+        return new PageImpl<T>(resultSet, pageable, page.getTotalElements());
+    }
+
+
+    @SneakyThrows
+    public Page<Document> queryByMql(QueryModel queryModel, Pageable pageable, String tableName) {
+        MongoCollection<Document> mongoCollection = this.mongoTemplate.getCollection(tableName);
+
+        final String mql = !StringUtils.hasText(queryModel.getMql()) ? "{}" : queryModel.getMql();
+        final Set<String> fields = queryModel.getFields() == null ? new HashSet<>() : queryModel.getFields();
+
+        //排序
+        Bson sort = sort(pageable.getSort());
+
+
+        //mql查询对象
+        Document mqlBson = Document.parse(mql);
+
+        //分页
+        long total = mongoCollection.countDocuments(mqlBson);
+        int skip = Integer.parseInt(String.valueOf(pageable.getOffset()));
+        int limit = pageable.getPageSize();
+
+
+        //构建查询语句
+        FindIterable<Document> findIterable = mongoCollection.find(mqlBson);
+
+        //过滤需要显示的字段
+        if (fields.size() > 0) {
+            findIterable = findIterable.projection(projection(fields));
+        }
+
+        //分页条件
+        findIterable = findIterable.skip(skip).limit(limit).sort(sort);
+
+
+        //结果集
+        List<Document> resultSet = new ArrayList<>();
+
+        //查询
+        for (Document document : findIterable) {
+            resultSet.add(document);
+        }
+
+        return new PageImpl<Document>(resultSet, pageable, total);
+    }
+
+    @SneakyThrows
+    public List<Document> queryByMql(QueryModel queryModel, Sort sort, String tableName) {
+        MongoCollection<Document> mongoCollection = this.mongoTemplate.getCollection(tableName);
+
+        final String mql = !StringUtils.hasText(queryModel.getMql()) ? "{}" : queryModel.getMql();
+        final Set<String> fields = queryModel.getFields() == null ? new HashSet<>() : queryModel.getFields();
+
+        //排序
+        Bson bsonSort = sort(sort);
+
+        //mql查询对象
+        Document mqlBson = Document.parse(mql);
+
+        //构建查询语句
+        FindIterable<Document> findIterable = mongoCollection.find(mqlBson);
+
+        //过滤需要显示的字段
+        if (fields.size() > 0) {
+            findIterable = findIterable.projection(projection(fields));
+        }
+
+        //分页条件
+        findIterable = findIterable.sort(bsonSort);
+
+        //结果集
+        List<Document> resultSet = new ArrayList<>();
+
+        //查询
+        for (Document document : findIterable) {
+            resultSet.add(document);
+        }
+
+        return resultSet;
+    }
+
+    /**
+     * 转换为sort
+     *
+     * @return
+     */
+    private static Document sort(Sort sort) {
+        Document bson = new Document();
+        if (sort.isUnsorted()) {
+            return bson;
+        }
+        sort.stream().forEach((order) -> {
+                    bson.put(order.getProperty(), order.getDirection() == Sort.Direction.DESC ? -1 : 1);
+                }
+        );
+        return bson;
+    }
+
+    /**
+     * 转换为过滤器
+     *
+     * @param fields
+     * @return
+     */
+    private static Document projection(Set<String> fields) {
+        Document bson = new Document();
+        fields.forEach((it) -> {
+            bson.put(it, 1);
+        });
+        return bson;
+    }
+
+}

+ 30 - 0
src/main/java/com/zswl/dataservice/helper/MongoTemplateNearest.java

@@ -0,0 +1,30 @@
+package com.zswl.dataservice.helper;
+
+import com.mongodb.ReadPreference;
+import lombok.experimental.Delegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MongoTemplateNearest {
+
+
+    @Delegate(types = MongoTemplate.class)
+    private MongoTemplate mongoTemplate;
+
+
+    @Autowired
+    private void init(MongoTemplate mongoTemplate) {
+
+        //实例化 mongoTemplate
+        mongoTemplate = new MongoTemplate(
+                mongoTemplate.getMongoDatabaseFactory(),
+                mongoTemplate.getConverter()
+        );
+
+        //  最小的延迟,会从复制集中选择最低网络延迟的节点处理读请求,这种方式不能保证数据一致性,也不能保证减少IO以及CPU的负载
+        mongoTemplate.setReadPreference(ReadPreference.nearest());
+    }
+
+}

+ 284 - 0
src/main/java/com/zswl/dataservice/helper/ReIndexHelper.java

@@ -0,0 +1,284 @@
+package com.zswl.dataservice.helper;
+
+import com.zswl.dataservice.domain.SuperEntity;
+import com.zswl.dataservice.utils.bean.BeanUtil;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.index.Index;
+import org.springframework.data.mongodb.core.index.IndexInfo;
+import org.springframework.data.mongodb.core.index.IndexOperations;
+import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 重置索引
+ */
+@Slf4j
+@Component
+public class ReIndexHelper {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+
+    //每个索引里最大数量
+    private final static int MaxIndexCount = 24;
+
+
+    /**
+     * 重建索引
+     */
+    public void reIndexFromField(Class<? extends SuperEntity> entityClass, String fieldName, Class<?> cls) {
+        //构建索引
+        Set<Index> nowIndexNames = BeanUtil.readBeanType(cls).keySet()
+                .stream()
+                .map((it) -> {
+                    final String indexName = fieldName + "." + it;
+                    return new Index().named(indexName).on(indexName, Sort.Direction.ASC);
+                }).collect(Collectors.toSet());
+
+        //更新索引
+        updateIndex(entityClass, fieldName, nowIndexNames.toArray(new Index[0]));
+    }
+
+
+    /**
+     * 重置索引
+     */
+    public void reIndexFromMap(Class<? extends SuperEntity> entityClass, String fieldName) {
+        //构建索引
+        Set<Index> nowIndexNames = getIndexNamesFromMap(entityClass, fieldName)
+                .stream()
+                .map((it) -> {
+                    final String indexName = fieldName + "." + it;
+                    return new Index().named(indexName).on(indexName, Sort.Direction.ASC);
+                }).collect(Collectors.toSet());
+
+        //更新索引
+        updateIndex(entityClass, fieldName, nowIndexNames.toArray(new Index[0]));
+    }
+
+
+    /**
+     * 取出现有点索引
+     *
+     * @return
+     */
+    public Set<String> getIndexNames(String tableName) {
+        //现有索引
+        return this.mongoTemplate.indexOps(tableName)
+                .getIndexInfo()
+                .stream()
+                .map((it) -> {
+                    return it.getName();
+                }).collect(Collectors.toSet());
+    }
+
+
+    public void copyIndex(String tableName, String newTableName) {
+        final IndexOperations indexOperations = this.mongoTemplate.indexOps(tableName);
+        indexOperations.getIndexInfo().stream().filter(it -> !Set.of("_id_", "_id").contains(it.getName())).forEach((indexInfo) -> {
+            final String indexName = indexInfo.getName();
+            final IndexOperations newIndexOperations = this.mongoTemplate.indexOps(newTableName);
+
+            //删除索引
+            newIndexOperations.getIndexInfo().stream().filter(it -> indexName.equals(it.getName())).forEach((it) -> {
+                newIndexOperations.dropIndex(it.getName());
+            });
+            final Index newIndex = new Index();
+            newIndex.named(indexName);
+            indexInfo.getIndexFields().forEach((it) -> {
+                newIndex.on(it.getKey(), it.getDirection());
+            });
+
+            //创建索引
+            newIndexOperations.ensureIndex(newIndex);
+        });
+    }
+
+
+    /**
+     * 取出现有点索引
+     *
+     * @param entityClass
+     * @return
+     */
+    public Set<String> getIndexNames(Class<? extends SuperEntity> entityClass) {
+        return this.getIndexNames(this.mongoTemplate.getCollectionName(entityClass));
+    }
+
+
+    /**
+     * 更新索引
+     *
+     * @param tableName
+     * @param indexs
+     */
+    @SneakyThrows
+    public void updateIndex(String tableName, Index... indexs) {
+        //现有索引
+        final Set<String> nowIndexNames = getIndexNames(tableName);
+
+        //索引
+        final IndexOperations indexOperations = this.mongoTemplate.indexOps(tableName);
+
+        //索引不存在建索引
+        Arrays.stream(indexs).filter(it -> it.getIndexKeys().size() > 0).forEach((it) -> {
+            String indexName = getIndexName(it);
+            if ((nowIndexNames.contains(indexName))) {
+                indexOperations.dropIndex(indexName);
+            }
+            String ret = indexOperations.ensureIndex(it);
+            log.info("update index : " + ret);
+        });
+    }
+
+
+    @SneakyThrows
+    private String getIndexName(Index index) {
+        final Field field = FieldUtils.getDeclaredField(Index.class, "name", true);
+        if (field == null) {
+            return null;
+        }
+        Object val = field.get(index);
+        if (val == null) {
+            return null;
+        }
+        return String.valueOf(val);
+    }
+
+    /**
+     * 更新索引,独立的索引项
+     *
+     * @param entityClass
+     * @param indexs
+     */
+    @SneakyThrows
+    public void updateIndex(Class<? extends SuperEntity> entityClass, Index... indexs) {
+        this.updateIndex(this.mongoTemplate.getCollectionName(entityClass), indexs);
+    }
+
+
+    /**
+     * 更新索引,共用一个索引项
+     *
+     * @param entityClass
+     */
+    @SneakyThrows
+    public void updateIndex(Class<? extends SuperEntity> entityClass, String indexName, Index... indexs) {
+        boolean isUpdate = false;
+        List<IndexInfo> indexInfos = this.mongoTemplate.indexOps(entityClass)
+                .getIndexInfo()
+                .stream()
+                .filter((it) -> {
+                    return it.getName().length() > indexName.length() + 1 && it.getName().substring(0, indexName.length()).equals(indexName);
+                }).collect(Collectors.toList());
+        if (indexInfos != null && indexInfos.size() > 0) {
+            isUpdate = isNeedUpdateIndex(indexInfos, indexs);
+        } else {
+            isUpdate = true;
+        }
+
+        //进行更新索引
+        if (isUpdate) {
+            final IndexOperations indexOperations = this.mongoTemplate.indexOps(entityClass);
+
+            //如果存在则删除所有的和符合索引
+            indexOperations.getIndexInfo().stream().filter((it) -> {
+                return it.getName().length() > indexName.length() + 1 && it.getName().substring(0, indexName.length()).equals(indexName);
+            }).forEach((it) -> {
+                indexOperations.dropIndex(it.getName());
+            });
+
+            int size = (int) (indexs.length / MaxIndexCount);
+            for (int i = 0; i < size; i++) {
+                updateIndex(indexOperations, indexName + "_" + i, i, indexs);
+            }
+            if (indexs.length % MaxIndexCount != 0) {
+                updateIndex(indexOperations, indexName + "_" + size, size, indexs);
+            }
+        }
+    }
+
+    @SneakyThrows
+    private void updateIndex(IndexOperations indexOperations, String indexName, int page, final Index[] indexs) {
+        Index index = new Index();
+        index.named(indexName);
+
+        for (int j = 0; j < MaxIndexCount; j++) {
+            //索引
+            int i = page * MaxIndexCount + j;
+            if (i >= indexs.length) {
+                continue;
+            }
+            Index it = indexs[i];
+            Field field = it.getClass().getDeclaredField("name");
+            field.setAccessible(true);
+            String fieldName = String.valueOf(field.get(it));
+            index.on(fieldName, Sort.Direction.ASC);
+        }
+        log.info("update index : {}", indexName);
+        indexOperations.ensureIndex(index);
+
+    }
+
+
+    /**
+     * 需要更新的名字
+     *
+     * @return
+     */
+    private boolean isNeedUpdateIndex(List<IndexInfo> indexInfos, Index[] indexs) {
+        //取出需要更新的索引名
+        Set<String> newUpdateNames = Arrays.stream(indexs).map((it) -> {
+            return it.getIndexOptions().get("name");
+        }).filter((it) -> {
+            return it != null;
+        }).map((it) -> {
+            return String.valueOf(it);
+        }).collect(Collectors.toSet());
+
+        //取出现有的索引名
+        Set<String> nowIndexName = new HashSet<>();
+        indexInfos.forEach((it) -> {
+            nowIndexName.addAll(it.getIndexFields().stream().map((index) -> {
+                return index.getKey();
+            }).collect(Collectors.toSet()));
+        });
+
+
+        for (String updateName : newUpdateNames) {
+            if (!nowIndexName.contains(updateName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * 取出Map属性对应的所有key的集合
+     *
+     * @return
+     */
+    public Set<String> getIndexNamesFromMap(Class<? extends SuperEntity> entityClass, String fieldName) {
+        String collectionName = this.mongoTemplate.getCollectionName(entityClass);
+        String map = "function(){if(this." + fieldName + "==null){return}for(var key in this." + fieldName + "){emit(key,1)}};";
+        String reduce = "function(key,values){return values.length};";
+        Set<String> indexNames = new HashSet<>();
+        MapReduceResults<Map> mapReduceResults = this.mongoTemplate.mapReduce(collectionName, map, reduce, Map.class);
+        mapReduceResults.forEach((it) -> {
+            indexNames.add(String.valueOf(it.get("_id")));
+        });
+        return indexNames;
+    }
+
+
+}

+ 103 - 0
src/main/java/com/zswl/dataservice/helper/jpa/TransactionHelper.java

@@ -0,0 +1,103 @@
+package com.zswl.dataservice.helper.jpa;
+
+import com.zswl.dataservice.utils.os.SystemUtil;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Component
+public class TransactionHelper {
+
+
+    @Autowired
+    private TransactionTemplate transactionTemplate;
+
+    //线程池
+    ExecutorService threadPool = Executors.newFixedThreadPool(SystemUtil.getCpuCoreCount() * 2);
+
+    @Autowired
+    private void init(ApplicationContext applicationContext) {
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            threadPool.shutdownNow();
+        }));
+    }
+
+
+    /**
+     * 创建一个新事务
+     *
+     * @param action
+     * @param <T>
+     */
+    @SneakyThrows
+    public <T> T newTransaction(TransactionCallback<T> action) {
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        Object[] ts = new Object[1];
+        new Thread(() -> {
+            try {
+                ts[0] = transaction(action);
+            } catch (TransactionException e) {
+                e.printStackTrace();
+            }
+            countDownLatch.countDown();
+        }).start();
+        countDownLatch.await();
+        return ts[0] == null ? null : (T) ts[0];
+    }
+
+
+    /**
+     * 创建一个没有事务的操作执行环境
+     *
+     * @param runnable
+     */
+    @SneakyThrows
+    public void noTransaction(Runnable runnable) {
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        threadPool.execute(() -> {
+            try {
+                runnable.run();
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                countDownLatch.countDown();
+            }
+        });
+        countDownLatch.await();
+    }
+
+
+    /**
+     * 编程事务
+     */
+    public <T> T transaction(TransactionCallback<T> action) {
+        return transactionTemplate.execute(action);
+    }
+
+    /**
+     * 回滚事务
+     */
+    public void rollbackTransaction() {
+        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+    }
+
+
+    /**
+     * 提交事务
+     * 注: 不可多次提交
+     */
+    public void commitTransaction() {
+        transactionTemplate.getTransactionManager().commit(TransactionAspectSupport.currentTransactionStatus());
+    }
+
+
+}

+ 32 - 0
src/main/java/com/zswl/dataservice/model/AppInfoModel.java

@@ -0,0 +1,32 @@
+package com.zswl.dataservice.model;
+
+import com.zswl.dataservice.type.AppState;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AppInfoModel {
+    /**
+     * 渠道ID
+     */
+    private String entId;
+    /**
+     * appSecret
+     */
+    private String appSecret;
+    /**
+     * 应用ID
+     */
+    private String appId;
+    /**
+     * 账户状态
+     */
+    private AppState appState;
+}

+ 26 - 0
src/main/java/com/zswl/dataservice/model/QueryModel.java

@@ -0,0 +1,26 @@
+package com.zswl.dataservice.model;
+
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import java.util.Set;
+
+/**
+ * 查询模型
+ */
+@Data
+@Builder
+@EqualsAndHashCode
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class QueryModel {
+
+    //mongo的查询语句
+    private String mql;
+
+    //关键词,如果为null则全部查询,否则只查询需要的字段
+    private Set<String> fields;
+
+
+}

+ 22 - 0
src/main/java/com/zswl/dataservice/model/TokenModel.java

@@ -0,0 +1,22 @@
+package com.zswl.dataservice.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/3/21
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TokenModel {
+    @Schema(description = "Token")
+    private String access_token;
+    @Schema(description = "过期时间")
+    private Long expires_at;
+    @Schema(description = "生成时间")
+    private Long auth_time;
+}

+ 12 - 0
src/main/java/com/zswl/dataservice/model/baseParam/IDParam.java

@@ -0,0 +1,12 @@
+package com.zswl.dataservice.model.baseParam;
+
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/5/16
+ */
+@Data
+public class IDParam {
+    private String id;
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/model/mqtt/DeviceInfoAddParam.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.model.mqtt;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/5/16
+ */
+@Data
+public class DeviceInfoAddParam extends SuperParam {
+
+    @Schema(description = "设备ID")
+    private String deviceId;
+
+    @Schema(description = "设备名称")
+    private String deviceName;
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/model/mqtt/DeviceInfoModel.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.model.mqtt;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/5/16
+ */
+@Data
+public class DeviceInfoModel extends SuperModel {
+
+    @Schema(description = "设备ID")
+    private String deviceId;
+
+    @Schema(description = "设备名称")
+    private String deviceName;
+}

+ 18 - 0
src/main/java/com/zswl/dataservice/model/mqtt/DeviceInfoSearchParam.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservice.model.mqtt;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/5/16
+ */
+@Data
+public class DeviceInfoSearchParam extends SuperSearchParam {
+
+    @Schema(description = "设备ID", required = false)
+    private String deviceId;
+
+    @Schema(description = "设备名称", required = false)
+    private String deviceName;
+}

+ 25 - 0
src/main/java/com/zswl/dataservice/model/mqtt/GateWayBindDeviceParam.java

@@ -0,0 +1,25 @@
+package com.zswl.dataservice.model.mqtt;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/5/21
+ */
+@Data
+public class GateWayBindDeviceParam {
+    @Schema(description = "网关ID")
+    private String gateWayId;
+
+    @Schema(description = "网关名称")
+    private String gateWayName;
+
+    @Schema(description = "设备列表")
+    private List<DeviceInfoAddParam> devices;
+
+    @Schema(description = "网关连接账号")
+    private String userName;
+}

+ 21 - 0
src/main/java/com/zswl/dataservice/model/mqtt/GateWayInfoAddParam.java

@@ -0,0 +1,21 @@
+package com.zswl.dataservice.model.mqtt;
+
+import com.zswl.dataservice.utils.mqtt.type.OnLineState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/5/17
+ */
+@Data
+public class GateWayInfoAddParam extends SuperParam {
+    @Schema(description = "网关ID")
+    private String gateWayId;
+
+    @Schema(description = "网关名称")
+    private String gateWayName;
+
+    @Schema(description = "设备在线状态")
+    OnLineState state = OnLineState.OffLine;
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно