浏览代码

智能司法平台demo

jessie 5 年之前
当前提交
64a5cff0b1
共有 52 个文件被更改,包括 3783 次插入0 次删除
  1. 310 0
      mvnw
  2. 182 0
      mvnw.cmd
  3. 197 0
      pom.xml
  4. 32 0
      src/main/java/com/pavis/ai/app/judicial/JudicialApplication.java
  5. 31 0
      src/main/java/com/pavis/ai/app/judicial/common/config/CorsFilterConfig.java
  6. 29 0
      src/main/java/com/pavis/ai/app/judicial/common/config/JudicialConfig.java
  7. 21 0
      src/main/java/com/pavis/ai/app/judicial/common/config/MybatisPlusConfig.java
  8. 15 0
      src/main/java/com/pavis/ai/app/judicial/common/config/PasswordEncoderConfig.java
  9. 27 0
      src/main/java/com/pavis/ai/app/judicial/common/config/ResourceServerConfig.java
  10. 37 0
      src/main/java/com/pavis/ai/app/judicial/common/config/Swagger2Config.java
  11. 24 0
      src/main/java/com/pavis/ai/app/judicial/common/config/WebMvcConfig.java
  12. 27 0
      src/main/java/com/pavis/ai/app/judicial/common/config/WebSecurityConfig.java
  13. 13 0
      src/main/java/com/pavis/ai/app/judicial/common/config/WebSocketConfig.java
  14. 47 0
      src/main/java/com/pavis/ai/app/judicial/common/config/constants/Constants.java
  15. 103 0
      src/main/java/com/pavis/ai/app/judicial/common/config/constants/ErrorCode.java
  16. 21 0
      src/main/java/com/pavis/ai/app/judicial/common/config/constants/ResourceType.java
  17. 16 0
      src/main/java/com/pavis/ai/app/judicial/common/config/properties/CommonProperties.java
  18. 15 0
      src/main/java/com/pavis/ai/app/judicial/common/config/properties/Dir.java
  19. 22 0
      src/main/java/com/pavis/ai/app/judicial/common/exception/AlertException.java
  20. 36 0
      src/main/java/com/pavis/ai/app/judicial/common/exception/BaseException.java
  21. 179 0
      src/main/java/com/pavis/ai/app/judicial/common/exception/GlobalExceptionHandler.java
  22. 106 0
      src/main/java/com/pavis/ai/app/judicial/common/http/ErrorCode.java
  23. 155 0
      src/main/java/com/pavis/ai/app/judicial/common/http/ResultBody.java
  24. 27 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/AuthenticationUtils.java
  25. 93 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/BeanConvertUtils.java
  26. 11 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/DateUtils.java
  27. 110 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/EncodeUtils.java
  28. 23 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/IgnoreUtils.java
  29. 29 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/RandomValueUtils.java
  30. 83 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/SpringContextHolder.java
  31. 540 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/StrUtils.java
  32. 469 0
      src/main/java/com/pavis/ai/app/judicial/common/utils/WebUtils.java
  33. 56 0
      src/main/java/com/pavis/ai/app/judicial/controller/CaseController.java
  34. 26 0
      src/main/java/com/pavis/ai/app/judicial/form/LegalInfo.java
  35. 20 0
      src/main/java/com/pavis/ai/app/judicial/form/OpData.java
  36. 25 0
      src/main/java/com/pavis/ai/app/judicial/form/OpMessage.java
  37. 173 0
      src/main/java/com/pavis/ai/app/judicial/form/QaWebSocket.java
  38. 14 0
      src/main/java/com/pavis/ai/app/judicial/mapper/CaseMapper.java
  39. 14 0
      src/main/java/com/pavis/ai/app/judicial/mapper/OpMapper.java
  40. 20 0
      src/main/java/com/pavis/ai/app/judicial/model/Case.java
  41. 22 0
      src/main/java/com/pavis/ai/app/judicial/model/Op.java
  42. 11 0
      src/main/java/com/pavis/ai/app/judicial/service/CancelCallback.java
  43. 24 0
      src/main/java/com/pavis/ai/app/judicial/service/CaseService.java
  44. 18 0
      src/main/java/com/pavis/ai/app/judicial/service/JqasService.java
  45. 17 0
      src/main/java/com/pavis/ai/app/judicial/service/OpService.java
  46. 116 0
      src/main/java/com/pavis/ai/app/judicial/service/impl/CaseServiceImpl.java
  47. 55 0
      src/main/java/com/pavis/ai/app/judicial/service/impl/JqasServiceImpl.java
  48. 57 0
      src/main/java/com/pavis/ai/app/judicial/service/impl/OpServiceImpl.java
  49. 36 0
      src/main/resources/application-dev.yml
  50. 11 0
      src/main/resources/application.yml
  51. 22 0
      src/main/resources/error.properties
  52. 16 0
      src/test/java/com/pavis/ai/app/judicial/JudicialApplicationTests.java

+ 310 - 0
mvnw

@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# 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%

+ 197 - 0
pom.xml

@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.1.10.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.pavis.ai.app</groupId>
+    <artifactId>judicial</artifactId>
+    <version>0.0.1</version>
+    <name>judicial</name>
+    <description>司法平台</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <spring-cloud.version>Greenwich.SR5</spring-cloud.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jdbc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-quartz</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </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>
+        <dependency>
+            <groupId>org.springframework.amqp</groupId>
+            <artifactId>spring-rabbit-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- 通用包 -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>swagger-bootstrap-ui</artifactId>
+            <version>1.9.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>27.0.1-jre</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.47</version>
+        </dependency>
+
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.14</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-text</artifactId>
+            <version>1.8</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-websocket</artifactId>
+            <version>5.0.4.RELEASE</version>
+        </dependency>
+
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>${spring-cloud.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 32 - 0
src/main/java/com/pavis/ai/app/judicial/JudicialApplication.java

@@ -0,0 +1,32 @@
+package com.pavis.ai.app.judicial;
+
+import com.pavis.ai.app.judicial.form.QaWebSocket;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@MapperScan("com.pavis.ai.app.judicial.mapper")
+@EnableAsync
+@SpringBootApplication
+public class JudicialApplication implements WebMvcConfigurer {
+
+    public static void main(String[] args) {
+        // SpringApplication.run(JudicialApplication.class, args);
+        /**
+         * 解决WebSocket不能注入的问题
+         */
+        SpringApplication springApplication = new SpringApplication(JudicialApplication.class);
+        ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);
+        QaWebSocket.setApplicationContext(configurableApplicationContext);
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+    }
+}

+ 31 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/CorsFilterConfig.java

@@ -0,0 +1,31 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class CorsFilterConfig implements Filter {
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
+        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
+        httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
+        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
+        httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
+        if ("OPTIONS".equalsIgnoreCase(httpServletRequest.getMethod())) {
+            httpServletResponse.setStatus(HttpServletResponse.SC_OK);
+        } else {
+            chain.doFilter(httpServletRequest, httpServletResponse);
+        }
+    }
+}

+ 29 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/JudicialConfig.java

@@ -0,0 +1,29 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import com.pavis.ai.app.judicial.common.config.properties.CommonProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
+import org.springframework.web.client.RestTemplate;
+
+import javax.sql.DataSource;
+
+@Configuration
+@EnableConfigurationProperties({CommonProperties.class})
+public class JudicialConfig {
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Bean
+    public JdbcClientDetailsService jdbcClientDetailsService() {
+        return new JdbcClientDetailsService(dataSource);
+    }
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+}

+ 21 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/MybatisPlusConfig.java

@@ -0,0 +1,21 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@Configuration
+@EnableTransactionManagement
+public class MybatisPlusConfig {
+
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
+        // 设置请求的页面大于最大页后操作,true调回到首页,false 继续请求  默认false
+        paginationInterceptor.setOverflow(false);
+        // 设置最大单页限制数量,默认 500 条,-1 不受限制
+        paginationInterceptor.setLimit(-1);
+        return paginationInterceptor;
+    }
+}

+ 15 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/PasswordEncoderConfig.java

@@ -0,0 +1,15 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@Configuration
+public class PasswordEncoderConfig {
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+}

+ 27 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/ResourceServerConfig.java

@@ -0,0 +1,27 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
+
+    @Override
+    public void configure(HttpSecurity http) throws Exception {
+        http
+                .csrf()
+                .disable()
+                .authorizeRequests()
+                .antMatchers("/swagger-resources/**",
+                        "/swagger-ui.html",
+                        "/v2/**",
+                        "/webjars/**",
+                        "/doc.html")
+                .permitAll()
+                .anyRequest()
+                .authenticated();
+    }
+}

+ 37 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/Swagger2Config.java

@@ -0,0 +1,37 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class Swagger2Config {
+
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.pavis.ai.app.judicial.controller"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("智能司法平台")
+                .description("接口文档说明")
+                .contact(new Contact("管慧娟", "", "ghj@s-privacy.com"))
+                .version("1.0")
+                .build();
+    }
+}
+

+ 24 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/WebMvcConfig.java

@@ -0,0 +1,24 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import com.pavis.ai.app.judicial.common.config.properties.CommonProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+    @Autowired
+    private CommonProperties commonProperties;
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        // 对已上传的文件地址做映射访问
+        registry.addResourceHandler("/export/jqas/**").addResourceLocations("file:" + commonProperties.getDir().getUpload());
+
+    }
+
+
+}

+ 27 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/WebSecurityConfig.java

@@ -0,0 +1,27 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+                .authorizeRequests()
+                .antMatchers("/swagger-resources/**",
+                        "/swagger-ui.html",
+                        "/v2/**",
+                        "/webjars/**",
+                        "/doc.html")
+                .permitAll()
+                .anyRequest()
+                .authenticated()
+                .and()
+                .csrf()
+                .disable();
+    }
+
+}

+ 13 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/WebSocketConfig.java

@@ -0,0 +1,13 @@
+package com.pavis.ai.app.judicial.common.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+public class WebSocketConfig {
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+}

+ 47 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/constants/Constants.java

@@ -0,0 +1,47 @@
+package com.pavis.ai.app.judicial.common.config.constants;
+
+/**
+ * 通用常量
+ */
+public class Constants {
+
+    public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    public static final String DATE_FORMAT_1 = "yyyy-MM-dd";
+    public static final String DATE_FORMAT_2 = "yyyyMMdd";
+
+    /**
+     * 基础服务名称
+     */
+    public static final String BASE_SERVER_NAME = "pavis-base-server";
+
+
+    /**
+     * 交换机名称
+     */
+    public static final String EXCHANGE_NAME = "pavis.exchange.judicial.jqas";
+
+    /**
+     * 命令队列名称
+     */
+    public static final String QUEUE_OP_NAME = "pavis.queue.op.judicial.jqas";
+
+    /**
+     * 命令队列路由键
+     */
+    public static final String ROUTING_OP_KEY = "pavis.queue.key.op.judicial.jqas";
+
+    /**
+     * 结果队列名称
+     */
+    public static final String QUEUE_OP_RESULT_NAME = "pavis.queue.op.result.judicial.jqas";
+    /**
+     * 结果队列路由键
+     */
+    public static final String ROUTING_OP_RESULT_KEY = "pavis.queue.key.op.result.judicial.jqas";
+
+
+    /**
+     * 默认组名
+     */
+    public static final String ROBOT_DEFAULT_GROUP = "Group-";
+}

+ 103 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/constants/ErrorCode.java

@@ -0,0 +1,103 @@
+package com.pavis.ai.app.judicial.common.config.constants;
+
+/**
+ * 自定义返回码
+ */
+
+public enum ErrorCode {
+    /**
+     * 成功
+     */
+    OK(0, "success"),
+    FAIL(1000, "fail"),
+    ALERT(1001, "alert"),
+
+    /**
+     * oauth2返回码
+     */
+    INVALID_TOKEN(2000, "invalid_token"),
+    INVALID_SCOPE(2001, "invalid_scope"),
+    INVALID_REQUEST(2002, "invalid_request"),
+    INVALID_CLIENT(2003, "invalid_client"),
+    INVALID_GRANT(2004, "invalid_grant"),
+    REDIRECT_URI_MISMATCH(2005, "redirect_uri_mismatch"),
+    UNAUTHORIZED_CLIENT(2006, "unauthorized_client"),
+    EXPIRED_TOKEN(2007, "expired_token"),
+    UNSUPPORTED_GRANT_TYPE(2008, "unsupported_grant_type"),
+    UNSUPPORTED_RESPONSE_TYPE(2009, "unsupported_response_type"),
+    UNAUTHORIZED(2012, "unauthorized"),
+    SIGNATURE_DENIED(2013, "signature_denied"),
+
+    ACCESS_DENIED(4030, "access_denied"),
+    ACCESS_DENIED_BLACK_LIMITED(4031, "access_denied_black_limited"),
+    ACCESS_DENIED_WHITE_LIMITED(4032, "access_denied_white_limited"),
+    ACCESS_DENIED_AUTHORITY_EXPIRED(4033, "access_denied_authority_expired"),
+    ACCESS_DENIED_UPDATING(4034, "access_denied_updating"),
+    ACCESS_DENIED_DISABLED(4035, "access_denied_disabled"),
+    ACCESS_DENIED_NOT_OPEN(4036, "access_denied_not_open"),
+    /**
+     * 账号错误
+     */
+    BAD_CREDENTIALS(3000, "bad_credentials"),
+    ACCOUNT_DISABLED(3001, "account_disabled"),
+    ACCOUNT_EXPIRED(3002, "account_expired"),
+    CREDENTIALS_EXPIRED(3003, "credentials_expired"),
+    ACCOUNT_LOCKED(3004, "account_locked"),
+    USERNAME_NOT_FOUND(3005, "username_not_found"),
+
+    /**
+     * 请求错误
+     */
+    BAD_REQUEST(4000, "bad_request"),
+    NOT_FOUND(4004, "not_found"),
+    METHOD_NOT_ALLOWED(4005, "method_not_allowed"),
+    MEDIA_TYPE_NOT_ACCEPTABLE(4006, "media_type_not_acceptable"),
+    TOO_MANY_REQUESTS(4029, "too_many_requests"),
+    /**
+     * 系统错误
+     */
+    ERROR(5000, "error"),
+    GATEWAY_TIMEOUT(5004, "gateway_timeout"),
+    SERVICE_UNAVAILABLE(5003, "service_unavailable");
+
+
+    private int code;
+    private String message;
+
+    ErrorCode() {
+    }
+
+    private ErrorCode(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public static ErrorCode getResultEnum(int code) {
+        for (ErrorCode type : ErrorCode.values()) {
+            if (type.getCode() == code) {
+                return type;
+            }
+        }
+        return ERROR;
+    }
+
+    public static ErrorCode getResultEnum(String message) {
+        for (ErrorCode type : ErrorCode.values()) {
+            if (type.getMessage().equals(message)) {
+                return type;
+            }
+        }
+        return ERROR;
+    }
+
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+
+}

+ 21 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/constants/ResourceType.java

@@ -0,0 +1,21 @@
+package com.pavis.ai.app.judicial.common.config.constants;
+
+/**
+ * 资源类型
+ */
+public enum ResourceType {
+
+    /**
+     * 菜单资源
+     */
+    menu,
+    /**
+     * 操作资源
+     */
+    action,
+    /**
+     * API接口资源
+     */
+    api
+
+}

+ 16 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/properties/CommonProperties.java

@@ -0,0 +1,16 @@
+package com.pavis.ai.app.judicial.common.config.properties;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ConfigurationProperties(prefix = "judicial.common")
+public class CommonProperties {
+    private Dir dir;
+}

+ 15 - 0
src/main/java/com/pavis/ai/app/judicial/common/config/properties/Dir.java

@@ -0,0 +1,15 @@
+package com.pavis.ai.app.judicial.common.config.properties;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class Dir {
+    private String upload;
+    private String avatar;
+}

+ 22 - 0
src/main/java/com/pavis/ai/app/judicial/common/exception/AlertException.java

@@ -0,0 +1,22 @@
+package com.pavis.ai.app.judicial.common.exception;
+
+/**
+ * 消息提示异常
+ */
+public class AlertException extends BaseException {
+
+    public AlertException() {
+    }
+
+    public AlertException(String msg) {
+        super(msg);
+    }
+
+    public AlertException(int code, String msg) {
+        super(code, msg);
+    }
+
+    public AlertException(int code, String msg, Throwable cause) {
+        super(code, msg, cause);
+    }
+}

+ 36 - 0
src/main/java/com/pavis/ai/app/judicial/common/exception/BaseException.java

@@ -0,0 +1,36 @@
+package com.pavis.ai.app.judicial.common.exception;
+
+import com.pavis.ai.app.judicial.common.http.ErrorCode;
+
+/**
+ * 基础错误异常
+ */
+public class BaseException extends RuntimeException {
+
+    private int code = ErrorCode.ERROR.getCode();
+
+    public BaseException() {
+    }
+
+    public BaseException(String msg) {
+        super(msg);
+    }
+
+    public BaseException(int code, String msg) {
+        super(msg);
+        this.code = code;
+    }
+
+    public BaseException(int code, String msg, Throwable cause) {
+        super(msg, cause);
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+}

+ 179 - 0
src/main/java/com/pavis/ai/app/judicial/common/exception/GlobalExceptionHandler.java

@@ -0,0 +1,179 @@
+package com.pavis.ai.app.judicial.common.exception;
+
+
+import com.alibaba.fastjson.JSON;
+import com.pavis.ai.app.judicial.common.http.ErrorCode;
+import com.pavis.ai.app.judicial.common.http.ResultBody;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Objects;
+
+/**
+ * 统一异常处理器
+ */
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    /**
+     * 统一异常处理
+     * AuthenticationException
+     */
+    @ExceptionHandler({AuthenticationException.class})
+    public static ResultBody authenticationException(Exception ex, HttpServletRequest request, HttpServletResponse response) {
+        ResultBody resultBody = resolveException(ex, request.getRequestURI());
+        response.setStatus(resultBody.getHttpStatus());
+        return resultBody;
+    }
+
+    /**
+     * OAuth2Exception
+     */
+    @ExceptionHandler({OAuth2Exception.class, InvalidTokenException.class})
+    public static ResultBody oauth2Exception(Exception ex, HttpServletRequest request, HttpServletResponse response) {
+        ResultBody resultBody = resolveException(ex, request.getRequestURI());
+        response.setStatus(resultBody.getHttpStatus());
+        return resultBody;
+    }
+
+    /**
+     * 其他异常
+     */
+    @ExceptionHandler({Exception.class})
+    public static ResultBody exception(Exception ex, HttpServletRequest request, HttpServletResponse response) {
+        ResultBody resultBody = resolveException(ex, request.getRequestURI());
+        response.setStatus(resultBody.getHttpStatus());
+        return resultBody;
+    }
+
+    /**
+     * 静态解析异常,可以直接调用
+     */
+    public static ResultBody resolveException(Exception ex, String path) {
+        ErrorCode code = ErrorCode.ERROR;
+        int httpStatus = HttpStatus.INTERNAL_SERVER_ERROR.value();
+        String message = ex.getMessage();
+        String className = ex.getClass().getName();
+        log.info("exception class name:{}", className);
+        if (className.contains("UsernameNotFoundException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.USERNAME_NOT_FOUND;
+        } else if (className.contains("BadCredentialsException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.BAD_CREDENTIALS;
+        } else if (className.contains("AccountExpiredException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.ACCOUNT_EXPIRED;
+        } else if (className.contains("LockedException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.ACCOUNT_LOCKED;
+        } else if (className.contains("DisabledException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.ACCOUNT_DISABLED;
+        } else if (className.contains("CredentialsExpiredException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.CREDENTIALS_EXPIRED;
+        } else if (className.contains("InvalidClientException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.INVALID_CLIENT;
+        } else if (className.contains("UnauthorizedClientException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.UNAUTHORIZED_CLIENT;
+        } else if (className.contains("InsufficientAuthenticationException") || className.contains("AuthenticationCredentialsNotFoundException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.UNAUTHORIZED;
+        } else if (className.contains("InvalidGrantException")) {
+            code = ErrorCode.ALERT;
+            if ("Bad credentials".contains(message)) {
+                code = ErrorCode.BAD_CREDENTIALS;
+            } else if ("User is disabled".contains(message)) {
+                code = ErrorCode.ACCOUNT_DISABLED;
+            } else if ("User account is locked".contains(message)) {
+                code = ErrorCode.ACCOUNT_LOCKED;
+            }
+        } else if (className.contains("InvalidScopeException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.INVALID_SCOPE;
+        } else if (className.contains("InvalidTokenException")) {
+            httpStatus = HttpStatus.UNAUTHORIZED.value();
+            code = ErrorCode.INVALID_TOKEN;
+        } else if (className.contains("InvalidRequestException")) {
+            httpStatus = HttpStatus.BAD_REQUEST.value();
+            code = ErrorCode.INVALID_REQUEST;
+        } else if (className.contains("RedirectMismatchException")) {
+            code = ErrorCode.REDIRECT_URI_MISMATCH;
+        } else if (className.contains("UnsupportedGrantTypeException")) {
+            code = ErrorCode.UNSUPPORTED_GRANT_TYPE;
+        } else if (className.contains("UnsupportedResponseTypeException")) {
+            code = ErrorCode.UNSUPPORTED_RESPONSE_TYPE;
+        } else if (className.contains("UserDeniedAuthorizationException")) {
+            code = ErrorCode.ACCESS_DENIED;
+        } else if (className.contains("AccessDeniedException")) {
+            code = ErrorCode.ACCESS_DENIED;
+            httpStatus = HttpStatus.FORBIDDEN.value();
+            if (ErrorCode.ACCESS_DENIED_BLACK_LIMITED.getMessage().contains(message)) {
+                code = ErrorCode.ACCESS_DENIED_BLACK_LIMITED;
+            } else if (ErrorCode.ACCESS_DENIED_WHITE_LIMITED.getMessage().contains(message)) {
+                code = ErrorCode.ACCESS_DENIED_WHITE_LIMITED;
+            } else if (ErrorCode.ACCESS_DENIED_AUTHORITY_EXPIRED.getMessage().contains(message)) {
+                code = ErrorCode.ACCESS_DENIED_AUTHORITY_EXPIRED;
+            } else if (ErrorCode.ACCESS_DENIED_UPDATING.getMessage().contains(message)) {
+                code = ErrorCode.ACCESS_DENIED_UPDATING;
+            } else if (ErrorCode.ACCESS_DENIED_DISABLED.getMessage().contains(message)) {
+                code = ErrorCode.ACCESS_DENIED_DISABLED;
+            } else if (ErrorCode.ACCESS_DENIED_NOT_OPEN.getMessage().contains(message)) {
+                code = ErrorCode.ACCESS_DENIED_NOT_OPEN;
+            }
+        } else if (className.contains("HttpMessageNotReadableException")
+                || className.contains("TypeMismatchException")
+                || className.contains("MissingServletRequestParameterException")) {
+            httpStatus = HttpStatus.BAD_REQUEST.value();
+            code = ErrorCode.BAD_REQUEST;
+        } else if (className.contains("NoHandlerFoundException")) {
+            httpStatus = HttpStatus.NOT_FOUND.value();
+            code = ErrorCode.NOT_FOUND;
+        } else if (className.contains("HttpRequestMethodNotSupportedException")) {
+            httpStatus = HttpStatus.METHOD_NOT_ALLOWED.value();
+            code = ErrorCode.METHOD_NOT_ALLOWED;
+        } else if (className.contains("HttpMediaTypeNotAcceptableException")) {
+            httpStatus = HttpStatus.BAD_REQUEST.value();
+            code = ErrorCode.MEDIA_TYPE_NOT_ACCEPTABLE;
+        } else if (className.contains("MethodArgumentNotValidException")) {
+            BindingResult bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
+            code = ErrorCode.ALERT;
+            return ResultBody.failed().code(code.getCode()).msg(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
+        } else if (className.contains("IllegalArgumentException")) {
+            // 参数错误
+            code = ErrorCode.ALERT;
+            httpStatus = HttpStatus.BAD_REQUEST.value();
+        } else if (className.contains("AlertException")) {
+            code = ErrorCode.ALERT;
+        } else if (message.equalsIgnoreCase(ErrorCode.TOO_MANY_REQUESTS.name())) {
+            code = ErrorCode.TOO_MANY_REQUESTS;
+        }
+        return buildBody(ex, code, path, httpStatus);
+    }
+
+    /**
+     * 构建返回结果对象
+     */
+    private static ResultBody buildBody(Exception exception, ErrorCode resultCode, String path, int httpStatus) {
+        if (resultCode == null) {
+            resultCode = ErrorCode.ERROR;
+        }
+        ResultBody resultBody = ResultBody.failed().code(resultCode.getCode()).msg(exception.getMessage()).path(path).httpStatus(httpStatus);
+        log.error("==> error:{} exception:{}", JSON.toJSONString(resultBody), exception);
+        return resultBody;
+    }
+
+}

+ 106 - 0
src/main/java/com/pavis/ai/app/judicial/common/http/ErrorCode.java

@@ -0,0 +1,106 @@
+package com.pavis.ai.app.judicial.common.http;
+
+/**
+ * 自定义返回码
+ */
+
+public enum ErrorCode {
+
+    /**
+     * 成功
+     */
+    OK(0, "success"),
+    FAIL(1000, "fail"),
+    ALERT(1001, "alert"),
+
+    /**
+     * oauth2返回码
+     */
+    INVALID_TOKEN(2000, "invalid_token"),
+    INVALID_SCOPE(2001, "invalid_scope"),
+    INVALID_REQUEST(2002, "invalid_request"),
+    INVALID_CLIENT(2003, "invalid_client"),
+    INVALID_GRANT(2004, "invalid_grant"),
+    REDIRECT_URI_MISMATCH(2005, "redirect_uri_mismatch"),
+    UNAUTHORIZED_CLIENT(2006, "unauthorized_client"),
+    EXPIRED_TOKEN(2007, "expired_token"),
+    UNSUPPORTED_GRANT_TYPE(2008, "unsupported_grant_type"),
+    UNSUPPORTED_RESPONSE_TYPE(2009, "unsupported_response_type"),
+    UNAUTHORIZED(2012, "unauthorized"),
+    SIGNATURE_DENIED(2013, "signature_denied"),
+
+    ACCESS_DENIED(4030, "access_denied"),
+    ACCESS_DENIED_BLACK_LIMITED(4031, "access_denied_black_limited"),
+    ACCESS_DENIED_WHITE_LIMITED(4032, "access_denied_white_limited"),
+    ACCESS_DENIED_AUTHORITY_EXPIRED(4033, "access_denied_authority_expired"),
+    ACCESS_DENIED_UPDATING(4034, "access_denied_updating"),
+    ACCESS_DENIED_DISABLED(4035, "access_denied_disabled"),
+    ACCESS_DENIED_NOT_OPEN(4036, "access_denied_not_open"),
+
+    /**
+     * 账号错误
+     */
+    BAD_CREDENTIALS(3000, "bad_credentials"),
+    ACCOUNT_DISABLED(3001, "account_disabled"),
+    ACCOUNT_EXPIRED(3002, "account_expired"),
+    CREDENTIALS_EXPIRED(3003, "credentials_expired"),
+    ACCOUNT_LOCKED(3004, "account_locked"),
+    USERNAME_NOT_FOUND(3005, "username_not_found"),
+
+    /**
+     * 请求错误
+     */
+    BAD_REQUEST(4000, "bad_request"),
+    NOT_FOUND(4004, "not_found"),
+    METHOD_NOT_ALLOWED(4005, "method_not_allowed"),
+    MEDIA_TYPE_NOT_ACCEPTABLE(4006, "media_type_not_acceptable"),
+    TOO_MANY_REQUESTS(4029, "too_many_requests"),
+
+    /**
+     * 系统错误
+     */
+    ERROR(5000, "error"),
+    GATEWAY_TIMEOUT(5004, "gateway_timeout"),
+    SERVICE_UNAVAILABLE(5003, "service_unavailable");
+
+
+    private int code;
+    private String message;
+
+    ErrorCode() {
+    }
+
+    private ErrorCode(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public static ErrorCode getResultEnum(int code) {
+        for (ErrorCode type : ErrorCode.values()) {
+            if (type.getCode() == code) {
+                return type;
+            }
+        }
+        return ERROR;
+    }
+
+    public static ErrorCode getResultEnum(String message) {
+        for (ErrorCode type : ErrorCode.values()) {
+            if (type.getMessage().equals(message)) {
+                return type;
+            }
+        }
+        return ERROR;
+    }
+
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+
+}

+ 155 - 0
src/main/java/com/pavis/ai/app/judicial/common/http/ResultBody.java

@@ -0,0 +1,155 @@
+package com.pavis.ai.app.judicial.common.http;
+
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.collect.Maps;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Map;
+import java.util.ResourceBundle;
+
+@ApiModel(value = "响应结果")
+public class ResultBody {
+
+    /**
+     * 响应编码
+     */
+    @ApiModelProperty(value = "响应编码:0-请求处理成功")
+    private int code = 0;
+
+    /**
+     * 提示消息
+     */
+    @ApiModelProperty(value = "提示消息")
+    private String message;
+
+    /**
+     * 请求路径
+     */
+    @ApiModelProperty(value = "请求路径")
+    private String path;
+
+    /**
+     * 响应数据
+     */
+    @ApiModelProperty(value = "响应数据")
+    private Object data;
+
+    /**
+     * http状态码
+     */
+    private int httpStatus;
+
+    /**
+     * 附加数据
+     */
+    @ApiModelProperty(value = "附加数据")
+    private Map<String, Object> extra;
+
+    /**
+     * 响应时间
+     */
+    @ApiModelProperty(value = "响应时间")
+    private long timestamp = System.currentTimeMillis();
+
+    public ResultBody() {
+
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public Map<String, Object> getExtra() {
+        return extra;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @JSONField(serialize = false, deserialize = false)
+    @JsonIgnore
+    public int getHttpStatus() {
+        return httpStatus;
+    }
+
+    @JSONField(serialize = false, deserialize = false)
+    @JsonIgnore
+    public boolean isOk() {
+        return this.code == ErrorCode.OK.getCode();
+    }
+
+
+    public static ResultBody ok() {
+        return new ResultBody().code(ErrorCode.OK.getCode()).msg(ErrorCode.OK.getMessage());
+    }
+
+    public static ResultBody failed() {
+        return new ResultBody().code(ErrorCode.FAIL.getCode()).msg(ErrorCode.FAIL.getMessage());
+    }
+
+    public ResultBody code(int code) {
+        this.code = code;
+        return this;
+    }
+
+    public ResultBody msg(String message) {
+        this.message = i18n(ErrorCode.getResultEnum(this.code).getMessage(), message);
+        return this;
+    }
+
+    public ResultBody data(Object data) {
+        this.data = data;
+        return this;
+    }
+
+    public ResultBody path(String path) {
+        this.path = path;
+        return this;
+    }
+
+    public ResultBody httpStatus(int httpStatus) {
+        this.httpStatus = httpStatus;
+        return this;
+    }
+
+    public ResultBody put(String key, Object value) {
+        if (this.extra == null) {
+            this.extra = Maps.newHashMap();
+        }
+        this.extra.put(key, value);
+        return this;
+    }
+
+    /**
+     * 错误信息配置
+     */
+    @JSONField(serialize = false, deserialize = false)
+    @JsonIgnore
+    private static ResourceBundle resourceBundle = ResourceBundle.getBundle("error");
+
+    /**
+     * 提示信息国际化
+     */
+    @JSONField(serialize = false, deserialize = false)
+    @JsonIgnore
+    private static String i18n(String message, String defaultMessage) {
+        return resourceBundle.containsKey(message) ? resourceBundle.getString(message) : defaultMessage;
+    }
+
+}

+ 27 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/AuthenticationUtils.java

@@ -0,0 +1,27 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.util.Collection;
+
+public class AuthenticationUtils {
+
+    public static String getCurrentUsername() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (null != authentication) {
+            return authentication.getName();
+        }
+        return "";
+    }
+
+    public static Collection<? extends GrantedAuthority> getCurrentUserAuthorities() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (null != authentication) {
+            return authentication.getAuthorities();
+        }
+        return null;
+    }
+
+}

+ 93 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/BeanConvertUtils.java

@@ -0,0 +1,93 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+
+public class BeanConvertUtils {
+
+    /**
+     * 方法说明:将bean转化为另一种bean实体
+     */
+    public static <T> T convertBean(Object object, Class<T> entityClass) {
+        if (null == object) {
+            return null;
+        }
+        return JSON.parseObject(JSON.toJSONString(object), entityClass);
+    }
+
+
+    /**
+     * 方法说明:对象转换
+     *  
+     *
+     * @param source           原对象
+     * @param target           目标对象
+     * @param ignoreProperties 排除要copy的属性
+     */
+    public static <T> T copy(Object source, Class<T> target, String... ignoreProperties) {
+        T targetInstance = null;
+        try {
+            targetInstance = target.newInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (ArrayUtils.isEmpty(ignoreProperties)) {
+            assert targetInstance != null;
+            BeanUtils.copyProperties(source, targetInstance);
+        } else {
+            assert targetInstance != null;
+            BeanUtils.copyProperties(source, targetInstance, ignoreProperties);
+        }
+        return targetInstance;
+
+    }
+
+    /**
+     * 方法说明:对象转换(List)
+     *  
+     *
+     * @param list             原对象
+     * @param target           目标对象
+     * @param ignoreProperties 排除要copy的属性
+     */
+    public static <T, E> List<T> copyList(List<E> list, Class<T> target, String... ignoreProperties) {
+        List<T> targetList = new ArrayList<>();
+        if (CollectionUtils.isEmpty(list)) {
+            return targetList;
+        }
+        for (E e : list) {
+            targetList.add(copy(e, target, ignoreProperties));
+        }
+        return targetList;
+    }
+
+    /**
+     * 方法说明:map转化为对象
+     *  
+     */
+    public static <T> T mapToObject(Map<String, Object> map, Class<T> t) {
+        try {
+            T instance = t.newInstance();
+            org.apache.commons.beanutils.BeanUtils.populate(instance, map);
+            return instance;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 方法说明:对象转化为Map
+     *  
+     */
+    public static Map<?, ?> objectToMap(Object object) {
+        return convertBean(object, Map.class);
+    }
+
+}

+ 11 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/DateUtils.java

@@ -0,0 +1,11 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import com.pavis.ai.app.judicial.common.config.constants.Constants;
+import org.joda.time.DateTime;
+
+public class DateUtils {
+
+    public static String now() {
+        return DateTime.now().toString(Constants.DEFAULT_DATETIME_FORMAT);
+    }
+}

+ 110 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/EncodeUtils.java

@@ -0,0 +1,110 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.Hex;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * 封装各种格式的编码解码工具类.
+ * 1.Commons-Codec的 hex/base64 编码
+ * 2.自制的base62 编码
+ * 3.Commons-Lang的xml/html escape
+ * 4.JDK提供的URLEncoder
+ */
+public class EncodeUtils {
+
+    private static final String ENCODING = "UTF-8";
+    private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
+
+    /**
+     * Hex编码.
+     */
+    public static String encodeHex(byte[] input) {
+        return new String(Hex.encodeHex(input));
+    }
+
+    /**
+     * Hex解码.
+     */
+    public static byte[] decodeHex(String input) {
+        try {
+            return Hex.decodeHex(input.toCharArray());
+        } catch (DecoderException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Base64编码.
+     */
+    public static String encodeBase64(byte[] input) {
+        return new String(Base64.encodeBase64(input));
+    }
+
+    /**
+     * Base64编码.
+     */
+    public static String encodeBase64(String input) {
+        try {
+            return new String(Base64.encodeBase64(input.getBytes(ENCODING)));
+        } catch (UnsupportedEncodingException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Base64解码.
+     */
+    public static byte[] decodeBase64(String input) {
+        return Base64.decodeBase64(input.getBytes());
+    }
+
+    /**
+     * Base64解码.
+     */
+    public static String decodeBase64String(String input) {
+        try {
+            return new String(Base64.decodeBase64(input.getBytes()), ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Base62编码。
+     */
+    public static String encodeBase62(byte[] input) {
+        char[] chars = new char[input.length];
+        for (int i = 0; i < input.length; i++) {
+            chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
+        }
+        return new String(chars);
+    }
+
+    /**
+     * URL 编码, Encode默认为UTF-8.
+     */
+    public static String encodeUrl(String part) {
+        try {
+            return URLEncoder.encode(part, ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            return null;
+        }
+    }
+
+    /**
+     * URL 解码, Encode默认为UTF-8.
+     */
+    public static String decodeUrl(String part) {
+        try {
+            return URLDecoder.decode(part, ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            return null;
+        }
+    }
+
+}

+ 23 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/IgnoreUtils.java

@@ -0,0 +1,23 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+
+import java.beans.PropertyDescriptor;
+import java.util.HashSet;
+import java.util.Set;
+
+public class IgnoreUtils {
+    public static String[] getNullPropertyNames(Object source) {
+        BeanWrapper src = new BeanWrapperImpl(source);
+        PropertyDescriptor[] pds = src.getPropertyDescriptors();
+        Set<String> emptyNames = new HashSet<>();
+        for (PropertyDescriptor pd : pds) {
+            Object srcValue = src.getPropertyValue(pd.getName());
+            if (srcValue == null)
+                emptyNames.add(pd.getName());
+        }
+        return emptyNames.toArray(new String[emptyNames.size()]);
+    }
+
+}

文件差异内容过多而无法显示
+ 29 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/RandomValueUtils.java


+ 83 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/SpringContextHolder.java

@@ -0,0 +1,83 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2018 yadu.liu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.pavis.ai.app.judicial.common.utils;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * 以静态变量保存Spring ApplicationContext,可在任何代码任何地方任何时候中取出ApplicaitonContext.
+ */
+public class SpringContextHolder implements ApplicationContextAware {
+
+    private static ApplicationContext applicationContext;
+
+    /**
+     * 实现ApplicationContextAware接口的context注入函数,将其存入静态变量.
+     */
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        SpringContextHolder.applicationContext = applicationContext;
+    }
+
+    /**
+     * 取得存储在静态变量中的ApplicationContext.
+     */
+    public static ApplicationContext getApplicationContext() {
+        checkApplicationContext();
+        return applicationContext;
+    }
+
+    /**
+     * 从静态变量ApplicationContext中取得Bean,自动转型为所赋值对象的类型.
+     */
+    public static <T> T getBean(String name) {
+        checkApplicationContext();
+        return (T) applicationContext.getBean(name);
+    }
+
+    /**
+     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+     */
+    public static <T> T getBean(Class<T> clazz) {
+        checkApplicationContext();
+        return (T) applicationContext.getBean(clazz);
+    }
+
+    /**
+     * 清除applicationContext静态变量.
+     */
+    public static void cleanApplicationContext() {
+        applicationContext = null;
+    }
+
+    private static void checkApplicationContext() {
+        if (applicationContext == null) {
+            throw new IllegalStateException(
+                    "applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
+        }
+    }
+}  

+ 540 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/StrUtils.java

@@ -0,0 +1,540 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringEscapeUtils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
+ */
+public class StrUtils extends StringUtils {
+
+    private static final char SEPARATOR = '_';
+    private static final String CHARSET = "UTF-8";
+
+    /**
+     * 转换为字节数组
+     */
+    public static byte[] getBytes(String str) {
+        if (str != null) {
+            try {
+                return str.getBytes(CHARSET);
+            } catch (UnsupportedEncodingException e) {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 转换为字节数组
+     */
+    public static String toString(byte[] bytes) {
+        try {
+            return new String(bytes, CHARSET);
+        } catch (UnsupportedEncodingException e) {
+            return EMPTY;
+        }
+    }
+
+    /**
+     * 转换为Boolean类型
+     * 'true', 'on', 'y', 't', 'yes' or '1' (case insensitive) will return true. Otherwise, false is returned.
+     */
+    public static Boolean toBoolean(final Object val) {
+        if (val == null) {
+            return false;
+        }
+        return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString());
+    }
+
+
+    /**
+     * 如果对象为空,则使用defaultVal值
+     * see: ObjectUtils.toString(obj, defaultVal)
+     */
+    public static String toString(final Object obj, final String defaultVal) {
+        return obj == null ? defaultVal : obj.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     *
+     * @param str  验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inString(String str, String... strs) {
+        if (str != null) {
+            for (String s : strs) {
+                if (str.equals(trim(s))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 转换为Double类型
+     */
+    public static Double toDouble(Object val) {
+        if (val == null) {
+            return 0D;
+        }
+        try {
+            return Double.valueOf(trim(val.toString()));
+        } catch (Exception e) {
+            return 0D;
+        }
+    }
+
+    /**
+     * 转换为Float类型
+     */
+    public static Float toFloat(Object val) {
+        return toDouble(val).floatValue();
+    }
+
+    /**
+     * 转换为Long类型
+     */
+    public static Long toLong(Object val) {
+        return toDouble(val).longValue();
+    }
+
+    /**
+     * 转换为Integer类型
+     */
+    public static Integer toInteger(Object val) {
+        return toLong(val).intValue();
+    }
+
+    /**
+     * 缩略字符串(不区分中英文字符)
+     *
+     * @param str    目标字符串
+     * @param length 截取长度
+     */
+    public static String ellipsis(String str, int length) {
+        if (str == null) {
+            return "";
+        }
+        try {
+            StringBuilder sb = new StringBuilder();
+            int currentLength = 0;
+            for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
+                currentLength += String.valueOf(c).getBytes("GBK").length;
+                if (currentLength <= length - 3) {
+                    sb.append(c);
+                } else {
+                    sb.append("...");
+                    break;
+                }
+            }
+            return sb.toString();
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    /**
+     * 替换掉HTML标签方法
+     */
+    public static String replaceHtml(String html) {
+        if (isBlank(html)) {
+            return "";
+        }
+        String regEx = "<.+?>";
+        Pattern p = Pattern.compile(regEx);
+        Matcher m = p.matcher(html);
+        return m.replaceAll("");
+    }
+
+    /**
+     * Html 转码.
+     */
+    public static String escapeHtml(String html) {
+        return StringEscapeUtils.escapeHtml4(html);
+    }
+
+    /**
+     * Html 解码.
+     */
+    public static String unescapeHtml(String htmlEscaped) {
+        return StringEscapeUtils.unescapeHtml4(htmlEscaped);
+    }
+
+    /**
+     * Xml 转码.
+     */
+    public static String escapeXml(String xml) {
+        return StringEscapeUtils.escapeXml11(xml);
+    }
+
+    /**
+     * Xml 解码.
+     */
+    public static String unescapeXml(String xmlEscaped) {
+        return StringEscapeUtils.unescapeXml(xmlEscaped);
+    }
+
+    /**
+     * url追加参数
+     *
+     * @param url   传入的url ex:"http://exp.kunnr.com/so/index.html?kunnrId=16&userProfile=16#/app/home"
+     * @param name  参数名
+     * @param value 参数值
+     */
+    public static String appendURIParam(String url, String name, String value) {
+        url += (url.indexOf('?') == -1 ? '?' : '&');
+        url += EncodeUtils.encodeUrl(name) + '=' + EncodeUtils.encodeUrl(value);
+        return url;
+    }
+
+    /**
+     * 组装新的URL
+     */
+    public static String appendURIParam(String url, Map<String, String> map) {
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+            url = appendURIParam(url, entry.getKey(), entry.getValue());
+        }
+        return url;
+    }
+
+
+    /**
+     * 驼峰转下划线
+     * createTime > create_time
+     */
+    public static String camelToUnderline(String param) {
+        if (param == null || "".equals(param.trim())) {
+            return "";
+        }
+        int len = param.length();
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            char c = param.charAt(i);
+            if (Character.isUpperCase(c)) {
+                sb.append(SEPARATOR);
+                sb.append(Character.toLowerCase(c));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 下划线转驼峰
+     * create_time > createTime
+     */
+    public static String underlineToCamel(String param) {
+        if (param == null || "".equals(param.trim())) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder(param);
+        Matcher mc = Pattern.compile(String.valueOf(SEPARATOR)).matcher(param);
+        int i = 0;
+        while (mc.find()) {
+            int position = mc.end() - (i++);
+            sb.replace(position - 1, position + 1, sb.substring(position, position + 1).toUpperCase());
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 格式化存储单位
+     */
+    public static String formatBytes(long size) {
+        // 如果字节数少于1024,则直接以B为单位,否则先除于1024,后3位因太少无意义
+        int bytes = 1024;
+        if (size < bytes) {
+            return String.valueOf(size) + "Byte";
+        } else {
+            size = size / bytes;
+        }
+        // 如果原字节数除于1024之后,少于1024,则可以直接以KB作为单位 //因为还没有到达要使用另一个单位的时候 //接下去以此类推
+        if (size < bytes) {
+            return String.valueOf(size) + "K";
+        } else {
+            size = size / bytes;
+        }
+        if (size < bytes) {
+            // 因为如果以MB为单位的话,要保留最后1位小数, //因此,把此数乘以100之后再取余
+            size = size * 100;
+            return String.valueOf((size / 100)) + "." + String.valueOf((size % 100)) + "M";
+        } else { // 否则如果要以GB为单位的,先除于1024再作同样的处理
+            size = size * 100 / bytes;
+            return String.valueOf((size / 100)) + "." + String.valueOf((size % 100)) + "G";
+        }
+    }
+
+    /**
+     * 匿名手机号
+     *
+     * @param mobile 手机号
+     * @return 152****4799
+     */
+    public static String formatMobile(String mobile) {
+
+        if (isEmpty(mobile)) {
+            return null;
+        }
+        return mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
+    }
+
+    /**
+     * 匿名银行卡号
+     */
+    public static String formatBankCard(String bankCard) {
+        if (isEmpty(bankCard)) {
+            return null;
+        }
+        return bankCard.replaceAll("(\\d{5})\\d{5}\\d{2}(\\d{4})", "$1****$2");
+    }
+
+    /**
+     * 匿名身份证
+     *
+     * @return 4304*****7733
+     */
+    public static String formatIdCard(String idCard) {
+
+        if (isEmpty(idCard)) {
+            return null;
+        }
+        return idCard.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1*****$2");
+    }
+
+    /**
+     * 检测是否未手机号
+     * 中国电信号段
+     * 133、149、153、173、177、180、181、189、199
+     * 中国联通号段
+     * 130、131、132、145、155、156、166、175、176、185、186
+     * 中国移动号段
+     * 134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188、198
+     * 其他号段
+     * 14号段以前为上网卡专属号段,如中国联通的是145,中国移动的是147等等。
+     * 虚拟运营商
+     * 电信:1700、1701、1702
+     * 移动:1703、1705、1706
+     * 联通:1704、1707、1708、1709、171
+     */
+    public static boolean matchMobile(String mobile) {
+        if (StringUtils.isBlank(mobile)) {
+            return false;
+        }
+        String regex = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$";
+        return Pattern.matches(regex, mobile);
+    }
+
+    /**
+     * 检测Email
+     */
+    public static boolean matchEmail(String email) {
+        if (StringUtils.isBlank(email)) {
+            return false;
+        }
+        String regex = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?";
+        return Pattern.matches(regex, email);
+    }
+
+
+    /**
+     * 检测域名
+     */
+    public static boolean matchDomain(String domain) {
+        if (domain == null) {
+            return false;
+        }
+        String regex = "^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$";
+        return Pattern.matches(regex, domain);
+    }
+
+    /**
+     * 检测IP
+     */
+    public static boolean matchIp(String ip) {
+        if (ip == null) {
+            return false;
+        }
+        String regex = "^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$";
+        return Pattern.matches(regex, ip);
+    }
+
+    /**
+     * 检测HttpUrl
+     */
+    public static boolean matchHttpUrl(String url) {
+        if (url == null) {
+            return false;
+        }
+        String regex = "^(?=^.{3,255}$)(http(s)?:\\/\\/)?(www\\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\\d+)*(\\/\\w+\\.\\w+)*([\\?&]\\w+=\\w*)*$";
+        return Pattern.matches(regex, url);
+    }
+
+    /**
+     * 校验银行卡卡号
+     * 校验过程:
+     * 1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。
+     * 2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,将个位十位数字相加,即将其减去9),再求和。
+     * 3、将奇数位总和加上偶数位总和,结果应该可以被10整除。
+     */
+    public static boolean matchBankCard(String bankCard) {
+        if (bankCard == null) {
+            return false;
+        }
+        if (bankCard.length() < 15 || bankCard.length() > 19) {
+            return false;
+        }
+        char bit = getBankCardCheckCode(bankCard.substring(0, bankCard.length() - 1));
+        if (bit == 'N') {
+            return false;
+        }
+        return bankCard.charAt(bankCard.length() - 1) == bit;
+    }
+
+    /**
+     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
+     */
+    public static char getBankCardCheckCode(String nonCheckCodeBankCard) {
+        if (nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
+                || !nonCheckCodeBankCard.matches("\\d+")) {
+            //如果传的不是数据返回N
+            return 'N';
+        }
+        char[] chs = nonCheckCodeBankCard.trim().toCharArray();
+        int luhmSum = 0;
+        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
+            int k = chs[i] - '0';
+            if (j % 2 == 0) {
+                k *= 2;
+                k = k / 10 + k % 10;
+            }
+            luhmSum += k;
+        }
+        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
+    }
+
+
+    /**
+     * 处理非法字符
+     */
+    private static List<Pattern> patterns = null;
+
+    private static List<Object[]> getXssPatternList() {
+        List<Object[]> ret = new ArrayList<Object[]>();
+        ret.add(new Object[]{"<(no)?script[^>]*>.*?</(no)?script>", Pattern.CASE_INSENSITIVE});
+        ret.add(new Object[]{"eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL});
+        ret.add(new Object[]{"expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL});
+        ret.add(new Object[]{"(javascript:|vbscript:|view-source:)*", Pattern.CASE_INSENSITIVE});
+        ret.add(new Object[]{"<(\"[^\"]*\"|\'[^\']*\'|[^\'\">])*>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL});
+        ret.add(new Object[]{"(window\\.location|window\\.|\\.location|document\\.cookie|document\\.|alert\\(.*?\\)|window\\.open\\()*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL});
+        ret.add(new Object[]{"<+\\s*\\w*\\s*(oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondblclick|ondeactivate|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragstart|ondrop|onerror=|onerroupdate|onfilterchange|onfinish|onfocus|onfocusin|onfocusout|onhelp|onkeydown|onkeypress|onkeyup|onlayoutcomplete|onload|onlosecapture|onmousedown|onmouseenter|onmouseleave|onmousemove|onmousout|onmouseover|onmouseup|onmousewheel|onmove|onmoveend|onmovestart|onabort|onactivate|onafterprint|onafterupdate|onbefore|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onblur|onbounce|oncellchange|onchange|onclick|oncontextmenu|onpaste|onpropertychange|onreadystatuschange|onreset|onresize|onresizend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onselect|onselectionchange|onselectstart|onstart|onstop|onsubmit|onunload)+\\s*=+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL});
+        return ret;
+    }
+
+    private static List<Pattern> getPatterns() {
+
+        if (patterns == null) {
+
+            List<Pattern> list = new ArrayList<Pattern>();
+
+            String regex = null;
+            Integer flag = null;
+            int arrLength = 0;
+
+            for (Object[] arr : getXssPatternList()) {
+                arrLength = arr.length;
+                for (int i = 0; i < arrLength; i++) {
+                    regex = (String) arr[0];
+                    flag = (Integer) arr[1];
+                    list.add(Pattern.compile(regex, flag));
+                }
+            }
+
+            patterns = list;
+        }
+
+        return patterns;
+    }
+
+    public static String stripXss(String value) {
+        if (StringUtils.isNotBlank(value)) {
+            Matcher matcher = null;
+            for (Pattern pattern : getPatterns()) {
+                matcher = pattern.matcher(value);
+                if (matcher.find()) {
+                    value = matcher.replaceAll("");
+                }
+            }
+            value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
+        }
+        return value;
+    }
+
+    /**
+     * 密码强度
+     *
+     * @return Z = 字母 S = 数字 T = 特殊字符
+     */
+    public static String checkPassword(String passwordStr) {
+        String regexZ = "\\d*";
+        String regexS = "[a-zA-Z]+";
+        String regexT = "\\W+$";
+        String regexZT = "\\D*";
+        String regexST = "[\\d\\W]*";
+        String regexZS = "\\w*";
+        String regexZST = "[\\w\\W]*";
+
+        if (passwordStr.matches(regexZ)) {
+            return "弱";
+        }
+        if (passwordStr.matches(regexS)) {
+            return "弱";
+        }
+        if (passwordStr.matches(regexT)) {
+            return "弱";
+        }
+        if (passwordStr.matches(regexZT)) {
+            return "中";
+        }
+        if (passwordStr.matches(regexST)) {
+            return "中";
+        }
+        if (passwordStr.matches(regexZS)) {
+            return "中";
+        }
+        if (passwordStr.matches(regexZST)) {
+            return "强";
+        }
+        return passwordStr;
+    }
+
+
+    /**
+     * 将 Exception 转化为 String
+     */
+    public static String getExceptionToString(Throwable e) {
+        if (e == null) {
+            return "";
+        }
+        StringWriter stringWriter = new StringWriter();
+        e.printStackTrace(new PrintWriter(stringWriter));
+        return stringWriter.toString();
+    }
+
+}

+ 469 - 0
src/main/java/com/pavis/ai/app/judicial/common/utils/WebUtils.java

@@ -0,0 +1,469 @@
+package com.pavis.ai.app.judicial.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.net.HttpHeaders;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.MediaType;
+import org.springframework.util.Assert;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Http与Servlet工具类.
+ */
+public class WebUtils {
+
+    private final static String staticSuffix = ".css,.js,.png,.jpg,.gif,.jpeg,.bmp,.ico,.swf,.psd,.htc,.htm,.html,.crx,.xpi,.exe,.ipa,.apk,.woff2,.ico,.swf,.ttf,.otf,.svg,.woff";
+
+    /**
+     * 静态文件后缀
+     */
+    private final static String[] staticFiles = StringUtils.split(staticSuffix, ",");
+
+    /**
+     * 动态映射URL后缀
+     */
+    private final static String urlSuffix = ".html";
+
+    public static String[] getStaticFiles() {
+        return staticFiles;
+    }
+
+    /**
+     * 设置 Cookie(生成时间为1天)
+     *
+     * @param name  名称
+     * @param value 值
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value) {
+        setCookie(response, name, value, 60 * 60 * 24);
+    }
+
+    /**
+     * 设置 Cookie
+     *
+     * @param name  名称
+     * @param value 值
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, String path) {
+        setCookie(response, name, value, path, 60 * 60 * 24);
+    }
+
+    /**
+     * 设置 Cookie
+     *
+     * @param name   名称
+     * @param value  值
+     * @param maxAge 生存时间(单位秒)
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
+        setCookie(response, name, value, "/", maxAge);
+    }
+
+    /**
+     * 设置 Cookie
+     *
+     * @param name   名称
+     * @param value  值
+     * @param maxAge 生存时间(单位秒)
+     * @param path   路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, String path, int maxAge) {
+        Cookie cookie = new Cookie(name, null);
+        cookie.setPath(path);
+        cookie.setMaxAge(maxAge);
+        try {
+            cookie.setValue(URLEncoder.encode(value, "utf-8"));
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        response.addCookie(cookie);
+    }
+
+    /**
+     * 移除cookie
+     */
+    public static void removeCookie(HttpServletResponse response, String name) {
+        Cookie cookie = new Cookie(name, null);
+        cookie.setPath("/");
+        cookie.setMaxAge(0);
+        cookie.setValue(null);
+        response.addCookie(cookie);
+    }
+
+    /**
+     * 获得指定Cookie的值
+     *
+     * @param name 名称
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, String name) {
+        return getCookie(request, null, name, false);
+    }
+
+    /**
+     * 获得指定Cookie的值,并删除。
+     *
+     * @param name 名称
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name) {
+        return getCookie(request, response, name, true);
+    }
+
+    /**
+     * 获得指定Cookie的值
+     *
+     * @param request  请求对象
+     * @param response 响应对象
+     * @param name     名字
+     * @param isRemove 是否移除
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name, boolean isRemove) {
+        String value = null;
+        Cookie[] cookies = request.getCookies();
+        if (cookies != null) {
+            for (Cookie cookie : cookies) {
+                if (cookie.getName().equals(name)) {
+                    try {
+                        value = URLDecoder.decode(cookie.getValue(), "utf-8");
+                    } catch (UnsupportedEncodingException e) {
+                        e.printStackTrace();
+                    }
+                    if (isRemove) {
+                        cookie.setMaxAge(0);
+                        response.addCookie(cookie);
+                    }
+                }
+            }
+        }
+        return value;
+    }
+
+    /**
+     * 设置客户端缓存过期时间 的Header.
+     */
+    public static void setExpiresHeader(HttpServletResponse response, long expiresSeconds) {
+        // Http 1.0 header, set model fix expires date.
+        response.setDateHeader(HttpHeaders.EXPIRES, System.currentTimeMillis() + expiresSeconds * 1000);
+        // Http 1.1 header, set model time after now.
+        response.setHeader(HttpHeaders.CACHE_CONTROL, "private, max-age=" + expiresSeconds);
+    }
+
+
+    /**
+     * 设置禁止客户端缓存的Header.
+     */
+    public static void setNoCacheHeader(HttpServletResponse response) {
+        // Http 1.0 header
+        response.setDateHeader(HttpHeaders.EXPIRES, 1L);
+        response.addHeader(HttpHeaders.PRAGMA, "no-cache");
+        // Http 1.1 header
+        response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0");
+    }
+
+    /**
+     * 设置LastModified Header.
+     */
+    public static void setLastModifiedHeader(HttpServletResponse response, long lastModifiedDate) {
+        response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModifiedDate);
+    }
+
+    /**
+     * 设置Etag Header.
+     */
+    public static void setEtag(HttpServletResponse response, String etag) {
+        response.setHeader(HttpHeaders.ETAG, etag);
+    }
+
+    /**
+     * 根据浏览器If-Modified-Since Header, 计算文件是否已被修改.
+     * <p>
+     * 如果无修改, checkIfModify返回false ,设置304 not modify status.
+     *
+     * @param lastModified 内容的最后修改时间.
+     */
+    public static boolean checkIfModifiedSince(HttpServletRequest request, HttpServletResponse response,
+                                               long lastModified) {
+        long ifModifiedSince = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
+        if ((ifModifiedSince != -1) && (lastModified < ifModifiedSince + 1000)) {
+            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 根据浏览器 If-None-Match Header, 计算Etag是否已无效.
+     * <p>
+     * 如果Etag有效, checkIfNoneMatch返回false, 设置304 not modify status.
+     *
+     * @param etag 内容的ETag.
+     */
+    public static boolean checkIfNoneMatchEtag(HttpServletRequest request, HttpServletResponse response, String etag) {
+        String headerValue = request.getHeader(HttpHeaders.IF_NONE_MATCH);
+        if (headerValue != null) {
+            boolean conditionSatisfied = false;
+            if (!"*".equals(headerValue)) {
+                StringTokenizer commaTokenizer = new StringTokenizer(headerValue, ",");
+
+                while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
+                    String currentToken = commaTokenizer.nextToken();
+                    if (currentToken.trim().equals(etag)) {
+                        conditionSatisfied = true;
+                    }
+                }
+            } else {
+                conditionSatisfied = true;
+            }
+
+            if (conditionSatisfied) {
+                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+                response.setHeader(HttpHeaders.ETAG, etag);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 设置让浏览器弹出下载对话框的Header.
+     *
+     * @param fileName 下载后的文件名.
+     */
+    public static void setFileDownloadHeader(HttpServletResponse response, String fileName) {
+        try {
+            // 中文文件名支持
+            String encodedfileName = new String(fileName.getBytes(), "ISO8859-1");
+            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedfileName + "\"");
+        } catch (UnsupportedEncodingException e) {
+            e.getMessage();
+        }
+    }
+
+    /**
+     * 取得带相同前缀的Request Parameters, copy from spring WebUtils.
+     * <p>
+     * 返回的结果的Parameter名已去除前缀.
+     */
+    @SuppressWarnings("rawtypes")
+    public static Map<String, Object> getParametersWith(ServletRequest request, String prefix) {
+        Assert.notNull(request, "Request must not be null");
+        Enumeration paramNames = request.getParameterNames();
+        Map<String, Object> params = new TreeMap<String, Object>();
+        String pre = prefix;
+        if (pre == null) {
+            pre = "";
+        }
+        while (paramNames != null && paramNames.hasMoreElements()) {
+            String paramName = (String) paramNames.nextElement();
+            if ("".equals(pre) || paramName.startsWith(pre)) {
+                String unprefixed = paramName.substring(pre.length());
+                String[] values = request.getParameterValues(paramName);
+                if (values == null || values.length == 0) {
+                    values = new String[]{};
+                    // Do nothing, no values found at all.
+                } else if (values.length > 1) {
+                    params.put(unprefixed, values);
+                } else {
+                    params.put(unprefixed, values[0]);
+                }
+            }
+        }
+        return params;
+    }
+
+    /**
+     * 获取请求Body
+     */
+    public static String getBodyString(final ServletRequest request) {
+        StringBuilder sb = new StringBuilder();
+        InputStream inputStream = null;
+        BufferedReader reader = null;
+        try {
+            inputStream = cloneInputStream(request.getInputStream());
+            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
+            String line = "";
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 复制输入流
+     */
+    public static InputStream cloneInputStream(ServletInputStream inputStream) {
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int len;
+        try {
+            while ((len = inputStream.read(buffer)) > -1) {
+                byteArrayOutputStream.write(buffer, 0, len);
+            }
+            byteArrayOutputStream.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
+    }
+
+
+    /**
+     * 组合Parameters生成Query String的Parameter部分,并在paramter name上加上prefix.
+     */
+    public static String encodeParameterWithPrefix(Map<String, Object> params, String prefix) {
+        StringBuilder queryStringBuilder = new StringBuilder();
+
+        String pre = prefix;
+        if (pre == null) {
+            pre = "";
+        }
+        Iterator<Entry<String, Object>> it = params.entrySet().iterator();
+        while (it.hasNext()) {
+            Entry<String, Object> entry = it.next();
+            queryStringBuilder.append(pre).append(entry.getKey()).append("=").append(entry.getValue());
+            if (it.hasNext()) {
+                queryStringBuilder.append("&");
+            }
+        }
+        return queryStringBuilder.toString();
+    }
+
+    /**
+     * 客户端对Http Basic验证的 Header进行编码.
+     */
+    public static String encodeHttpBasic(String userName, String password) {
+        String encode = userName + ":" + password;
+        return "Basic " + EncodeUtils.encodeBase64(encode.getBytes());
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request) {
+        return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString())) || (request.getHeader("Content-Type") != null && request.getHeader("Content-Type").startsWith("application/json"));
+    }
+
+    /**
+     * 获取IP地址
+     */
+    public static String getRemoteAddress(HttpServletRequest request) {
+        String unknown = "unknown";
+        String ip = request.getHeader("X-Forwarded-For");
+        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_CLIENT_IP");
+        }
+        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+        }
+        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Real-IP");
+        }
+        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
+        if (ip != null && ip.length() > 0) {
+            String[] ips = ip.split(",");
+            if (ips.length > 0) {
+                ip = ips[0];
+            }
+        }
+        return ip;
+    }
+
+
+    /**
+     * 判断访问URI是否是静态文件请求
+     */
+    public static boolean isStaticFile(String uri) {
+        return StringUtils.endsWithAny(uri, staticFiles) && !StringUtils.endsWithAny(uri, new String[]{urlSuffix})
+                && !StringUtils.endsWithAny(uri, new String[]{".jsp"}) && !StringUtils.endsWithAny(uri, new String[]{".java"});
+    }
+
+    /**
+     * 客户端返回JSON字符串
+     */
+    public static void writeJson(HttpServletResponse response, Object object) throws IOException {
+        writeJson(response, JSON.toJSONString(object), MediaType.APPLICATION_JSON_UTF8_VALUE);
+    }
+
+    /**
+     * 客户端返回字符串
+     */
+    public static void writeJson(HttpServletResponse response, String string, String type) throws IOException {
+        response.setContentType(type);
+        response.setCharacterEncoding("utf-8");
+        response.getWriter().print(string);
+        response.getWriter().flush();
+        response.getWriter().close();
+    }
+
+    public static String getServerUrl(HttpServletRequest request) {
+        return request.getScheme() + "://" + request.getServerName()
+                + ":" + request.getServerPort() + request.getContextPath();
+    }
+
+
+    public static String getContextPath(HttpServletRequest request) {
+        return request.getContextPath();
+    }
+
+    public static HttpServletRequest getHttpServletRequest() {
+        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
+    }
+
+    public static Map<String, String> getHttpHeaders(HttpServletRequest request) {
+        Map<String, String> map = new LinkedHashMap<>();
+        if (request != null) {
+            Enumeration<String> enumeration = request.getHeaderNames();
+            if (enumeration != null) {
+                while (enumeration.hasMoreElements()) {
+                    String key = enumeration.nextElement();
+                    String value = request.getHeader(key);
+                    map.put(key, value);
+                }
+            }
+        }
+        return map;
+    }
+
+}

+ 56 - 0
src/main/java/com/pavis/ai/app/judicial/controller/CaseController.java

@@ -0,0 +1,56 @@
+package com.pavis.ai.app.judicial.controller;
+
+import com.pavis.ai.app.judicial.common.config.constants.ErrorCode;
+import com.pavis.ai.app.judicial.common.http.ResultBody;
+import com.pavis.ai.app.judicial.form.LegalInfo;
+import com.pavis.ai.app.judicial.service.CaseService;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:35
+ * @desc CaseController
+ **/
+@Slf4j
+@RestController
+@RequestMapping("/api")
+public class CaseController {
+
+
+    @Autowired
+    private CaseService caseService;
+
+
+    @ApiOperation("解析案件&问题分类接口")
+    @PostMapping("/case/classification")
+    public ResultBody plainTextCaseCsf(@RequestBody LegalInfo legalInfo) throws IOException, InterruptedException {
+
+        return ResultBody.ok().code(ErrorCode.OK.getCode()).msg("操作成功").data(caseService.plainTextCaseCs(legalInfo));
+    }
+
+    @ApiOperation("根据id获取结果接口")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "唯一标识id", required = false, dataType = "string", paramType = "path")
+    })
+    @PostMapping("/case/result/{id}")
+    public ResultBody result(@PathVariable("id") String id) throws InterruptedException {
+        return ResultBody.ok().code(ErrorCode.OK.getCode()).msg("操作成功").data(caseService.findOp(id));
+    }
+
+    @ApiOperation("测试接口")
+    @PostMapping("/case/test/{id}")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "唯一标识id", required = false, dataType = "string", paramType = "path")
+    })
+    public ResultBody plainTextCaseCsf(@PathVariable("id") String id) throws IOException, InterruptedException {
+        return ResultBody.ok().code(ErrorCode.OK.getCode()).msg("操作成功").data(id);
+    }
+
+}

+ 26 - 0
src/main/java/com/pavis/ai/app/judicial/form/LegalInfo.java

@@ -0,0 +1,26 @@
+package com.pavis.ai.app.judicial.form;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 6:44
+ * @desc LegalText
+ **/
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LegalInfo {
+    @TableId(type = IdType.ID_WORKER_STR)
+    @ApiModelProperty(value="唯一标识id",example="1583221125753",required=false)
+    private String id;
+    @ApiModelProperty(value="分类",example="0",required=false)
+    private String type;
+    @ApiModelProperty(value="输入的司法文本或问题描述信息",example="***",required=false)
+    private String info;
+}

+ 20 - 0
src/main/java/com/pavis/ai/app/judicial/form/OpData.java

@@ -0,0 +1,20 @@
+package com.pavis.ai.app.judicial.form;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-03-02 16:16
+ * @desc OpData
+ **/
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class OpData {
+    private String result;
+    private String type;
+}

+ 25 - 0
src/main/java/com/pavis/ai/app/judicial/form/OpMessage.java

@@ -0,0 +1,25 @@
+package com.pavis.ai.app.judicial.form;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-24 15:37
+ * @desc OpMessage
+ **/
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class OpMessage {
+    private String id;
+    private String timestamp;
+    private Boolean success;
+    private String code;
+    private String msg;
+    private OpData data;
+}
+

+ 173 - 0
src/main/java/com/pavis/ai/app/judicial/form/QaWebSocket.java

@@ -0,0 +1,173 @@
+package com.pavis.ai.app.judicial.form;
+
+import com.pavis.ai.app.judicial.service.CaseService;
+import com.pavis.ai.app.judicial.service.JqasService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-21 15:09
+ * @desc QaWebSocket
+ **/
+@Component
+@ServerEndpoint("/websocket/{uid}")
+@Slf4j
+public class QaWebSocket {
+    /**
+     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
+     */
+    private static int onlineCount = 0;
+    /**
+     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
+     */
+    private static CopyOnWriteArraySet<QaWebSocket> webSocketSet = new CopyOnWriteArraySet<QaWebSocket>();
+    /**
+     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
+     */
+    private Session session;
+    /**
+     * 接收sid
+     */
+    private String sid = "1";
+    private String uid;
+
+    // ----------单聊---------用户id和websocket的session绑定的路由表
+    // @SuppressWarnings("rawtypes")
+    // private static Map routeTable = new HashMap<>();
+
+    /**
+     * websocket注入service方式
+     */
+    private static ApplicationContext applicationContext;
+
+    public static void setApplicationContext(ApplicationContext applicationContext) {
+        QaWebSocket.applicationContext = applicationContext;
+    }
+
+    private JqasService jqasService;
+    private CaseService caseService;
+
+
+    /**
+     * 连接建立成功调用的方法
+     **/
+    @OnOpen
+    public void onOpen(Session session, @PathParam("uid") String uid) {
+        this.session = session;
+        // 加入set中
+        webSocketSet.add(this);
+        // 在线数加1
+        addOnlineCount();
+        log.info("有新窗口开始监听:【" + uid + "】,当前在线人数为" + getOnlineCount());
+        this.uid = uid;
+        try {
+            sendMessage("你好,有什么需要帮助您的吗?");
+        } catch (IOException e) {
+            log.error("websocket IO异常");
+        }
+        // 绑定之后就可以在其它地方根据id来获取session,私聊实现
+        // routeTable.put(uId, session);
+    }
+
+    /**
+     * 连接关闭调用的方法
+     */
+    @OnClose
+    public void onClose() {
+        // 从set中删除
+        webSocketSet.remove(this);
+        // 在线数减1
+        subOnlineCount();
+        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param message 客户端发送过来的消息
+     **/
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        log.info("收到来自窗口【" + uid + "】的信息:" + message);
+        try {
+            caseService = applicationContext.getBean(CaseService.class);
+            String id = caseService.plainTextCaseQa(message);
+            String mes = caseService.findOp(id);
+            log.info("回复窗口【" + uid + "】的信息:{}", mes);
+            sendMessage(mes);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        // // 群发消息
+        // for (QaWebSocket item : webSocketSet) {
+        //     try {
+        //         item.sendMessage(message);
+        //     } catch (IOException e) {
+        //         e.printStackTrace();
+        //     }
+        // }
+    }
+
+    public static String getRes(String res) {
+        return res;
+    }
+
+    /**
+     * @param session
+     * @param error
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.error("发生错误");
+        error.printStackTrace();
+    }
+
+    /**
+     * 实现服务器主动推送
+     */
+    public void sendMessage(String message) throws IOException {
+        this.session.getBasicRemote().sendText(message);
+    }
+
+    /**
+     * 群发自定义消息
+     */
+    public static void sendInfo(String message, @PathParam("uid") String uid) throws IOException {
+        log.info("推送消息到窗口【" + uid + "】,推送内容:" + message);
+        for (QaWebSocket item : webSocketSet) {
+            try {
+                // 这里可以设定只推送给这个sid的,为null则全部推送
+                if (uid == null) {
+                    item.sendMessage(message);
+                } else if (item.sid.equals(uid)) {
+                    item.sendMessage(message);
+                }
+            } catch (IOException e) {
+                continue;
+            }
+        }
+    }
+
+    public static synchronized int getOnlineCount() {
+        return onlineCount;
+    }
+
+    public static synchronized void addOnlineCount() {
+        QaWebSocket.onlineCount++;
+    }
+
+    public static synchronized void subOnlineCount() {
+        QaWebSocket.onlineCount--;
+    }
+}

+ 14 - 0
src/main/java/com/pavis/ai/app/judicial/mapper/CaseMapper.java

@@ -0,0 +1,14 @@
+package com.pavis.ai.app.judicial.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.ai.app.judicial.model.Case;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:22
+ * @desc CaseMapper
+ **/
+@Component
+public interface CaseMapper extends BaseMapper<Case> {
+}

+ 14 - 0
src/main/java/com/pavis/ai/app/judicial/mapper/OpMapper.java

@@ -0,0 +1,14 @@
+package com.pavis.ai.app.judicial.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.ai.app.judicial.model.Op;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:22
+ * @desc CaseMapper
+ **/
+@Component
+public interface OpMapper extends BaseMapper<Op> {
+}

+ 20 - 0
src/main/java/com/pavis/ai/app/judicial/model/Case.java

@@ -0,0 +1,20 @@
+package com.pavis.ai.app.judicial.model;
+
+import lombok.*;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:20
+ * @desc Case
+ **/
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class Case {
+
+    private String id;
+
+    private String caseClassification;
+}

+ 22 - 0
src/main/java/com/pavis/ai/app/judicial/model/Op.java

@@ -0,0 +1,22 @@
+package com.pavis.ai.app.judicial.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.*;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:20
+ * @desc Case
+ **/
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class Op {
+    @TableId(type = IdType.ID_WORKER_STR)
+    private String id;
+    private String type;
+    private String info;
+}

+ 11 - 0
src/main/java/com/pavis/ai/app/judicial/service/CancelCallback.java

@@ -0,0 +1,11 @@
+package com.pavis.ai.app.judicial.service;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-03-02 15:24
+ * @desc CancelCallback
+ **/
+// @FunctionalInterface
+public interface CancelCallback {
+
+}

+ 24 - 0
src/main/java/com/pavis/ai/app/judicial/service/CaseService.java

@@ -0,0 +1,24 @@
+package com.pavis.ai.app.judicial.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.pavis.ai.app.judicial.form.LegalInfo;
+import com.pavis.ai.app.judicial.model.Case;
+
+import java.io.IOException;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:17
+ * @desc CaseService
+ **/
+
+
+public interface CaseService extends IService<Case> {
+
+    String plainTextCaseCs(LegalInfo legalInfo) throws IOException, InterruptedException;
+
+    String plainTextCaseQa(String message) throws IOException, InterruptedException;
+
+    String findOp(String mes) throws InterruptedException;
+
+}

+ 18 - 0
src/main/java/com/pavis/ai/app/judicial/service/JqasService.java

@@ -0,0 +1,18 @@
+package com.pavis.ai.app.judicial.service;
+
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-24 13:22
+ * @desc JqasService
+ **/
+public interface JqasService extends RabbitTemplate.ConfirmCallback {
+
+    // void sendMessage(String routingKey, Object message, CorrelationData correlationData);
+
+    // String sendMessage(String question, String type) throws InterruptedException;
+
+    void sendMessage(String routingKey, Object message, CorrelationData correlationData);
+}

+ 17 - 0
src/main/java/com/pavis/ai/app/judicial/service/OpService.java

@@ -0,0 +1,17 @@
+package com.pavis.ai.app.judicial.service;
+
+import java.io.IOException;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-03-02 14:00
+ * @desc OpService
+ **/
+public interface OpService {
+    /**
+     * 监听算法回复的信息。
+     * @param bytes
+     * @throws IOException
+     */
+    void onReceiveOpMessage(byte[] bytes) throws IOException;
+}

+ 116 - 0
src/main/java/com/pavis/ai/app/judicial/service/impl/CaseServiceImpl.java

@@ -0,0 +1,116 @@
+package com.pavis.ai.app.judicial.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pavis.ai.app.judicial.common.config.constants.Constants;
+import com.pavis.ai.app.judicial.form.LegalInfo;
+import com.pavis.ai.app.judicial.mapper.CaseMapper;
+import com.pavis.ai.app.judicial.mapper.OpMapper;
+import com.pavis.ai.app.judicial.model.Case;
+import com.pavis.ai.app.judicial.model.Op;
+import com.pavis.ai.app.judicial.service.CaseService;
+import com.pavis.ai.app.judicial.service.JqasService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-20 5:18
+ * @desc CaseServiceImpl
+ **/
+@Slf4j
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class CaseServiceImpl extends ServiceImpl<CaseMapper, Case> implements CaseService {
+
+    @Autowired
+    private JqasService jqasService;
+
+    @Autowired
+    private OpMapper opMapper;
+
+    @Override
+    public String plainTextCaseCs(LegalInfo legalInfo) throws InterruptedException {
+        legalInfo.setId(String.valueOf(System.currentTimeMillis()));
+        Map<String, Object> rbmqMap = new HashMap<>();
+        rbmqMap.put("id", legalInfo.getId());
+        rbmqMap.put("type", legalInfo.getType());
+        rbmqMap.put("info", legalInfo.getInfo());
+        CorrelationData correlationData = new CorrelationData(legalInfo.getId());
+        jqasService.sendMessage(Constants.ROUTING_OP_KEY, JSON.toJSONString(rbmqMap), correlationData);
+
+        Thread.sleep(1000);
+        return legalInfo.getId();
+        // Response response = startTrans(JSON.toJSONString(legalInfo));
+        // String backData = response.body().string();
+        // System.err.println("res>" + backData);
+
+        // String backData = jqasService.sendMessage(legalInfo.getInfo(),legalInfo.getType());
+        // System.err.println("backData>"+backData);
+    }
+
+    @Override
+    public String plainTextCaseQa(String message) throws InterruptedException {
+        LegalInfo legalInfo = LegalInfo.builder()
+                .type("2")
+                .info(message)
+                .build();
+        return plainTextCaseCs(legalInfo);
+    }
+
+    @Override
+    public String findOp(String mes) throws InterruptedException {
+        log.info("get result:{}" , mes);
+        String res = "";
+        Op op = new Op();
+        for (int i = 0; i < 15; i++){
+            Thread.sleep(1000);
+            op = opMapper.selectById(mes);
+            if (!op.getInfo().equals("")){
+                res = op.getInfo();
+                break;
+            }
+        }
+
+        if (res.equals("")){
+            res = "无法判断";
+        }
+        log.info("result:{}" , res);
+        return res;
+    }
+
+    // /**
+    //  * 更换通信方式,暂时弃用。
+    //  * @param json
+    //  * @return
+    //  * @throws IOException
+    //  */
+    // private Response startTrans(String json) throws IOException {
+    //     MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+    //     OkHttpClient client = new OkHttpClient.Builder()
+    //             .readTimeout(10, TimeUnit.MINUTES)
+    //             .writeTimeout(10, TimeUnit.MINUTES)
+    //             .connectTimeout(10, TimeUnit.MINUTES)
+    //             .build();
+    //     okhttp3.RequestBody body = okhttp3.RequestBody.create(JSON, json);
+    //
+    //     Request request = new Request.Builder()
+    //             // .url("http://192.168.1.73:10080/api/legal")
+    //             .url("http://192.168.1.202:5678")
+    //             .post(body)
+    //             // .get()
+    //             .build();
+    //     Response response = client.newCall(request).execute();
+    //     return response;
+    // }
+
+
+}

+ 55 - 0
src/main/java/com/pavis/ai/app/judicial/service/impl/JqasServiceImpl.java

@@ -0,0 +1,55 @@
+package com.pavis.ai.app.judicial.service.impl;
+
+import com.pavis.ai.app.judicial.common.config.constants.Constants;
+import com.pavis.ai.app.judicial.mapper.OpMapper;
+import com.pavis.ai.app.judicial.model.Op;
+import com.pavis.ai.app.judicial.service.JqasService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-02-24 13:25
+ * @desc JqasServiceImpl
+ **/
+@Slf4j
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class JqasServiceImpl implements JqasService {
+
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+
+    @Autowired
+    private OpMapper opMapper;
+
+    @Override
+    public void sendMessage(String routingKey, Object message, CorrelationData correlationData) {
+        log.info("向模型发送的信息:{}", message);
+        rabbitTemplate.setConfirmCallback(this);
+        rabbitTemplate.convertAndSend(Constants.EXCHANGE_NAME, routingKey, message, correlationData);
+    }
+
+
+
+    @Override
+    public void confirm(CorrelationData correlationData, boolean b, String s) {
+        if (b) {
+            log.info("向模型发送信息成功,入库成功!");
+            // 发送成功,入库。
+            Op op = Op.builder()
+                    .id(correlationData.getId())
+                    .type("")
+                    .info("")
+                    .build();
+            opMapper.insert(op);
+            log.info("入库成功!",op.getId());
+        } else {
+            log.info("发送失败:{}", s);
+        }
+    }
+}

+ 57 - 0
src/main/java/com/pavis/ai/app/judicial/service/impl/OpServiceImpl.java

@@ -0,0 +1,57 @@
+package com.pavis.ai.app.judicial.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pavis.ai.app.judicial.common.config.constants.Constants;
+import com.pavis.ai.app.judicial.form.OpMessage;
+import com.pavis.ai.app.judicial.mapper.OpMapper;
+import com.pavis.ai.app.judicial.model.Op;
+import com.pavis.ai.app.judicial.service.OpService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author guanhuijuan
+ * @create 2020-03-02 14:00
+ * @desc OpServiceImpl
+ **/
+@Slf4j
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class OpServiceImpl implements OpService {
+
+    @Autowired
+    private OpMapper opMapper;
+
+    @Override
+    @RabbitListener(queues = Constants.QUEUE_OP_RESULT_NAME)
+    public void onReceiveOpMessage(byte[] bytes){
+        String message = new String(bytes);
+        log.info("收到模型的回复信息:{}", message);
+        OpMessage opMessage = JSONObject.parseObject(message, OpMessage.class);
+        updateById(opMessage);
+    }
+
+    public void updateById(OpMessage opMessage){
+        if (opMessage.getSuccess()){
+            Op op = Op.builder()
+                    .id(opMessage.getId())
+                    .type(opMessage.getData().getType())
+                    .info(opMessage.getData().getResult())
+                    .build();
+            opMapper.updateById(op);
+            log.info("解析成功,更新信息成功:{}",op.getInfo());
+        }else {
+            Op op = Op.builder()
+                    .id(opMessage.getId())
+                    .type(opMessage.getData().getType())
+                    .info("无法判断")
+                    .build();
+            opMapper.updateById(op);
+            log.info("解析失败,更新信息成功:{}",op.getInfo());
+        }
+    }
+
+}

+ 36 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,36 @@
+spring:
+  datasource:
+    url: jdbc:mysql://192.168.1.73/jqas?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: root
+  rabbitmq:
+    host: 192.168.1.73
+    #    host: localhost
+    port: 5672
+    username: jqas
+    password: jqas0227
+    virtual-host: jqas
+    publisher-confirms: true
+    publisher-returns: true
+judicial:
+  common:
+    dir:
+      # 上传文件存储文件夹
+      upload: E:/mnt/base/tmp/
+      # 用户头像存储文件夹
+      avatar: E:/mnt/base/avatar/
+security:
+  oauth2:
+    client:
+      client-id: iGKpGQXmPYNfj6XvXuiQtlSO
+      client-secret: tm6p3xq4zQOgJlCeIyeYYHMPNGAXuQVx
+      access-token-uri: http://192.168.1.23:8090/oauth/token
+      user-authorization-uri: http://192.168.1.23:8090/oauth/authorize
+    resource:
+      token-info-uri: http://192.168.1.23:8090/oauth/check_token
+logging:
+  level:
+    org.springframework.cloud: debug
+    org.springframework.boot: debug
+    com.pavis.ai.app.judicial.mapper: trace

+ 11 - 0
src/main/resources/application.yml

@@ -0,0 +1,11 @@
+server:
+  port: 10081
+spring:
+  application:
+    name: pavis-portal-server
+  profiles:
+    active: dev
+mybatis-plus:
+  mapper-locations: classpath*:/mapper/*Mapper.xml
+  typeAliasesPackage: com.pavis.ai.app.judicial.model
+

+ 22 - 0
src/main/resources/error.properties

@@ -0,0 +1,22 @@
+credentials_expired=\u51ED\u8BC1\u5DF2\u8FC7\u671F!
+bad_request=\u65E0\u6548\u7684\u8BF7\u6C42!
+not_found=\u65E0\u6548\u7684\u8BBF\u95EE\u5730\u5740\uFF01
+service_unavailable=\u670D\u52A1\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\uFF01
+method_not_allowed=\u8BF7\u6C42\u65B9\u5F0F\u4E0D\u652F\u6301!
+media_type_not_acceptable=\u5A92\u4F53\u7C7B\u578B\u4E0D\u652F\u6301!
+username_not_found=\u8D26\u53F7\u4E0D\u5B58\u5728!
+bad_credentials=\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF!
+account_disabled=\u8D26\u53F7\u5DF2\u88AB\u7981\u7528!
+account_expired=\u8D26\u53F7\u5DF2\u8FC7\u671F!
+account_locked=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A!
+error=\u670D\u52A1\u5668\u7E41\u5FD9,\u8BF7\u7A0D\u540E\u518D\u8BD5!
+unauthorized=\u8BA4\u8BC1\u5931\u8D25,\u8BF7\u91CD\u65B0\u767B\u5F55!
+too_many_requests=\u8BBF\u95EE\u592A\u8FC7\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5!
+access_denied=\u6743\u9650\u4E0D\u8DB3,\u62D2\u7EDD\u8BBF\u95EE!
+access_denied_black_limited=IP\u6216\u57DF\u540D\u62D2\u7EDD\u8BBF\u95EE!
+access_denied_white_limited=IP\u6216\u57DF\u540D\u4E0D\u5728\u767D\u540D\u5355\u5185,\u62D2\u7EDD\u8BBF\u95EE!
+access_denied_authority_expired=\u6388\u6743\u5DF2\u8FC7\u671F,\u62D2\u7EDD\u8BBF\u95EE!
+access_denied_updating=\u6B63\u5728\u5347\u7EA7\u7EF4\u62A4\u4E2D,\u8BF7\u7A0D\u540E\u518D\u8BD5!
+access_denied_disabled=\u8BF7\u6C42\u5730\u5740,\u7981\u6B62\u8BBF\u95EE!
+access_denied_not_open=\u8BF7\u6C42\u5730\u5740,\u62D2\u7EDD\u8BBF\u95EE!
+invalid_token=\u65E0\u6548\u7684\u8BBF\u95EE\u4EE4\u724C!

+ 16 - 0
src/test/java/com/pavis/ai/app/judicial/JudicialApplicationTests.java

@@ -0,0 +1,16 @@
+package com.pavis.ai.app.judicial;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class JudicialApplicationTests {
+
+    @Test
+    public void contextLoads() {
+    }
+
+}

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