浏览代码

********版本创建*********

slambb 4 年之前
当前提交
84cd5ebba4
共有 100 个文件被更改,包括 4372 次插入0 次删除
  1. 3 0
      .gitattributes
  2. 33 0
      .gitignore
  3. 118 0
      .mvn/wrapper/MavenWrapperDownloader.java
  4. 二进制
      .mvn/wrapper/maven-wrapper.jar
  5. 2 0
      .mvn/wrapper/maven-wrapper.properties
  6. 322 0
      mvnw
  7. 182 0
      mvnw.cmd
  8. 147 0
      pom.xml
  9. 200 0
      src/main/java/com/td/boss/BossApplication.java
  10. 21 0
      src/main/java/com/td/boss/annotation/Between.java
  11. 12 0
      src/main/java/com/td/boss/annotation/Decrypt.java
  12. 12 0
      src/main/java/com/td/boss/annotation/Encrypt.java
  13. 16 0
      src/main/java/com/td/boss/annotation/In.java
  14. 13 0
      src/main/java/com/td/boss/annotation/Like.java
  15. 197 0
      src/main/java/com/td/boss/aspect/SafetyAspect.java
  16. 77 0
      src/main/java/com/td/boss/common/controller/CommonController.java
  17. 22 0
      src/main/java/com/td/boss/common/pojo/IpVo.java
  18. 31 0
      src/main/java/com/td/boss/common/pojo/MonitorVo.java
  19. 39 0
      src/main/java/com/td/boss/common/pojo/PageCondition.java
  20. 62 0
      src/main/java/com/td/boss/common/pojo/PageInfo.java
  21. 42 0
      src/main/java/com/td/boss/common/pojo/ParameterRequestWrapper.java
  22. 61 0
      src/main/java/com/td/boss/common/pojo/Result.java
  23. 16 0
      src/main/java/com/td/boss/common/repository/CommonRepository.java
  24. 27 0
      src/main/java/com/td/boss/common/service/CommonService.java
  25. 159 0
      src/main/java/com/td/boss/common/service/CommonServiceImpl.java
  26. 27 0
      src/main/java/com/td/boss/config/async/AsyncConfig.java
  27. 26 0
      src/main/java/com/td/boss/config/enums/ResultEnum.java
  28. 25 0
      src/main/java/com/td/boss/config/exception/AuthorizeException.java
  29. 175 0
      src/main/java/com/td/boss/config/logback/LoggingWSServer.java
  30. 104 0
      src/main/java/com/td/boss/config/monitor/MonitorWSServer.java
  31. 172 0
      src/main/java/com/td/boss/config/security/CaptchaFilterConfig.java
  32. 88 0
      src/main/java/com/td/boss/config/security/DynamicallyUrlInterceptor.java
  33. 55 0
      src/main/java/com/td/boss/config/security/ErrorPageConfig.java
  34. 68 0
      src/main/java/com/td/boss/config/security/LoginFailureHandlerConfig.java
  35. 151 0
      src/main/java/com/td/boss/config/security/LoginSuccessHandlerConfig.java
  36. 37 0
      src/main/java/com/td/boss/config/security/LogoutHandlerConfig.java
  37. 56 0
      src/main/java/com/td/boss/config/security/MyAccessDecisionManager.java
  38. 77 0
      src/main/java/com/td/boss/config/security/MyFilterInvocationSecurityMetadataSource.java
  39. 51 0
      src/main/java/com/td/boss/config/security/MyInvalidSessionStrategy.java
  40. 20 0
      src/main/java/com/td/boss/config/security/PasswordConfig.java
  41. 142 0
      src/main/java/com/td/boss/config/security/SecurityConfig.java
  42. 51 0
      src/main/java/com/td/boss/config/security/UserConfig.java
  43. 51 0
      src/main/java/com/td/boss/config/security/gameConfig.java
  44. 26 0
      src/main/java/com/td/boss/config/websocket/MyEndpointConfigure.java
  45. 30 0
      src/main/java/com/td/boss/config/websocket/WebSocketConfig.java
  46. 15 0
      src/main/java/com/td/boss/game/combosses/controller/ComBossesController.java
  47. 22 0
      src/main/java/com/td/boss/game/combosses/pojo/ComBosses.java
  48. 9 0
      src/main/java/com/td/boss/game/combosses/repository/ComBossesRepository.java
  49. 8 0
      src/main/java/com/td/boss/game/combosses/service/ComBossesService.java
  50. 21 0
      src/main/java/com/td/boss/game/combosses/service/ComBossesServiceImpl.java
  51. 17 0
      src/main/java/com/td/boss/game/combosses/vo/ComBossesVo.java
  52. 15 0
      src/main/java/com/td/boss/game/comequipchest/controller/ComEquipChestController.java
  53. 27 0
      src/main/java/com/td/boss/game/comequipchest/pojo/ComEquipChest.java
  54. 9 0
      src/main/java/com/td/boss/game/comequipchest/repository/ComEquipChestRepository.java
  55. 8 0
      src/main/java/com/td/boss/game/comequipchest/service/ComEquipChestService.java
  56. 21 0
      src/main/java/com/td/boss/game/comequipchest/service/ComEquipChestServiceImpl.java
  57. 23 0
      src/main/java/com/td/boss/game/comequipchest/vo/ComEquipChestVo.java
  58. 15 0
      src/main/java/com/td/boss/game/comequips/controller/ComEquipsController.java
  59. 22 0
      src/main/java/com/td/boss/game/comequips/pojo/ComEquips.java
  60. 9 0
      src/main/java/com/td/boss/game/comequips/repository/ComEquipsRepository.java
  61. 8 0
      src/main/java/com/td/boss/game/comequips/service/ComEquipsService.java
  62. 21 0
      src/main/java/com/td/boss/game/comequips/service/ComEquipsServiceImpl.java
  63. 17 0
      src/main/java/com/td/boss/game/comequips/vo/ComEquipsVo.java
  64. 15 0
      src/main/java/com/td/boss/game/comgeneralattributes/controller/ComGeneralAttributesController.java
  65. 35 0
      src/main/java/com/td/boss/game/comgeneralattributes/pojo/ComGeneralAttributes.java
  66. 9 0
      src/main/java/com/td/boss/game/comgeneralattributes/repository/ComGeneralAttributesRepository.java
  67. 8 0
      src/main/java/com/td/boss/game/comgeneralattributes/service/ComGeneralAttributesService.java
  68. 21 0
      src/main/java/com/td/boss/game/comgeneralattributes/service/ComGeneralAttributesServiceImpl.java
  69. 31 0
      src/main/java/com/td/boss/game/comgeneralattributes/vo/ComGeneralAttributesVo.java
  70. 15 0
      src/main/java/com/td/boss/game/complayers/controller/ComPlayersController.java
  71. 20 0
      src/main/java/com/td/boss/game/complayers/pojo/ComPlayers.java
  72. 9 0
      src/main/java/com/td/boss/game/complayers/repository/ComPlayersRepository.java
  73. 8 0
      src/main/java/com/td/boss/game/complayers/service/ComPlayersService.java
  74. 21 0
      src/main/java/com/td/boss/game/complayers/service/ComPlayersServiceImpl.java
  75. 15 0
      src/main/java/com/td/boss/game/complayers/vo/ComPlayersVo.java
  76. 33 0
      src/main/java/com/td/boss/game/comusers/controller/ComUsersController.java
  77. 25 0
      src/main/java/com/td/boss/game/comusers/pojo/ComUsers.java
  78. 9 0
      src/main/java/com/td/boss/game/comusers/repository/ComUsersRepository.java
  79. 8 0
      src/main/java/com/td/boss/game/comusers/service/ComUsersService.java
  80. 21 0
      src/main/java/com/td/boss/game/comusers/service/ComUsersServiceImpl.java
  81. 21 0
      src/main/java/com/td/boss/game/comusers/vo/ComUsersVo.java
  82. 21 0
      src/main/java/com/td/boss/openapi/controller/OpenApiController.java
  83. 11 0
      src/main/java/com/td/boss/openapi/service/OpenApiService.java
  84. 12 0
      src/main/java/com/td/boss/openapi/service/OpenApiServiceImpl.java
  85. 24 0
      src/main/java/com/td/boss/sys/sysauthority/controller/SysAuthorityController.java
  86. 25 0
      src/main/java/com/td/boss/sys/sysauthority/pojo/SysAuthority.java
  87. 9 0
      src/main/java/com/td/boss/sys/sysauthority/repository/SysAuthorityRepository.java
  88. 8 0
      src/main/java/com/td/boss/sys/sysauthority/service/SysAuthorityService.java
  89. 70 0
      src/main/java/com/td/boss/sys/sysauthority/service/SysAuthorityServiceImpl.java
  90. 21 0
      src/main/java/com/td/boss/sys/sysauthority/vo/SysAuthorityVo.java
  91. 39 0
      src/main/java/com/td/boss/sys/sysmenu/controller/SysMenuController.java
  92. 30 0
      src/main/java/com/td/boss/sys/sysmenu/pojo/SysMenu.java
  93. 9 0
      src/main/java/com/td/boss/sys/sysmenu/repository/SysMenuRepository.java
  94. 12 0
      src/main/java/com/td/boss/sys/sysmenu/service/SysMenuService.java
  95. 122 0
      src/main/java/com/td/boss/sys/sysmenu/service/SysMenuServiceImpl.java
  96. 28 0
      src/main/java/com/td/boss/sys/sysmenu/vo/SysMenuVo.java
  97. 24 0
      src/main/java/com/td/boss/sys/syssetting/controller/SysSettingController.java
  98. 33 0
      src/main/java/com/td/boss/sys/syssetting/pojo/SysSetting.java
  99. 9 0
      src/main/java/com/td/boss/sys/syssetting/repository/SysSettingRepository.java
  100. 8 0
      src/main/java/com/td/boss/sys/syssetting/service/SysSettingService.java

