yusm 6 月之前
父節點
當前提交
10db0b5d53
共有 41 個文件被更改,包括 1924 次插入0 次删除
  1. 2 0
      fhKeeper/formulahousekeeper/ArticleOperation/.gitattributes
  2. 33 0
      fhKeeper/formulahousekeeper/ArticleOperation/.gitignore
  3. 二進制
      fhKeeper/formulahousekeeper/ArticleOperation/.mvn/wrapper/maven-wrapper.jar
  4. 2 0
      fhKeeper/formulahousekeeper/ArticleOperation/.mvn/wrapper/maven-wrapper.properties
  5. 1 0
      fhKeeper/formulahousekeeper/ArticleOperation/README.md
  6. 308 0
      fhKeeper/formulahousekeeper/ArticleOperation/mvnw
  7. 205 0
      fhKeeper/formulahousekeeper/ArticleOperation/mvnw.cmd
  8. 92 0
      fhKeeper/formulahousekeeper/ArticleOperation/pom.xml
  9. 71 0
      fhKeeper/formulahousekeeper/ArticleOperation/sql_file/big_event.sql
  10. 15 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/BigEventApplication.java
  11. 26 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/anno/State.java
  12. 25 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/config/WebConfig.java
  13. 53 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/ArticleController.java
  14. 66 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/CategoryController.java
  15. 25 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/FileUploadController.java
  16. 150 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/UserController.java
  17. 24 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/exception/GlobalExceptionHandler.java
  18. 46 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/interceptors/LoginInterceptor.java
  19. 23 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/mapper/ArticleMapper.java
  20. 24 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/mapper/CategoryMapper.java
  21. 27 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/mapper/UserMapper.java
  22. 32 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/Article.java
  23. 37 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/Category.java
  24. 16 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/PageBean.java
  25. 29 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/Result.java
  26. 29 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/User.java
  27. 15 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/ArticleService.java
  28. 16 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/CategoryService.java
  29. 16 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/UserService.java
  30. 107 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/impl/ArticleServiceImpl.java
  31. 53 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/impl/CategoryServiceImpl.java
  32. 57 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/impl/UserServiceImpl.java
  33. 30 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/utils/JwtUtil.java
  34. 73 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/utils/Md5Util.java
  35. 25 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/utils/ThreadLocalUtil.java
  36. 30 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/validation/StateValidation.java
  37. 20 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/resources/application.yml
  38. 21 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/main/resources/com/my/bigevent/mapper/ArticleMapper.xml
  39. 15 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/test/java/com/my/bigevent/BigEventApplicationTests.java
  40. 56 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/test/java/com/my/bigevent/JwtTest.java
  41. 29 0
      fhKeeper/formulahousekeeper/ArticleOperation/src/test/java/com/my/bigevent/ThreadLocalTest.java

+ 2 - 0
fhKeeper/formulahousekeeper/ArticleOperation/.gitattributes

@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto

+ 33 - 0
fhKeeper/formulahousekeeper/ArticleOperation/.gitignore

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

二進制
fhKeeper/formulahousekeeper/ArticleOperation/.mvn/wrapper/maven-wrapper.jar


+ 2 - 0
fhKeeper/formulahousekeeper/ArticleOperation/.mvn/wrapper/maven-wrapper.properties

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

+ 1 - 0
fhKeeper/formulahousekeeper/ArticleOperation/README.md

@@ -0,0 +1 @@
+用于练习java开发的springboot后端开发项目,大事件文章管理后台系统。

+ 308 - 0
fhKeeper/formulahousekeeper/ArticleOperation/mvnw

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

+ 205 - 0
fhKeeper/formulahousekeeper/ArticleOperation/mvnw.cmd

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

+ 92 - 0
fhKeeper/formulahousekeeper/ArticleOperation/pom.xml

@@ -0,0 +1,92 @@
+<?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.7.18</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.my</groupId>
+    <artifactId>ArticleOperation</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>ArticleOperation</name>
+    <description>ArticleOperation</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <mybatis.version>2.3.2</mybatis.version>
+    </properties>
+    <dependencies>
+        <!--web 启动依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!--mybatis 起步依赖-->
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>${mybatis.version}</version>
+        </dependency>
+
+        <!--mysql 驱动依赖-->
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!--lombok 依赖,自动在实体类中添加 getter setter 方法-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <!--validation 依赖,使用正则表达式校验前端传过来的参数-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!-- jwt 令牌验证-->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.10.3</version>
+        </dependency>
+
+        <!--springboot 单元测试依赖,比 junit 更好的测试 springboot 项目-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
+
+        <!--分页查询插件-->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.4.6</version>
+        </dependency>
+
+    </dependencies>
+
+    <!--打包插件,版本需要与springboot版本匹配-->
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+<!--                <version>3.2.0</version>-->
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 71 - 0
fhKeeper/formulahousekeeper/ArticleOperation/sql_file/big_event.sql

@@ -0,0 +1,71 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : phpstudy_mysql_8.0.12
+ Source Server Type    : MySQL
+ Source Server Version : 80012
+ Source Host           : localhost:3306
+ Source Schema         : big_event
+
+ Target Server Type    : MySQL
+ Target Server Version : 80012
+ File Encoding         : 65001
+
+ Date: 21/01/2024 19:17:30
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for article
+-- ----------------------------
+DROP TABLE IF EXISTS `article`;
+CREATE TABLE `article`  (
+  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
+  `title` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文章标题',
+  `content` varchar(10000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文章内容',
+  `cover_img` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '文章封面',
+  `state` varchar(3) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '草稿' COMMENT '文章状态: 只能是[已发布] 或者 [草稿]',
+  `category_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '文章分类ID',
+  `create_user` int(10) UNSIGNED NOT NULL COMMENT '创建人ID',
+  `create_time` datetime(0) NOT NULL COMMENT '创建时间',
+  `update_time` datetime(0) NOT NULL COMMENT '修改时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `fk_article_category`(`category_id`) USING BTREE,
+  INDEX `fk_article_user`(`create_user`) USING BTREE
+) ENGINE = MyISAM AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for category
+-- ----------------------------
+DROP TABLE IF EXISTS `category`;
+CREATE TABLE `category`  (
+  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
+  `category_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '分类名称',
+  `category_alias` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '分类别名',
+  `create_user` int(10) UNSIGNED NOT NULL COMMENT '创建人ID',
+  `create_time` datetime(0) NOT NULL COMMENT '创建时间',
+  `update_time` datetime(0) NOT NULL COMMENT '修改时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `fk_category_user`(`create_user`) USING BTREE
+) ENGINE = MyISAM AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Table structure for user
+-- ----------------------------
+DROP TABLE IF EXISTS `user`;
+CREATE TABLE `user`  (
+  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
+  `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '用户名',
+  `password` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '密码',
+  `nickname` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '昵称',
+  `email` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '邮箱',
+  `user_pic` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '头像',
+  `create_time` datetime(0) NOT NULL COMMENT '创建时间',
+  `update_time` datetime(0) NOT NULL COMMENT '修改时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `username`(`username`) USING BTREE
+) ENGINE = MyISAM AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 15 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/BigEventApplication.java

@@ -0,0 +1,15 @@
+package com.my.bigevent;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class BigEventApplication
+{
+
+    public static void main(String[] args)
+    {
+        SpringApplication.run(BigEventApplication.class, args);
+    }
+
+}

+ 26 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/anno/State.java

@@ -0,0 +1,26 @@
+package com.my.bigevent.anno;
+
+import com.my.bigevent.validation.StateValidation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+// 可以根据已有的注解进行仿写
+@Documented   // 表示形成帮助文档的时候,生成当前注解信息
+@Constraint(
+        validatedBy = {StateValidation.class}  // 这里指定 StateValidation.class 作为校验规则
+)   // 指定通过哪个类定义注解的校验逻辑
+@Target({ElementType.FIELD})  // 表示注解可以使用的对象,这里是字段
+@Retention(RetentionPolicy.RUNTIME)  // 表示注解持续作用到程序运行时
+public @interface State
+{
+    // 提供注解校验失败后的提示信息
+    String message() default "state参数的值,只能是已发布或者草稿!";
+
+    // 指定分组
+    Class<?>[] groups() default {};
+
+    // 负载,获取 state 注解附加信息,目前用不到
+    Class<? extends Payload>[] payload() default {};
+}

+ 25 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/config/WebConfig.java

@@ -0,0 +1,25 @@
+package com.my.bigevent.config;
+
+import com.my.bigevent.interceptors.LoginInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * 配置类,里面注册了自定义的拦截器。并没有使用 filter 过滤器
+ */
+@Configuration
+public class WebConfig implements WebMvcConfigurer
+{
+    @Autowired
+    private LoginInterceptor loginInterceptor;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry)
+    {
+        // 登录接口,注册接口,不拦截
+        // 将自定义的拦截器注册进来
+        registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");
+    }
+}

+ 53 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/ArticleController.java

@@ -0,0 +1,53 @@
+package com.my.bigevent.controller;
+
+import com.my.bigevent.pojo.Article;
+import com.my.bigevent.pojo.PageBean;
+import com.my.bigevent.pojo.Result;
+import com.my.bigevent.service.ArticleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/article")
+public class ArticleController
+{
+    @Autowired
+    ArticleService articleService;
+
+    /**
+     * 新增文章
+     * @param article
+     * @return
+     */
+    @PostMapping
+    public Result add( Article article)
+    {
+        articleService.add(article);
+        return Result.success();
+    }
+
+    /**
+     * 获取文章列表
+     * @param pageNum
+     * @param pageSize
+     * @param categoryId
+     * @param state
+     * @return
+     */
+    @GetMapping   // 这里的 PageBean 是事先定义好的实体类
+    public Result<PageBean<Article>> list(Integer pageNum,Integer pageSize,
+                                          @RequestParam(required = false) Integer categoryId,
+                                          @RequestParam(required = false) String state)
+    {
+        PageBean<Article> pb=articleService.list(pageNum,pageSize,categoryId,state);
+        return Result.success(pb);
+    }
+
+    @PostMapping("/getArticleById/{id}")
+    public Result<Article> getArticleById(@PathVariable(value = "id")Integer id){
+        Article article = articleService.getArticleById(id);
+        return Result.success(article);
+    }
+
+
+}

+ 66 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/CategoryController.java

@@ -0,0 +1,66 @@
+package com.my.bigevent.controller;
+
+import com.my.bigevent.pojo.Category;
+import com.my.bigevent.pojo.Result;
+import com.my.bigevent.service.CategoryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/category")
+public class CategoryController
+{
+    @Autowired
+    CategoryService categoryService;
+
+    /**
+     * 新增文章分类
+     * @param category
+     * @return
+     */
+    @PostMapping
+    public Result add(@RequestBody @Validated Category category)
+    {
+        categoryService.add(category);
+        return Result.success("新增分类成功!");
+    }
+
+    /**
+     * 获取文章列表
+     * @return
+     */
+    @GetMapping
+    public Result<List<Category>> list()
+    {
+        List<Category> categoryList=categoryService.list();
+        return Result.success(categoryList);
+    }
+
+    /**
+     * 更新文章分类
+     * @param category
+     * @return
+     */
+    @PutMapping                       //指定分组校验中的 Update.class 分组进行校验
+    public Result update(@RequestBody @Validated(Category.Update.class) Category category)
+    {
+        categoryService.update(category);
+        return Result.success("更新文章分类成功!");
+    }
+
+    /**
+     * 删除文章分类
+     * @param id
+     * @return
+     */
+    @DeleteMapping
+    public Result delete(Integer id)
+    {
+        categoryService.delete(id);
+        return Result.success("文章删除成功!");
+    }
+
+}

+ 25 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/FileUploadController.java

@@ -0,0 +1,25 @@
+package com.my.bigevent.controller;
+
+import com.my.bigevent.pojo.Result;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.util.UUID;
+
+@RestController
+public class FileUploadController
+{
+    @PostMapping("/upload")
+    public Result<String> upload(MultipartFile file) throws Exception
+    {
+        // 获取文件名
+        String originalFilename=file.getOriginalFilename();
+        // 保证文件名字是唯一的,从而防止文件被覆盖
+        String filename= UUID.randomUUID().toString()+originalFilename.substring(originalFilename.lastIndexOf("."));
+        // windows 系统写法,未考虑到 linux 系统情况
+        file.transferTo(new File("C:\\Users\\Vulner-6\\Desktop\\Temp\\"+filename));
+        return Result.success("http://test.com");
+    }
+}

+ 150 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/controller/UserController.java

@@ -0,0 +1,150 @@
+package com.my.bigevent.controller;
+
+import com.my.bigevent.pojo.Result;
+import com.my.bigevent.pojo.User;
+import com.my.bigevent.service.UserService;
+import com.my.bigevent.utils.JwtUtil;
+import com.my.bigevent.utils.Md5Util;
+import com.my.bigevent.utils.ThreadLocalUtil;
+import org.hibernate.validator.constraints.URL;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.constraints.Pattern;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/user")
+@Validated
+public class UserController
+{
+    @Autowired
+    UserService userService;
+
+    /**
+     * 注册功能
+     * @param username
+     * @param password
+     * @return
+     */
+    @PostMapping("/register")  // 这里的正则表达式,里面的转义字符需要两个,不同于直接的正则表达式。若不符合正则匹配规则,就会报异常,因此需要全局异常处理
+    public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password)
+    {
+
+        // 查询用户
+        User u=userService.findByUserName(username);
+        if(u==null)
+        {
+            // 用户不存在,则注册
+            userService.register(username,password);
+            return Result.success("注册成功!");
+        }
+        else
+        {
+            // 用户存在,则返回提示信息
+            return Result.error("用户已存在!");
+        }
+    }
+
+    /**
+     * 登录功能
+     * @param username
+     * @param password
+     * @return
+     */
+    @PostMapping("/login")
+    public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password)
+    {
+        // 根据用户名查询用户
+        User loginUser=userService.findByUserName(username);
+        // 若用户不存在,则返回结果
+        if(loginUser==null)
+        {
+            return Result.error("用户不存在!");
+        }
+        // 若用户存在,则校验密码,密码正确返回jwt令牌
+        if(Md5Util.getMD5String(password).equals(loginUser.getPassword()))
+        {
+            // 生成 jwt 令牌,存入当前用户信息
+            Map<String,Object> claims=new HashMap<>();
+            claims.put("id",loginUser.getId());
+            claims.put("username",loginUser.getUsername());
+            String token= JwtUtil.genToken(claims);
+            return Result.success(token);
+        }
+
+        // 若用户存在,但是密码校验不对
+        return Result.error("密码错误!");
+    }
+
+    /**
+     * 获取用户信息
+     * @param
+     * @return
+     */
+    @GetMapping("/userInfo")
+    public Result<User> userInfo()
+    {
+        // 根据用户名查询用户
+        Map<String,Object> map= ThreadLocalUtil.get();
+        String username=(String)map.get("username");
+        User user=userService.findByUserName(username);
+        return Result.success(user);
+    }
+
+    /**
+     * 更新用户信息
+     * @param user
+     * @return
+     */
+    @PutMapping("/update")
+    public Result update(@RequestBody @Validated User user)
+    {
+        userService.update(user);
+        return Result.success();
+    }
+
+    @PatchMapping("/updateAvatar")   // @URL 限定当前字符串满足 URL 格式
+    public Result updateAvatar(@RequestParam @URL String avatarUrl)
+    {
+        userService.updateAvatar(avatarUrl);
+        return Result.success();
+    }
+
+    @PatchMapping("/updatePwd")
+    public Result updatePwd(@RequestBody Map<String,String> params)
+    {
+        // 校验参数
+        String oldPwd=params.get("old_pwd");
+        String newPwd=params.get("new_pwd");
+        String rePwd=params.get("re_pwd");
+        if(!StringUtils.hasLength(oldPwd)||!StringUtils.hasLength(newPwd)||!StringUtils.hasLength(rePwd))
+        {
+            return Result.error("缺少参数!");
+        }
+
+        // 比对原密码是否正确
+        Map<String,Object> map=ThreadLocalUtil.get();
+        String username=(String) map.get("username");
+        User loginUser=userService.findByUserName(username);
+        if(!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd)))
+        {
+            return Result.error("原密码错误!");
+        }
+
+        // 校验新密码与确认密码是否一致
+        if(newPwd.equals(rePwd))
+        {
+            // 若原密码正确,且新密码与确认密码一致,则完成新密码的更新
+            userService.updatePwd(newPwd);
+            return Result.success();
+        }
+        else
+        {
+            return Result.error("新密码与确认密码不一致!");
+        }
+    }
+}

+ 24 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/exception/GlobalExceptionHandler.java

@@ -0,0 +1,24 @@
+package com.my.bigevent.exception;
+
+import com.my.bigevent.pojo.Result;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+
+@RestControllerAdvice // 用于捕获所有 Controller 中的异常,并返回 json 格式字符串
+public class GlobalExceptionHandler
+{
+    @ExceptionHandler(Exception.class)   // 所有类型的异常
+    public Result handleException(Exception e)
+    {
+        e.printStackTrace();
+        return Result.error(StringUtils.hasLength(e.getMessage())?e.getMessage():"操作失败!");
+    }
+
+    @ExceptionHandler(MaxUploadSizeExceededException.class)
+    public Result handleMaxFileException(MaxUploadSizeExceededException e){
+        e.printStackTrace();
+        return Result.error("文件过大");
+    }
+}

+ 46 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/interceptors/LoginInterceptor.java

@@ -0,0 +1,46 @@
+package com.my.bigevent.interceptors;
+
+import com.my.bigevent.utils.JwtUtil;
+import com.my.bigevent.utils.ThreadLocalUtil;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * 自定义拦截器,用于校验身份
+ */
+@Component
+public class LoginInterceptor implements HandlerInterceptor
+{
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
+    {
+        // 获得令牌
+        String token=request.getHeader("Authorization");
+        // 令牌验证
+        try
+        {
+            // 解析 jwt token,若无异常,则说明解析成功,放行
+            Map<String,Object> claims= JwtUtil.parseToken(token);
+            // 将业务数据存放到 ThreadLocl 中
+            ThreadLocalUtil.set(claims);
+            return true;
+        }
+        catch (Exception e)
+        {
+            // 设置状态码为401,不放行
+            response.setStatus(401);
+            return false;
+        }
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
+    {
+        // 每次请求结束后,清除 ThreadLocal 里的数据,否则会导致内存泄露问题!
+        ThreadLocalUtil.remove();
+    }
+}

+ 23 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/mapper/ArticleMapper.java

@@ -0,0 +1,23 @@
+package com.my.bigevent.mapper;
+
+import com.my.bigevent.pojo.Article;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+@Mapper
+public interface ArticleMapper
+{
+    @Insert("insert into article(title,content,cover_img,state,category_id,create_user,create_time,update_time)"+
+                        "values(#{title},#{content},#{coverImg},#{state},#{categoryId},#{createUser},#{createTime}," +
+            "#{updateTime})")
+    void add(Article article);
+
+    // 动态实现 sql,所以这里不用注解
+    List<Article> list(Integer userId, Integer categoryId, String state);
+
+    @Select("select * from article where id = #{id}")
+    Article getArticleById(Integer id);
+}

+ 24 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/mapper/CategoryMapper.java

@@ -0,0 +1,24 @@
+package com.my.bigevent.mapper;
+
+import com.my.bigevent.pojo.Category;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface CategoryMapper
+{
+    @Insert("insert into category(category_name,category_alias,create_user,create_time,update_time)"+
+            " values(#{categoryName},#{categoryAlias},#{createUser},#{createTime},#{updateTime});")
+    void add(Category category);
+
+    @Select("select * from category where create_user=#{userId}")
+    List<Category> list(Integer userId);
+
+    @Update("update category set category_name=#{categoryName},category_alias=#{categoryAlias}," +
+            "update_time=#{updateTime} where id=#{id}")
+    void update(Category category);
+
+    @Delete("delete from category where id=#{id}")
+    void delete(Integer id);
+}

+ 27 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/mapper/UserMapper.java

@@ -0,0 +1,27 @@
+package com.my.bigevent.mapper;
+
+import com.my.bigevent.pojo.User;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+@Mapper
+public interface UserMapper
+{
+    @Select("select * from user where username=#{username};")
+    User findByUserName(String username);
+
+    @Insert("insert into user(username,password,create_time,update_time)"+
+            " values(#{username},#{md5String},now(),now());")
+    void add(String username, String md5String);
+
+    @Update("update user set nickname=#{nickname},email=#{email},update_time=#{updateTime} where id=#{id}")
+    void update(User user);
+
+    @Update("update user set user_pic=#{avatarUrl},update_time=now() where id=#{id}")
+    void updateAvatar(String avatarUrl,Integer id);
+
+    @Update("update user set password=#{md5String},update_time=now() where id=#{id}")
+    void updatePwd(String md5String, Integer id);
+}

+ 32 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/Article.java

@@ -0,0 +1,32 @@
+package com.my.bigevent.pojo;
+
+
+import com.my.bigevent.anno.State;
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.time.LocalDateTime;
+@Data
+public class Article {
+    private Integer id;//主键ID
+    @NotEmpty
+    @Pattern(regexp = "^\\S{1,10}$")
+    private String title;//文章标题
+    @NotEmpty
+    private String content;//文章内容
+//    @NotEmpty
+//    @URL
+    private byte[] coverImg;//封面图像
+
+    private MultipartFile imgFile;
+    @State
+    private String state;//发布状态 已发布|草稿
+    @NotNull
+    private Integer categoryId;//文章分类id
+    private Integer createUser;//创建人ID
+    private LocalDateTime createTime;//创建时间
+    private LocalDateTime updateTime;//更新时间
+}

+ 37 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/Category.java

@@ -0,0 +1,37 @@
+package com.my.bigevent.pojo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import javax.validation.groups.Default;
+import java.time.LocalDateTime;
+@Data
+public class Category {
+    @NotNull(groups = Update.class)
+    private Integer id;//主键ID
+    @NotEmpty
+    private String categoryName;//分类名称
+    @NotEmpty
+    private String categoryAlias;//分类别名
+    private Integer createUser;//创建人ID
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")   // 规定时间格式
+    private LocalDateTime createTime;//创建时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")   // 规定时间格式
+    private LocalDateTime updateTime;//更新时间
+
+
+    // 分组校验
+    // 如果某个校验没有指定分组,那么默认是 Default 分组
+    // 分组之间可以继承,A extends B,那么A中拥有B中所有的校验项
+    public interface Add extends Default
+    {
+        // 虽然暂时变量上,并没有使用到 Add.class ,但是这个目前是用于演示区分 Update.class 的效果
+    }
+
+    public interface Update extends Default
+    {
+
+    }
+}

+ 16 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/PageBean.java

@@ -0,0 +1,16 @@
+package com.my.bigevent.pojo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+//分页返回结果对象,为了满足接口文档中返回的数据格式
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageBean <T>{
+    private Long total;//总条数
+    private List<T> items;//当前页数据集合
+}

+ 29 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/Result.java

@@ -0,0 +1,29 @@
+package com.my.bigevent.pojo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+//统一响应结果
+@NoArgsConstructor  // 生成无参数构造方法,若我们定义了(有/无)参数构造方法,则编译器不会默认自动生成无参数构造方法,因此这里要手动生成
+@AllArgsConstructor // 生成有参数构造方法
+@Data  // 编译后自动生成 getter setter 方法
+public class Result<T> {
+    private Integer code;//业务状态码  0-成功  1-失败
+    private String message;//提示信息
+    private T data;//响应数据
+
+    //快速返回操作成功响应结果(带响应数据)
+    public static <E> Result<E> success(E data) {
+        return new Result<>(0, "操作成功", data);
+    }
+
+    //快速返回操作成功响应结果
+    public static Result success() {
+        return new Result(0, "操作成功", null);
+    }
+
+    public static Result error(String message) {
+        return new Result(1, message, null);
+    }
+}

+ 29 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/pojo/User.java

@@ -0,0 +1,29 @@
+package com.my.bigevent.pojo;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.time.LocalDateTime;
+@Data   // 该注解可以让实体类在编译后,自动存在 getter setter 方法
+public class User {
+    @NotNull
+    private Integer id;//主键ID
+    private String username;//用户名
+    @JsonIgnore // 让 springMVC 把当前对象转换成 json 字符串的时候,忽略 password ,最终 json 字符串中就没有 password 这个属性了
+    private String password;//密码
+
+    @NotEmpty
+    @Pattern(regexp = "^\\S{1,10}$")
+    private String nickname;//昵称
+
+    @NotEmpty
+    @Email   //满足邮箱格式
+    private String email;//邮箱
+    private String userPic;//用户头像地址
+    private LocalDateTime createTime;//创建时间
+    private LocalDateTime updateTime;//更新时间
+}

+ 15 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/ArticleService.java

@@ -0,0 +1,15 @@
+package com.my.bigevent.service;
+
+import com.my.bigevent.pojo.Article;
+import com.my.bigevent.pojo.PageBean;
+
+public interface ArticleService
+{
+    // 新增文章
+    void add(Article article);
+
+    // 条件分页列表查询
+    PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state);
+
+    Article getArticleById(Integer id);
+}

+ 16 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/CategoryService.java

@@ -0,0 +1,16 @@
+package com.my.bigevent.service;
+
+import com.my.bigevent.pojo.Category;
+
+import java.util.List;
+
+public interface CategoryService
+{
+    void add(Category category);
+
+    List<Category> list();
+
+    void update(Category category);
+
+    void delete(Integer id);
+}

+ 16 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/UserService.java

@@ -0,0 +1,16 @@
+package com.my.bigevent.service;
+
+import com.my.bigevent.pojo.User;
+
+public interface UserService
+{
+    User findByUserName(String username);
+
+    void register(String username, String password);
+
+    void update(User user);
+
+    void updateAvatar(String avatarUrl);
+
+    void updatePwd(String newPwd);
+}

+ 107 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/impl/ArticleServiceImpl.java

@@ -0,0 +1,107 @@
+package com.my.bigevent.service.impl;
+
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import com.my.bigevent.mapper.ArticleMapper;
+import com.my.bigevent.pojo.Article;
+import com.my.bigevent.pojo.PageBean;
+import com.my.bigevent.service.ArticleService;
+import com.my.bigevent.utils.ThreadLocalUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@Service
+public class ArticleServiceImpl implements ArticleService
+{
+    @Autowired
+    ArticleMapper articleMapper;
+
+    private static List<String> fileTypeList = new ArrayList<>();
+    static {
+        fileTypeList.add("png");
+        fileTypeList.add("jpg");
+        fileTypeList.add("jpeg");
+    }
+
+    @Override
+    @Transactional
+    public void add(Article article)
+    {
+        Optional.ofNullable(article.getCategoryId()).orElseThrow(()->{return new RuntimeException("参数有误");});
+        Optional.ofNullable(article.getTitle()).orElseThrow(()->{return new RuntimeException("参数有误");});
+        Optional.ofNullable(article.getContent()).orElseThrow(()->{return new RuntimeException("参数有误");});
+        Optional.ofNullable(article.getState()).orElseThrow(()->{return new RuntimeException("参数有误");});
+        Optional.ofNullable(article.getImgFile()).orElseThrow(()->{return new RuntimeException("参数有误");});
+        if(0 == article.getImgFile().getSize()){
+            throw new RuntimeException("参数有误");
+        }
+        String fileName = article.getImgFile().getOriginalFilename();
+        String fileType = fileName.substring(fileName.lastIndexOf("."));
+        if(!fileTypeList.contains(fileType)){
+            throw new RuntimeException("文件类型有误");
+        }
+
+        // 补充属性
+        article.setCreateTime(LocalDateTime.now());
+        article.setUpdateTime(LocalDateTime.now());
+        Map<String,Object> map=ThreadLocalUtil.get();
+        Integer userId=(Integer)map.get("id");
+        article.setCreateUser(userId);
+
+        byte[] bytes = null;
+        try {
+            bytes = article.getImgFile().getBytes();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        article.setCoverImg(bytes);
+
+
+        articleMapper.add(article);
+    }
+
+    /**
+     * 条件分页列表查询
+     * @param pageNum
+     * @param pageSize
+     * @param categoryId
+     * @param state
+     * @return
+     */
+    @Override
+    public PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state)
+    {
+        // 创建 PageBean 对象
+        PageBean<Article> pb=new PageBean<>();
+
+        // 开启分页查询
+        PageHelper.startPage(pageNum,pageSize);
+
+        // 调用 mapper
+        Map<String,Object> map=ThreadLocalUtil.get();
+        Integer userId=(Integer)map.get("id");
+        List<Article> as=articleMapper.list(userId,categoryId,state);
+        // Page 中提供了方法,可以获取 PageHelper 分页查询后,得到的总记录条数和当前页数据
+        Page<Article> p=(Page<Article>) as;
+
+        // 把数据填充到 PageBean 对象中
+        pb.setTotal(p.getTotal());
+        pb.setItems(p.getResult());
+
+        return pb;
+    }
+
+    @Override
+    public Article getArticleById(Integer id) {
+        Article article = articleMapper.getArticleById(id);
+        return article;
+    }
+}

+ 53 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/impl/CategoryServiceImpl.java

@@ -0,0 +1,53 @@
+package com.my.bigevent.service.impl;
+
+import com.my.bigevent.mapper.CategoryMapper;
+import com.my.bigevent.pojo.Category;
+import com.my.bigevent.service.CategoryService;
+import com.my.bigevent.utils.ThreadLocalUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class CategoryServiceImpl implements CategoryService
+{
+    @Autowired
+    CategoryMapper categoryMapper;
+    @Override
+    public void add(Category category)
+    {
+        // 补充属性值,数据库里规定 category 的字段都不为 null
+        category.setCreateTime(LocalDateTime.now());
+        category.setUpdateTime(LocalDateTime.now());
+
+        Map<String,Object> map= ThreadLocalUtil.get();
+        Integer userId=(Integer)map.get("id");
+        category.setCreateUser(userId);
+
+        categoryMapper.add(category);
+    }
+
+    @Override
+    public List<Category> list()
+    {
+        Map<String,Object> map=ThreadLocalUtil.get();
+        Integer userId=(Integer) map.get("id");
+        return categoryMapper.list(userId);
+    }
+
+    @Override
+    public void update(Category category)
+    {
+        category.setUpdateTime(LocalDateTime.now());
+        categoryMapper.update(category);
+    }
+
+    @Override
+    public void delete(Integer id)
+    {
+        categoryMapper.delete(id);
+    }
+}

+ 57 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/service/impl/UserServiceImpl.java

@@ -0,0 +1,57 @@
+package com.my.bigevent.service.impl;
+
+import com.my.bigevent.mapper.UserMapper;
+import com.my.bigevent.pojo.User;
+import com.my.bigevent.service.UserService;
+import com.my.bigevent.utils.Md5Util;
+import com.my.bigevent.utils.ThreadLocalUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Map;
+
+@Service
+public class UserServiceImpl implements UserService
+{
+    @Autowired
+    UserMapper userMapper;
+    @Override
+    public User findByUserName(String username)
+    {
+        User u=userMapper.findByUserName(username);
+        return u;
+    }
+
+    @Override
+    public void register(String username, String password)
+    {
+        // 密码先加密,再添加至数据库
+        String md5String= Md5Util.getMD5String(password);
+        // 添加至数据库
+        userMapper.add(username,md5String);
+    }
+
+    @Override
+    public void update(User user)
+    {
+        user.setUpdateTime(LocalDateTime.now());
+        userMapper.update(user);
+    }
+
+    @Override
+    public void updateAvatar(String avatarUrl)
+    {
+        Map<String,Object> map= ThreadLocalUtil.get();
+        Integer id=(Integer) map.get("id");
+        userMapper.updateAvatar(avatarUrl,id);
+    }
+
+    @Override
+    public void updatePwd(String newPwd)
+    {
+        Map<String,Object> map= ThreadLocalUtil.get();
+        Integer id=(Integer) map.get("id");
+        userMapper.updatePwd(Md5Util.getMD5String(newPwd),id);
+    }
+}

+ 30 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/utils/JwtUtil.java

@@ -0,0 +1,30 @@
+package com.my.bigevent.utils;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+
+import java.util.Date;
+import java.util.Map;
+
+public class JwtUtil {
+
+    private static final String KEY = "itheima";
+	
+	//接收业务数据,生成token并返回
+    public static String genToken(Map<String, Object> claims) {
+        return JWT.create()
+                .withClaim("claims", claims)
+                .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))
+                .sign(Algorithm.HMAC256(KEY));
+    }
+
+	//接收token,验证token,并返回业务数据
+    public static Map<String, Object> parseToken(String token) {
+        return JWT.require(Algorithm.HMAC256(KEY))
+                .build()
+                .verify(token)
+                .getClaim("claims")
+                .asMap();
+    }
+
+}

+ 73 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/utils/Md5Util.java

@@ -0,0 +1,73 @@
+package com.my.bigevent.utils;
+
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class Md5Util {
+    /**
+     * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合
+     */
+    protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+    protected static MessageDigest messagedigest = null;
+
+    static {
+        try {
+            messagedigest = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException nsaex) {
+            System.err.println(Md5Util.class.getName() + "初始化失败,MessageDigest不支持MD5Util。");
+            nsaex.printStackTrace();
+        }
+    }
+
+    /**
+     * 生成字符串的md5校验值
+     *
+     * @param s
+     * @return
+     */
+    public static String getMD5String(String s) {
+        return getMD5String(s.getBytes());
+    }
+
+    /**
+     * 判断字符串的md5校验码是否与一个已知的md5码相匹配
+     *
+     * @param password  要校验的字符串
+     * @param md5PwdStr 已知的md5校验码
+     * @return
+     */
+    public static boolean checkPassword(String password, String md5PwdStr) {
+        String s = getMD5String(password);
+        return s.equals(md5PwdStr);
+    }
+
+
+    public static String getMD5String(byte[] bytes) {
+        messagedigest.update(bytes);
+        return bufferToHex(messagedigest.digest());
+    }
+
+    private static String bufferToHex(byte bytes[]) {
+        return bufferToHex(bytes, 0, bytes.length);
+    }
+
+    private static String bufferToHex(byte bytes[], int m, int n) {
+        StringBuffer stringbuffer = new StringBuffer(2 * n);
+        int k = m + n;
+        for (int l = m; l < k; l++) {
+            appendHexPair(bytes[l], stringbuffer);
+        }
+        return stringbuffer.toString();
+    }
+
+    private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
+        char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>>
+        // 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
+        char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
+        stringbuffer.append(c0);
+        stringbuffer.append(c1);
+    }
+
+}

+ 25 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/utils/ThreadLocalUtil.java

@@ -0,0 +1,25 @@
+package com.my.bigevent.utils;
+
+/**
+ * ThreadLocal 工具类
+ */
+@SuppressWarnings("all")
+public class ThreadLocalUtil {
+    //提供ThreadLocal对象
+    private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();
+
+    //根据键获取值
+    public static <T> T get(){
+        return (T) THREAD_LOCAL.get();
+    }
+	
+    //存储键值对
+    public static void set(Object value){
+        THREAD_LOCAL.set(value);
+    }
+
+    //清除ThreadLocal 防止内存泄漏
+    public static void remove(){
+        THREAD_LOCAL.remove();
+    }
+}

+ 30 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/java/com/my/bigevent/validation/StateValidation.java

@@ -0,0 +1,30 @@
+package com.my.bigevent.validation;
+
+import com.my.bigevent.anno.State;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+// 定义 State 注解具体的逻辑与功能
+public class StateValidation implements ConstraintValidator<State,String>
+{
+    // 重写方法,提供校验规则
+    // String s 是将来要校验的数据
+    @Override
+    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext)
+    {
+        // 提供校验规则
+        if(s==null)
+        {
+            // 返回 false 表示校验不通过
+            return false;
+        }
+        if(s.equals("yes")||s.equals("no"))
+        {
+            // 返回 true,表示校验通过
+            return true;
+        }
+        return false;
+
+    }
+}

+ 20 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/resources/application.yml

@@ -0,0 +1,20 @@
+# 数据源配置
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://47.101.180.183:17089/big_event?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
+    username: root
+    password: P011430@Huoshi*
+  servlet:
+    multipart:
+      max-file-size: 10MB
+      max-request-size: 20MB
+
+
+# 开启数据库字段下划线与驼峰命名转换
+mybatis:
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+server:
+  port: 8091

+ 21 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/main/resources/com/my/bigevent/mapper/ArticleMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!--这里是 ArticleMapper.java 接口文件的地址-->
+<mapper namespace="com.my.bigevent.mapper.ArticleMapper">
+    <!--动态 sql 写法,真实项目中常用-->
+    <select id="list" resultType="com.my.bigevent.pojo.Article">
+        select * from article
+        <where>
+            <if test="categoryId!=null">
+                category_id=#{categoryId}
+            </if>
+
+            <if test="state!=null">
+                and state=#{state}
+            </if>
+        and create_user=#{userId}
+        </where>
+    </select>
+</mapper>

+ 15 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/test/java/com/my/bigevent/BigEventApplicationTests.java

@@ -0,0 +1,15 @@
+package com.my.bigevent;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class BigEventApplicationTests
+{
+
+    @Test
+    void contextLoads()
+    {
+    }
+
+}

+ 56 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/test/java/com/my/bigevent/JwtTest.java

@@ -0,0 +1,56 @@
+package com.my.bigevent;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import org.junit.jupiter.api.Test;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class JwtTest
+{
+    /**
+     * 生成 jwt token
+     */
+    @Test
+    public void testGen()
+    {
+        //准备信息
+        Map<String, Object> claims=new HashMap<>();
+        claims.put("id",1);
+        claims.put("username","张三");
+
+        //生成 jwt
+        String token= JWT.create()
+                .withClaim("user",claims)
+                .withExpiresAt(new Date(System.currentTimeMillis()+1000*60*60*12))   // 12小时后过期
+                .sign(Algorithm.HMAC256("BigEvent"));  // 指定算法,配置密钥
+
+        // 打印密文
+        System.out.println(token);
+    }
+
+    /**
+     * 测试解析 jwt token
+     */
+    /*
+    @Test
+    public void testParse()
+    {
+        // 模拟前端传送到后端的jwt token
+        String token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +
+                ".eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6IuW8oOS4iSJ9LCJleHAiOjE3MDQyMDM2OTN9.pJbEHpE7FwN_-rI-eY3TXpHRX-lootw8R7IeJVKBFyc";
+
+        // 根据后端生成 token 的算法与密钥,制作一个校验器
+        JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256("BigEvent")).build();
+
+        // 验证 token ,生成一个解析后的 jwt 对象。
+        DecodedJWT decodedJWT=jwtVerifier.verify(token);
+        // 获取解析后的 jwt 对象中的信息
+        Map<String, Claim> claims=decodedJWT.getClaims();
+        System.out.println(claims.get("user"));
+    }
+    */
+
+}

+ 29 - 0
fhKeeper/formulahousekeeper/ArticleOperation/src/test/java/com/my/bigevent/ThreadLocalTest.java

@@ -0,0 +1,29 @@
+package com.my.bigevent;
+
+import org.junit.jupiter.api.Test;
+
+public class ThreadLocalTest
+{
+    @Test
+    public void testThreadLocalSetAndGet()
+    {
+        // 提供一个 ThreadLocal 对象
+        ThreadLocal tl=new ThreadLocal();
+
+        // 开启两个线程,lambda写法
+        new Thread(()->{
+            tl.set("消炎");
+            System.out.println(Thread.currentThread().getName()+":"+tl.get());
+            System.out.println(Thread.currentThread().getName()+":"+tl.get());
+            System.out.println(Thread.currentThread().getName()+":"+tl.get());
+        },"蓝色").start();
+
+        new Thread(()->{
+            tl.set("药老");
+            System.out.println(Thread.currentThread().getName()+":"+tl.get());
+            System.out.println(Thread.currentThread().getName()+":"+tl.get());
+            System.out.println(Thread.currentThread().getName()+":"+tl.get());
+        },"红色").start();
+
+    }
+}