Răsfoiți Sursa

1.哔蹦后台 + layui项目

slambb 3 ani în urmă
comite
5e63982551
100 a modificat fișierele cu 5545 adăugiri și 0 ștergeri
  1. 310 0
      mvnw
  2. 182 0
      mvnw.cmd
  3. 313 0
      pom.xml
  4. 241 0
      src/main/java/com/YuyeTech/TPlat/TPlatApplication.java
  5. 18 0
      src/main/java/com/YuyeTech/TPlat/VO/AiInfoVO.java
  6. 30 0
      src/main/java/com/YuyeTech/TPlat/VO/EmailVO.java
  7. 22 0
      src/main/java/com/YuyeTech/TPlat/VO/FavoritesVO.java
  8. 27 0
      src/main/java/com/YuyeTech/TPlat/VO/FitnessVO.java
  9. 35 0
      src/main/java/com/YuyeTech/TPlat/VO/FriendInfoVO.java
  10. 24 0
      src/main/java/com/YuyeTech/TPlat/VO/GameVO.java
  11. 14 0
      src/main/java/com/YuyeTech/TPlat/VO/LoginVO.java
  12. 25 0
      src/main/java/com/YuyeTech/TPlat/VO/RankInfoVO.java
  13. 34 0
      src/main/java/com/YuyeTech/TPlat/VO/RankingVO.java
  14. 25 0
      src/main/java/com/YuyeTech/TPlat/VO/ResultVO.java
  15. 38 0
      src/main/java/com/YuyeTech/TPlat/VO/UserInfoVO.java
  16. 21 0
      src/main/java/com/YuyeTech/TPlat/annotation/Between.java
  17. 12 0
      src/main/java/com/YuyeTech/TPlat/annotation/Decrypt.java
  18. 12 0
      src/main/java/com/YuyeTech/TPlat/annotation/Encrypt.java
  19. 16 0
      src/main/java/com/YuyeTech/TPlat/annotation/In.java
  20. 13 0
      src/main/java/com/YuyeTech/TPlat/annotation/Like.java
  21. 28 0
      src/main/java/com/YuyeTech/TPlat/annotation/RedisUpdate.java
  22. 112 0
      src/main/java/com/YuyeTech/TPlat/aspect/AuthorizeFilter.java
  23. 180 0
      src/main/java/com/YuyeTech/TPlat/aspect/SafetyAspect.java
  24. 82 0
      src/main/java/com/YuyeTech/TPlat/common/controller/CommonController.java
  25. 22 0
      src/main/java/com/YuyeTech/TPlat/common/pojo/IpVo.java
  26. 31 0
      src/main/java/com/YuyeTech/TPlat/common/pojo/MonitorVo.java
  27. 39 0
      src/main/java/com/YuyeTech/TPlat/common/pojo/PageCondition.java
  28. 83 0
      src/main/java/com/YuyeTech/TPlat/common/pojo/PageInfo.java
  29. 42 0
      src/main/java/com/YuyeTech/TPlat/common/pojo/ParameterRequestWrapper.java
  30. 79 0
      src/main/java/com/YuyeTech/TPlat/common/pojo/Result.java
  31. 16 0
      src/main/java/com/YuyeTech/TPlat/common/repository/CommonRepository.java
  32. 58 0
      src/main/java/com/YuyeTech/TPlat/common/service/CommonService.java
  33. 302 0
      src/main/java/com/YuyeTech/TPlat/common/service/CommonServiceImpl.java
  34. 32 0
      src/main/java/com/YuyeTech/TPlat/config/AliyunConfig.java
  35. 18 0
      src/main/java/com/YuyeTech/TPlat/config/GameConfigTime.java
  36. 34 0
      src/main/java/com/YuyeTech/TPlat/config/WebConfig.java
  37. 20 0
      src/main/java/com/YuyeTech/TPlat/config/WechatAccountConfig.java
  38. 147 0
      src/main/java/com/YuyeTech/TPlat/config/WxMaConfiguration.java
  39. 46 0
      src/main/java/com/YuyeTech/TPlat/config/WxMaProperties.java
  40. 27 0
      src/main/java/com/YuyeTech/TPlat/config/async/AsyncConfig.java
  41. 17 0
      src/main/java/com/YuyeTech/TPlat/config/config.java
  42. 25 0
      src/main/java/com/YuyeTech/TPlat/config/exception/AuthorizeException.java
  43. 175 0
      src/main/java/com/YuyeTech/TPlat/config/logback/LoggingWSServer.java
  44. 104 0
      src/main/java/com/YuyeTech/TPlat/config/monitor/MonitorWSServer.java
  45. 174 0
      src/main/java/com/YuyeTech/TPlat/config/security/CaptchaFilterConfig.java
  46. 88 0
      src/main/java/com/YuyeTech/TPlat/config/security/DynamicallyUrlInterceptor.java
  47. 55 0
      src/main/java/com/YuyeTech/TPlat/config/security/ErrorPageConfig.java
  48. 75 0
      src/main/java/com/YuyeTech/TPlat/config/security/LoginFailureHandlerConfig.java
  49. 157 0
      src/main/java/com/YuyeTech/TPlat/config/security/LoginSuccessHandlerConfig.java
  50. 37 0
      src/main/java/com/YuyeTech/TPlat/config/security/LogoutHandlerConfig.java
  51. 56 0
      src/main/java/com/YuyeTech/TPlat/config/security/MyAccessDecisionManager.java
  52. 77 0
      src/main/java/com/YuyeTech/TPlat/config/security/MyFilterInvocationSecurityMetadataSource.java
  53. 51 0
      src/main/java/com/YuyeTech/TPlat/config/security/MyInvalidSessionStrategy.java
  54. 20 0
      src/main/java/com/YuyeTech/TPlat/config/security/PasswordConfig.java
  55. 175 0
      src/main/java/com/YuyeTech/TPlat/config/security/SecurityConfig.java
  56. 51 0
      src/main/java/com/YuyeTech/TPlat/config/security/UserConfig.java
  57. 51 0
      src/main/java/com/YuyeTech/TPlat/config/security/gameConfig.java
  58. 53 0
      src/main/java/com/YuyeTech/TPlat/config/token/WebConfig.java
  59. 26 0
      src/main/java/com/YuyeTech/TPlat/config/websocket/MyEndpointConfigure.java
  60. 32 0
      src/main/java/com/YuyeTech/TPlat/config/websocket/WebSocketConfig.java
  61. 11 0
      src/main/java/com/YuyeTech/TPlat/constant/CookieConstant.java
  62. 12 0
      src/main/java/com/YuyeTech/TPlat/constant/RankingConstant.java
  63. 17 0
      src/main/java/com/YuyeTech/TPlat/constant/RedisConstant.java
  64. 19 0
      src/main/java/com/YuyeTech/TPlat/dataobject/AdminInfo.java
  65. 26 0
      src/main/java/com/YuyeTech/TPlat/dataobject/AiInfo.java
  66. 25 0
      src/main/java/com/YuyeTech/TPlat/dataobject/AppleInfo.java
  67. 39 0
      src/main/java/com/YuyeTech/TPlat/dataobject/ClientInfo.java
  68. 32 0
      src/main/java/com/YuyeTech/TPlat/dataobject/DeviceInfo.java
  69. 26 0
      src/main/java/com/YuyeTech/TPlat/dataobject/Favorites.java
  70. 25 0
      src/main/java/com/YuyeTech/TPlat/dataobject/FitnessProgram.java
  71. 27 0
      src/main/java/com/YuyeTech/TPlat/dataobject/FriendInfo.java
  72. 37 0
      src/main/java/com/YuyeTech/TPlat/dataobject/LevelCondition.java
  73. 26 0
      src/main/java/com/YuyeTech/TPlat/dataobject/LevelHonor.java
  74. 47 0
      src/main/java/com/YuyeTech/TPlat/dataobject/LevelJump.java
  75. 26 0
      src/main/java/com/YuyeTech/TPlat/dataobject/MainInfo.java
  76. 25 0
      src/main/java/com/YuyeTech/TPlat/dataobject/OtaInfo.java
  77. 22 0
      src/main/java/com/YuyeTech/TPlat/dataobject/Pictures.java
  78. 42 0
      src/main/java/com/YuyeTech/TPlat/dataobject/ProductCategory.java
  79. 29 0
      src/main/java/com/YuyeTech/TPlat/dataobject/RankInfo.java
  80. 30 0
      src/main/java/com/YuyeTech/TPlat/dataobject/Ranking.java
  81. 31 0
      src/main/java/com/YuyeTech/TPlat/dataobject/RecentlyPlaying.java
  82. 29 0
      src/main/java/com/YuyeTech/TPlat/dataobject/Recommend.java
  83. 30 0
      src/main/java/com/YuyeTech/TPlat/dataobject/SignIn.java
  84. 28 0
      src/main/java/com/YuyeTech/TPlat/dataobject/SignInReward.java
  85. 43 0
      src/main/java/com/YuyeTech/TPlat/dataobject/UserInfo.java
  86. 31 0
      src/main/java/com/YuyeTech/TPlat/dataobject/UserLevel.java
  87. 43 0
      src/main/java/com/YuyeTech/TPlat/dataobject/UserReward.java
  88. 27 0
      src/main/java/com/YuyeTech/TPlat/dataobject/UserWallets.java
  89. 32 0
      src/main/java/com/YuyeTech/TPlat/dataobject/VersionCode.java
  90. 30 0
      src/main/java/com/YuyeTech/TPlat/dataobject/VersionInfo.java
  91. 24 0
      src/main/java/com/YuyeTech/TPlat/dataobject/WeightInfo.java
  92. 26 0
      src/main/java/com/YuyeTech/TPlat/dataobject/WxInfo.java
  93. 28 0
      src/main/java/com/YuyeTech/TPlat/dto/BLToothDTO.java
  94. 28 0
      src/main/java/com/YuyeTech/TPlat/dto/DeviceBindDTO.java
  95. 54 0
      src/main/java/com/YuyeTech/TPlat/dto/FcDTO.java
  96. 60 0
      src/main/java/com/YuyeTech/TPlat/dto/FriendInfoDTO.java
  97. 60 0
      src/main/java/com/YuyeTech/TPlat/dto/GameDTO.java
  98. 29 0
      src/main/java/com/YuyeTech/TPlat/dto/GameTagDTO.java
  99. 33 0
      src/main/java/com/YuyeTech/TPlat/dto/LevelConditionDTO.java
  100. 27 0
      src/main/java/com/YuyeTech/TPlat/dto/LevelHonorDTO.java

+ 310 - 0
mvnw