+ 3 - 0
.gitattributes

@@ -0,0 +1,3 @@
+*.js linguist-language=Java
+*.css linguist-language=Java
+*.html linguist-language=Java

+ 33 - 0
.gitignore

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

+ 118 - 0
.mvn/wrapper/MavenWrapperDownloader.java

@@ -0,0 +1,118 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+    private static final String WRAPPER_VERSION = "0.5.6";
+    /**
+     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+     */
+    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+            + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+    /**
+     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+     * use instead of the default one.
+     */
+    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+            ".mvn/wrapper/maven-wrapper.properties";
+
+    /**
+     * Path where the maven-wrapper.jar will be saved to.
+     */
+    private static final String MAVEN_WRAPPER_JAR_PATH =
+            ".mvn/wrapper/maven-wrapper.jar";
+
+    /**
+     * Name of the property which should be used to override the default download url for the wrapper.
+     */
+    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+    public static void main(String args[]) {
+        System.out.println("- Downloader started");
+        File baseDirectory = new File(args[0]);
+        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+        // If the maven-wrapper.properties exists, read it and check if it contains a custom
+        // wrapperUrl parameter.
+        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+        String url = DEFAULT_DOWNLOAD_URL;
+        if (mavenWrapperPropertyFile.exists()) {
+            FileInputStream mavenWrapperPropertyFileInputStream = null;
+            try {
+                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+                Properties mavenWrapperProperties = new Properties();
+                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+            } catch (IOException e) {
+                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+            } finally {
+                try {
+                    if (mavenWrapperPropertyFileInputStream != null) {
+                        mavenWrapperPropertyFileInputStream.close();
+                    }
+                } catch (IOException e) {
+                    // Ignore ...
+                }
+            }
+        }
+        System.out.println("- Downloading from: " + url);
+
+        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+        if (!outputFile.getParentFile().exists()) {
+            if (!outputFile.getParentFile().mkdirs()) {
+                System.out.println(
+                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+            }
+        }
+        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+        try {
+            downloadFileFromURL(url, outputFile);
+            System.out.println("Done");
+            System.exit(0);
+        } catch (Throwable e) {
+            System.out.println("- Error downloading");
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+            String username = System.getenv("MVNW_USERNAME");
+            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+            Authenticator.setDefault(new Authenticator() {
+                @Override
+                protected PasswordAuthentication getPasswordAuthentication() {
+                    return new PasswordAuthentication(username, password);
+                }
+            });
+        }
+        URL website = new URL(urlString);
+        ReadableByteChannel rbc;
+        rbc = Channels.newChannel(website.openStream());
+        FileOutputStream fos = new FileOutputStream(destination);
+        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+        fos.close();
+        rbc.close();
+    }
+
+}

二进制
.mvn/wrapper/maven-wrapper.jar


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

@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

+ 322 - 0
mvnw

@@ -0,0 +1,322 @@
+#!/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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven 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.6/maven-wrapper-0.5.6.jar"
+  else
+    jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.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 Maven 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 keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%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.6/maven-wrapper-0.5.6.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.6/maven-wrapper-0.5.6.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%

+ 147 - 0
pom.xml

@@ -0,0 +1,147 @@
+<?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.td</groupId>
+    <artifactId>boss</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>boss</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-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+		
+		        <!--热部署工具dev-tools-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+            <scope>runtime</scope>
+        </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>
+
+        <!--添加springdata-jpa依赖 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+
+        <!--添加MySQL驱动依赖 -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>8.0.13</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>
+
+        <!--aop 面向切面-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!--https://github.com/oshi/oshi。-->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-json</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+			<!-- 跳过启动测试 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 200 - 0
src/main/java/com/td/boss/BossApplication.java

@@ -0,0 +1,200 @@
+package com.td.boss;
+import com.td.boss.sys.sysmenu.vo.SysMenuVo;
+import com.td.boss.sys.syssetting.service.SysSettingService;
+import com.td.boss.sys.syssetting.vo.SysSettingVo;
+import com.td.boss.sys.sysshortcutmenu.service.SysShortcutMenuService;
+import com.td.boss.sys.sysshortcutmenu.vo.SysShortcutMenuVo;
+import com.td.boss.sys.sysuser.service.SysUserService;
+import com.td.boss.sys.sysuser.vo.SysUserVo;
+import com.td.boss.sys.sysusermenu.service.SysUserMenuService;
+import com.td.boss.util.*;
+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.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+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;
+
+@EnableAsync//开启异步调用
+@SpringBootApplication
+public class BossApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(BossApplication.class, args);
+    }
+
+    /**
+     * 解决不能注入session注册表问题
+     */
+    @Bean
+    SessionRegistry sessionRegistry() {
+        return new SessionRegistryImpl();
+    }
+}
+
+@Slf4j
+@Controller
+@RequestMapping("/")
+@Configuration
+class IndexController {
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    @Autowired
+    private SysSettingService sysSettingService;
+
+    @Autowired
+    private SysUserMenuService sysUserMenuService;
+
+    @Autowired
+    private SysShortcutMenuService sysShortcutMenuService;
+
+    @Value("${server.servlet.context-path:}")
+    private String contextPath;
+
+
+    /**
+     * 端口
+     */
+    @Value("${server.port}")
+    private String port;
+
+    /**
+     * 启动成功
+     */
+    @Bean
+    public ApplicationRunner applicationRunner() {
+        return applicationArguments -> {
+            try {
+                //系统启动时获取数据库数据,设置到公用静态集合sysSettingMap
+                SysSettingVo sysSettingVo = sysSettingService.get("1").getData();
+                SysSettingUtil.setSysSettingMap(sysSettingVo);
+
+                //获取本机内网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");
+
+        //系统信息
+        modelAndView.addObject("sys", SysSettingUtil.getSysSetting());
+
+        //后端公钥
+        String publicKey = RsaUtil.getPublicKey();
+        log.info("后端公钥:" + publicKey);
+        modelAndView.addObject("publicKey", publicKey);
+
+        return modelAndView;
+    }
+
+    /**
+     * 跳转首页
+     */
+    @GetMapping("")
+    public void index1(HttpServletResponse response){
+        //内部重定向
+        try {
+            response.sendRedirect("/index");
+        } catch (IOException e) {
+            //输出到日志文件中
+            log.error(ErrorUtil.errorInfoToString(e));
+        }
+    }
+    @GetMapping("index")
+    public ModelAndView index(){
+        ModelAndView modelAndView = new ModelAndView("index");
+
+        //系统信息
+        modelAndView.addObject("sys", SysSettingUtil.getSysSetting());
+
+        //登录用户
+        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 = RsaUtil.getPublicKey();
+        log.info("后端公钥:" + publicKey);
+        modelAndView.addObject("publicKey", publicKey);
+
+        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);
+    }
+}

+ 21 - 0
src/main/java/com/td/boss/annotation/Between.java

@@ -0,0 +1,21 @@
+package com.td.boss.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/td/boss/annotation/Decrypt.java

@@ -0,0 +1,12 @@
+package com.td.boss.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/td/boss/annotation/Encrypt.java

@@ -0,0 +1,12 @@
+package com.td.boss.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/td/boss/annotation/In.java

@@ -0,0 +1,16 @@
+package com.td.boss.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/td/boss/annotation/Like.java

@@ -0,0 +1,13 @@
+package com.td.boss.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 {
+
+}

+ 197 - 0
src/main/java/com/td/boss/aspect/SafetyAspect.java

@@ -0,0 +1,197 @@
+package com.td.boss.aspect;
+
+import com.td.boss.annotation.Decrypt;
+import com.td.boss.annotation.Encrypt;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.config.exception.AuthorizeException;
+import com.td.boss.util.*;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.jsonwebtoken.ExpiredJwtException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+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 {
+
+    private final JwtTokenUtil jwtTokenUtil;
+    private final String tokenHeader;
+
+    public SafetyAspect(JwtTokenUtil jwtTokenUtil, @Value("${jwt.token}") String tokenHeader) {
+        this.jwtTokenUtil = jwtTokenUtil;
+        this.tokenHeader = tokenHeader;
+    }
+    /**
+     * Pointcut 切入点
+     * 匹配
+     * com.td.boss.sys.*.controller、
+     * com.td.boss.*.controller包下面的所有方法
+     */
+    @Pointcut(value = "execution(public * com.td.boss.sys.*.controller.*.*(..)) || " +
+            "execution(public * com.td.boss.*.controller.*.*(..)) && ! execution(public * com.td.boss.game.*.controller.*.*(..))")
+    public void safetyAspect() {}
+
+    /**
+     * 环绕通知
+     */
+    @Around(value = "safetyAspect()")
+    public Object around(ProceedingJoinPoint pjp) {
+       try {
+
+           //判断api加密开关是否开启
+           if("N".equals(SysSettingUtil.getSysSetting().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;
+            for (Annotation annotation : annotations) {
+                if (annotation.annotationType() == Decrypt.class) {
+                    hasDecrypt = true;
+                }
+                if (annotation.annotationType() == Encrypt.class) {
+                    hasEncrypt = 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
+                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());
+                }
+            }
+
+            //执行并替换最新形参参数   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));
+
+                //转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());
+        }
+    }
+
+
+    @Pointcut(value = "execution(public * com.td.boss.game.*.controller.*.*(..))")
+    public void gameAspect(){}
+
+    @Before(value = "gameAspect()")
+    public void before(JoinPoint joinPoint) throws Exception {
+        //获取上下文request,获取token并解析
+        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = requestAttributes.getRequest();
+        //todo  token 操作
+        final String requestHeader = request.getHeader(this.tokenHeader);
+        String userId = null;
+        String authToken = null;
+        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
+            authToken = requestHeader.substring(7);
+            try {
+                userId = jwtTokenUtil.getUserIdFromToken(authToken);
+                log.info("userId:{}", userId);
+                //todo 如果需要校验的话,取本地或者数据库一个userId校验
+                log.info("validateToken:{}", jwtTokenUtil.validateToken(authToken, userId));
+                //获取参数并赋值
+                Object[] args = joinPoint.getArgs();
+            } catch (ExpiredJwtException e) {
+            }
+        }else{
+            throw  new ExpiredJwtException(null,null,"error");
+//            throw new AuthorizeException(ResultEnum.TOKEN_IS_ILLEGAL.getCode(),
+//                    ResultEnum.TOKEN_IS_ILLEGAL.getMessage());
+        }
+    }
+
+}

+ 77 - 0
src/main/java/com/td/boss/common/controller/CommonController.java

@@ -0,0 +1,77 @@
+package com.td.boss.common.controller;
+
+import com.td.boss.annotation.Decrypt;
+import com.td.boss.annotation.Encrypt;
+import com.td.boss.common.pojo.PageInfo;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.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);
+    }
+
+    @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/td/boss/common/pojo/IpVo.java

@@ -0,0 +1,22 @@
+package com.td.boss.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/td/boss/common/pojo/MonitorVo.java

@@ -0,0 +1,31 @@
+package com.td.boss.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/td/boss/common/pojo/PageCondition.java

@@ -0,0 +1,39 @@
+package com.td.boss.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);
+    }
+}

+ 62 - 0
src/main/java/com/td/boss/common/pojo/PageInfo.java

@@ -0,0 +1,62 @@
+package com.td.boss.common.pojo;
+
+import com.td.boss.util.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;
+    }
+
+    /**
+     * 获取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/td/boss/common/pojo/ParameterRequestWrapper.java

@@ -0,0 +1,42 @@
+package com.td.boss.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)});
+            }
+        }
+    }
+}

+ 61 - 0
src/main/java/com/td/boss/common/pojo/Result.java

@@ -0,0 +1,61 @@
+package com.td.boss.common.pojo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 统一返回对象
+ */
+
+@Data
+public class Result<T> implements Serializable {
+    /**
+     * 通信数据
+     */
+    private T data;
+    /**
+     * 通信状态
+     */
+    private boolean flag = true;
+    /**
+     * 通信描述
+     */
+    private String msg = "操作成功";
+
+    /**
+     * 通过静态方法获取实例
+     */
+    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);
+    }
+
+    @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;
+    }
+
+}

+ 16 - 0
src/main/java/com/td/boss/common/repository/CommonRepository.java

@@ -0,0 +1,16 @@
+package com.td.boss.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> {
+
+}

+ 27 - 0
src/main/java/com/td/boss/common/service/CommonService.java

@@ -0,0 +1,27 @@
+package com.td.boss.common.service;
+
+
+import com.td.boss.common.pojo.PageInfo;
+import com.td.boss.common.pojo.Result;
+
+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);
+
+    Result<List<V>> list(V entityVo);
+
+    Result<V> get(T id);
+
+    Result<V> save(V entityVo);
+
+    Result<T> delete(T id);
+}

+ 159 - 0
src/main/java/com/td/boss/common/service/CommonServiceImpl.java

@@ -0,0 +1,159 @@
+package com.td.boss.common.service;
+
+import com.td.boss.common.pojo.PageCondition;
+import com.td.boss.common.pojo.PageInfo;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.common.repository.CommonRepository;
+import com.td.boss.util.CopyUtil;
+import com.td.boss.util.ErrorUtil;
+import com.td.boss.util.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.data.domain.Example;
+import org.springframework.data.domain.Page;
+import org.springframework.util.StringUtils;
+
+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
+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;//注入实体类仓库
+
+    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 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 Result<V> save(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(!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;
+                    }
+                }
+                //如果前端不传这两个值,后台来维护创建时间、更新时间
+                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 Result.of(CopyUtil.copy(e, entityVoClass));
+    }
+
+    @Override
+    public Result<T> delete(T id) {
+        commonRepository.deleteById(id);
+        return Result.of(id);
+    }
+}

+ 27 - 0
src/main/java/com/td/boss/config/async/AsyncConfig.java

@@ -0,0 +1,27 @@
+package com.td.boss.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;
+    }
+}

+ 26 - 0
src/main/java/com/td/boss/config/enums/ResultEnum.java

@@ -0,0 +1,26 @@
+package com.td.boss.config.enums;
+
+import lombok.Getter;
+
+/**
+ * 返回的
+ * @author:slambb
+ * @date:2019/12/5
+ */
+@Getter
+public enum ResultEnum {
+    SUCCESS(0,"成功"),
+    TOKEN_SUCCESS(300,"用户授权认证通过!"),
+    TOKEN_IS_ILLEGAL(301,"用户授权认证没有通过!客户端请求参数TOKEN信息无效"),
+    TOKEN_DOES_NOT_EXIST(302,"用户授权认证没有通过!客户端请求参数中无TOKEN信息"),
+
+    ;
+    private Integer code;
+
+    private String message;
+
+    ResultEnum(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+}

+ 25 - 0
src/main/java/com/td/boss/config/exception/AuthorizeException.java

@@ -0,0 +1,25 @@
+package com.td.boss.config.exception;
+
+import com.td.boss.config.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/td/boss/config/logback/LoggingWSServer.java

@@ -0,0 +1,175 @@
+package com.td.boss.config.logback;
+
+
+import com.td.boss.config.websocket.MyEndpointConfigure;
+import com.td.boss.util.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/td/boss/config/monitor/MonitorWSServer.java

@@ -0,0 +1,104 @@
+package com.td.boss.config.monitor;
+
+
+import com.td.boss.config.websocket.MyEndpointConfigure;
+import com.td.boss.util.ErrorUtil;
+import com.td.boss.util.SystemMonitorUtil;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+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));
+        }
+    }
+}

+ 172 - 0
src/main/java/com/td/boss/config/security/CaptchaFilterConfig.java

@@ -0,0 +1,172 @@
+package com.td.boss.config.security;
+
+import com.td.boss.common.pojo.ParameterRequestWrapper;
+import com.td.boss.util.*;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.jsonwebtoken.ExpiredJwtException;
+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.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+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.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+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;
+
+
+    @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();
+
+//        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
+//
+//            UserDetails userDetails = userConfig.loadUserByUsername(username);
+//
+//            if (jwtTokenUtil.validateToken(authToken, userDetails)) {
+//                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+//                SecurityContextHolder.getContext().setAuthentication(authentication);
+//            }
+//
+//        }
+
+
+        /*
+            注:详情可在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(SysSettingUtil.getSysSetting().getSysApiEncrypt())) {
+                //解密
+                try {
+                    //AES加密后的数据
+                    String data = request.getParameter("data");
+                    //后端RSA公钥加密后的AES的key
+                    String aesKey = request.getParameter("aesKey");
+                    //前端公钥
+                    publicKey = request.getParameter("publicKey");
+
+                    log.info("前端公钥:" + publicKey);
+
+                    //后端私钥解密的到AES的key
+                    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);
+
+                    //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(SysSettingUtil.getSysSetting().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));
+                        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/td/boss/config/security/DynamicallyUrlInterceptor.java

@@ -0,0 +1,88 @@
+package com.td.boss.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/td/boss/config/security/ErrorPageConfig.java

@@ -0,0 +1,55 @@
+package com.td.boss.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");
+    }
+}

+ 68 - 0
src/main/java/com/td/boss/config/security/LoginFailureHandlerConfig.java

@@ -0,0 +1,68 @@
+package com.td.boss.config.security;
+
+import com.td.boss.util.AesUtil;
+import com.td.boss.util.ErrorUtil;
+import com.td.boss.util.RsaUtil;
+import com.td.boss.util.SysSettingUtil;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Base64;
+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 {
+    @Override
+    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
+        String msg = "{\"code\":\"400\",\"msg\":\"用户名或密码错误\"}";
+
+        //判断api加密开关是否开启
+        if("Y".equals(SysSettingUtil.getSysSetting().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));
+                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();
+    }
+}

+ 151 - 0
src/main/java/com/td/boss/config/security/LoginSuccessHandlerConfig.java

@@ -0,0 +1,151 @@
+package com.td.boss.config.security;
+
+import com.td.boss.sys.sysuser.service.SysUserService;
+import com.td.boss.sys.sysuser.vo.SysUserVo;
+import com.td.boss.util.*;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+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;
+
+    @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(SysSettingUtil.getSysSetting().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));
+
+                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/td/boss/config/security/LogoutHandlerConfig.java

@@ -0,0 +1,37 @@
+package com.td.boss.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/td/boss/config/security/MyAccessDecisionManager.java

@@ -0,0 +1,56 @@
+package com.td.boss.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/td/boss/config/security/MyFilterInvocationSecurityMetadataSource.java

@@ -0,0 +1,77 @@
+package com.td.boss.config.security;
+
+import com.td.boss.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/td/boss/config/security/MyInvalidSessionStrategy.java

@@ -0,0 +1,51 @@
+package com.td.boss.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/td/boss/config/security/PasswordConfig.java

@@ -0,0 +1,20 @@
+package com.td.boss.config.security;
+
+import com.td.boss.util.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));
+    }
+}

+ 142 - 0
src/main/java/com/td/boss/config/security/SecurityConfig.java

@@ -0,0 +1,142 @@
+package com.td.boss.config.security;
+
+import com.td.boss.sys.sysauthority.service.SysAuthorityService;
+import com.td.boss.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.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
+    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
+                //定制url访问权限,动态权限读取,参考:https://www.jianshu.com/p/0a06496e75ea
+                .addFilterAfter(dynamicallyUrlInterceptor(), FilterSecurityInterceptor.class)
+                .authorizeRequests()
+
+                //无需权限访问
+                .antMatchers("/favicon.ico","/common/**", "/webjars/**", "/getVerifyCodeImage","/error/*","/openApi/*","/game/**").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/td/boss/config/security/UserConfig.java

@@ -0,0 +1,51 @@
+package com.td.boss.config.security;
+
+import com.td.boss.sys.sysuser.service.SysUserService;
+import com.td.boss.sys.sysuser.vo.SysUserVo;
+import com.td.boss.sys.sysuserauthority.service.SysUserAuthorityService;
+import com.td.boss.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/td/boss/config/security/gameConfig.java

@@ -0,0 +1,51 @@
+package com.td.boss.config.security;
+
+import com.td.boss.sys.sysuser.service.SysUserService;
+import com.td.boss.sys.sysuser.vo.SysUserVo;
+import com.td.boss.sys.sysuserauthority.service.SysUserAuthorityService;
+import com.td.boss.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()));
+    }
+}

+ 26 - 0
src/main/java/com/td/boss/config/websocket/MyEndpointConfigure.java

@@ -0,0 +1,26 @@
+package com.td.boss.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;
+    }
+}

+ 30 - 0
src/main/java/com/td/boss/config/websocket/WebSocketConfig.java

@@ -0,0 +1,30 @@
+package com.td.boss.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 ();
+    }
+}

+ 15 - 0
src/main/java/com/td/boss/game/combosses/controller/ComBossesController.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.combosses.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.game.combosses.pojo.ComBosses;
+import com.td.boss.game.combosses.vo.ComBossesVo;
+import com.td.boss.game.combosses.service.ComBossesService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comBosses/")
+public class ComBossesController extends CommonController<ComBossesVo, ComBosses, Integer> {
+    @Autowired
+    private ComBossesService comBossesService;
+}

+ 22 - 0
src/main/java/com/td/boss/game/combosses/pojo/ComBosses.java

@@ -0,0 +1,22 @@
+package com.td.boss.game.combosses.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_bosses")
+@Data
+public class ComBosses implements Serializable {
+    @Id
+    @GeneratedValue(strategy= GenerationType.IDENTITY)
+    private Integer id;//该角色的id
+
+    private String name;//角色名词
+
+    private Integer allHealth;//boss的总血量
+
+    private Date allTime;//boos 存在的时间
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/combosses/repository/ComBossesRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.combosses.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.combosses.pojo.ComBosses;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComBossesRepository extends CommonRepository<ComBosses, Integer> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/combosses/service/ComBossesService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.combosses.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.combosses.pojo.ComBosses;
+import com.td.boss.game.combosses.vo.ComBossesVo;
+
+public interface ComBossesService extends CommonService<ComBossesVo, ComBosses, Integer> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/combosses/service/ComBossesServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.combosses.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.combosses.pojo.ComBosses;
+import com.td.boss.game.combosses.vo.ComBossesVo;
+import com.td.boss.game.combosses.repository.ComBossesRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComBossesServiceImpl extends CommonServiceImpl<ComBossesVo, ComBosses, Integer> implements ComBossesService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComBossesRepository comBossesRepository;
+}

+ 17 - 0
src/main/java/com/td/boss/game/combosses/vo/ComBossesVo.java

@@ -0,0 +1,17 @@
+package com.td.boss.game.combosses.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComBossesVo extends PageCondition implements Serializable {
+    private Integer id;//该角色的id
+
+    private String name;//角色名词
+
+    private Integer allHealth;//boss的总血量
+
+    private Date allTime;//boos 存在的时间
+
+}

+ 15 - 0
src/main/java/com/td/boss/game/comequipchest/controller/ComEquipChestController.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.comequipchest.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.game.comequipchest.pojo.ComEquipChest;
+import com.td.boss.game.comequipchest.vo.ComEquipChestVo;
+import com.td.boss.game.comequipchest.service.ComEquipChestService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comEquipChest/")
+public class ComEquipChestController extends CommonController<ComEquipChestVo, ComEquipChest, Integer> {
+    @Autowired
+    private ComEquipChestService comEquipChestService;
+}

+ 27 - 0
src/main/java/com/td/boss/game/comequipchest/pojo/ComEquipChest.java

@@ -0,0 +1,27 @@
+package com.td.boss.game.comequipchest.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_equip_chest")
+@Data
+public class ComEquipChest implements Serializable {
+    @Id
+    private Integer id;//
+
+    private String type;//宝箱类型(1:金,2:银,3:铜,4:铁,0:纸)
+
+    private String red;//
+
+    private String yellow;//
+
+    private String blue;//
+
+    private String green;//
+
+    private String white;//
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/comequipchest/repository/ComEquipChestRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.comequipchest.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.comequipchest.pojo.ComEquipChest;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComEquipChestRepository extends CommonRepository<ComEquipChest, Integer> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/comequipchest/service/ComEquipChestService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.comequipchest.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comequipchest.pojo.ComEquipChest;
+import com.td.boss.game.comequipchest.vo.ComEquipChestVo;
+
+public interface ComEquipChestService extends CommonService<ComEquipChestVo, ComEquipChest, Integer> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/comequipchest/service/ComEquipChestServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.comequipchest.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comequipchest.pojo.ComEquipChest;
+import com.td.boss.game.comequipchest.vo.ComEquipChestVo;
+import com.td.boss.game.comequipchest.repository.ComEquipChestRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComEquipChestServiceImpl extends CommonServiceImpl<ComEquipChestVo, ComEquipChest, Integer> implements ComEquipChestService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComEquipChestRepository comEquipChestRepository;
+}

+ 23 - 0
src/main/java/com/td/boss/game/comequipchest/vo/ComEquipChestVo.java

@@ -0,0 +1,23 @@
+package com.td.boss.game.comequipchest.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComEquipChestVo extends PageCondition implements Serializable {
+    private Integer id;//
+
+    private String type;//宝箱类型(1:金,2:银,3:铜,4:铁,0:纸)
+
+    private String red;//
+
+    private String yellow;//
+
+    private String blue;//
+
+    private String green;//
+
+    private String white;//
+
+}

+ 15 - 0
src/main/java/com/td/boss/game/comequips/controller/ComEquipsController.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.comequips.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.game.comequips.pojo.ComEquips;
+import com.td.boss.game.comequips.vo.ComEquipsVo;
+import com.td.boss.game.comequips.service.ComEquipsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comEquips/")
+public class ComEquipsController extends CommonController<ComEquipsVo, ComEquips, Integer> {
+    @Autowired
+    private ComEquipsService comEquipsService;
+}

+ 22 - 0
src/main/java/com/td/boss/game/comequips/pojo/ComEquips.java

@@ -0,0 +1,22 @@
+package com.td.boss.game.comequips.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_equips")
+@Data
+public class ComEquips implements Serializable {
+    @Id
+    @GeneratedValue(strategy= GenerationType.IDENTITY)
+    private Integer id;//装备id
+
+    private Integer playerId;//拥有该装备的角色ID
+
+    private String name;//装备名词
+
+    private String describe;//装备描述
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/comequips/repository/ComEquipsRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.comequips.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.comequips.pojo.ComEquips;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComEquipsRepository extends CommonRepository<ComEquips, Integer> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/comequips/service/ComEquipsService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.comequips.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comequips.pojo.ComEquips;
+import com.td.boss.game.comequips.vo.ComEquipsVo;
+
+public interface ComEquipsService extends CommonService<ComEquipsVo, ComEquips, Integer> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/comequips/service/ComEquipsServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.comequips.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comequips.pojo.ComEquips;
+import com.td.boss.game.comequips.vo.ComEquipsVo;
+import com.td.boss.game.comequips.repository.ComEquipsRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComEquipsServiceImpl extends CommonServiceImpl<ComEquipsVo, ComEquips, Integer> implements ComEquipsService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComEquipsRepository comEquipsRepository;
+}

+ 17 - 0
src/main/java/com/td/boss/game/comequips/vo/ComEquipsVo.java

@@ -0,0 +1,17 @@
+package com.td.boss.game.comequips.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComEquipsVo extends PageCondition implements Serializable {
+    private Integer id;//装备id
+
+    private Integer playerId;//拥有该装备的角色ID
+
+    private String name;//装备名词
+
+    private String describe;//装备描述
+
+}

+ 15 - 0
src/main/java/com/td/boss/game/comgeneralattributes/controller/ComGeneralAttributesController.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.comgeneralattributes.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.game.comgeneralattributes.pojo.ComGeneralAttributes;
+import com.td.boss.game.comgeneralattributes.vo.ComGeneralAttributesVo;
+import com.td.boss.game.comgeneralattributes.service.ComGeneralAttributesService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comGeneralAttributes/")
+public class ComGeneralAttributesController extends CommonController<ComGeneralAttributesVo, ComGeneralAttributes, Integer> {
+    @Autowired
+    private ComGeneralAttributesService comGeneralAttributesService;
+}

+ 35 - 0
src/main/java/com/td/boss/game/comgeneralattributes/pojo/ComGeneralAttributes.java

@@ -0,0 +1,35 @@
+package com.td.boss.game.comgeneralattributes.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_general_attributes")
+@Data
+public class ComGeneralAttributes implements Serializable {
+    @Id
+    private Integer id;//
+
+    private Integer healthPoint;//血单位(HP)
+
+    private Integer magicPoint;//魔法值(MP)
+
+    private Integer attack;//攻击力(ATK)
+
+    private Integer defence;//防御力(DEF)
+
+    private Integer comboRate;//连击率
+
+    private Integer critRate;//暴击率
+
+    private Integer dodgeBlue;//闪避回蓝
+
+    private Integer blockBlood;//格挡回血
+
+    private Integer autoBlood;//被动回血 1/s
+
+    private Integer autoBlue;//被动回蓝 1/s
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/comgeneralattributes/repository/ComGeneralAttributesRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.comgeneralattributes.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.comgeneralattributes.pojo.ComGeneralAttributes;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComGeneralAttributesRepository extends CommonRepository<ComGeneralAttributes, Integer> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/comgeneralattributes/service/ComGeneralAttributesService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.comgeneralattributes.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comgeneralattributes.pojo.ComGeneralAttributes;
+import com.td.boss.game.comgeneralattributes.vo.ComGeneralAttributesVo;
+
+public interface ComGeneralAttributesService extends CommonService<ComGeneralAttributesVo, ComGeneralAttributes, Integer> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/comgeneralattributes/service/ComGeneralAttributesServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.comgeneralattributes.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comgeneralattributes.pojo.ComGeneralAttributes;
+import com.td.boss.game.comgeneralattributes.vo.ComGeneralAttributesVo;
+import com.td.boss.game.comgeneralattributes.repository.ComGeneralAttributesRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComGeneralAttributesServiceImpl extends CommonServiceImpl<ComGeneralAttributesVo, ComGeneralAttributes, Integer> implements ComGeneralAttributesService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComGeneralAttributesRepository comGeneralAttributesRepository;
+}

+ 31 - 0
src/main/java/com/td/boss/game/comgeneralattributes/vo/ComGeneralAttributesVo.java

@@ -0,0 +1,31 @@
+package com.td.boss.game.comgeneralattributes.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComGeneralAttributesVo extends PageCondition implements Serializable {
+    private Integer id;//
+
+    private Integer healthPoint;//血单位(HP)
+
+    private Integer magicPoint;//魔法值(MP)
+
+    private Integer attack;//攻击力(ATK)
+
+    private Integer defence;//防御力(DEF)
+
+    private Integer comboRate;//连击率
+
+    private Integer critRate;//暴击率
+
+    private Integer dodgeBlue;//闪避回蓝
+
+    private Integer blockBlood;//格挡回血
+
+    private Integer autoBlood;//被动回血 1/s
+
+    private Integer autoBlue;//被动回蓝 1/s
+
+}

+ 15 - 0
src/main/java/com/td/boss/game/complayers/controller/ComPlayersController.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.complayers.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.game.complayers.pojo.ComPlayers;
+import com.td.boss.game.complayers.vo.ComPlayersVo;
+import com.td.boss.game.complayers.service.ComPlayersService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comPlayers/")
+public class ComPlayersController extends CommonController<ComPlayersVo, ComPlayers, Integer> {
+    @Autowired
+    private ComPlayersService comPlayersService;
+}

+ 20 - 0
src/main/java/com/td/boss/game/complayers/pojo/ComPlayers.java

@@ -0,0 +1,20 @@
+package com.td.boss.game.complayers.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_players")
+@Data
+public class ComPlayers implements Serializable {
+    @Id
+    @GeneratedValue(strategy= GenerationType.IDENTITY)
+    private Integer id;//该角色的id
+
+    private String userId;//创建该角色的用户id
+
+    private String name;//角色名词
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/complayers/repository/ComPlayersRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.complayers.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.complayers.pojo.ComPlayers;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComPlayersRepository extends CommonRepository<ComPlayers, Integer> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/complayers/service/ComPlayersService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.complayers.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayers.pojo.ComPlayers;
+import com.td.boss.game.complayers.vo.ComPlayersVo;
+
+public interface ComPlayersService extends CommonService<ComPlayersVo, ComPlayers, Integer> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/complayers/service/ComPlayersServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.complayers.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayers.pojo.ComPlayers;
+import com.td.boss.game.complayers.vo.ComPlayersVo;
+import com.td.boss.game.complayers.repository.ComPlayersRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComPlayersServiceImpl extends CommonServiceImpl<ComPlayersVo, ComPlayers, Integer> implements ComPlayersService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComPlayersRepository comPlayersRepository;
+}

+ 15 - 0
src/main/java/com/td/boss/game/complayers/vo/ComPlayersVo.java

@@ -0,0 +1,15 @@
+package com.td.boss.game.complayers.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayersVo extends PageCondition implements Serializable {
+    private Integer id;//该角色的id
+
+    private String userId;//创建该角色的用户id
+
+    private String name;//角色名词
+
+}

+ 33 - 0
src/main/java/com/td/boss/game/comusers/controller/ComUsersController.java

@@ -0,0 +1,33 @@
+package com.td.boss.game.comusers.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.game.comusers.pojo.ComUsers;
+import com.td.boss.game.comusers.vo.ComUsersVo;
+import com.td.boss.game.comusers.service.ComUsersService;
+import com.td.boss.util.JwtTokenUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/game/comUsers/")
+public class ComUsersController extends CommonController<ComUsersVo, ComUsers, String> {
+    @Autowired
+    private ComUsersService comUsersService;
+
+    @Autowired
+    private JwtTokenUtil jwtTokenUtil;
+
+
+    @GetMapping("test")
+    public Result<String> test() {
+        return Result.of("无需登录的接口:comUsers测试数据!");
+    }
+
+    @PostMapping("login")
+    public Result<String> userLogin() {
+        //todo 后续在 comUsersService 取出 id 生成token
+        final String token = jwtTokenUtil.generateToken("slambb");
+        return Result.of(token);
+    }
+}

+ 25 - 0
src/main/java/com/td/boss/game/comusers/pojo/ComUsers.java

@@ -0,0 +1,25 @@
+package com.td.boss.game.comusers.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_users")
+@Data
+public class ComUsers implements Serializable {
+    @Id
+    private String userId;//用户id
+
+    private Integer energy;//用户体力值
+
+    private Integer mnt;//
+
+    private Integer mnw;//
+
+    private Integer bgb;//
+
+    private Integer mns;//
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/comusers/repository/ComUsersRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.comusers.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.comusers.pojo.ComUsers;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComUsersRepository extends CommonRepository<ComUsers, String> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/comusers/service/ComUsersService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.comusers.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comusers.pojo.ComUsers;
+import com.td.boss.game.comusers.vo.ComUsersVo;
+
+public interface ComUsersService extends CommonService<ComUsersVo, ComUsers, String> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/comusers/service/ComUsersServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.comusers.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.comusers.pojo.ComUsers;
+import com.td.boss.game.comusers.vo.ComUsersVo;
+import com.td.boss.game.comusers.repository.ComUsersRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComUsersServiceImpl extends CommonServiceImpl<ComUsersVo, ComUsers, String> implements ComUsersService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComUsersRepository comUsersRepository;
+}

+ 21 - 0
src/main/java/com/td/boss/game/comusers/vo/ComUsersVo.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.comusers.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComUsersVo extends PageCondition implements Serializable {
+    private String userId;//用户id
+
+    private Integer energy;//用户体力值
+
+    private Integer mnt;//
+
+    private Integer mnw;//
+
+    private Integer bgb;//
+
+    private Integer mns;//
+
+}

+ 21 - 0
src/main/java/com/td/boss/openapi/controller/OpenApiController.java

@@ -0,0 +1,21 @@
+package com.td.boss.openapi.controller;
+
+import com.td.boss.common.pojo.Result;
+import com.td.boss.openapi.service.OpenApiService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/openApi/")
+public class OpenApiController {
+
+    @Autowired
+    private OpenApiService openApiService;
+
+    @GetMapping("test")
+    public Result<String> test() {
+        return openApiService.test();
+    }
+}

+ 11 - 0
src/main/java/com/td/boss/openapi/service/OpenApiService.java

@@ -0,0 +1,11 @@
+package com.td.boss.openapi.service;
+
+import com.td.boss.common.pojo.Result;
+
+public interface OpenApiService {
+    /**
+     * open api test测试
+     * @return 测试数据
+     */
+    Result<String> test();
+}

+ 12 - 0
src/main/java/com/td/boss/openapi/service/OpenApiServiceImpl.java

@@ -0,0 +1,12 @@
+package com.td.boss.openapi.service;
+
+import com.td.boss.common.pojo.Result;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OpenApiServiceImpl implements OpenApiService {
+    @Override
+    public Result<String> test() {
+        return Result.of("无需登录的接口:OpenApi测试数据!");
+    }
+}

+ 24 - 0
src/main/java/com/td/boss/sys/sysauthority/controller/SysAuthorityController.java

@@ -0,0 +1,24 @@
+package com.td.boss.sys.sysauthority.controller;
+
+import com.td.boss.common.controller.CommonController;
+import com.td.boss.sys.sysauthority.pojo.SysAuthority;
+import com.td.boss.sys.sysauthority.service.SysAuthorityService;
+import com.td.boss.sys.sysauthority.vo.SysAuthorityVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
+
+@RestController
+@RequestMapping("/sys/sysAuthority/")
+public class SysAuthorityController extends CommonController<SysAuthorityVo, SysAuthority, String> {
+    @Autowired
+    private SysAuthorityService sysAuthorityService;
+
+    @GetMapping("authority")
+    public ModelAndView authority(){
+        return new ModelAndView("sys/authority/authority");
+    }
+
+}

+ 25 - 0
src/main/java/com/td/boss/sys/sysauthority/pojo/SysAuthority.java

@@ -0,0 +1,25 @@
+package com.td.boss.sys.sysauthority.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "sys_authority")
+@Data
+public class SysAuthority implements Serializable {
+    @Id
+    private String authorityId;//权限id
+
+    private String authorityName;//权限名称,ROLE_开头,全大写
+
+    private String authorityContent;//权限内容,可访问的url,多个时用,隔开
+
+    private String authorityRemark;//权限描述
+
+    private Date createTime;//创建时间
+
+    private Date updateTime;//修改时间
+
+}

+ 9 - 0
src/main/java/com/td/boss/sys/sysauthority/repository/SysAuthorityRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.sys.sysauthority.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.sys.sysauthority.pojo.SysAuthority;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SysAuthorityRepository extends CommonRepository<SysAuthority, String> {
+}

+ 8 - 0
src/main/java/com/td/boss/sys/sysauthority/service/SysAuthorityService.java

@@ -0,0 +1,8 @@
+package com.td.boss.sys.sysauthority.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.sys.sysauthority.pojo.SysAuthority;
+import com.td.boss.sys.sysauthority.vo.SysAuthorityVo;
+
+public interface SysAuthorityService extends CommonService<SysAuthorityVo, SysAuthority, String> {
+}

+ 70 - 0
src/main/java/com/td/boss/sys/sysauthority/service/SysAuthorityServiceImpl.java

@@ -0,0 +1,70 @@
+package com.td.boss.sys.sysauthority.service;
+
+import com.td.boss.common.pojo.Result;
+import com.td.boss.common.service.CommonServiceImpl;
+import com.td.boss.config.security.MyFilterInvocationSecurityMetadataSource;
+import com.td.boss.sys.sysauthority.pojo.SysAuthority;
+import com.td.boss.sys.sysauthority.repository.SysAuthorityRepository;
+import com.td.boss.sys.sysauthority.vo.SysAuthorityVo;
+import com.td.boss.sys.sysuserauthority.service.SysUserAuthorityService;
+import com.td.boss.sys.sysuserauthority.vo.SysUserAuthorityVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.List;
+
+@Service
+@Transactional
+public class SysAuthorityServiceImpl extends CommonServiceImpl<SysAuthorityVo, SysAuthority, String> implements SysAuthorityService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private SysAuthorityRepository sysAuthorityRepository;
+
+    @Autowired
+    private SysAuthorityService sysAuthorityService;
+
+    @Autowired
+    private SysUserAuthorityService sysUserAuthorityService;
+
+    @Autowired
+    private MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;
+
+    /**
+     * 重写save方法,当新增、修改权限表后需要去更新权限集合
+     */
+    @Override
+    public Result<SysAuthorityVo> save(SysAuthorityVo entityVo) {
+        Result<SysAuthorityVo> result = super.save(entityVo);
+
+        //更新权限集合
+        List<SysAuthorityVo> authorityVoList = sysAuthorityService.list(new SysAuthorityVo()).getData();
+        myFilterInvocationSecurityMetadataSource.setRequestMap(authorityVoList);
+        return result;
+    }
+
+    /**
+     * 重写delete方法
+     */
+    @Override
+    public Result<String> delete(String id) {
+        //删除权限之前,删除用户权限关联表对应数据
+        SysUserAuthorityVo sysUserAuthorityVo = new SysUserAuthorityVo();
+        sysUserAuthorityVo.setAuthorityId(id);
+        sysUserAuthorityService.list(sysUserAuthorityVo).getData().forEach((vo)->{
+            sysUserAuthorityService.delete(vo.getUserAuthorityId());
+        });
+
+        //再删除自己
+        Result<String> result = super.delete(id);
+
+        //更新权限集合
+        List<SysAuthorityVo> authorityVoList = sysAuthorityService.list(new SysAuthorityVo()).getData();
+        myFilterInvocationSecurityMetadataSource.setRequestMap(authorityVoList);
+        return result;
+    }
+}

+ 21 - 0
src/main/java/com/td/boss/sys/sysauthority/vo/SysAuthorityVo.java

@@ -0,0 +1,21 @@
+package com.td.boss.sys.sysauthority.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class SysAuthorityVo extends PageCondition implements Serializable {
+    private String authorityId;//权限id
+
+    private String authorityName;//权限名称,ROLE_开头,全大写
+
+    private String authorityContent;//权限内容,可访问的url,多个时用,隔开
+
+    private String authorityRemark;//权限描述
+
+    private Date createTime;//创建时间
+
+    private Date updateTime;//修改时间
+
+}

+ 39 - 0
src/main/java/com/td/boss/sys/sysmenu/controller/SysMenuController.java

@@ -0,0 +1,39 @@
+package com.td.boss.sys.sysmenu.controller;
+
+import com.td.boss.annotation.Decrypt;
+import com.td.boss.annotation.Encrypt;
+import com.td.boss.common.controller.CommonController;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.sys.sysmenu.pojo.SysMenu;
+import com.td.boss.sys.sysmenu.service.SysMenuService;
+import com.td.boss.sys.sysmenu.vo.SysMenuVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/sys/sysMenu/")
+public class SysMenuController extends CommonController<SysMenuVo, SysMenu, String> {
+    @Autowired
+    private SysMenuService sysMenuService;
+
+    @GetMapping("menu")
+    public ModelAndView menu(){
+        return new ModelAndView("sys/menu/menu");
+    }
+
+    /**
+     * 分层级
+     */
+    @PostMapping("listByTier")
+    @Decrypt
+    @Encrypt
+    public Result<List<SysMenuVo>> listByTier(SysMenuVo entityVo) {
+        return sysMenuService.listByTier(entityVo);
+    }
+}

+ 30 - 0
src/main/java/com/td/boss/sys/sysmenu/pojo/SysMenu.java

@@ -0,0 +1,30 @@
+package com.td.boss.sys.sysmenu.pojo;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "sys_menu")
+@Data
+public class SysMenu implements Serializable {
+    @Id
+    private String menuId;//菜单id
+
+    private String menuName;//菜单名称
+
+    private String menuPath;//菜单路径
+
+    private String menuParentId;//上级id
+
+    private Integer sortWeight;//同级排序权重:0-10
+
+    private Date createTime;//创建时间
+
+    private Date updateTime;//修改时间
+
+}

+ 9 - 0
src/main/java/com/td/boss/sys/sysmenu/repository/SysMenuRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.sys.sysmenu.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.sys.sysmenu.pojo.SysMenu;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SysMenuRepository extends CommonRepository<SysMenu, String> {
+}

+ 12 - 0
src/main/java/com/td/boss/sys/sysmenu/service/SysMenuService.java

@@ -0,0 +1,12 @@
+package com.td.boss.sys.sysmenu.service;
+
+import com.td.boss.common.pojo.Result;
+import com.td.boss.common.service.*;
+import com.td.boss.sys.sysmenu.pojo.SysMenu;
+import com.td.boss.sys.sysmenu.vo.SysMenuVo;
+
+import java.util.List;
+
+public interface SysMenuService extends CommonService<SysMenuVo, SysMenu, String> {
+    Result<List<SysMenuVo>> listByTier(SysMenuVo entityVo);
+}

+ 122 - 0
src/main/java/com/td/boss/sys/sysmenu/service/SysMenuServiceImpl.java

@@ -0,0 +1,122 @@
+package com.td.boss.sys.sysmenu.service;
+
+import com.td.boss.common.pojo.Result;
+import com.td.boss.common.service.CommonServiceImpl;
+import com.td.boss.sys.sysmenu.pojo.SysMenu;
+import com.td.boss.sys.sysmenu.repository.SysMenuRepository;
+import com.td.boss.sys.sysmenu.vo.SysMenuVo;
+import com.td.boss.sys.sysusermenu.service.SysUserMenuService;
+import com.td.boss.sys.sysusermenu.vo.SysUserMenuVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+@Service
+@Transactional
+public class SysMenuServiceImpl extends CommonServiceImpl<SysMenuVo, SysMenu, String> implements SysMenuService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private SysMenuRepository sysMenuRepository;
+
+    @Autowired
+    private SysUserMenuService sysUserMenuService;
+
+    @Override
+    public Result<String> delete(String id) {
+        //先删除子节点
+        SysMenuVo sysMenuVo = new SysMenuVo();
+        sysMenuVo.setMenuParentId(id);
+        super.list(sysMenuVo).getData().forEach((menuVo)->{
+            super.delete(menuVo.getMenuId());
+        });
+
+        //后删除所有用户菜单表关联信息
+        SysUserMenuVo sysUserMenuVo = new SysUserMenuVo();
+        sysUserMenuVo.setMenuId(id);
+        sysUserMenuService.list(sysUserMenuVo).getData().forEach((vo)->{
+            sysUserMenuService.delete(vo.getUserMenuId());
+        });
+
+        //再删除自己
+        return super.delete(id);
+    }
+
+    @Override
+    public Result<List<SysMenuVo>> listByTier(SysMenuVo entityVo) {
+        List<SysMenuVo> menuVoList = new ArrayList<>();
+        List<SysMenuVo> sysMenuVoList = super.list(entityVo).getData();
+        sysMenuVoList.forEach((sysMenuVo) -> {
+            if(StringUtils.isEmpty(sysMenuVo.getMenuParentId())){
+                //上级节点
+                menuVoList.add(sysMenuVo);
+            }
+        });
+        sysMenuVoList.forEach((sysMenuVo) -> {
+            if(!StringUtils.isEmpty(sysMenuVo.getMenuParentId())){
+                //子节点
+                menuVoList.forEach((sysMenuVoP) -> {
+                    if(sysMenuVoP.getMenuId().equals(sysMenuVo.getMenuParentId())){
+                        sysMenuVoP.getChildren().add(sysMenuVo);
+                    }
+                });
+            }
+        });
+
+        //排序
+        menuVoList.sort(order());
+        menuVoList.forEach((sysMenuVoP) -> {
+            sysMenuVoP.getChildren().sort(order());
+        });
+
+        return Result.of(menuVoList);
+    }
+
+    /**
+     * 排序,根据sortWeight排序
+     */
+    private Comparator<SysMenuVo> order(){
+        return (o1, o2) -> {
+            if (!o1.getSortWeight().equals(o2.getSortWeight())){
+                return o1.getSortWeight() - o2.getSortWeight();
+            }
+            return 0 ;
+        };
+    }
+
+    /**
+     * 获取子节点
+     * @param id 父节点id
+     * @param allMenu 所有菜单列表
+     * @return 每个根节点下,所有子菜单列表
+     */
+    private List<SysMenuVo> getChild(String id,List<SysMenuVo> allMenu){
+        //子菜单
+        List<SysMenuVo> childList = new ArrayList<SysMenuVo>();
+        for (SysMenuVo nav : allMenu) {
+            // 遍历所有节点,将所有菜单的父id与传过来的根节点的id比较
+            //相等说明:为该根节点的子节点。
+            if (nav.getMenuParentId().equals(id)){
+                childList.add(nav);
+            }
+        }
+        //递归
+        for (SysMenuVo nav : childList) {
+            nav.setChildren(getChild(nav.getMenuId(), allMenu));
+        }
+        childList.sort(order()); //排序
+        //如果节点下没有子节点,返回一个空List(递归退出)
+        if (childList.size() == 0 ){
+            return new ArrayList<>();
+        }
+        return childList;
+    }
+}

+ 28 - 0
src/main/java/com/td/boss/sys/sysmenu/vo/SysMenuVo.java

@@ -0,0 +1,28 @@
+package com.td.boss.sys.sysmenu.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class SysMenuVo extends PageCondition implements Serializable {
+    private String menuId;//菜单id
+
+    private String menuName;//菜单名称
+
+    private String menuPath;//菜单路径
+
+    private String menuParentId;//上级id
+
+    private Integer sortWeight;//同级排序权重:0-10
+
+    private Date createTime;//创建时间
+
+    private Date updateTime;//修改时间
+
+    private List<SysMenuVo> children = new ArrayList<>();//如果是父类,这里存孩子节点
+}

+ 24 - 0
src/main/java/com/td/boss/sys/syssetting/controller/SysSettingController.java

@@ -0,0 +1,24 @@
+package com.td.boss.sys.syssetting.controller;
+
+import com.td.boss.common.controller.CommonController;
+import com.td.boss.sys.syssetting.pojo.SysSetting;
+import com.td.boss.sys.syssetting.service.SysSettingService;
+import com.td.boss.sys.syssetting.vo.SysSettingVo;
+import com.td.boss.util.SysSettingUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
+
+@RestController
+@RequestMapping("/sys/sysSetting/")
+public class SysSettingController extends CommonController<SysSettingVo, SysSetting, String> {
+    @Autowired
+    private SysSettingService sysSettingService;
+
+    @GetMapping("setting")
+    public ModelAndView setting() {
+        return new ModelAndView("sys/setting/setting", "sys", SysSettingUtil.getSysSetting());
+    }
+}

+ 33 - 0
src/main/java/com/td/boss/sys/syssetting/pojo/SysSetting.java

@@ -0,0 +1,33 @@
+package com.td.boss.sys.syssetting.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "sys_setting")
+@Data
+public class SysSetting implements Serializable {
+    @Id
+    private String id;//表id
+
+    private String sysName;//系统名称
+
+    private String sysLogo;//系统logo图标
+
+    private String sysBottomText;//系统底部信息
+
+    private String sysColor;//系统颜色
+
+    private String sysNoticeText;//系统公告
+
+    private String sysApiEncrypt;//API加密 Y/N
+
+    private Date createTime;//创建时间
+
+    private Date updateTime;//修改时间
+
+    private String userInitPassword;//用户管理:初始、重置密码
+
+}

+ 9 - 0
src/main/java/com/td/boss/sys/syssetting/repository/SysSettingRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.sys.syssetting.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.sys.syssetting.pojo.SysSetting;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SysSettingRepository extends CommonRepository<SysSetting, String> {
+}

+ 8 - 0
src/main/java/com/td/boss/sys/syssetting/service/SysSettingService.java

@@ -0,0 +1,8 @@
+package com.td.boss.sys.syssetting.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.sys.syssetting.pojo.SysSetting;
+import com.td.boss.sys.syssetting.vo.SysSettingVo;
+
+public interface SysSettingService extends CommonService<SysSettingVo, SysSetting, String> {
+}

部分文件因为文件数量过多而无法显示