@@ -0,0 +1,310 @@
+#!/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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   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 /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
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -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 "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; 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="`which 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
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# 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/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+##########################################################################################
+# 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.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    if [ -n "$MVNW_REPOURL" ]; then
+      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+    else
+      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+    fi
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $jarUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+    if $cygwin; then
+      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+    fi
+
+    if command -v wget > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget "$jarUrl" -O "$wrapperJarPath"
+        else
+            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl -o "$wrapperJarPath" "$jarUrl" -f
+        else
+            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+        fi
+        
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaClass=`cygpath --path --windows "$javaClass"`
+        fi
+        if [ -e "$javaClass" ]; then
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaClass")
+            fi
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+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 "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -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
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 182 - 0
mvnw.cmd

@@ -0,0 +1,182 @@
+@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 Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@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 key stroke 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 "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\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 DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_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 DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_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('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@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 "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\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%
+
+exit /B %ERROR_CODE%

+ 313 - 0
pom.xml

@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.4.3</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.slambb</groupId>
+    <artifactId>smallshop</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>smallshop</name>
+    <description>Demo project for Spring Boot</description>
+
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-properties-migrator</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!--   热更新   -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.junit.vintage</groupId>
+                    <artifactId>junit-vintage-engine</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.7.22</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+
+        <!--添加lombok工具,需要在plugin下载-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <!--mysql-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <!--操作数据库工具-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+
+        <!--微信小程序sdk-->
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-miniapp</artifactId>
+            <version>3.6.0</version>
+        </dependency>
+        <!--缓存服务-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-cache</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!--阿里云oss服务-->
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.8.0</version>
+        </dependency>
+
+        <!--配置lettuce时候,引入-->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <!--阿里云短信服务-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.8</version>
+        </dependency>
+
+        <!--验证苹果登录操作相关-->
+        <!--<dependency>-->
+        <!--    <groupId>io.jsonwebtoken</groupId>-->
+        <!--    <artifactId>jjwt</artifactId>-->
+        <!--    <version>0.9.1</version>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>jwks-rsa</artifactId>
+            <version>0.9.0</version>
+        </dependency>
+<!--        <dependency>-->
+<!--        <groupId>org.apache.httpcomponents</groupId>-->
+<!--        <artifactId>httpclient</artifactId>-->
+<!--        <version>4.5.5</version>-->
+<!--    </dependency>-->
+        <!--https://github.com/oshi/oshi。-->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-json</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.60</version>
+        </dependency>
+
+        <!--二维码依赖-->
+        <!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.3.3</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.3.3</version>
+        </dependency>
+        <!-- security安全校验 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+
+        <!--jwt-->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
+        <!-- thymeleaf模板 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+
+        <!--后台管理相关-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-freemarker</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>angularjs</artifactId>
+            <version>1.5.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>angular-translate</artifactId>
+            <version>2.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>ng-file-upload</artifactId>
+            <version>12.0.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>1.12</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.junrar</groupId>
+            <artifactId>junrar</artifactId>
+            <version>0.7</version>
+        </dependency>
+        <!--RSA加密部分-->
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.13</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+        </dependency>
+
+        <!-- CopyUtil需要用到 -->
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.2</version>
+        </dependency>
+
+        <!-- springboot websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
+        <!-- Base64编码需要  -->
+        <dependency>
+            <groupId>org.apache.directory.studio</groupId>
+            <artifactId>org.apache.commons.codec</artifactId>
+            <version>1.8</version>
+        </dependency>
+
+        <!--提供更多的加密、填充方式-->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+            <version>1.46</version>
+        </dependency>
+
+        <!--定制请求跳过ssl证书验证-->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+        </dependency>
+        <!--定制请求跳过ssl证书验证-->
+    </dependencies>
+
+    <build>
+        <finalName>TPlat</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <!--  启动修改之后实时生效   -->
+                <configuration>
+                    <fork>true</fork>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 241 - 0
src/main/java/com/YuyeTech/TPlat/TPlatApplication.java

@@ -0,0 +1,241 @@
+package com.YuyeTech.TPlat;
+
+import com.YuyeTech.TPlat.enums.RedisType;
+import com.YuyeTech.TPlat.game.bluetoothinfo.service.BluetoothInfoService;
+import com.YuyeTech.TPlat.sys.sysmenu.vo.SysMenuVo;
+import com.YuyeTech.TPlat.sys.sysshortcutmenu.service.SysShortcutMenuService;
+import com.YuyeTech.TPlat.sys.sysshortcutmenu.vo.SysShortcutMenuVo;
+import com.YuyeTech.TPlat.sys.sysuser.service.SysUserService;
+import com.YuyeTech.TPlat.sys.sysuser.vo.SysUserVo;
+import com.YuyeTech.TPlat.sys.sysusermenu.service.SysUserMenuService;
+import com.YuyeTech.TPlat.utils.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.session.SessionRegistryImpl;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+
+@SpringBootApplication
+@EnableCaching//开启基于注解缓存
+@ServletComponentScan(basePackages = "com.slambb.smallshop")
+public class TPlatApplication {
+    //    @PostConstruct
+//    void started() {
+//        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+//    }
+    public static void main(String[] args) {
+        SpringApplication.run(TPlatApplication.class, args);
+    }
+
+    /**
+     * 解决不能注入session注册表问题
+     */
+    @Bean
+    SessionRegistry sessionRegistry() {
+        return new SessionRegistryImpl();
+    }
+}
+
+@Slf4j
+@Controller
+@RequestMapping("/")
+@Configuration
+class IndexController {
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    @Autowired
+    private RedisSettingMap redisSettingMap;
+
+    @Autowired
+    private SysUserMenuService sysUserMenuService;
+
+    @Autowired
+    private SysShortcutMenuService sysShortcutMenuService;
+
+    @Autowired
+    private BluetoothInfoService bluetoothInfoService;
+
+    @Autowired
+    private AliyunOSSUtil aliyunOSSUtil;
+
+
+
+    @Value("${server.servlet.context-path:}")
+    private String contextPath;
+
+
+    /**
+     * 端口
+     */
+    @Value("${server.port}")
+    private String port;
+
+    /**
+     * 启动成功
+     */
+    @Bean
+    public ApplicationRunner applicationRunner() {
+        return applicationArguments -> {
+            try {
+                /**
+                 * 当启动时候,向redis设置一次数据。
+                 */
+                //更新sys_setting
+                redisSettingMap.updateSysSettingMap();
+
+                //更新一次到缓存
+                bluetoothInfoService.updateListToCache();
+
+                //获取本机内网IP
+                log.info("启动成功:" + "http://" + InetAddress.getLocalHost().getHostAddress() + ":" + port + contextPath);
+            } catch (UnknownHostException e) {
+                //输出到日志文件中
+                log.error(ErrorUtil.errorInfoToString(e));
+            }
+        };
+    }
+
+    /**
+     * 跳转登录页面
+     */
+    @GetMapping("loginPage")
+    public ModelAndView login() {
+        ModelAndView modelAndView = new ModelAndView("login");
+
+        //系统信息 SysSettingUtil.getSysSetting()
+        modelAndView.addObject("sys", redisSettingMap.getSysSettingMap());
+
+        //系统限制信息 SysSettingLimitUtil.getSysSettingLimit()
+        modelAndView.addObject("sysSettingLimit", redisSettingMap.getSysSettingLimitMap());
+
+
+        //后端公钥
+        String publicKey = redisSettingMap.getRSAPublicKeyBase64();  //RsaUtil.getPublicKey();
+        log.info("login后端公钥:" + publicKey);
+        modelAndView.addObject("publicKey", publicKey);
+
+        //阿里云url,返回一个前缀
+        modelAndView.addObject("domainName", aliyunOSSUtil.getDomainName());
+
+        return modelAndView;
+    }
+
+    /**
+     * 跳转首页
+     */
+    @GetMapping("")
+    public void index1(HttpServletResponse response) {
+        //内部重定向
+        try {
+            response.sendRedirect(contextPath + "/index");
+        } catch (IOException e) {
+            //输出到日志文件中
+            log.error(ErrorUtil.errorInfoToString(e));
+        }
+    }
+
+    @GetMapping("index")
+    public ModelAndView index() {
+        ModelAndView modelAndView = new ModelAndView("index");
+
+        //系统信息 SysSettingUtil.getSysSetting()
+        modelAndView.addObject("sys", redisSettingMap.getSysSettingMap());
+
+        //系统限制信息 SysSettingLimitUtil.getSysSettingLimit()
+        modelAndView.addObject("sysSettingLimit", redisSettingMap.getSysSettingLimitMap());
+
+        //登录用户
+        SysUserVo sysUserVo = sysUserService.findByLoginName(SecurityUtil.getLoginUser().getUsername()).getData();
+        sysUserVo.setPassword(null);//隐藏部分属性
+        modelAndView.addObject("loginUser", sysUserVo);
+
+        //登录用户系统菜单
+        List<SysMenuVo> menuVoList = sysUserMenuService.findByUserId(sysUserVo.getUserId()).getData();
+        modelAndView.addObject("menuList", menuVoList);
+
+        //登录用户快捷菜单
+        List<SysShortcutMenuVo> shortcutMenuVoList = sysShortcutMenuService.findByUserId(sysUserVo.getUserId()).getData();
+        modelAndView.addObject("shortcutMenuList", shortcutMenuVoList);
+
+        //后端公钥
+        String publicKey = redisSettingMap.getRSAPublicKeyBase64(); // RsaUtil.getPublicKey();
+        log.info("index后端公钥:" + publicKey);
+        modelAndView.addObject("publicKey", publicKey);
+
+        //获取一个全平台的用户数据
+        Long allComUserCount = 0L;//comUsersService.findAllCount();
+        modelAndView.addObject("allComUserCount", allComUserCount);
+
+        Long todayComUserCount = 0L;// comUsersService.newToday();
+        modelAndView.addObject("todayComUserCount", todayComUserCount);
+
+        //阿里云url,返回一个前缀
+        modelAndView.addObject("domainName", aliyunOSSUtil.getDomainName());
+
+
+        return modelAndView;
+    }
+
+    /**
+     * 获取验证码图片和文本(验证码文本会保存在HttpSession中)
+     */
+    @RequestMapping("getVerifyCodeImage")
+    public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        //设置页面不缓存
+        response.setHeader("Pragma", "no-cache");
+        response.setHeader("Cache-Control", "no-cache");
+        response.setDateHeader("Expires", 0);
+        response.getOutputStream();
+        String verifyCode = VerifyCodeImageUtil.generateTextCode(VerifyCodeImageUtil.TYPE_NUM_UPPER, 4, null);
+
+        //将验证码放到HttpSession里面
+        request.getSession().setAttribute("verifyCode", verifyCode);
+        log.info("本次生成的验证码为:" + verifyCode + ",已存放到HttpSession中");
+
+        //设置输出的内容的类型为JPEG图像
+        response.setContentType("image/jpeg");
+        BufferedImage bufferedImage = VerifyCodeImageUtil.generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE, Color.BLACK, null);
+
+        //写给浏览器
+        ImageIO.write(bufferedImage, "JPEG", response.getOutputStream());
+    }
+
+    /**
+     * 跳转实时系统硬件监控
+     */
+    @GetMapping("monitor")
+    public ModelAndView monitor() {
+        return new ModelAndView("monitor.html", "port", port);
+    }
+
+    /**
+     * 跳转实时日志
+     */
+    @GetMapping("logging")
+    public ModelAndView logging() {
+        return new ModelAndView("logging.html", "port", port);
+    }
+}

+ 18 - 0
src/main/java/com/YuyeTech/TPlat/VO/AiInfoVO.java

@@ -0,0 +1,18 @@
+package com.YuyeTech.TPlat.VO;
+
+import lombok.Data;
+
+/**
+ * @author:slambb
+ * @date:2020/3/25
+ */
+@Data
+public class AiInfoVO {
+
+    private Integer aiId;
+    private String aiName;
+    private String aiAvatar;
+    private Integer aiGender;
+    private String aiType;
+
+}

+ 30 - 0
src/main/java/com/YuyeTech/TPlat/VO/EmailVO.java

@@ -0,0 +1,30 @@
+package com.YuyeTech.TPlat.VO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author:slambb
+ * @date:2021/9/18
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class EmailVO implements Serializable {
+
+    /**
+     * 邮件接收方,可多人
+     */
+    private String[] tos;
+    /**
+     * 邮件主题
+     */
+    private String subject;
+    /**
+     * 邮件内容
+     */
+    private String content;
+}

+ 22 - 0
src/main/java/com/YuyeTech/TPlat/VO/FavoritesVO.java

@@ -0,0 +1,22 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/14
+ */
+@Data
+public class FavoritesVO {
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date createTime;
+
+    private Double targetWeight;
+
+    private Integer calorie;
+
+    private Double sportTime;
+}

+ 27 - 0
src/main/java/com/YuyeTech/TPlat/VO/FitnessVO.java

@@ -0,0 +1,27 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/2
+ */
+@Data
+public class FitnessVO {
+
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy/MM/dd",timezone="GMT+8")
+    private Date startTime;
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy/MM/dd",timezone="GMT+8")
+    private Date endTime;
+
+    private Double targetWeight;
+
+    private Integer cumulativeCalorie;
+
+    private Integer calorie;
+
+    private Double sportTime;
+}

+ 35 - 0
src/main/java/com/YuyeTech/TPlat/VO/FriendInfoVO.java

@@ -0,0 +1,35 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 用户信息
+ * 返回给前端的json字段格式
+ * @author:slambb
+ * @date:2019/12/21
+ */
+@Data
+public class FriendInfoVO {
+
+    private String username;
+
+    private String gender;
+
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy/MM/dd",timezone="GMT+8")
+    private Date birthday;
+
+    private String signature;
+
+    private String avatarUrl;
+
+    private String cityCode;
+
+    private double height;
+
+    private double weight;
+
+
+}

+ 24 - 0
src/main/java/com/YuyeTech/TPlat/VO/GameVO.java

@@ -0,0 +1,24 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/3/20
+ */
+
+@Data
+public class GameVO {
+    private String gameId;
+    private String gameName;
+    private String gameDescription;
+    private String gameIcon;
+    private String gamePicture;
+    private Boolean gameFavorite;
+
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd",timezone="GMT+8")
+    private Date createTime;
+}

+ 14 - 0
src/main/java/com/YuyeTech/TPlat/VO/LoginVO.java

@@ -0,0 +1,14 @@
+package com.YuyeTech.TPlat.VO;
+
+import lombok.Data;
+
+/**
+ * @author:slambb
+ * @date:2019/12/26
+ */
+@Data
+public class LoginVO {
+    private String token;
+    //是否是新用户
+    private Boolean newUser;
+}

+ 25 - 0
src/main/java/com/YuyeTech/TPlat/VO/RankInfoVO.java

@@ -0,0 +1,25 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * @author:slambb
+ * @date:2020/3/20
+ */
+
+@Data
+public class RankInfoVO {
+
+    @JsonProperty("rankScore")
+    private Double rankScore;
+
+    @JsonProperty("rankType")
+    private Integer rankType;
+    @JsonProperty("rankShow")
+    private Integer rankShow;
+
+    @JsonProperty("rankGameId")
+    private String RObjectId;
+
+}

+ 34 - 0
src/main/java/com/YuyeTech/TPlat/VO/RankingVO.java

@@ -0,0 +1,34 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.YuyeTech.TPlat.dto.UserDTO;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author:slambb
+ * @date:2020/3/19
+ */
+@Data
+public class RankingVO {
+
+    @JsonProperty("userInfo")
+    private UserInfoVO userInfo;
+
+    @JsonProperty("userScore")
+    private Double userScore;
+
+    @JsonProperty("userRank")
+    private Long userRank;
+
+    @JsonProperty("rankingList")
+    private List<UserDTO> userInfoVOList;
+
+    @JsonProperty("rankScoreList")
+    private List<Double> scoreList;
+
+    @JsonProperty("rankingType")
+    private String type;
+
+}

+ 25 - 0
src/main/java/com/YuyeTech/TPlat/VO/ResultVO.java

@@ -0,0 +1,25 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * http 请求返回的最外层对象
+ *
+ * @author:slambb
+ * @date:2019/12/2
+ */
+
+@Data
+public class ResultVO<T> {
+    //错误码
+    private Integer code;
+    //请求返回信息
+    private String msg;
+    //请求返回数据
+    private T data;
+
+
+//    @JsonProperty("name")
+//    private String TestName;
+}

+ 38 - 0
src/main/java/com/YuyeTech/TPlat/VO/UserInfoVO.java

@@ -0,0 +1,38 @@
+package com.YuyeTech.TPlat.VO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 用户信息
+ * 返回给前端的json字段格式
+ * @author:slambb
+ * @date:2019/12/21
+ */
+@Data
+public class UserInfoVO {
+
+//    private String userId;
+
+    private String username;
+
+    private String gender;
+
+//    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy/MM/dd",timezone="GMT+8")
+    private Date birthday;
+
+    private String signature;
+
+    private String avatarUrl;
+
+    private String cityCode;
+
+    private double height;
+
+    private double weight;
+
+
+}

+ 21 - 0
src/main/java/com/YuyeTech/TPlat/annotation/Between.java

@@ -0,0 +1,21 @@
+package com.YuyeTech.TPlat.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Between {
+
+    /**
+     * 最小值的实体属性名
+     */
+    String min();
+
+    /**
+     * 最大值的实体属性名
+     */
+    String max();
+}

+ 12 - 0
src/main/java/com/YuyeTech/TPlat/annotation/Decrypt.java

@@ -0,0 +1,12 @@
+package com.YuyeTech.TPlat.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Decrypt {
+
+}

+ 12 - 0
src/main/java/com/YuyeTech/TPlat/annotation/Encrypt.java

@@ -0,0 +1,12 @@
+package com.YuyeTech.TPlat.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Encrypt {
+
+}

+ 16 - 0
src/main/java/com/YuyeTech/TPlat/annotation/In.java

@@ -0,0 +1,16 @@
+package com.YuyeTech.TPlat.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface In {
+
+    /**
+     * in的具体集合的属性名
+     */
+    String values();
+}

+ 13 - 0
src/main/java/com/YuyeTech/TPlat/annotation/Like.java

@@ -0,0 +1,13 @@
+package com.YuyeTech.TPlat.annotation;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Like {
+
+}

+ 28 - 0
src/main/java/com/YuyeTech/TPlat/annotation/RedisUpdate.java

@@ -0,0 +1,28 @@
+package com.YuyeTech.TPlat.annotation;
+
+import com.YuyeTech.TPlat.enums.GameEnum;
+import com.YuyeTech.TPlat.enums.RedisType;
+
+import javax.persistence.GenerationType;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RedisUpdate {
+
+    /**
+     * key值,对应redis里面的key
+     * @return
+     */
+    String key() default "";
+
+    /**
+     * 当前枚举策略
+     * @return
+     */
+    RedisType strategy() default RedisType.NULL;
+
+}

+ 112 - 0
src/main/java/com/YuyeTech/TPlat/aspect/AuthorizeFilter.java

@@ -0,0 +1,112 @@
+package com.YuyeTech.TPlat.aspect;
+
+import com.YuyeTech.TPlat.VO.ResultVO;
+import com.YuyeTech.TPlat.constant.RedisConstant;
+import com.YuyeTech.TPlat.enums.ResultEnum;
+import com.YuyeTech.TPlat.utils.JsonUtils;
+import com.YuyeTech.TPlat.utils.ResultVOUtil;
+import com.YuyeTech.TPlat.utils.TokenRequestWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author:slambb
+ * @date:2019/12/27
+ */
+@Slf4j
+//@WebFilter(filterName = "authorizeFilter", urlPatterns = "/*")
+public class AuthorizeFilter implements Filter {
+
+    @Autowired
+    StringRedisTemplate redisTemplate;
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        //处理跨域请求
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        response.setHeader("Access-Control-Allow-Origin", "*");
+        response.setHeader("Access-Control-Allow-Credentials", "true");
+        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
+        response.setHeader("Access-Control-Max-Age", "3600");
+        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept , token");
+//        log.info("********进入过滤器********");
+        HttpServletRequest req = (HttpServletRequest) servletRequest;
+        String method = req.getMethod();
+//        log.info("method:{}",method);
+        if (method.equals("OPTIONS")) {
+            response.setStatus(200);
+            return;
+        }
+        String token = req.getHeader("token");
+        Integer platform = req.getIntHeader("platform");
+
+        boolean isFilter = false;
+        Object userId = null;
+        String path = req.getServletPath();
+        //静态资源放行
+        String reg = ".+(.JPEG|.jpeg|.JPG|.jpg|.png|.PNG|.js|.css|.woff|.woff2|.ttf)$";
+        Matcher matcher = Pattern.compile(reg).matcher(path);
+        //登录,获取验证码,不用登录的接口
+        if (path.indexOf("login") > -1 ||
+                path.indexOf("getCode") > -1 ||
+                path.indexOf("dontLogin") > -1 ||
+                path.indexOf("client_game") > -1 ||
+                path.indexOf("backstage") > -1 ||
+//                path.indexOf("css") > -1 ||
+                matcher.find()||
+                path.indexOf("bundles") > -1||
+                path.indexOf("plugins") > -1||
+                path.indexOf("angular.min.js") > -1 ||
+                /**
+                 * 3D视界接口放行
+                 */
+                path.indexOf("td") > -1
+        ) {
+            //登录情况直接放行
+//            log.info("********登录情况直接放行********");
+            filterChain.doFilter(servletRequest, response);
+            return;
+        }
+        if (null == token || token.isEmpty()) {
+//            log.info("Url =={} == {}",req.getRequestURI(),req.getServletPath());
+//          throw new AuthorizeException(ResultEnum.TOKEN_DOES_NOT_EXIST.getCode(), ResultEnum.TOKEN_DOES_NOT_EXIST.getMessage());
+            ResultVO resultVO = ResultVOUtil.error(ResultEnum.TOKEN_IS_ILLEGAL.getCode(), ResultEnum.TOKEN_IS_ILLEGAL.getMessage());
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(JsonUtils.toJson(resultVO));
+            return;
+        } else {
+            userId = redisTemplate.opsForHash().get(String.format(RedisConstant.TOKEN_PREFIX, token), "userId");
+            if (!StringUtils.isEmpty(userId)) {
+                isFilter = true;
+            } else {
+                ResultVO resultVO = ResultVOUtil.error(ResultEnum.TOKEN_IS_ILLEGAL.getCode(), ResultEnum.TOKEN_IS_ILLEGAL.getMessage());
+                response.setCharacterEncoding("utf-8");
+                response.getWriter().print(JsonUtils.toJson(resultVO));
+                return;
+            }
+        }
+        if (isFilter) {
+            filterChain.doFilter(new TokenRequestWrapper((HttpServletRequest) servletRequest, userId.toString(),platform), response);
+        }
+
+    }
+}

+ 180 - 0
src/main/java/com/YuyeTech/TPlat/aspect/SafetyAspect.java

@@ -0,0 +1,180 @@
+package com.YuyeTech.TPlat.aspect;
+
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import com.YuyeTech.TPlat.annotation.RedisUpdate;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.YuyeTech.TPlat.annotation.Decrypt;
+import com.YuyeTech.TPlat.annotation.Encrypt;
+import com.YuyeTech.TPlat.common.pojo.Result;
+import com.YuyeTech.TPlat.utils.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+
+/**
+ * AES + RSA 加解密AOP处理
+ */
+@Slf4j
+@Aspect
+@Component
+public class SafetyAspect {
+
+    @Autowired
+    private RedisSettingMap redisSettingMap;
+
+    private final JwtTokenUtil jwtTokenUtil;
+    private final String tokenHeader;
+
+    public SafetyAspect(JwtTokenUtil jwtTokenUtil, @Value("${jwt.token}") String tokenHeader) {
+        this.jwtTokenUtil = jwtTokenUtil;
+        this.tokenHeader = tokenHeader;
+    }
+
+    /**
+     * Pointcut 切入点
+     */
+    @Pointcut(value = "execution(public * com.YuyeTech.TPlat.sys.*.controller.*.*(..)) || " +
+            "execution(public * com.YuyeTech.TPlat.*.controller.*.*(..))||" +
+            "execution(public * com.YuyeTech.TPlat.game.*.controller.*.*(..))")
+    public void safetyAspect() {
+    }
+
+    /**
+     * 环绕通知
+     */
+    @Around(value = "safetyAspect()")
+    public Object around(ProceedingJoinPoint pjp) {
+        try {
+            log.info("---------------进入aop---------------");
+            //判断api加密开关是否开启 SysSettingUtil.getSysSetting()
+            if ("N".equals(redisSettingMap.getSysSettingMap().getSysApiEncrypt())) {
+                return pjp.proceed(pjp.getArgs());
+            }
+
+
+            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+            assert attributes != null;
+            //request对象
+            HttpServletRequest request = attributes.getRequest();
+
+            //http请求方法  post get
+            String httpMethod = request.getMethod().toLowerCase();
+
+            //method方法
+            Method method = ((MethodSignature) pjp.getSignature()).getMethod();
+
+            //method方法上面的注解
+            Annotation[] annotations = method.getAnnotations();
+
+            //方法的形参参数
+            Object[] args = pjp.getArgs();
+
+            //是否有@Decrypt
+            boolean hasDecrypt = false;
+            //是否有@Encrypt
+            boolean hasEncrypt = false;
+            //是否有@RedisUpdate
+            boolean hasRedisUpdate = false;
+            for (Annotation annotation : annotations) {
+                if (annotation.annotationType() == Decrypt.class) {
+                    hasDecrypt = true;
+                }
+                if (annotation.annotationType() == Encrypt.class) {
+                    hasEncrypt = true;
+                }
+                if(annotation.annotationType() == RedisUpdate.class){
+                    hasRedisUpdate = true;
+                }
+            }
+
+            //前端公钥
+            String publicKey = null;
+
+            //jackson
+            ObjectMapper mapper = new ObjectMapper();
+            //jackson 序列化和反序列化 date处理
+            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+
+            //执行方法之前解密,且只拦截post请求
+            if ("post".equals(httpMethod) && hasDecrypt) {
+                //AES加密后的数据
+                String data = request.getParameter("data");
+                //后端RSA公钥加密后的AES的key
+                String aesKey = request.getParameter("aesKey");
+                //前端公钥
+                publicKey = request.getParameter("publicKey");
+                log.info("前端公钥:" + publicKey);
+                //后端私钥解密的到AES的key
+                //切换一个方式
+                log.info(redisSettingMap.getRSAPrivateKeyBase64());
+                RSA rsa = new RSA(redisSettingMap.getRSAPrivateKeyBase64(), null);
+                byte[] plaintext = rsa.decrypt(Base64.decodeBase64(aesKey), KeyType.PrivateKey);
+                //byte[] plaintext = RsaUtil.decryptByPrivateKey(Base64.decodeBase64(aesKey), RsaUtil.getPrivateKey());
+                aesKey = new String(plaintext);
+                log.info("解密出来的AES的key:" + aesKey);
+                //AES解密得到明文data数据
+                String decrypt = AesUtil.decrypt(data, aesKey);
+                log.info("解密出来的data数据:" + decrypt);
+                //设置到方法的形参中,目前只能设置只有一个参数的情况
+                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                //注:参数最好用Vo对象来接参,单用String来接,args有长度但获取为空,很奇怪不知道为什么
+                if (args.length > 0) {
+                    args[0] = mapper.readValue(decrypt, args[0].getClass());
+                }
+                //HashMap hashMap = mapper.readValue(decrypt, HashMap.class);
+                //ParameterRequestWrapper parameterRequestWrapper = new ParameterRequestWrapper(request);
+                //for (Object key : hashMap.keySet()) {
+                //    parameterRequestWrapper.addParameter(String.valueOf(key), hashMap.get(key));
+                //}
+                //request = (HttpServletRequest) parameterRequestWrapper;
+            }
+
+            //执行并替换最新形参参数   PS:这里有一个需要注意的地方,method方法必须是要public修饰的才能设置值,private的设置不了
+            Object o = pjp.proceed(args);
+
+            //返回结果之前加密
+            if (hasEncrypt) {
+                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                //每次响应之前随机获取AES的key,加密data数据
+                String key = AesUtil.getKey();
+                log.info("AES的key:" + key);
+                String dataString = mapper.writeValueAsString(o);
+                log.info("需要加密的data数据:" + dataString);
+                String data = AesUtil.encrypt(dataString, key);
+
+                //用前端的公钥来解密AES的key,并转成Base64
+                //String aesKey = Base64.encodeBase64String(RsaUtil.encryptByPublicKey(key.getBytes(), publicKey));
+                //切换一个方式
+                RSA rsa = new RSA(null, publicKey);
+                String aesKey = Base64.encodeBase64String(rsa.encrypt(key.getBytes(), KeyType.PublicKey));
+                //转json字符串并转成Object对象,设置到Result中并赋值给返回值o
+                o = Result.of(mapper.readValue("{\"data\":\"" + data + "\",\"aesKey\":\"" + aesKey + "\"}", Object.class));
+            }
+
+            //返回
+            return o;
+
+        } catch (Throwable e) {
+            //输出到日志文件中
+            log.error(ErrorUtil.errorInfoToString(e));
+            return Result.of(null, false, "加解密异常:\n\t" + e.getMessage());
+        }
+    }
+
+}

+ 82 - 0
src/main/java/com/YuyeTech/TPlat/common/controller/CommonController.java

@@ -0,0 +1,82 @@
+package com.YuyeTech.TPlat.common.controller;
+
+import com.YuyeTech.TPlat.annotation.Decrypt;
+import com.YuyeTech.TPlat.annotation.Encrypt;
+import com.YuyeTech.TPlat.common.pojo.PageInfo;
+import com.YuyeTech.TPlat.common.pojo.Result;
+import com.YuyeTech.TPlat.common.service.CommonService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+
+/**
+ * 通用Controller
+ *
+ * @param <V> 实体类Vo
+ * @param <E> 实体类
+ * @param <T> id主键类型
+ */
+public class CommonController<V, E, T> {
+
+    @Autowired
+    private CommonService<V, E, T> commonService;
+
+    /*
+        CRUD、分页、排序测试
+     */
+    @PostMapping("page")
+    @Decrypt
+    @Encrypt
+    public Result<PageInfo<V>> page(V entityVo) {
+        return commonService.page(entityVo);
+    }
+
+    @PostMapping("list")
+    @Decrypt
+    @Encrypt
+    public Result<List<V>> list(V entityVo) {
+        return commonService.list(entityVo);
+    }
+
+    @GetMapping("get/{id}")
+    public Result<V> get(@PathVariable("id") T id) {
+        return commonService.get(id);
+    }
+
+    /**
+     * 保存对应vo数据
+     * @param entityVo
+     * @return
+     */
+    @PostMapping("save")
+    @Decrypt
+    @Encrypt
+    public Result<V> save(V entityVo) {
+        return commonService.save(entityVo);
+    }
+
+    @DeleteMapping("delete/{id}")
+    public Result<T> delete( @PathVariable("id") T id) {
+        /*
+        批量删除
+        @DeleteMapping("deleteBatch")
+        public Result<T> deleteBatch(@RequestBody List<String> ids){}
+        前端调用:
+        $.ajax({
+            url: ctx + "deleteBatch",
+            type: "DELETE",
+            data: JSON.stringify([id1,id2]),
+            dataType: "JSON",
+            contentType: 'application/json',
+            success: function (data) {
+
+            }
+        });
+         */
+        return commonService.delete(id);
+    }
+}

+ 22 - 0
src/main/java/com/YuyeTech/TPlat/common/pojo/IpVo.java

@@ -0,0 +1,22 @@
+package com.YuyeTech.TPlat.common.pojo;
+
+import lombok.Data;
+
+/**
+ * ip
+ */
+@Data
+public class IpVo {
+    private String ip;//IP地址
+    private String pro;//省
+    private String proCode;//省编码
+    private String city;//城市
+    private String cityCode;//城市编码
+    private String region;//区
+    private String regionCode;//区编码
+    private String addr;//详细地址 + 运营商
+
+    //主要用于接参,无实际意义
+    private String regionNames;
+    private String err;
+}

+ 31 - 0
src/main/java/com/YuyeTech/TPlat/common/pojo/MonitorVo.java

@@ -0,0 +1,31 @@
+package com.YuyeTech.TPlat.common.pojo;
+
+import lombok.Data;
+
+/**
+ * 系统监控信息Vo
+ */
+@Data
+public class MonitorVo {
+    private String os;//操作系统
+    private String runTime;//程序启动时间
+    private String jvmJavaVersion;//java版本
+
+    //jvm
+    private String jvmHeapInit;//jvm内存的初始大小
+    private String jvmHeapMax;//jvm最大可用内存量
+    private String jvmHeapUsed;//jvm已使用的内存量
+    private String jvmHeapCommitted;//jvm已申请的内存量
+    private String jvmNonHeapInit;//jvm内存的初始大小
+    private String jvmNonHeapMax;//jvm最大可用内存量
+    private String jvmNonHeapUsed;//jvm已使用的内存量
+    private String jvmNonHeapCommitted;//jvm已申请的内存量
+
+    //硬件信息
+    private String cpuInfo;//CPU信息
+    private String cpuUseRate;//CPU使用率
+    private String ramTotal;//系统内存总量
+    private String ramUsed;//已使用的系统内存量
+    private String diskTotal;//系统磁盘总量
+    private String diskUsed;//已使用的系统磁盘量
+}

+ 39 - 0
src/main/java/com/YuyeTech/TPlat/common/pojo/PageCondition.java

@@ -0,0 +1,39 @@
+package com.YuyeTech.TPlat.common.pojo;
+
+import lombok.Data;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.thymeleaf.util.StringUtils;
+
+/**
+ * 分页条件(参考JqGrid插件)
+ */
+@Data
+public class PageCondition {
+    private int page = 1;//当前页码
+    private int rows = 10;//页面大小
+    private String sidx;//排序字段
+    private String sord;//排序方式
+
+    /**
+     * 获取JPA的分页查询对象
+     */
+    public Pageable getPageable() {
+        //处理非法页码
+        if (page < 0) {
+            page = 1;
+        }
+        //处理非法页面大小
+        if (rows < 0) {
+            rows = 10;
+        }
+        //处理排序
+        if(!StringUtils.isEmpty(sidx) && !StringUtils.isEmpty(sord)){
+            Direction direction = "desc".equals(sidx.toLowerCase()) ? Direction.DESC : Direction.ASC;
+            return PageRequest.of(page - 1, rows, Sort.by(direction, sord));
+        }
+        return PageRequest.of(page - 1, rows);
+    }
+}

+ 83 - 0
src/main/java/com/YuyeTech/TPlat/common/pojo/PageInfo.java

@@ -0,0 +1,83 @@
+package com.YuyeTech.TPlat.common.pojo;
+
+import com.YuyeTech.TPlat.utils.CopyUtil;
+import lombok.Data;
+import org.hibernate.query.internal.NativeQueryImpl;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.repository.support.PageableExecutionUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.util.List;
+
+/**
+ * 分页对象(参考JqGrid插件)
+ */
+@Data
+public class PageInfo<M> {
+    private int page;//当前页码
+    private int pageSize;//页面大小
+    private String sidx;//排序字段
+    private String sord;//排序方式
+
+    private List<M> rows;//分页结果
+    private int records;//总记录数
+    private int total;//总页数
+
+    /**
+     * 获取统一分页结果
+     */
+    public static <M> PageInfo<M> of(Page page, Class<M> entityModelClass) {
+        int records = (int) page.getTotalElements();
+        int pageSize = page.getSize();
+        int total = records % pageSize == 0 ? records / pageSize : records / pageSize + 1;
+
+        PageInfo<M> pageInfo = new PageInfo<>();
+        pageInfo.setPage(page.getNumber() + 1);//页码
+        pageInfo.setPageSize(pageSize);//页面大小
+        pageInfo.setRows(CopyUtil.copyList(page.getContent(), entityModelClass));//分页结果
+        pageInfo.setRecords(records);//总记录数
+        pageInfo.setTotal(total);//总页数
+        return pageInfo;
+    }
+
+    /**
+     * 设置当前页面的content
+     * @param page
+     * @param content
+     * @param <M>
+     * @return
+     */
+    public static <M> PageInfo<M> customContent(Page page, List<M> content) {
+        int records = (int) page.getTotalElements();
+        int pageSize = page.getSize();
+        int total = records % pageSize == 0 ? records / pageSize : records / pageSize + 1;
+
+        PageInfo<M> pageInfo = new PageInfo<>();
+        pageInfo.setPage(page.getNumber() + 1);//页码
+        pageInfo.setPageSize(pageSize);//页面大小
+        pageInfo.setRows(content);//分页结果
+        pageInfo.setRecords(records);//总记录数
+        pageInfo.setTotal(total);//总页数
+        return pageInfo;
+    }
+
+    /**
+     * 获取JPA的分页对象
+     */
+    public static Page getJPAPage(Query query, PageRequest pageRequest, EntityManager em) {
+        query.setFirstResult((int) pageRequest.getOffset());
+        query.setMaxResults(pageRequest.getPageSize());
+
+        //获取分页结果
+        return PageableExecutionUtils.getPage(query.getResultList(), pageRequest, () -> {
+            //设置countQuerySQL语句
+            Query countQuery = em.createNativeQuery("select count(*) from ( " + ((NativeQueryImpl) query).getQueryString() + " ) count_table");
+            //设置countQuerySQL参数
+            query.getParameters().forEach(parameter -> countQuery.setParameter(parameter.getName(), query.getParameterValue(parameter.getName())));
+            //返回一个总数
+            return Long.valueOf(countQuery.getResultList().get(0).toString());
+        });
+    }
+}

+ 42 - 0
src/main/java/com/YuyeTech/TPlat/common/pojo/ParameterRequestWrapper.java

@@ -0,0 +1,42 @@
+package com.YuyeTech.TPlat.common.pojo;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 重写一个RequestWrapper,实现可修改Parameter的值
+ */
+public class ParameterRequestWrapper extends HttpServletRequestWrapper {
+
+    private Map<String , String[]> params = new HashMap<String, String[]>();
+
+    public ParameterRequestWrapper(HttpServletRequest request) {
+        super(request);
+        this.params.putAll(request.getParameterMap());
+    }
+
+    //重写getParameter,从当前类中的map获取(查看UsernamePasswordAuthenticationFilter可知)
+    @Override
+    public String getParameter(String name) {
+        String[]values = params.get(name);
+        if(values == null || values.length == 0) {
+            return null;
+        }
+        return values[0];
+    }
+
+    //增加参数
+    public void addParameter(String name, Object value) {
+        if(value != null) {
+            if(value instanceof String[]) {
+                params.put(name , (String[])value);
+            }else if(value instanceof String) {
+                params.put(name , new String[] {(String)value});
+            }else {
+                params.put(name , new String[] {String.valueOf(value)});
+            }
+        }
+    }
+}

+ 79 - 0
src/main/java/com/YuyeTech/TPlat/common/pojo/Result.java

@@ -0,0 +1,79 @@
+package com.YuyeTech.TPlat.common.pojo;
+
+import com.YuyeTech.TPlat.enums.ResultEnum;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 统一返回对象
+ */
+
+@Data
+public class Result<T> implements Serializable {
+    /**
+     * 通信数据
+     */
+    private T data;
+    /**
+     * 通信状态
+     */
+    private boolean flag = true;
+    /**
+     * 通信描述
+     */
+    private String msg = "操作成功";
+
+    /**
+     * 通信code
+     */
+    private Integer code = 0;
+
+    /**
+     * 通过静态方法获取实例
+     */
+    public static <T> Result<T> of(T data) {
+        return new Result<>(data);
+    }
+
+    public static <T> Result<T> of(T data, boolean flag) {
+        return new Result<>(data, flag);
+    }
+
+    public static <T> Result<T> of(T data, boolean flag, String msg) {
+        return new Result<>(data, flag, msg);
+    }
+    public static <T> Result<T> of(T data, boolean flag, String msg,Integer code) {
+        return new Result<>(data, flag, msg,code);
+    }
+
+    public static <T> Result<T> of(T data, boolean flag, ResultEnum resultEnum) {
+        return new Result<>(data, flag, resultEnum.getMessage(),resultEnum.getCode());
+    }
+    @Deprecated
+    public Result() {
+
+    }
+
+    private Result(T data) {
+        this.data = data;
+    }
+
+    private Result(T data, boolean flag) {
+        this.data = data;
+        this.flag = flag;
+    }
+
+    private Result(T data, boolean flag, String msg) {
+        this.data = data;
+        this.flag = flag;
+        this.msg = msg;
+    }
+
+    private Result(T data, boolean flag, String msg ,Integer code) {
+        this.data = data;
+        this.flag = flag;
+        this.msg = msg;
+        this.code = code;
+    }
+}

+ 16 - 0
src/main/java/com/YuyeTech/TPlat/common/repository/CommonRepository.java

@@ -0,0 +1,16 @@
+package com.YuyeTech.TPlat.common.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.NoRepositoryBean;
+
+/**
+ * 通用Repository
+ *
+ * @param <E> 实体类
+ * @param <T> id主键类型
+ */
+@NoRepositoryBean
+public interface CommonRepository<E,T> extends JpaRepository<E,T>, JpaSpecificationExecutor<E> {
+
+}

+ 58 - 0
src/main/java/com/YuyeTech/TPlat/common/service/CommonService.java

@@ -0,0 +1,58 @@
+package com.YuyeTech.TPlat.common.service;
+
+
+import com.YuyeTech.TPlat.common.pojo.PageInfo;
+import com.YuyeTech.TPlat.common.pojo.Result;
+import com.YuyeTech.TPlat.enums.RedisType;
+
+import java.util.List;
+
+/**
+ * 通用Service
+ *
+ * @param <V> 实体类Vo
+ * @param <E> 实体类
+ * @param <T> id主键类型
+ */
+public interface CommonService<V, E,T> {
+
+    Result<PageInfo<V>> page(V entityVo);
+
+    PageInfo<V> pageByClass(V entityVo, Class entityModelClass);
+
+    Result<List<V>> list(V entityVo);
+
+
+    Result<V> get(T id);
+
+    V getVo(T id);
+
+    Result<V> save(V entityVo);
+
+    Result<T> delete(T id);
+
+    //更新当前列表数据到缓存
+    List<E> updateListToCache(String key);
+    //添加缓存列表操作
+    List<E> getListFromCache(String key);
+
+    //注解操作
+
+    /**
+     * 获取对应的列表缓存
+     * @return
+     */
+    List<E> getListFromCache();
+
+    /**
+     * 更新对应的列表缓存
+     * @return
+     */
+    List<E> updateListToCache();
+
+
+    V saveAndCache(V entityVo);
+
+    T deleteAndCache(T id);
+
+}

+ 302 - 0
src/main/java/com/YuyeTech/TPlat/common/service/CommonServiceImpl.java

@@ -0,0 +1,302 @@
+package com.YuyeTech.TPlat.common.service;
+
+import cn.hutool.json.JSONUtil;
+import com.YuyeTech.TPlat.common.pojo.PageCondition;
+import com.YuyeTech.TPlat.common.pojo.PageInfo;
+import com.YuyeTech.TPlat.common.pojo.Result;
+import com.YuyeTech.TPlat.common.repository.CommonRepository;
+import com.YuyeTech.TPlat.enums.RedisType;
+import com.YuyeTech.TPlat.utils.CopyUtil;
+import com.YuyeTech.TPlat.utils.ErrorUtil;
+import com.YuyeTech.TPlat.utils.UUIDUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.hibernate.annotations.NotFound;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 通用Service实现类
+ *
+ * @param <V> 实体类Vo
+ * @param <E> 实体类
+ * @param <T> id主键类型
+ */
+@Slf4j
+@CacheConfig(cacheNames = "com",keyGenerator = "keyGenerator")
+public class CommonServiceImpl<V, E, T> implements CommonService<V, E, T> {
+
+    private Class<V> entityVoClass;//实体类Vo
+
+    private Class<E> entityClass;//实体类
+
+
+    @Autowired
+    private CommonRepository<E, T> commonRepository;//注入实体类仓库
+
+    @Autowired
+    private StringRedisTemplate redisTemplate; //注入缓存机制
+
+    @Value("${spring.application.name}")
+    private String applicationName;
+    //key 的前缀
+    private String keyPrefixStr = "com:";
+
+
+    public CommonServiceImpl() {
+        Type[] types = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
+        this.entityVoClass = (Class<V>) types[0];
+        this.entityClass = (Class<E>) types[1];
+    }
+
+    @Override
+    public Result<PageInfo<V>> page(V entityVo) {
+        //实体类缺失分页信息
+        if (!(entityVo instanceof PageCondition)) {
+            throw new RuntimeException("实体类" + entityVoClass.getName() + "未继承PageCondition。");
+        }
+        PageCondition pageCondition = (PageCondition) entityVo;
+        Page<E> page = commonRepository.findAll(Example.of(CopyUtil.copy(entityVo, entityClass)), pageCondition.getPageable());
+        return Result.of(PageInfo.of(page, entityVoClass));
+    }
+
+    @Override
+    public PageInfo<V> pageByClass(V entityVo, Class entityModelClass) {
+        //实体类缺失分页信息
+        if (!(entityVo instanceof PageCondition)) {
+            throw new RuntimeException("实体类" + entityVoClass.getName() + "未继承PageCondition。");
+        }
+        PageCondition pageCondition = (PageCondition) entityVo;
+        Page<E> page = commonRepository.findAll(Example.of(CopyUtil.copy(entityVo, entityClass)), pageCondition.getPageable());
+        return PageInfo.of(page, entityModelClass);
+    }
+
+    @Override
+    public Result<List<V>> list(V entityVo) {
+        List<E> entityList = commonRepository.findAll(Example.of(CopyUtil.copy(entityVo, entityClass)));
+        List<V> entityModelList = CopyUtil.copyList(entityList, entityVoClass);
+        return Result.of(entityModelList);
+    }
+
+    @Override
+    public Result<V> get(T id) {
+        Optional<E> optionalE = commonRepository.findById(id);
+        if (!optionalE.isPresent()) {
+            return Result.of(null, false, "ID不存在!");
+        }
+        return Result.of(CopyUtil.copy(optionalE.get(), entityVoClass));
+    }
+
+    @Override
+    public V getVo(T id) {
+        Optional<E> optionalE = commonRepository.findById(id);
+        return !optionalE.isPresent() ? null : CopyUtil.copy(optionalE.get(), entityVoClass);
+    }
+
+    @Override
+    public Result<V> save(V entityVo) {
+        E e = this.saveEntityVo(entityVo);
+        return Result.of(CopyUtil.copy(e, entityVoClass));
+    }
+
+    @Override
+    public Result<T> delete(T id) {
+        commonRepository.deleteById(id);
+        return Result.of(id);
+    }
+
+
+    /**
+     * 更新当前列表数据到缓存
+     *
+     * @param key
+     */
+    public List<E> updateListToCache(String key) {
+        key = keyPrefixStr.concat(key);
+        List<E> entityList = commonRepository.findAll();
+        redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(entityList));
+        return entityList;
+    }
+
+
+    /**
+     * 从缓存中获取列表,没有缓存更新一次数据库数据到缓存
+     *
+     * @param key
+     * @return
+     */
+    @Override
+    public List<E> getListFromCache(String key) {
+        key = keyPrefixStr.concat(key);
+        List<E> entityList;
+        String s = redisTemplate.opsForValue().get(key);
+        if (StringUtils.hasText(s)) {
+            entityList = JSONUtil.toList(s, entityClass);
+        } else {
+            entityList = commonRepository.findAll();
+            redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(entityList));
+        }
+        return entityList;
+    }
+
+
+    /**
+     * 检测是否有对应的缓存,没有则写入缓存
+     * 注意:如果缓存有数据,不会再更新缓存
+     * @return
+     */
+    @Override
+    @Cacheable(key = "targetClass+'_findAll'")
+    public List<E> getListFromCache() {
+        List<E> entityList = commonRepository.findAll();
+        return entityList;
+    }
+
+    /**
+     * 更新数据后重新获取全部数据到缓存
+     * @return
+     */
+    @Override
+    @CachePut(key = "targetClass+'_findAll'")
+    public List<E> updateListToCache() {
+        List<E> entityList = commonRepository.findAll();
+        return entityList;
+    }
+
+
+    @Override
+    public V saveAndCache(V entityVo) {
+        E e = this.saveEntityVo(entityVo);
+        //更新当前缓存
+        this.updateListToCache();
+        return CopyUtil.copy(e, entityVoClass);
+    }
+
+    @Override
+    public T deleteAndCache(T id) {
+        commonRepository.deleteById(id);
+        //更新当前缓存
+        this.updateListToCache();
+        return id;
+    }
+
+    /**
+     * 保存操作
+     * @param entityVo
+     * @return
+     */
+    private E saveEntityVo(V entityVo) {
+        //传进来的对象(属性可能残缺)
+        E entity = CopyUtil.copy(entityVo, entityClass);
+
+        //最终要保存的对象
+        E entityFull = entity;
+
+        //为空的属性值,忽略属性,BeanUtils复制的时候用到
+        List<String> ignoreProperties = new ArrayList<String>();
+
+        //获取最新数据,解决部分更新时jpa其他字段设置null问题
+        try {
+            //新增 true,更新 false,要求实体类的Id属性排在第一位,因为for循环读取是按照顺序的
+            boolean isInsert = false;
+
+            //反射获取Class的属性(Field表示类中的成员变量)
+            for (Field field : entity.getClass().getDeclaredFields()) {
+                //获取授权
+                field.setAccessible(true);
+                //属性名称
+                String fieldName = field.getName();
+                //属性的值
+                Object fieldValue = field.get(entity);
+
+                //找出Id主键,自增的不设置
+                if (field.isAnnotationPresent(Id.class)) {
+                    if (!field.isAnnotationPresent(GeneratedValue.class)) {
+                        //UUID 部分
+                        if (!StringUtils.isEmpty(fieldValue)) {
+                            //如果Id主键不为空,则为更新
+                            Optional<E> one = commonRepository.findById((T) fieldValue);
+                            if (one.isPresent()) {
+                                entityFull = one.get();
+                            }
+                        } else {
+                            //如果Id主键为空,则为新增
+                            fieldValue = UUIDUtil.getUUID();
+                            //set方法,第一个参数是对象
+                            field.set(entity, fieldValue);
+                            isInsert = true;
+                        }
+                    } else {
+                        //自增id处理数据
+                        if (!StringUtils.isEmpty(fieldValue)) {
+                            //如果Id主键不为空,则为更新
+                            Optional<E> one = commonRepository.findById((T) fieldValue);
+                            if (one.isPresent()) {
+                                entityFull = one.get();
+                            }
+                        } else {
+                            //如果Id主键为空,则为新增
+                            //单纯插入数据,id自增
+                            isInsert = true;
+                        }
+                    }
+
+                }
+                //Boolean is = "createTime".equals(fieldName);
+                //if(is){
+                //    log.info(isInsert +" == "+ is+" == "+StringUtils.isEmpty(fieldValue));
+                //}
+                //如果前端不传这两个值,后台来维护创建时间、更新时间
+                if (isInsert && "createTime".equals(fieldName) && StringUtils.isEmpty(fieldValue)) {
+                    //先赋值给fieldValue,以免后续进行copy对象判断属性是否为忽略属性是出错
+                    fieldValue = new Date();
+
+                    //set方法,第一个参数是对象
+                    field.set(entity, fieldValue);
+                }
+                if ("updateTime".equals(fieldName) && StringUtils.isEmpty(fieldValue)) {
+                    //先赋值给fieldValue,以免后续进行copy对象判断属性是否为忽略属性是出错
+                    fieldValue = new Date();
+
+                    //set方法,第一个参数是对象
+                    field.set(entity, fieldValue);
+                }
+
+                //找出值为空的属性,值为空则为忽略属性,或者被NotFound标注,我们复制的时候不进行赋值
+                if (null == fieldValue || field.isAnnotationPresent(NotFound.class)) {
+                    ignoreProperties.add(fieldName);
+                }
+            }
+            /*
+                org.springframework.beans BeanUtils.copyProperties(A,B); 是A中的值付给B
+                org.apache.commons.beanutils; BeanUtils.copyProperties(A,B);是B中的值付给A
+                把entity的值赋给entityFull,第三个参数是忽略属性,表示不进行赋值
+             */
+            BeanUtils.copyProperties(entity, entityFull, ignoreProperties.toArray(new String[0]));
+        } catch (IllegalAccessException e) {
+            //输出到日志文件中
+            log.error(ErrorUtil.errorInfoToString(e));
+        }
+
+        E e = commonRepository.save(entityFull);
+        return e;
+    }
+}

+ 32 - 0
src/main/java/com/YuyeTech/TPlat/config/AliyunConfig.java

@@ -0,0 +1,32 @@
+package com.YuyeTech.TPlat.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author:slambb
+ * @date:2019/12/16
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "aliyun")
+public class AliyunConfig {
+    //公共
+    private String accessKeyId;
+    private String AccessKeySecret;
+    //oss 服务
+    private Boolean usingDomain;
+    private String domainName;
+    private String endpoint;
+    private String bucketName;
+    private String fileHost;
+    private String fileAvatar;
+    private String filePublicAvatar;
+    private String fileGameIcon;
+    private String filePictures;
+    //短信服务
+    private String regionId;
+    private String signName;
+    private String templateCode;
+}

+ 18 - 0
src/main/java/com/YuyeTech/TPlat/config/GameConfigTime.java

@@ -0,0 +1,18 @@
+package com.YuyeTech.TPlat.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author:slambb
+ * @date:2020/7/15
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "game")
+public class GameConfigTime {
+    //设置时间
+    private String endTime;
+
+}

+ 34 - 0
src/main/java/com/YuyeTech/TPlat/config/WebConfig.java

@@ -0,0 +1,34 @@
+package com.YuyeTech.TPlat.config;
+
+import com.YuyeTech.TPlat.aspect.AuthorizeFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.filter.DelegatingFilterProxy;
+
+import javax.servlet.Filter;
+
+/**
+ * @author:slambb
+ * @date:2019/12/27
+ */
+//@Configuration
+//public class WebConfig {
+//
+//    @Bean
+//    public Filter AuthorizeFilter() {
+//        return new AuthorizeFilter();
+//    }
+//
+//
+//    @Bean
+//    public FilterRegistrationBean authorizeFilterRegistration() {
+//        FilterRegistrationBean registration = new FilterRegistrationBean();
+//        registration.setFilter(new DelegatingFilterProxy("AuthorizeFilter"));
+//        registration.addUrlPatterns("/*");
+//        registration.setName("AuthorizeFilter");
+//        registration.setOrder(1);
+//        return registration;
+//    }
+//
+//}

+ 20 - 0
src/main/java/com/YuyeTech/TPlat/config/WechatAccountConfig.java

@@ -0,0 +1,20 @@
+package com.YuyeTech.TPlat.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author:slambb
+ * @date:2019/12/4
+ */
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "wechat")
+public class WechatAccountConfig {
+
+    private String wxAppId;
+
+    private String wxAppSecret;
+}

+ 147 - 0
src/main/java/com/YuyeTech/TPlat/config/WxMaConfiguration.java

@@ -0,0 +1,147 @@
+package com.YuyeTech.TPlat.config;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
+import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
+import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
+import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
+import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
+import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
+import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
+import me.chanjar.weixin.common.error.WxErrorException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author:slambb
+ * @date:2019/12/13
+ */
+@Configuration
+@EnableConfigurationProperties(WxMaProperties.class)
+public class WxMaConfiguration {
+    private WxMaProperties properties;
+
+    private static Map<String, WxMaMessageRouter> routers = Maps.newHashMap();
+    private static Map<String, WxMaService> maServices = Maps.newHashMap();
+
+    @Autowired
+    public WxMaConfiguration(WxMaProperties properties) {
+        this.properties = properties;
+    }
+
+    public static WxMaService getMaService(String appid) {
+        WxMaService wxService = maServices.get(appid);
+        if (wxService == null) {
+            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
+        }
+
+        return wxService;
+    }
+
+    public static WxMaMessageRouter getRouter(String appid) {
+        return routers.get(appid);
+    }
+
+    @PostConstruct
+    public void init() {
+        List<WxMaProperties.Config> configs = this.properties.getConfigs();
+        if (configs == null) {
+            throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
+        }
+
+        maServices = configs.stream()
+                .map(a -> {
+                    WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
+                    config.setAppid(a.getAppid());
+                    config.setSecret(a.getSecret());
+                    config.setToken(a.getToken());
+                    config.setAesKey(a.getAesKey());
+                    config.setMsgDataFormat(a.getMsgDataFormat());
+
+                    WxMaService service = new WxMaServiceImpl();
+                    service.setWxMaConfig(config);
+                    routers.put(a.getAppid(), this.newRouter(service));
+                    return service;
+                }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));
+    }
+
+    private WxMaMessageRouter newRouter(WxMaService service) {
+        final WxMaMessageRouter router = new WxMaMessageRouter(service);
+        router
+                .rule().handler(logHandler).next()
+                .rule().async(false).content("模板").handler(templateMsgHandler).end()
+                .rule().async(false).content("文本").handler(textHandler).end()
+                .rule().async(false).content("图片").handler(picHandler).end()
+                .rule().async(false).content("二维码").handler(qrcodeHandler).end();
+        return router;
+    }
+
+    private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) -> {
+        service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()
+                .templateId("此处更换为自己的模板id")
+                .formId("自己替换可用的formid")
+                .data(Lists.newArrayList(
+                        new WxMaTemplateData("keyword1", "339208499", "#173177")))
+                .toUser(wxMessage.getFromUser())
+                .build());
+        return null;
+    };
+
+    private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
+        System.out.println("收到消息:" + wxMessage.toString());
+        service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
+                .toUser(wxMessage.getFromUser()).build());
+        return null;
+    };
+
+    private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {
+        service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
+                .toUser(wxMessage.getFromUser()).build());
+        return null;
+    };
+
+    private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
+        try {
+            WxMediaUploadResult uploadResult = service.getMediaService()
+                    .uploadMedia("image", "png",
+                            ClassLoader.getSystemResourceAsStream("tmp.png"));
+            service.getMsgService().sendKefuMsg(
+                    WxMaKefuMessage
+                            .newImageBuilder()
+                            .mediaId(uploadResult.getMediaId())
+                            .toUser(wxMessage.getFromUser())
+                            .build());
+        } catch (WxErrorException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    };
+
+    private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
+        try {
+            final File file = service.getQrcodeService().createQrcode("123", 430);
+            WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
+            service.getMsgService().sendKefuMsg(
+                    WxMaKefuMessage
+                            .newImageBuilder()
+                            .mediaId(uploadResult.getMediaId())
+                            .toUser(wxMessage.getFromUser())
+                            .build());
+        } catch (WxErrorException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    };
+}

+ 46 - 0
src/main/java/com/YuyeTech/TPlat/config/WxMaProperties.java

@@ -0,0 +1,46 @@
+package com.YuyeTech.TPlat.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author:slambb
+ * @date:2019/12/13
+ */
+@Data
+//@Component
+@ConfigurationProperties(prefix = "wx.miniapp")
+public class WxMaProperties {
+    private List<Config> configs;
+
+    @Data
+    public static class Config {
+        /**
+         * 设置微信小程序的appid
+         */
+        private String appid;
+
+        /**
+         * 设置微信小程序的Secret
+         */
+        private String secret;
+
+        /**
+         * 设置微信小程序消息服务器配置的token
+         */
+        private String token;
+
+        /**
+         * 设置微信小程序消息服务器配置的EncodingAESKey
+         */
+        private String aesKey;
+
+        /**
+         * 消息格式,XML或者JSON
+         */
+        private String msgDataFormat;
+    }
+}

+ 27 - 0
src/main/java/com/YuyeTech/TPlat/config/async/AsyncConfig.java

@@ -0,0 +1,27 @@
+package com.YuyeTech.TPlat.config.async;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.AsyncTaskExecutor;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+/**
+ * 线程池的配置
+ */
+@Configuration
+public class AsyncConfig {
+
+    private static final int MAX_POOL_SIZE = 50;
+
+    private static final int CORE_POOL_SIZE = 20;
+
+    @Bean("asyncTaskExecutor")
+    public AsyncTaskExecutor asyncTaskExecutor() {
+        ThreadPoolTaskExecutor asyncTaskExecutor = new ThreadPoolTaskExecutor();
+        asyncTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
+        asyncTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
+        asyncTaskExecutor.setThreadNamePrefix("async-task-thread-pool-");
+        asyncTaskExecutor.initialize();
+        return asyncTaskExecutor;
+    }
+}

+ 17 - 0
src/main/java/com/YuyeTech/TPlat/config/config.java

@@ -0,0 +1,17 @@
+package com.YuyeTech.TPlat.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author:slambb
+ * @date:2019/12/4
+ */
+@Component
+public class config {
+
+     @Autowired
+    private WechatAccountConfig accountConfig;
+//    @Bean
+
+}

+ 25 - 0
src/main/java/com/YuyeTech/TPlat/config/exception/AuthorizeException.java

@@ -0,0 +1,25 @@
+package com.YuyeTech.TPlat.config.exception;
+
+import com.YuyeTech.TPlat.enums.ResultEnum;
+import lombok.Getter;
+
+/**
+ * @author:slambb
+ * @date:2019/12/13
+ */
+@Getter
+public class AuthorizeException extends RuntimeException {
+
+    private Integer code;
+
+    public AuthorizeException(ResultEnum resultEnum) {
+        super(resultEnum.getMessage());
+
+        this.code = resultEnum.getCode();
+    }
+
+    public AuthorizeException(Integer code, String message) {
+        super(message);
+        this.code = code;
+    }
+}

+ 175 - 0
src/main/java/com/YuyeTech/TPlat/config/logback/LoggingWSServer.java

@@ -0,0 +1,175 @@
+package com.YuyeTech.TPlat.config.logback;
+
+
+import com.YuyeTech.TPlat.config.websocket.MyEndpointConfigure;
+import com.YuyeTech.TPlat.utils.ErrorUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.thymeleaf.util.StringUtils;
+
+import javax.websocket.*;
+import javax.websocket.server.ServerEndpoint;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * WebSocket获取实时日志并输出到Web页面
+ */
+@Slf4j
+@Component
+@ServerEndpoint(value = "/websocket/logging", configurator = MyEndpointConfigure.class)
+public class LoggingWSServer {
+
+    @Value("${spring.application.name}")
+    private String applicationName;
+
+    /**
+     * 连接集合
+     */
+    private static Map<String, Session> sessionMap = new ConcurrentHashMap<String, Session>();
+    private static Map<String, Integer> lengthMap = new ConcurrentHashMap<String, Integer>();
+
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session) {
+        //添加到集合中
+        sessionMap.put(session.getId(), session);
+        lengthMap.put(session.getId(), 1);//默认从第一行开始
+
+        //获取日志信息
+        new Thread(()->{
+            log.info("LoggingWebSocketServer 任务开始");
+            boolean first = true;
+            BufferedReader reader = null;
+            while (sessionMap.get(session.getId()) != null) {
+                try {
+                    //日志文件,获取最新的
+                    FileReader fileReader = new FileReader(System.getProperty("user.home") + "/log/" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + applicationName + ".log");
+
+                    //字符流
+                    reader = new BufferedReader(fileReader);
+                    Object[] lines = reader.lines().toArray();
+
+                    //只取从上次之后产生的日志
+                    Object[] copyOfRange = Arrays.copyOfRange(lines, lengthMap.get(session.getId()), lines.length);
+
+                    //对日志进行着色,更加美观  PS:注意,这里要根据日志生成规则来操作
+                    for (int i = 0; i < copyOfRange.length; i++) {
+                        String line = String.valueOf(copyOfRange[i]);
+                        //先转义
+                        line = line.replaceAll("&", "&amp;")
+                                .replaceAll("<", "&lt;")
+                                .replaceAll(">", "&gt;")
+                                .replaceAll("\"", "&quot;");
+
+                        //处理等级
+                        line = line.replace("DEBUG", "<span style='color: blue;'>DEBUG</span>");
+                        line = line.replace("INFO", "<span style='color: green;'>INFO</span>");
+                        line = line.replace("WARN", "<span style='color: orange;'>WARN</span>");
+                        line = line.replace("ERROR", "<span style='color: red;'>ERROR</span>");
+
+                        //处理类名
+                        String[] split = line.split("]");
+                        if (split.length >= 2) {
+                            String[] split1 = split[1].split("-");
+                            if (split1.length >= 2) {
+                                line = split[0] + "]" + "<span style='color: #298a8a;'>" + split1[0] + "</span>" + "-" + split1[1];
+                            }
+                        }
+
+                        // 匹配日期开头加换行,2019-08-12 14:15:04
+                        Pattern r = Pattern.compile("[\\d+][\\d+][\\d+][\\d+]-[\\d+][\\d+]-[\\d+][\\d+] [\\d+][\\d+]:[\\d+][\\d+]:[\\d+][\\d+]");
+                        Matcher m = r.matcher(line);
+                        if (m.find( )) {
+                            //找到下标
+                            int start = m.start();
+                            //插入
+                            StringBuilder  sb = new StringBuilder (line);
+                            sb.insert(start,"<br/><br/>");
+                            line = sb.toString();
+                        }
+
+                        copyOfRange[i] = line;
+                    }
+
+                    //存储最新一行开始
+                    lengthMap.replace(session.getId(), lines.length);
+
+                    //第一次如果太大,截取最新的200行就够了,避免传输的数据太大
+                    if(first && copyOfRange.length > 200){
+                        copyOfRange = Arrays.copyOfRange(copyOfRange, copyOfRange.length - 200, copyOfRange.length);
+                        first = false;
+                    }
+
+                    String result = StringUtils.join(copyOfRange, "<br/>");
+
+                    //发送
+                    send(session, result);
+
+                    //休眠一秒
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    //输出到日志文件中
+                    log.error(ErrorUtil.errorInfoToString(e));
+                }
+            }
+            try {
+                reader.close();
+            } catch (IOException e) {
+                //输出到日志文件中
+                log.error(ErrorUtil.errorInfoToString(e));
+            }
+            log.info("LoggingWebSocketServer 任务结束");
+        }).start();
+    }
+
+    /**
+     * 连接关闭调用的方法
+     */
+    @OnClose
+    public void onClose(Session session) {
+        //从集合中删除
+        sessionMap.remove(session.getId());
+        lengthMap.remove(session.getId());
+    }
+
+    /**
+     * 发生错误时调用
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        //输出到日志文件中
+        log.error(ErrorUtil.errorInfoToString(error));
+    }
+
+    /**
+     * 服务器接收到客户端消息时调用的方法
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+
+    }
+
+    /**
+     * 封装一个send方法,发送消息到前端
+     */
+    private void send(Session session, String message) {
+        try {
+            session.getBasicRemote().sendText(message);
+        } catch (Exception e) {
+            //输出到日志文件中
+            log.error(ErrorUtil.errorInfoToString(e));
+        }
+    }
+}

+ 104 - 0
src/main/java/com/YuyeTech/TPlat/config/monitor/MonitorWSServer.java

@@ -0,0 +1,104 @@
+package com.YuyeTech.TPlat.config.monitor;
+
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.YuyeTech.TPlat.config.websocket.MyEndpointConfigure;
+import com.YuyeTech.TPlat.utils.ErrorUtil;
+import com.YuyeTech.TPlat.utils.SystemMonitorUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.ServerEndpoint;
+import java.text.SimpleDateFormat;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * WebSocket获取实时系统监控并输出到Web页面
+ */
+@Slf4j
+@Component
+@ServerEndpoint(value = "/websocket/monitor", configurator = MyEndpointConfigure.class)
+public class MonitorWSServer {
+
+    @Value("${spring.application.name}")
+    private String applicationName;
+
+    /**
+     * 连接集合
+     */
+    private static Map<String, Session> sessionMap = new ConcurrentHashMap<String, Session>();
+
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session) {
+        //添加到集合中
+        sessionMap.put(session.getId(), session);
+
+        //获取系统监控信息
+        new Thread(()->{
+            log.info("MonitorWSServer 任务开始");
+            ObjectMapper mapper = new ObjectMapper();
+            //当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输
+            mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+            //设置日期格式
+            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+            while (sessionMap.get(session.getId()) != null) {
+                try {
+                    //获取系统监控信息 发送
+                    send(session,  mapper.writeValueAsString(SystemMonitorUtil.getSysMonitor()));
+
+                    //休眠一秒
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    //输出到日志文件中
+                    log.error(ErrorUtil.errorInfoToString(e));
+                }
+            }
+            log.info("MonitorWSServer 任务结束");
+        }).start();
+    }
+
+    /**
+     * 连接关闭调用的方法
+     */
+    @OnClose
+    public void onClose(Session session) {
+        //从集合中删除
+        sessionMap.remove(session.getId());
+    }
+
+    /**
+     * 发生错误时调用
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        //输出到日志文件中
+        log.error(ErrorUtil.errorInfoToString(error));
+    }
+
+    /**
+     * 服务器接收到客户端消息时调用的方法
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+
+    }
+
+    /**
+     * 封装一个send方法,发送消息到前端
+     */
+    private void send(Session session, String message) {
+        try {
+            session.getBasicRemote().sendText(message);
+        } catch (Exception e) {
+            //输出到日志文件中
+            log.error(ErrorUtil.errorInfoToString(e));
+        }
+    }
+}

+ 174 - 0
src/main/java/com/YuyeTech/TPlat/config/security/CaptchaFilterConfig.java

@@ -0,0 +1,174 @@
+package com.YuyeTech.TPlat.config.security;
+
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.YuyeTech.TPlat.common.pojo.ParameterRequestWrapper;
+import com.YuyeTech.TPlat.utils.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+
+/**
+ * 校验账号、密码前,先进行验证码处理,需要在这里进行登录解密操作
+ */
+@Component
+@Slf4j
+public class CaptchaFilterConfig implements Filter {
+
+    @Value("${captcha.enable}")
+    private Boolean captchaEnable;
+
+    @Value("${server.servlet.context-path:}")
+    private String contextPath;
+
+    @Autowired
+    private SessionRegistry sessionRegistry;
+
+    @Autowired
+    private UserConfig userConfig;
+
+    @Autowired
+    private JwtTokenUtil jwtTokenUtil;
+    @Value("${jwt.token}")
+    private String tokenHeader;
+
+    @Autowired
+    private RedisSettingMap redisSettingMap;
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        HttpSession session = request.getSession();
+
+        /*
+            注:详情可在SessionManagementFilter中进行断点调试查看
+            security框架会在session的attribute存储登录信息,先从session.getAttribute(this.springSecurityContextKey)中获取登录用户信息
+            ,如果没有,再从本地上下文SecurityContextHolder.getContext().getAuthentication()获取,因此想要强制用户下线得进行如下操作
+
+            另外,虽然重启了服务,sessionRegistry.getAllSessions()为空,但之前的用户session未过期同样能访问系统,也是这个原因
+         */
+        SessionInformation sessionInformation = sessionRegistry.getSessionInformation(session.getId());
+        if (sessionInformation == null && session.getAttribute("SPRING_SECURITY_CONTEXT") != null) {
+            //直接输出js脚本跳转强制用户下线
+            response.setContentType("text/html;charset=UTF-8");
+            response.getWriter().print("<script type='text/javascript'>window.location.href = '" + contextPath + "/logout'</script>");
+        }
+
+        //只拦截登录请求,且开发环境下不拦截
+        if ("POST".equals(request.getMethod()) && "/login".equals(request.getRequestURI().replaceFirst(contextPath, ""))) {
+            //前端公钥
+            String publicKey = null;
+
+            //jackson
+            ObjectMapper mapper = new ObjectMapper();
+            //jackson 序列化和反序列化 date处理
+            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+
+            //判断api加密开关是否开启
+            if ("Y".equals(redisSettingMap.getSysSettingMap().getSysApiEncrypt())) {
+                //解密
+                try {
+                    //AES加密后的数据
+                    String data = request.getParameter("data");
+                    //后端RSA公钥加密后的AES的key
+                    String aesKey = request.getParameter("aesKey");
+                    //前端公钥
+                    publicKey = request.getParameter("publicKey");
+                    log.info("前端data:" + data);
+                    log.info("前端aesKey:" + aesKey);
+                    log.info("前端公钥:" + publicKey);
+                    //log.info("私钥:" + RsaUtil.getPrivateKey());
+                    //String _aesKey2 = aesKey;
+                    //后端私钥解密的到AES的key
+                    //切换一个方式
+                    RSA rsa = new RSA(redisSettingMap.getRSAPrivateKeyBase64(), null);
+                    byte[] plaintext = rsa.decrypt(Base64.decodeBase64(aesKey), KeyType.PrivateKey);
+                    //byte[] plaintext = RsaUtil.decryptByPrivateKey(Base64.decodeBase64(aesKey), RsaUtil.getPrivateKey());
+                    aesKey = new String(plaintext);
+                    log.info("解密出来的AES的key:" + aesKey);
+                    //log.info("前端aesKey2:" + _aesKey2);
+                    //String base64String = new Base64().encodeToString(_aesKey2.getBytes());
+                    //byte[] plaintext2 = RsaUtil.decryptByPrivateKey(Base64.decodeBase64(_aesKey2), RsaUtil.getPrivateKey());
+                    //String aesKey2 = new String(plaintext2);
+                    //log.info("解密出来的AES的key2:" + aesKey2);
+                    //AES解密得到明文data数据
+                    String decrypt = AesUtil.decrypt(data, aesKey);
+                    log.info("解密出来的data数据:" + decrypt);
+
+                    //设置到方法的形参中,目前只能设置只有一个参数的情况
+                    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+                    //new一个自定义RequestWrapper
+                    HashMap hashMap = mapper.readValue(decrypt, HashMap.class);
+                    ParameterRequestWrapper parameterRequestWrapper = new ParameterRequestWrapper(request);
+                    for (Object key : hashMap.keySet()) {
+                        parameterRequestWrapper.addParameter(String.valueOf(key), hashMap.get(key));
+                    }
+
+                    servletRequest = parameterRequestWrapper;
+                    request = (HttpServletRequest) servletRequest;
+                } catch (Throwable e) {
+                    //输出到日志文件中
+                    log.error(ErrorUtil.errorInfoToString(e));
+                }
+            }
+
+            //从session中获取生成的验证码
+            String verifyCode = session.getAttribute("verifyCode").toString();
+
+            if (captchaEnable && !verifyCode.toLowerCase().equals(request.getParameter("captcha").toLowerCase())) {
+                String dataString = "{\"code\":\"400\",\"msg\":\"验证码错误\"}";
+
+                //判断api加密开关是否开启
+                if ("Y".equals(redisSettingMap.getSysSettingMap().getSysApiEncrypt())) {
+                    //加密
+                    try {
+                        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                        //每次响应之前随机获取AES的key,加密data数据
+                        String key = AesUtil.getKey();
+                        log.info("AES的key:" + key);
+                        log.info("需要加密的data数据:" + dataString);
+                        String data = AesUtil.encrypt(dataString, key);
+
+                        //用前端的公钥来解密AES的key,并转成Base64
+                        //String aesKey = Base64.encodeBase64String(RsaUtil.encryptByPublicKey(key.getBytes(), publicKey));
+                        //切换一个方式
+                        RSA rsa = new RSA(null, publicKey);
+                        String aesKey = Base64.encodeBase64String(rsa.encrypt(key.getBytes(), KeyType.PublicKey));
+                        dataString = "{\"data\":{\"data\":\"" + data + "\",\"aesKey\":\"" + aesKey + "\"}}";
+                    } catch (Throwable e) {
+                        //输出到日志文件中
+                        log.error(ErrorUtil.errorInfoToString(e));
+                    }
+                }
+
+                //转json字符串并转成Object对象,设置到Result中并赋值给返回值o
+                response.setCharacterEncoding("UTF-8");
+                response.setContentType("application/json; charset=utf-8");
+                PrintWriter out = response.getWriter();
+                out.print(dataString);
+                out.flush();
+                out.close();
+                return;
+            }
+        }
+
+        filterChain.doFilter(servletRequest, servletResponse);
+    }
+}

+ 88 - 0
src/main/java/com/YuyeTech/TPlat/config/security/DynamicallyUrlInterceptor.java

@@ -0,0 +1,88 @@
+package com.YuyeTech.TPlat.config.security;
+
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.SecurityMetadataSource;
+import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
+import org.springframework.security.access.intercept.InterceptorStatusToken;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+import javax.servlet.*;
+import java.io.IOException;
+
+/**
+ * 自定义动态数据拦截器
+ */
+public class DynamicallyUrlInterceptor extends AbstractSecurityInterceptor implements Filter {
+
+    //标记自定义的url拦截器已经加载
+    private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied_dynamically";
+
+    private FilterInvocationSecurityMetadataSource securityMetadataSource;
+    private boolean observeOncePerRequest = true;
+
+
+    @Override
+    public Class<?> getSecureObjectClass() {
+        return FilterInvocation.class;
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        FilterInvocation fi = new FilterInvocation(request, response, chain);
+        invoke(fi);
+    }
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
+        return this.securityMetadataSource;
+    }
+
+    public SecurityMetadataSource obtainSecurityMetadataSource() {
+        return this.securityMetadataSource;
+    }
+
+    public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
+        this.securityMetadataSource = newSource;
+    }
+
+    @Override
+    public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
+        super.setAccessDecisionManager(accessDecisionManager);
+    }
+
+    public void invoke(FilterInvocation fi) throws IOException, ServletException {
+
+        if ((fi.getRequest() != null)
+                && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
+                && observeOncePerRequest) {
+            // filter already applied to this request and user wants us to observe
+            // once-per-request handling, so don't re-do security checking
+            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+        }
+        else {
+            // first time this request being called, so perform security checking
+            if (fi.getRequest() != null) {
+                fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
+            }
+
+            InterceptorStatusToken token = super.beforeInvocation(fi);
+
+            try {
+                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+            }
+            finally {
+                super.finallyInvocation(token);
+            }
+
+            super.afterInvocation(token, null);
+        }
+    }
+}

+ 55 - 0
src/main/java/com/YuyeTech/TPlat/config/security/ErrorPageConfig.java

@@ -0,0 +1,55 @@
+package com.YuyeTech.TPlat.config.security;
+
+import org.springframework.boot.web.server.ErrorPage;
+import org.springframework.boot.web.server.ErrorPageRegistrar;
+import org.springframework.boot.web.server.ErrorPageRegistry;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * 自定义errorPage
+ */
+@Component
+public class ErrorPageConfig implements ErrorPageRegistrar {
+
+    @Override
+    public void registerErrorPages(ErrorPageRegistry registry) {
+
+        /**
+         * ErrorPage 有两个参数
+         * 参数1 响应状态码
+         * 参数2 出现响应状态码的时候的跳转路径  可以自定义跳转路径
+         */
+
+        //将ErrorPage 注册到注册器中
+        registry.addErrorPages(
+                new ErrorPage(HttpStatus.FORBIDDEN, "/error/403"),
+                new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"),
+                new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")
+                );
+    }
+}
+
+/**
+ * 错误页面跳转
+ */
+@Controller
+class ErrorPageController {
+    @GetMapping("/error/403")
+    public ModelAndView error403(){
+        return new ModelAndView("common/error/403");
+    }
+
+    @GetMapping("/error/404")
+    public ModelAndView error404(){
+        return new ModelAndView("common/error/404");
+    }
+
+    @GetMapping("/error/500")
+    public ModelAndView error500(){
+        return new ModelAndView("common/error/500");
+    }
+}

+ 75 - 0
src/main/java/com/YuyeTech/TPlat/config/security/LoginFailureHandlerConfig.java

@@ -0,0 +1,75 @@
+package com.YuyeTech.TPlat.config.security;
+
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.YuyeTech.TPlat.utils.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+
+/**
+ * 登录失败处理
+ */
+@Component
+@Slf4j
+public class LoginFailureHandlerConfig implements AuthenticationFailureHandler {
+
+    @Autowired
+    private RedisSettingMap redisSettingMap;
+
+    @Override
+    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
+        String msg = "{\"code\":\"400\",\"msg\":\"用户名或密码错误\"}";
+
+        //判断api加密开关是否开启
+        if("Y".equals(redisSettingMap.getSysSettingMap().getSysApiEncrypt())){
+            //加密
+            try {
+                //前端公钥
+                String publicKey = httpServletRequest.getParameter("publicKey");
+
+                log.info("前端公钥:" + publicKey);
+
+                //jackson
+                ObjectMapper mapper = new ObjectMapper();
+                //jackson 序列化和反序列化 date处理
+                mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                //每次响应之前随机获取AES的key,加密data数据
+                String key = AesUtil.getKey();
+                log.info("AES的key:" + key);
+                log.info("需要加密的data数据:" + msg);
+                String data = AesUtil.encrypt(msg, key);
+
+                //用前端的公钥来解密AES的key,并转成Base64
+                //String aesKey = Base64.encodeBase64String(RsaUtil.encryptByPublicKey(key.getBytes(), publicKey));
+                //切换一个方式
+                RSA rsa = new RSA(null, publicKey);
+                String aesKey = Base64.encodeBase64String(rsa.encrypt(key.getBytes(), KeyType.PublicKey));
+                msg = "{\"data\":{\"data\":\"" + data + "\",\"aesKey\":\"" + aesKey + "\"}}";
+            } catch (Throwable ee) {
+                //输出到日志文件中
+                log.error(ErrorUtil.errorInfoToString(ee));
+            }
+        }
+
+        //转json字符串并转成Object对象,设置到Result中并赋值给返回值o
+        httpServletResponse.setCharacterEncoding("UTF-8");
+        httpServletResponse.setContentType("application/json; charset=utf-8");
+        PrintWriter out = httpServletResponse.getWriter();
+        out.print(msg);
+        out.flush();
+        out.close();
+    }
+}

+ 157 - 0
src/main/java/com/YuyeTech/TPlat/config/security/LoginSuccessHandlerConfig.java

@@ -0,0 +1,157 @@
+package com.YuyeTech.TPlat.config.security;
+
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.YuyeTech.TPlat.sys.sysuser.service.SysUserService;
+import com.YuyeTech.TPlat.sys.sysuser.vo.SysUserVo;
+import com.YuyeTech.TPlat.utils.*;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
+import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 登录成功处理,登陆成功后还需要验证账号的有效性
+ */
+@Component
+@Slf4j
+public class LoginSuccessHandlerConfig implements AuthenticationSuccessHandler {
+    @Autowired
+    private SessionRegistry sessionRegistry;
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Autowired
+    private RedisSettingMap redisSettingMap;
+
+    @Override
+    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
+        //从全局注册表中获取所有登陆用户,做用户单登陆判断
+        ArrayList<String> allSessionIdList = new ArrayList<>();
+        List<SessionInformation> allSessions = sessionRegistry.getAllSessions(authentication.getPrincipal(), false);
+        for (SessionInformation sessionInformation : allSessions) {
+            allSessionIdList.add(sessionInformation.getSessionId());
+        }
+
+        //查询当前与系统交互的用户,存储在本地线程安全上下文,校验账号有效性
+        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        SysUserVo sysUserVo = sysUserService.findByLoginName(user.getUsername()).getData();
+
+        //默认登陆成功
+        String msg = "{\"code\":\"300\",\"msg\":\"登录成功\",\"url\":\"/index\"}";
+        boolean flag = false;
+
+        //登陆IP不在白名单
+        String ipAddr = IpUtil.getIpAddr(httpServletRequest);
+        String limitedIp = sysUserVo.getLimitedIp();
+        if (!StringUtils.isEmpty(limitedIp) && !Arrays.asList(limitedIp.split(",")).contains(ipAddr)) {
+            msg = "{\"code\":\"400\",\"msg\":\"登陆IP不在白名单,请联系管理员\"}";
+            flag = true;
+        }
+
+        //禁止多人在线
+        if ("N".equals(sysUserVo.getLimitMultiLogin()) && allSessionIdList.size() > 0) {
+            msg = "{\"code\":\"400\",\"msg\":\"该账号禁止多人在线,请联系管理员\"}";
+            flag = true;
+        }
+
+        //超出有效时间
+        if (!StringUtils.isEmpty(sysUserVo.getExpiredTime()) && new Date().getTime() > sysUserVo.getExpiredTime().getTime()) {
+            msg = "{\"code\":\"400\",\"msg\":\"该账号已失效,请联系管理员\"}";
+            flag = true;
+        }
+
+        //禁止登陆系统
+        if ("N".equals(sysUserVo.getValid())) {
+            msg = "{\"code\":\"400\",\"msg\":\"该账号已被禁止登陆系统,请联系管理员\"}";
+            flag = true;
+        }
+
+        //校验不通过
+        if (flag) {
+            //清除当前的上下文
+            SecurityContextHolder.clearContext();
+
+            //清除remember-me持久化tokens
+            persistentTokenRepository1().removeUserTokens(user.getUsername());
+        } else {
+            //校验通过,注册session
+            sessionRegistry.registerNewSession(httpServletRequest.getSession().getId(), user);
+        }
+
+        //判断api加密开关是否开启
+        if ("Y".equals(redisSettingMap.getSysSettingMap().getSysApiEncrypt())) {
+            //加密
+            try {
+                //前端公钥
+                String publicKey = httpServletRequest.getParameter("publicKey");
+
+                log.info("前端公钥:" + publicKey);
+
+                //jackson
+                ObjectMapper mapper = new ObjectMapper();
+                //jackson 序列化和反序列化 date处理
+                mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+                //每次响应之前随机获取AES的key,加密data数据
+                String key = AesUtil.getKey();
+                log.info("AES的key:" + key);
+                log.info("需要加密的data数据:" + msg);
+                String data = AesUtil.encrypt(msg, key);
+
+                //用前端的公钥来解密AES的key,并转成Base64
+                //String aesKey = Base64.encodeBase64String(RsaUtil.encryptByPublicKey(key.getBytes(), publicKey));
+                //切换一个方式
+                RSA rsa = new RSA(null, publicKey);
+                String aesKey = Base64.encodeBase64String(rsa.encrypt(key.getBytes(), KeyType.PublicKey));
+                msg = "{\"data\":{\"data\":\"" + data + "\",\"aesKey\":\"" + aesKey + "\"}}";
+            } catch (Throwable e) {
+                //输出到日志文件中
+                log.error(ErrorUtil.errorInfoToString(e));
+            }
+        }
+
+        //转json字符串并转成Object对象,设置到Result中并赋值给返回值o
+        httpServletResponse.setCharacterEncoding("UTF-8");
+        httpServletResponse.setContentType("application/json; charset=utf-8");
+        PrintWriter out = httpServletResponse.getWriter();
+        out.print(msg);
+        out.flush();
+        out.close();
+    }
+
+    @Bean
+    public PersistentTokenRepository persistentTokenRepository1() {
+        JdbcTokenRepositoryImpl persistentTokenRepository = new JdbcTokenRepositoryImpl();
+        persistentTokenRepository.setDataSource(dataSource);
+        return persistentTokenRepository;
+    }
+}

+ 37 - 0
src/main/java/com/YuyeTech/TPlat/config/security/LogoutHandlerConfig.java

@@ -0,0 +1,37 @@
+package com.YuyeTech.TPlat.config.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.web.authentication.logout.LogoutHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 注销处理
+ */
+@Component
+public class LogoutHandlerConfig implements LogoutHandler {
+    @Autowired
+    private SessionRegistry sessionRegistry;
+
+    @Override
+    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
+        //剔除退出用户
+        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        if (principal !=null){
+            List<SessionInformation> allSessions = sessionRegistry.getAllSessions(principal, false);
+            if (allSessions != null) {
+                for (SessionInformation sessionInformation : allSessions) {
+                    sessionInformation.expireNow();
+                    sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
+                }
+            }
+        }
+    }
+}

+ 56 - 0
src/main/java/com/YuyeTech/TPlat/config/security/MyAccessDecisionManager.java

@@ -0,0 +1,56 @@
+package com.YuyeTech.TPlat.config.security;
+
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.vote.AbstractAccessDecisionManager;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 提供一个认证管理器
+ */
+public class MyAccessDecisionManager extends AbstractAccessDecisionManager {
+
+    MyAccessDecisionManager(List<AccessDecisionVoter<?>> decisionVoters) {
+        super(decisionVoters);
+    }
+
+    @Override
+    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
+            throws AccessDeniedException, InsufficientAuthenticationException {
+        int deny = 0;
+
+        for (AccessDecisionVoter voter : getDecisionVoters()) {
+            int result = voter.vote(authentication, object, configAttributes);
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("Voter: " + voter + ", returned: " + result);
+            }
+
+            switch (result) {
+                case AccessDecisionVoter.ACCESS_GRANTED:
+                    return;
+
+                case AccessDecisionVoter.ACCESS_DENIED:
+                    deny++;
+
+                    break;
+
+                default:
+                    break;
+            }
+        }
+
+        if (deny > 0) {
+            throw new AccessDeniedException(messages.getMessage(
+                    "AbstractAccessDecisionManager.accessDenied", "Access is denied"));
+        }
+
+        // To get this far, every AccessDecisionVoter abstained
+        checkAllowIfAllAbstainDecisions();
+    }
+}

+ 77 - 0
src/main/java/com/YuyeTech/TPlat/config/security/MyFilterInvocationSecurityMetadataSource.java

@@ -0,0 +1,77 @@
+package com.YuyeTech.TPlat.config.security;
+
+import com.YuyeTech.TPlat.sys.sysauthority.vo.SysAuthorityVo;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 配置认证数据源,实现动态权限加载(注意:不要手动new,把它交给spring管理,spring默认单例)
+ */
+@Component
+public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
+    //权限数据
+    private Map<RequestMatcher, Collection<ConfigAttribute>> requestMap;
+
+    /**
+     * 在我们初始化的权限数据中找到对应当前url的权限数据
+     */
+    @Override
+    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+        FilterInvocation fi = (FilterInvocation) object;
+        HttpServletRequest request = fi.getRequest();
+
+        //遍历我们初始化的权限数据,找到对应的url对应的权限
+        for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap
+                .entrySet()) {
+            if (entry.getKey().matches(request)) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Collection<ConfigAttribute> getAllConfigAttributes() {
+        return null;
+    }
+
+    @Override
+    public boolean supports(Class<?> clazz) {
+        return FilterInvocation.class.isAssignableFrom(clazz);
+    }
+
+    /**
+     * 更新权限集合
+     */
+    public void setRequestMap(List<SysAuthorityVo> authorityVoList){
+        Map<RequestMatcher, Collection<ConfigAttribute>> map = new ConcurrentHashMap<>();
+        for (SysAuthorityVo sysAuthorityVo : authorityVoList) {
+            String authorityName = sysAuthorityVo.getAuthorityName();
+            if (StringUtils.isEmpty(sysAuthorityVo.getAuthorityContent())) continue;
+            for (String url : sysAuthorityVo.getAuthorityContent().split(",")) {
+                Collection<ConfigAttribute> value = map.get(new AntPathRequestMatcher(url));
+                if (StringUtils.isEmpty(value)) {
+                    ArrayList<ConfigAttribute> configs = new ArrayList<>();
+                    configs.add(new SecurityConfig(authorityName));
+                    map.put(new AntPathRequestMatcher(url), configs);
+                } else {
+                    value.add(new SecurityConfig(authorityName));
+                }
+            }
+        }
+        this.requestMap = map;
+    }
+}

+ 51 - 0
src/main/java/com/YuyeTech/TPlat/config/security/MyInvalidSessionStrategy.java

@@ -0,0 +1,51 @@
+package com.YuyeTech.TPlat.config.security;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.session.InvalidSessionStrategy;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+/**
+ * 自定义session失效策略
+ */
+@Component
+@Slf4j
+public class MyInvalidSessionStrategy implements InvalidSessionStrategy {
+    @Autowired
+    private SessionRegistry sessionRegistry;
+
+    @Value("${server.servlet.context-path:}")
+    private String contextPath;
+
+    @Override
+    public void onInvalidSessionDetected(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
+        HttpSession session = httpServletRequest.getSession();
+        String sessionId = httpServletRequest.getRequestedSessionId();
+        if(!session.isNew()){
+            //内部重定向
+            httpServletResponse.sendRedirect("/loginPage");
+        }else{
+            //直接输出js脚本跳转
+            httpServletResponse.setContentType("text/html;charset=UTF-8");
+            httpServletResponse.getWriter().print("<script type='text/javascript'>window.location.href = \"" + contextPath + "/loginPage\"</script>");
+        }
+        SessionInformation sessionInformation = sessionRegistry.getSessionInformation(sessionId);
+        if(sessionInformation != null){
+            User user = (User) sessionInformation.getPrincipal();
+            sessionRegistry.removeSessionInformation(sessionId);
+            log.info("剔除过期用户:"+user.getUsername());
+        }
+        log.info("session失效处理 " + sessionRegistry.getAllPrincipals().size()+"");
+        httpServletResponse.flushBuffer();
+    }
+}

+ 20 - 0
src/main/java/com/YuyeTech/TPlat/config/security/PasswordConfig.java

@@ -0,0 +1,20 @@
+package com.YuyeTech.TPlat.config.security;
+
+import com.YuyeTech.TPlat.utils.MD5Util;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PasswordConfig implements PasswordEncoder {
+
+    @Override
+    public String encode(CharSequence charSequence) {
+        //charSequence是用户输入的密码,password是存库的密码
+        return MD5Util.getMD5(charSequence.toString());
+    }
+
+    @Override
+    public boolean matches(CharSequence charSequence, String password) {
+        return password.contentEquals(encode(charSequence));
+    }
+}

+ 175 - 0
src/main/java/com/YuyeTech/TPlat/config/security/SecurityConfig.java

@@ -0,0 +1,175 @@
+package com.YuyeTech.TPlat.config.security;
+
+import com.YuyeTech.TPlat.sys.sysauthority.service.SysAuthorityService;
+import com.YuyeTech.TPlat.sys.sysauthority.vo.SysAuthorityVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.vote.RoleVoter;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
+import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
+
+import javax.sql.DataSource;
+import java.util.ArrayList;
+import java.util.List;
+
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Autowired
+    private CaptchaFilterConfig captchaFilterConfig;
+
+    @Autowired
+    private UserConfig userConfig;
+
+    @Autowired
+    private PasswordConfig passwordConfig;
+
+    @Autowired
+    private LoginFailureHandlerConfig loginFailureHandlerConfig;
+
+    @Autowired
+    private LoginSuccessHandlerConfig loginSuccessHandlerConfig;
+
+    @Autowired
+    private LogoutHandlerConfig logoutHandlerConfig;
+
+    @Autowired
+    private SysAuthorityService sysAuthorityService;
+
+    @Autowired
+    private MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;
+
+    @Autowired
+    private MyInvalidSessionStrategy myInvalidSessionStrategy;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Override
+    public void configure(WebSecurity web) throws Exception {
+        // game 走 token验证流程
+        web.ignoring().antMatchers(
+                "/game/**"
+                ,"/game_websocket/**"
+                ,"/static/**"
+                ,
+                //***new
+                "/app/**",
+                "/bluetooth/**",
+                "/client_game/**",
+                "/device/**",
+                "/favorites/**",
+                "/FC/**",
+                "/fitness_program/**",
+                "/game/**",
+                "/level/**",
+                "/program/**",//登录相关
+                "/manager/**",
+                "/navigation/**",
+                "/OTA/**",
+                "/ranking/**",
+                "/recently_playing/**",
+                "/reward/**",
+                "/oss/**",
+                "/user_info/**",
+                "/wxlogin/**"
+                //,
+                //"/backstage_ble/**"
+        );
+    }
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+        auth
+                //用户认证处理
+                .userDetailsService(userConfig)
+                //密码处理
+                .passwordEncoder(passwordConfig);
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+                // 关闭csrf防护
+                .csrf().disable()
+                .headers().frameOptions().disable()
+                .and();
+
+        http
+                //登录处理
+                .addFilterBefore(captchaFilterConfig, UsernamePasswordAuthenticationFilter.class)
+                .formLogin()
+                .loginProcessingUrl("/login")
+                //未登录时默认跳转页面
+                .loginPage("/loginPage")
+                .failureHandler(loginFailureHandlerConfig)
+                .successHandler(loginSuccessHandlerConfig)
+                .permitAll()
+                .and();
+        http
+                //登出处理
+                .logout()
+                .addLogoutHandler(logoutHandlerConfig)
+                .logoutUrl("/logout")
+                .logoutSuccessUrl("/loginPage")
+                .permitAll()
+                .and();
+        http
+                //"play_back"
+                //.mvcMatcher("/game")
+                //定制url访问权限,动态权限读取,参考:https://www.jianshu.com/p/0a06496e75ea
+                .addFilterAfter(dynamicallyUrlInterceptor(), FilterSecurityInterceptor.class)
+                .authorizeRequests()
+                //无需权限访问
+                .antMatchers("/favicon.ico","/common/**", "/webjars/**", "/getVerifyCodeImage","/error/*"
+                ).permitAll()
+                 //其他接口需要登录后才能访问
+                .anyRequest().authenticated()
+                .and();
+        http.sessionManagement()
+                //session无效处理策略
+                .invalidSessionStrategy(myInvalidSessionStrategy)
+                .and();
+        http
+                //开启记住我
+                .rememberMe()
+                .tokenValiditySeconds(604800)//七天免登陆
+                .tokenRepository(persistentTokenRepository())
+                .userDetailsService(userConfig)
+                .and();
+    }
+
+    @Bean
+    public PersistentTokenRepository persistentTokenRepository() {
+        JdbcTokenRepositoryImpl persistentTokenRepository = new JdbcTokenRepositoryImpl();
+        persistentTokenRepository.setDataSource(dataSource);
+        return persistentTokenRepository;
+    }
+
+    //配置filter
+    @Bean
+    public DynamicallyUrlInterceptor dynamicallyUrlInterceptor(){
+        //首次获取
+        List<SysAuthorityVo> authorityVoList = sysAuthorityService.list(new SysAuthorityVo()).getData();
+        myFilterInvocationSecurityMetadataSource.setRequestMap(authorityVoList);
+        //初始化拦截器并添加数据源
+        DynamicallyUrlInterceptor interceptor = new DynamicallyUrlInterceptor();
+        interceptor.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource);
+
+        //配置RoleVoter决策
+        List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
+        decisionVoters.add(new RoleVoter());
+
+        //设置认证决策管理器
+        interceptor.setAccessDecisionManager(new MyAccessDecisionManager(decisionVoters));
+        return interceptor;
+    }
+}

+ 51 - 0
src/main/java/com/YuyeTech/TPlat/config/security/UserConfig.java

@@ -0,0 +1,51 @@
+package com.YuyeTech.TPlat.config.security;
+
+import com.YuyeTech.TPlat.sys.sysuser.service.SysUserService;
+import com.YuyeTech.TPlat.sys.sysuser.vo.SysUserVo;
+import com.YuyeTech.TPlat.sys.sysuserauthority.service.SysUserAuthorityService;
+import com.YuyeTech.TPlat.sys.sysuserauthority.vo.SysUserAuthorityVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+
+@Component
+public class UserConfig implements UserDetailsService {
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    @Autowired
+    private SysUserAuthorityService sysUserAuthorityService;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        //查询用户
+        SysUserVo sysUserVo = sysUserService.findByLoginName(username).getData();
+        //查询权限
+        List<SysUserAuthorityVo> sysUserAuthorityVoList = sysUserAuthorityService.findByUserId(sysUserVo.getUserId()).getData();
+        StringBuilder authorityList = new StringBuilder();
+        for (int i = 0; i < sysUserAuthorityVoList.size(); i++) {
+            SysUserAuthorityVo sysUserAuthorityVo = sysUserAuthorityVoList.get(i);
+            authorityList.append(sysUserAuthorityVo.getSysAuthority().getAuthorityName());
+            if (i != sysUserAuthorityVoList.size() - 1) {
+                authorityList.append(",");
+            }
+        }
+
+        //查无此用户
+        if(StringUtils.isEmpty(sysUserVo.getUserId())){
+            sysUserVo.setLoginName("查无此用户");
+            sysUserVo.setPassword("查无此用户");
+        }
+
+        // 封装用户信息,并返回。参数分别是:用户名,密码,用户权限
+        return new User(sysUserVo.getLoginName(), sysUserVo.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(authorityList.toString()));
+    }
+}

+ 51 - 0
src/main/java/com/YuyeTech/TPlat/config/security/gameConfig.java

@@ -0,0 +1,51 @@
+package com.YuyeTech.TPlat.config.security;
+
+import com.YuyeTech.TPlat.sys.sysuser.service.SysUserService;
+import com.YuyeTech.TPlat.sys.sysuser.vo.SysUserVo;
+import com.YuyeTech.TPlat.sys.sysuserauthority.service.SysUserAuthorityService;
+import com.YuyeTech.TPlat.sys.sysuserauthority.vo.SysUserAuthorityVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+
+@Component
+public class gameConfig implements UserDetailsService {
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    @Autowired
+    private SysUserAuthorityService sysUserAuthorityService;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        //查询用户
+        SysUserVo sysUserVo = sysUserService.findByLoginName(username).getData();
+        //查询权限
+        List<SysUserAuthorityVo> sysUserAuthorityVoList = sysUserAuthorityService.findByUserId(sysUserVo.getUserId()).getData();
+        StringBuilder authorityList = new StringBuilder();
+        for (int i = 0; i < sysUserAuthorityVoList.size(); i++) {
+            SysUserAuthorityVo sysUserAuthorityVo = sysUserAuthorityVoList.get(i);
+            authorityList.append(sysUserAuthorityVo.getSysAuthority().getAuthorityName());
+            if (i != sysUserAuthorityVoList.size() - 1) {
+                authorityList.append(",");
+            }
+        }
+
+        //查无此用户
+        if(StringUtils.isEmpty(sysUserVo.getUserId())){
+            sysUserVo.setLoginName("查无此用户");
+            sysUserVo.setPassword("查无此用户");
+        }
+
+        // 封装用户信息,并返回。参数分别是:用户名,密码,用户权限
+        return new User(sysUserVo.getLoginName(), sysUserVo.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(authorityList.toString()));
+    }
+}

+ 53 - 0
src/main/java/com/YuyeTech/TPlat/config/token/WebConfig.java

@@ -0,0 +1,53 @@
+package com.YuyeTech.TPlat.config.token;
+
+import com.YuyeTech.TPlat.filter.gameFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.filter.DelegatingFilterProxy;
+
+import javax.servlet.Filter;
+
+/**
+ * @author:slambb
+ * @date:2021/03/27
+ */
+@Configuration
+public class WebConfig {
+
+    @Bean
+    public Filter gameFilter() {
+        return new gameFilter();
+    }
+
+
+    @Bean
+    public FilterRegistrationBean authorizeFilterRegistration() {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new DelegatingFilterProxy("gameFilter"));
+        registration.addUrlPatterns(
+                "/app/*",
+                "/bluetooth/*",
+                "/client_game/*",
+                "/device/*",
+                "/favorites/*",
+                "/FC/*",
+                "/fitness_program/*",
+                "/game/*",
+                "/level/*",
+                "/program/*",//登录相关
+                "/manager/*",
+                "/navigation/*",
+                "/OTA/*",
+                "/ranking/*",
+                "/recently_playing/*",
+                "/reward/*",
+                "/oss/*",
+                "/user_info/*",
+                "/wxlogin/*");
+        registration.setName("gameFilter");
+        registration.setOrder(1);
+        return registration;
+    }
+
+}

+ 26 - 0
src/main/java/com/YuyeTech/TPlat/config/websocket/MyEndpointConfigure.java

@@ -0,0 +1,26 @@
+package com.YuyeTech.TPlat.config.websocket;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import javax.websocket.server.ServerEndpointConfig;
+
+/**
+ * 解决注入其他类的问题,详情参考这篇帖子:webSocket无法注入其他类:https://blog.csdn.net/tornadojava/article/details/78781474
+ */
+public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
+
+    private static volatile BeanFactory context;
+
+    @Override
+    public <T> T getEndpointInstance(Class<T> clazz){
+        return context.getBean(clazz);
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        MyEndpointConfigure.context = applicationContext;
+    }
+}

+ 32 - 0
src/main/java/com/YuyeTech/TPlat/config/websocket/WebSocketConfig.java

@@ -0,0 +1,32 @@
+package com.YuyeTech.TPlat.config.websocket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * WebSocket配置
+ */
+@Configuration
+public class WebSocketConfig {
+
+
+    /**
+     * 用途:扫描并注册所有携带@ServerEndpoint注解的实例。 @ServerEndpoint("/websocket")
+     * PS:如果使用外部容器 则无需提供ServerEndpointExporter。
+     */
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+
+    /**
+     * 支持注入其他类
+     */
+    @Bean
+    public MyEndpointConfigure newMyEndpointConfigure (){
+        return new MyEndpointConfigure ();
+    }
+
+
+}

+ 11 - 0
src/main/java/com/YuyeTech/TPlat/constant/CookieConstant.java

@@ -0,0 +1,11 @@
+package com.YuyeTech.TPlat.constant;
+
+/**
+ * @author:slambb
+ * @date:2019/12/13
+ */
+public interface CookieConstant {
+    String TOKEN = "token";
+
+    Integer EXPIRE = 7200;
+}

+ 12 - 0
src/main/java/com/YuyeTech/TPlat/constant/RankingConstant.java

@@ -0,0 +1,12 @@
+package com.YuyeTech.TPlat.constant;
+
+/**
+ * @author:slambb
+ * @date:2020/3/20
+ */
+public interface RankingConstant {
+    //城市key
+    String cityKey = "city_%s_gameId_%s";
+    //全国key 直接用gameId
+    String chinaKey = "gameId_%s";
+}

+ 17 - 0
src/main/java/com/YuyeTech/TPlat/constant/RedisConstant.java

@@ -0,0 +1,17 @@
+package com.YuyeTech.TPlat.constant;
+
+/**
+ * redis 常量
+ * @author:slambb
+ * @date:2019/12/13
+ */
+public interface RedisConstant {
+    String TOKEN_PREFIX = "token_%s";
+    //设置1个月
+    Integer EXPIRE = 60*60*24*30;//7200;//2小时
+
+    //短信信息
+    String SMS_PREFIX = "code_%s";
+
+    Integer  CODE_EXPIRE = 300;//5分钟
+}

+ 19 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/AdminInfo.java

@@ -0,0 +1,19 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+@Data
+@Entity
+public class AdminInfo {
+    @Id
+    private Integer adminId;
+    private String adminName;
+    private String adminPassword;
+    private Date loginTime;
+    private Date createTime;
+    private Date updateTime;
+}

+ 26 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/AiInfo.java

@@ -0,0 +1,26 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/3/25
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class AiInfo {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer aiId;
+    private String aiType;
+    private String aiName;
+    private Integer aiGender;
+    private String aiAvatar;
+}

+ 25 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/AppleInfo.java

@@ -0,0 +1,25 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/6/4
+ */
+
+@Data
+@Entity
+public class AppleInfo {
+
+    @Id
+    private String userId;
+
+    /**
+     * 苹果用户的userID
+     */
+    private String appleId;
+
+}

+ 39 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/ClientInfo.java

@@ -0,0 +1,39 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/6/11
+ */
+@Data
+@Entity
+public class ClientInfo {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer clientId;
+
+    private String userId;
+
+    private String brand;
+
+    private String model;
+
+    private Integer screenWidth;
+
+    private Integer screenHeight;
+
+    private String clientSystem;
+
+    private String version;
+
+    private String platform;
+
+    private String sdkVersion;
+}

+ 32 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/DeviceInfo.java

@@ -0,0 +1,32 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/6/11
+ */
+@Data
+@Entity
+public class DeviceInfo {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer deviceId;
+
+    private String userId;
+
+    private String deviceUuid;
+
+    private Integer deviceStatus;
+
+    private Integer deviceType;
+
+    private String identifier;
+
+}

+ 26 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/Favorites.java

@@ -0,0 +1,26 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/14
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class Favorites {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer favoritesId;
+    private Integer favoritesType;
+
+    @Column(name="f_object_id")
+    private String FObjectId;
+    private String userId;
+    private Date createTime;
+}

+ 25 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/FitnessProgram.java

@@ -0,0 +1,25 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2019/12/31
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class FitnessProgram {
+    @Id
+    private String userId;
+    private Date startTime;
+    private Date endTime;
+    private Double targetWeight;
+    private Integer cumulativeCalorie;
+    private Integer calorie;
+    private Double sportTime;
+}

+ 27 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/FriendInfo.java

@@ -0,0 +1,27 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/7/26
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class FriendInfo {
+    @Id
+    private String id;
+    private String userId;
+    private String friendId;
+    private Integer isOut;
+
+    private Date createdAt;
+}

+ 37 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/LevelCondition.java

@@ -0,0 +1,37 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/8/4
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class LevelCondition {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private Integer type;
+    private String explain;
+    /**
+     * 用于条件说明。比如关卡结束时候的限制条件
+     */
+    private Integer limitType;
+    /**
+     * 是否是分数,和一个分数限制值
+     */
+    private Integer isScore;
+    private Integer limitScore;
+    /**
+     * 对应的关卡
+     */
+    private Integer limitLevel;
+}

+ 26 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/LevelHonor.java

@@ -0,0 +1,26 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/8/4
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class LevelHonor {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private String name;
+    private Integer type;
+    private String explain;
+    private String url;
+}

+ 47 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/LevelJump.java

@@ -0,0 +1,47 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2021/8/4
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class LevelJump {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private String name;//关卡名字
+    private String describe;//关卡描述
+    private Integer rewardGold;//奖励金币
+    private Integer rewardDiamond;//奖励钻石
+    private Integer rewardHonor;//过关荣誉
+    private Integer consumeGold;//消耗金币
+    private Integer consumeDiamond;//消耗钻石
+    private Integer signCount;//标志块的总数
+    private String signType;//标志块的种类
+    private Integer limitTime;//限时(秒),0-不限时
+    /** 解锁条件类型. */
+    private String conditionUnlock;
+    /** 通过关卡时候的类型. */
+    private Integer conditionPassed;
+    /** 补充说明 */
+    private String explain;
+    /** 人数类型 1单人 2pk*/
+    private Integer numberType;
+    /** 顺序设计,和number type 一起使用。用于游戏排序 */
+    private Integer sort;
+    /**
+     * 关卡类型,1代表 跳,2代表拳击
+     */
+    private Integer type;
+}

+ 26 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/MainInfo.java

@@ -0,0 +1,26 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2019/12/31
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class MainInfo {
+    @Id
+    private String  userId;
+
+    private String username;
+    private String password;
+
+    private String telephoneNumber;
+
+    private String email;
+}

+ 25 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/OtaInfo.java

@@ -0,0 +1,25 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class OtaInfo {
+    @Id
+    private Integer otaId;
+    private String otaName;
+    private String bleName;
+    private Integer bleType;
+    private Integer otaStatus;
+    private String otaDownload;
+}

+ 22 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/Pictures.java

@@ -0,0 +1,22 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2020/1/16
+ */
+@Data
+@Entity
+public class Pictures {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer pictureId;
+    private Integer pictureType;
+    private String pictureUrl;
+}

+ 42 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/ProductCategory.java

@@ -0,0 +1,42 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * 类目
+ *
+ * @author:slambb
+ * @date:2019/11/28
+ * @Data 需要引入组件lombok,之后这里get,set ,toString 方法可省略处理步骤
+ * 编译时候处理get set ,不影响性能
+ */
+
+@Entity
+@DynamicUpdate
+@Data
+public class ProductCategory {
+    // 类目id
+    //采用的是 IDENTITY。主键由数据库自动生成(主要是自动增长型)
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer categoryId;
+    //类目名字
+    private String categoryName;
+    //类目编号
+    private Integer categoryType;
+
+    public ProductCategory() {
+    }
+
+    public ProductCategory(String categoryName, Integer categoryType) {
+        this.categoryName = categoryName;
+        this.categoryType = categoryType;
+    }
+}

+ 29 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/RankInfo.java

@@ -0,0 +1,29 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/3/20
+ */
+@Data
+@Entity
+public class RankInfo {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer rankId;
+    private Integer rankType;
+    //是否显示
+    private Integer rankShow;
+    private Double rankScore;
+
+    @Column(name="r_object_id")
+    private String RObjectId;
+
+    private String userId;
+
+}

+ 30 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/Ranking.java

@@ -0,0 +1,30 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+/**
+ * @author:slambb
+ * @date:2020/3/20
+ */
+@Data
+@Entity
+public class Ranking {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer rankingId;
+    private Integer rankType;
+    /**
+     * 城市代码
+     */
+    private String cityCode;
+    private Double rankScore;
+
+    @Column(name="r_object_id")
+    private String RObjectId;
+
+    private String userId;
+
+}

+ 31 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/RecentlyPlaying.java

@@ -0,0 +1,31 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/14
+ */
+@Data
+@Entity
+//@DynamicUpdate
+public class RecentlyPlaying {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer recentlyId;
+    private Integer recentlyType;
+
+    @Column(name="f_object_id")
+    private String FObjectId;
+    private String userId;
+
+//    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date createTime;
+
+}

+ 29 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/Recommend.java

@@ -0,0 +1,29 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/2/3
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class Recommend {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer recommendId;
+    private Integer recommendType;
+
+    @Column(name="r_object_id")
+    private String RObjectId;
+    /** 游戏显示时间. */
+    private Date showTime;
+    private Date createTime;
+
+
+}

+ 30 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/SignIn.java

@@ -0,0 +1,30 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2021/9/02
+ */
+@Data
+@Entity
+public class SignIn {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+
+    private String userId;
+
+    private Integer continueDays;
+
+    private Date settingTime;
+
+    private Date updateTime;
+}

+ 28 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/SignInReward.java

@@ -0,0 +1,28 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2021/9/02
+ */
+@Data
+@Entity
+public class SignInReward {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+
+    private Integer days;
+
+    private Integer gold;
+
+    private Integer diamond;
+}

+ 43 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/UserInfo.java

@@ -0,0 +1,43 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2019/12/5
+ */
+@Data
+@Entity
+public class UserInfo {
+
+    @Id
+    private String userId;
+
+    private String username;
+
+    private String gender;
+
+    /**
+     * 城市代码
+     */
+    private String cityCode;
+
+    private Date birthday;
+
+    private String signature;
+
+    private String avatarUrl;
+
+    private Double height;
+
+    private Double weight;
+
+    /** 创建时间. */
+    private Date registerTime;
+
+    private Integer status;
+}

+ 31 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/UserLevel.java

@@ -0,0 +1,31 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2021/8/5
+ */
+
+@Data
+@Entity
+public class UserLevel {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private String userId;
+    private String unlockState;
+    private String passedState;
+    /**
+     * 这里是处理记录的关卡类型,比如1代表 数据表level_jump 对应的关卡数据
+     */
+    private Integer eventType;
+    /** 创建时间. */
+    private Date createTime;
+}

+ 43 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/UserReward.java

@@ -0,0 +1,43 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2021/8/5
+ */
+
+@Data
+@Entity
+public class UserReward {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private String userId;
+    private Integer gold;
+    private String goldExplain;
+    private Integer diamond;
+    private String diamondExplain;
+    private Integer honor;
+    private String honorName;
+    private String honorExplain;
+    private String honorUrl;
+
+    private Integer eventId;
+    private String eventName;
+    private Integer eventState;
+    private Integer eventType;
+    /**
+     * 玩通过的次数
+     */
+    private Integer playCount;
+
+    /** 创建时间. */
+    private Date createTime;
+}

+ 27 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/UserWallets.java

@@ -0,0 +1,27 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2021/8/5
+ */
+
+@Data
+@Entity
+public class UserWallets {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private String userId;
+    private Integer gold;
+    private Integer diamond;
+    /** 创建时间. */
+    private Date createTime;
+}

+ 32 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/VersionCode.java

@@ -0,0 +1,32 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class VersionCode {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+    private String title;
+    private String code;
+    /**0:全都限制,1:限制 android ,2:限制ios,*/
+    private Integer limitPlatform;
+    @Column(name="is_show_game")
+    private Integer isShowGame;
+    @Column(name="is_show_video")
+    private Integer isShowVideo;
+    private String describe;
+    private Date deleteTime;
+    private Date createTime;
+    private Date updateTime;
+}

+ 30 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/VersionInfo.java

@@ -0,0 +1,30 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+@Entity
+@DynamicUpdate
+public class VersionInfo {
+    @Id
+    private Integer versionId;
+    private String versionName;
+    private String versionNumber;
+    private String versionCode;
+    private String versionAppid;
+    private String versionDescribe;
+    private String versionNote;
+    private Integer versionStatus;
+    /** 资源列表. */
+    private String apk;
+    private String ios;
+}

+ 24 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/WeightInfo.java

@@ -0,0 +1,24 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.Date;
+
+
+/**
+ * @author:slambb
+ * @date:2019/12/31
+ */
+@Data
+@DynamicUpdate
+@Entity
+public class WeightInfo {
+    @Id
+    private String weightId;
+    private String userId;
+    private Double weight;
+    private Date createTime;
+}

+ 26 - 0
src/main/java/com/YuyeTech/TPlat/dataobject/WxInfo.java

@@ -0,0 +1,26 @@
+package com.YuyeTech.TPlat.dataobject;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author:slambb
+ * @date:2019/12/13
+ */
+@Data
+@Entity
+public class WxInfo {
+
+    @Id
+    private String userId;
+
+    private String openid;
+
+    private String unionid;
+
+
+
+
+}

+ 28 - 0
src/main/java/com/YuyeTech/TPlat/dto/BLToothDTO.java

@@ -0,0 +1,28 @@
+package com.YuyeTech.TPlat.dto;
+
+import lombok.Data;
+
+/**
+ * 绑定的设备信息
+ *
+ * @author:slambb
+ * @date:2020/6/12
+ */
+@Data
+public class BLToothDTO {
+    private Integer bluetoothId;
+    private Integer bluetoothType;
+    private String bluetoothMac;
+    private String identifier;
+
+    public BLToothDTO(Integer bluetoothId,
+                      Integer bluetoothType,
+                      String bluetoothMac,
+                      String identifier)
+    {
+        this.bluetoothId = bluetoothId;
+        this.bluetoothType = bluetoothType;
+        this.bluetoothMac = bluetoothMac;
+        this.identifier = identifier;
+    }
+}

+ 28 - 0
src/main/java/com/YuyeTech/TPlat/dto/DeviceBindDTO.java

@@ -0,0 +1,28 @@
+package com.YuyeTech.TPlat.dto;
+
+import lombok.Data;
+
+/**
+ * 绑定的设备信息
+ *
+ * @author:slambb
+ * @date:2020/6/12
+ */
+@Data
+public class DeviceBindDTO {
+    private Integer deviceId;
+    private Integer deviceType;
+    private String deviceUuid;
+    private String identifier;
+
+    public DeviceBindDTO(Integer deviceId,
+                         Integer deviceType,
+                         String deviceUuid,
+                         String identifier)
+    {
+        this.deviceId = deviceId;
+        this.deviceType = deviceType;
+        this.deviceUuid = deviceUuid;
+        this.identifier = identifier;
+    }
+}

+ 54 - 0
src/main/java/com/YuyeTech/TPlat/dto/FcDTO.java

@@ -0,0 +1,54 @@
+package com.YuyeTech.TPlat.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+public class FcDTO {
+    private Integer gameId;
+    private String gameName;
+    private String gameDescription;
+    private String gameIcon;
+    private String gamePicture;
+    private String gameDownloadUrl;
+    private Boolean gameFavorite;
+
+    /** 排行榜的游戏id. */
+    private String gameRankingId;
+    /** 是否在排行榜显示的游戏 0 是隐藏,1是显示. */
+    private Boolean gameRankingShow;
+
+
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd",timezone="GMT+8")
+    private Date createTime;
+//    private Integer gameStatus;
+//    private Integer gameType;
+
+    public FcDTO(Integer gameId,
+                 String gameName,
+                 String gameIcon,
+                 String gameDescription,
+                 String gamePicture,
+                 String gameDownloadUrl,
+                 Boolean gameFavorite,
+                 String gameRankingId,
+                 Boolean gameRankingShow,
+                 Date createTime) {
+        this.gameId = gameId;
+        this.gameIcon = gameIcon;
+        this.gameName = gameName;
+        this.gameDescription = gameDescription;
+        this.gamePicture = gamePicture;
+        this.gameDownloadUrl = gameDownloadUrl;
+        this.gameFavorite = gameFavorite;
+        this.gameRankingId = gameRankingId;
+        this.gameRankingShow = gameRankingShow;
+        this.createTime = createTime;
+    }
+}

+ 60 - 0
src/main/java/com/YuyeTech/TPlat/dto/FriendInfoDTO.java

@@ -0,0 +1,60 @@
+package com.YuyeTech.TPlat.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+public class FriendInfoDTO {
+    private String username;
+
+    private String gender;
+
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy/MM/dd",timezone="GMT+8")
+    private Date birthday;
+
+    private String signature;
+
+    private String avatarUrl;
+
+    private String cityCode;
+
+    private Double height;
+
+    private Double weight;
+
+    private Boolean isFriend;
+
+    //关注的信息列表对应的一个id
+    private String friendId;
+
+
+    public FriendInfoDTO(String username,
+                   String gender,
+                   String signature,
+                   String avatarUrl,
+                   String cityCode,
+                   Double height,
+                   Double weight,
+                   Date birthday,
+                   Boolean bFriend,
+                   String friendId) {
+        this.username = username;
+        this.gender = gender;
+        this.signature = signature;
+        this.avatarUrl = avatarUrl;
+        this.cityCode = cityCode;
+        this.height = height;
+        this.weight = weight;
+        this.birthday = birthday;
+        this.isFriend = bFriend;
+        this.friendId = friendId;
+    }
+}

+ 60 - 0
src/main/java/com/YuyeTech/TPlat/dto/GameDTO.java

@@ -0,0 +1,60 @@
+package com.YuyeTech.TPlat.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+public class GameDTO {
+    private String gameId;
+    private String gameName;
+    private String gameDescription;
+    private String gameIcon;
+    private String gamePicture;
+    private Boolean gameFavorite;
+    /** 平台区分,0 :android ,1:ios ,2:android & ios*/
+    private Integer  platform;
+
+    /** 排行榜的游戏id. */
+    private String gameRankingId;
+    /** 是否在排行榜显示的游戏 0 是隐藏,1是显示. */
+    private Boolean gameRankingShow;
+
+
+    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd",timezone="GMT+8")
+    private Date createTime;
+//    private Integer gameStatus;
+//    private Integer gameType;
+    private List<GameTagDTO> gameTags;
+
+    public GameDTO(String gameId,
+                   String gameName,
+                   String gameIcon,
+                   String gameDescription,
+                   String gamePicture,
+                   Boolean gameFavorite,
+                   String gameRankingId,
+                   Boolean gameRankingShow,
+                   Date createTime,
+                   List<GameTagDTO> gameTags,
+                   Integer platform) {
+        this.gameId = gameId;
+        this.gameIcon = gameIcon;
+        this.gameName = gameName;
+        this.gameDescription = gameDescription;
+        this.gamePicture = gamePicture;
+        this.gameFavorite = gameFavorite;
+        this.gameRankingId = gameRankingId;
+        this.gameRankingShow = gameRankingShow;
+        this.createTime = createTime;
+        this.gameTags = gameTags;
+        this.platform = platform;
+    }
+}

+ 29 - 0
src/main/java/com/YuyeTech/TPlat/dto/GameTagDTO.java

@@ -0,0 +1,29 @@
+package com.YuyeTech.TPlat.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+public class GameTagDTO {
+    private Integer tagId;
+    private String tagName;
+    private String tagMode;
+    private Integer tagIsDefault;
+
+    public GameTagDTO(Integer tagId,
+                      String tagName,
+                      String tagMode,
+                      Integer tagIsDefault) {
+        this.tagId = tagId;
+        this.tagName = tagName;
+        this.tagMode = tagMode;
+        this.tagIsDefault = tagIsDefault;
+
+    }
+}

+ 33 - 0
src/main/java/com/YuyeTech/TPlat/dto/LevelConditionDTO.java

@@ -0,0 +1,33 @@
+package com.YuyeTech.TPlat.dto;
+
+import lombok.Data;
+
+/**
+ * @author:slambb
+ * @date:2020/1/10
+ */
+@Data
+public class LevelConditionDTO {
+    private Integer type;
+    private String explain;
+    private Integer limitType;
+    private Boolean isScore;
+    private Integer limitScore;
+    private Integer limitLevel;
+
+    public LevelConditionDTO(
+                         Integer type,
+                         String explain,
+                         Integer limitType,
+                         Integer isScore,
+                         Integer limitScore,
+                         Integer limitLevel) {
+        this.type = type;
+        this.explain = explain;
+        this.limitType = limitType;
+        this.isScore = isScore == 1?true:false;
+        this.limitScore = limitScore;
+        this.limitLevel = limitLevel;
+
+    }
+}

+ 27 - 0
src/main/java/com/YuyeTech/TPlat/dto/LevelHonorDTO.java

@@ -0,0 +1,27 @@
+package com.YuyeTech.TPlat.dto;
+
+import lombok.Data;
+
+/**
+ * @author:slambb
+ * @date:2021/8/4
+ */
+@Data
+public class LevelHonorDTO {
+    private String name;
+    private Integer type;
+    private String explain;
+    private String url;
+
+    public LevelHonorDTO(
+                         String name,
+                         Integer type,
+                         String explain,
+                         String url) {
+        this.type = type;
+        this.name = name;
+        this.explain = explain;
+        this.url = url;
+
+    }
+}

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff