├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── oym │ │ └── cms │ │ ├── CmsApplication.java │ │ ├── client │ │ ├── ContractClient.java │ │ └── FastDFSClient.java │ │ ├── config │ │ ├── fisco │ │ │ └── FiscoBcos.java │ │ ├── mapper │ │ │ ├── DataSourceConfiguration.java │ │ │ └── SessionFactoryConfiguration.java │ │ ├── redis │ │ │ ├── JedisPoolFactory.java │ │ │ ├── JedisUtil.java │ │ │ └── RedisConfiguration.java │ │ ├── service │ │ │ └── TransactionManagementConfiguration.java │ │ ├── shiro │ │ │ ├── MySessionManager.java │ │ │ ├── MyShiroRealm.java │ │ │ └── ShiroConfig.java │ │ └── web │ │ │ └── MvcConfiguration.java │ │ ├── contract │ │ └── CertificateIQ.java │ │ ├── controller │ │ ├── CertificateController.java │ │ └── UserController.java │ │ ├── dto │ │ ├── CertificateDTO.java │ │ ├── ImageHolder.java │ │ └── UserDTO.java │ │ ├── entity │ │ ├── Certificate.java │ │ └── User.java │ │ ├── enums │ │ ├── CertificateTypeEnum.java │ │ ├── DTOMsgEnum.java │ │ ├── UserIdStatusEnum.java │ │ └── UserPositionEnum.java │ │ ├── exceptions │ │ ├── CertificateException.java │ │ └── UserException.java │ │ ├── mapper │ │ ├── JurisdictionMapper.java │ │ └── UserMapper.java │ │ ├── service │ │ ├── CacheService.java │ │ ├── CertificateService.java │ │ ├── UserService.java │ │ └── impl │ │ │ ├── CacheServiceImpl.java │ │ │ ├── CertificateServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── util │ │ ├── CertificateIdBuildUtil.java │ │ ├── DESUtil.java │ │ ├── EncryptionUtil.java │ │ ├── HttpServletRequestUtil.java │ │ ├── ImageUtil.java │ │ ├── PageCalculator.java │ │ └── PasswordHelper.java └── resources │ ├── FastDFSConfig.properties │ ├── application.yml │ ├── conf │ ├── ca.crt │ ├── sdk.crt │ ├── sdk.key │ └── sdk.publickey │ ├── contract │ ├── CertificateIQ.sol │ └── Table.sol │ ├── mapper │ ├── JurisdicitonMapper.xml │ └── UserMapper.xml │ ├── mybatis-config.xml │ └── slf4j.xml └── test └── java └── com └── oym └── cms ├── CmsApplicationTests.java ├── contract └── ContractTest.java ├── mapper ├── JurisdictionMapperTest.java └── UserMapperTest.java └── service ├── CertificateServiceImpl.java └── UserServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dylan666666/Certificate-Management-System/a633b8fc9e5ea006b7a086d4bca96be87abbc14d/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /usr/local/etc/mavenrc ] ; then 40 | . /usr/local/etc/mavenrc 41 | fi 42 | 43 | if [ -f /etc/mavenrc ] ; then 44 | . /etc/mavenrc 45 | fi 46 | 47 | if [ -f "$HOME/.mavenrc" ] ; then 48 | . "$HOME/.mavenrc" 49 | fi 50 | 51 | fi 52 | 53 | # OS specific support. $var _must_ be set to either true or false. 54 | cygwin=false; 55 | darwin=false; 56 | mingw=false 57 | case "`uname`" in 58 | CYGWIN*) cygwin=true ;; 59 | MINGW*) mingw=true;; 60 | Darwin*) darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | export JAVA_HOME="`/usr/libexec/java_home`" 66 | else 67 | export JAVA_HOME="/Library/Java/Home" 68 | fi 69 | fi 70 | ;; 71 | esac 72 | 73 | if [ -z "$JAVA_HOME" ] ; then 74 | if [ -r /etc/gentoo-release ] ; then 75 | JAVA_HOME=`java-config --jre-home` 76 | fi 77 | fi 78 | 79 | if [ -z "$M2_HOME" ] ; then 80 | ## resolve links - $0 may be a link to maven's home 81 | PRG="$0" 82 | 83 | # need this for relative symlinks 84 | while [ -h "$PRG" ] ; do 85 | ls=`ls -ld "$PRG"` 86 | link=`expr "$ls" : '.*-> \(.*\)$'` 87 | if expr "$link" : '/.*' > /dev/null; then 88 | PRG="$link" 89 | else 90 | PRG="`dirname "$PRG"`/$link" 91 | fi 92 | done 93 | 94 | saveddir=`pwd` 95 | 96 | M2_HOME=`dirname "$PRG"`/.. 97 | 98 | # make it fully qualified 99 | M2_HOME=`cd "$M2_HOME" && pwd` 100 | 101 | cd "$saveddir" 102 | # echo Using m2 at $M2_HOME 103 | fi 104 | 105 | # For Cygwin, ensure paths are in UNIX format before anything is touched 106 | if $cygwin ; then 107 | [ -n "$M2_HOME" ] && 108 | M2_HOME=`cygpath --unix "$M2_HOME"` 109 | [ -n "$JAVA_HOME" ] && 110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 111 | [ -n "$CLASSPATH" ] && 112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 113 | fi 114 | 115 | # For Mingw, ensure paths are in UNIX format before anything is touched 116 | if $mingw ; then 117 | [ -n "$M2_HOME" ] && 118 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 119 | [ -n "$JAVA_HOME" ] && 120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 121 | fi 122 | 123 | if [ -z "$JAVA_HOME" ]; then 124 | javaExecutable="`which javac`" 125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 126 | # readlink(1) is not available as standard on Solaris 10. 127 | readLink=`which readlink` 128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 129 | if $darwin ; then 130 | javaHome="`dirname \"$javaExecutable\"`" 131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 132 | else 133 | javaExecutable="`readlink -f \"$javaExecutable\"`" 134 | fi 135 | javaHome="`dirname \"$javaExecutable\"`" 136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 137 | JAVA_HOME="$javaHome" 138 | export JAVA_HOME 139 | fi 140 | fi 141 | fi 142 | 143 | if [ -z "$JAVACMD" ] ; then 144 | if [ -n "$JAVA_HOME" ] ; then 145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 146 | # IBM's JDK on AIX uses strange locations for the executables 147 | JAVACMD="$JAVA_HOME/jre/sh/java" 148 | else 149 | JAVACMD="$JAVA_HOME/bin/java" 150 | fi 151 | else 152 | JAVACMD="`\\unset -f command; \\command -v java`" 153 | fi 154 | fi 155 | 156 | if [ ! -x "$JAVACMD" ] ; then 157 | echo "Error: JAVA_HOME is not defined correctly." >&2 158 | echo " We cannot execute $JAVACMD" >&2 159 | exit 1 160 | fi 161 | 162 | if [ -z "$JAVA_HOME" ] ; then 163 | echo "Warning: JAVA_HOME environment variable is not set." 164 | fi 165 | 166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 167 | 168 | # traverses directory structure from process work directory to filesystem root 169 | # first directory with .mvn subdirectory is considered project base directory 170 | find_maven_basedir() { 171 | 172 | if [ -z "$1" ] 173 | then 174 | echo "Path not specified to find_maven_basedir" 175 | return 1 176 | fi 177 | 178 | basedir="$1" 179 | wdir="$1" 180 | while [ "$wdir" != '/' ] ; do 181 | if [ -d "$wdir"/.mvn ] ; then 182 | basedir=$wdir 183 | break 184 | fi 185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 186 | if [ -d "${wdir}" ]; then 187 | wdir=`cd "$wdir/.."; pwd` 188 | fi 189 | # end of workaround 190 | done 191 | echo "${basedir}" 192 | } 193 | 194 | # concatenates all lines of a file 195 | concat_lines() { 196 | if [ -f "$1" ]; then 197 | echo "$(tr -s '\n' ' ' < "$1")" 198 | fi 199 | } 200 | 201 | BASE_DIR=`find_maven_basedir "$(pwd)"` 202 | if [ -z "$BASE_DIR" ]; then 203 | exit 1; 204 | fi 205 | 206 | ########################################################################################## 207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 208 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 209 | ########################################################################################## 210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Found .mvn/wrapper/maven-wrapper.jar" 213 | fi 214 | else 215 | if [ "$MVNW_VERBOSE" = true ]; then 216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 217 | fi 218 | if [ -n "$MVNW_REPOURL" ]; then 219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 220 | else 221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 222 | fi 223 | while IFS="=" read key value; do 224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 225 | esac 226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 227 | if [ "$MVNW_VERBOSE" = true ]; then 228 | echo "Downloading from: $jarUrl" 229 | fi 230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 231 | if $cygwin; then 232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 233 | fi 234 | 235 | if command -v wget > /dev/null; then 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Found wget ... using wget" 238 | fi 239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | else 242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 243 | fi 244 | elif command -v curl > /dev/null; then 245 | if [ "$MVNW_VERBOSE" = true ]; then 246 | echo "Found curl ... using curl" 247 | fi 248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 249 | curl -o "$wrapperJarPath" "$jarUrl" -f 250 | else 251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 252 | fi 253 | 254 | else 255 | if [ "$MVNW_VERBOSE" = true ]; then 256 | echo "Falling back to using Java to download" 257 | fi 258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 259 | # For Cygwin, switch paths to Windows format before running javac 260 | if $cygwin; then 261 | javaClass=`cygpath --path --windows "$javaClass"` 262 | fi 263 | if [ -e "$javaClass" ]; then 264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 265 | if [ "$MVNW_VERBOSE" = true ]; then 266 | echo " - Compiling MavenWrapperDownloader.java ..." 267 | fi 268 | # Compiling the Java class 269 | ("$JAVA_HOME/bin/javac" "$javaClass") 270 | fi 271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 272 | # Running the downloader 273 | if [ "$MVNW_VERBOSE" = true ]; then 274 | echo " - Running MavenWrapperDownloader.java ..." 275 | fi 276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 277 | fi 278 | fi 279 | fi 280 | fi 281 | ########################################################################################## 282 | # End of extension 283 | ########################################################################################## 284 | 285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 286 | if [ "$MVNW_VERBOSE" = true ]; then 287 | echo $MAVEN_PROJECTBASEDIR 288 | fi 289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 290 | 291 | # For Cygwin, switch paths to Windows format before running java 292 | if $cygwin; then 293 | [ -n "$M2_HOME" ] && 294 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 295 | [ -n "$JAVA_HOME" ] && 296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 297 | [ -n "$CLASSPATH" ] && 298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 299 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 301 | fi 302 | 303 | # Provide a "standardized" way to retrieve the CLI args that will 304 | # work with both Windows and non-Windows executions. 305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 306 | export MAVEN_CMD_LINE_ARGS 307 | 308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 309 | 310 | exec "$JAVACMD" \ 311 | $MAVEN_OPTS \ 312 | $MAVEN_DEBUG_OPTS \ 313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 314 | "-Dmaven.home=${M2_HOME}" \ 315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 317 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 124 | 125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% ^ 162 | %JVM_CONFIG_MAVEN_PROPS% ^ 163 | %MAVEN_OPTS% ^ 164 | %MAVEN_DEBUG_OPTS% ^ 165 | -classpath %WRAPPER_JAR% ^ 166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 168 | if ERRORLEVEL 1 goto error 169 | goto end 170 | 171 | :error 172 | set ERROR_CODE=1 173 | 174 | :end 175 | @endlocal & set ERROR_CODE=%ERROR_CODE% 176 | 177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 181 | :skipRcPost 182 | 183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 185 | 186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 187 | 188 | cmd /C exit /B %ERROR_CODE% 189 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.1.RELEASE 9 | 10 | 11 | com.oym 12 | cms 13 | 0.0.1-SNAPSHOT 14 | cms 15 | jar 16 | 17 | 18 | 11 19 | 4.1 20 | 1.8.0 21 | 3.3.1 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-jdbc 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | org.mybatis.spring.boot 35 | mybatis-spring-boot-starter 36 | 2.1.3 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-configuration-processor 41 | true 42 | 43 | 44 | 45 | mysql 46 | mysql-connector-java 47 | runtime 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-test 53 | test 54 | 55 | 56 | org.junit.vintage 57 | junit-vintage-engine 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.fisco-bcos.java-sdk 65 | fisco-bcos-java-sdk 66 | 2.8.0 67 | 68 | 69 | org.springframework 70 | spring 71 | 72 | 73 | org.slf4j 74 | slf4j-log4j12 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.projectlombok 82 | lombok 83 | true 84 | 85 | 86 | 87 | 88 | javax.servlet 89 | javax.servlet-api 90 | 4.0.1 91 | 92 | 93 | 94 | 95 | com.fasterxml.jackson.core 96 | jackson-databind 97 | 2.11.0 98 | 99 | 100 | com.alibaba 101 | fastjson 102 | 1.2.70 103 | 104 | 105 | 106 | 107 | mysql 108 | mysql-connector-java 109 | 8.0.19 110 | 111 | 112 | com.mchange 113 | c3p0 114 | 0.9.5.2 115 | 116 | 117 | 118 | 119 | redis.clients 120 | jedis 121 | 2.9.0 122 | 123 | 124 | 125 | 126 | junit 127 | junit 128 | test 129 | 130 | 131 | 132 | 133 | commons-fileupload 134 | commons-fileupload 135 | 1.4 136 | 137 | 138 | org.apache.directory.studio 139 | org.apache.commons.codec 140 | 1.8 141 | 142 | 143 | 144 | 145 | net.coobird 146 | thumbnailator 147 | 0.4.10 148 | 149 | 150 | 151 | 152 | commons-collections 153 | commons-collections 154 | 3.2.2 155 | 156 | 157 | 158 | 159 | org.apache.commons 160 | commons-lang3 161 | 3.4 162 | 163 | 164 | 165 | 166 | org.apache.commons 167 | commons-collections4 168 | ${commons-collections4.version} 169 | 170 | 171 | 172 | 173 | org.apache.shiro 174 | shiro-spring 175 | ${shiro-spring.version} 176 | 177 | 178 | org.crazycake 179 | shiro-redis 180 | ${shiro-redis.version} 181 | 182 | 183 | 184 | 185 | javax.validation 186 | validation-api 187 | 2.0.1.Final 188 | 189 | 190 | 191 | 192 | com.google.guava 193 | guava 194 | 31.0.1-jre 195 | 196 | 197 | 198 | 199 | cn.bestwu 200 | fastdfs-client-java 201 | 1.27 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | org.springframework.boot 210 | spring-boot-maven-plugin 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/CmsApplication.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @Author: Mr_OO 8 | * @Date: 2022/2/23 16:17 9 | */ 10 | @SpringBootApplication 11 | public class CmsApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(CmsApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/client/ContractClient.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.client; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.oym.cms.config.fisco.FiscoBcos; 5 | import com.oym.cms.contract.CertificateIQ; 6 | import com.oym.cms.entity.Certificate; 7 | import com.oym.cms.enums.DTOMsgEnum; 8 | import lombok.RequiredArgsConstructor; 9 | import lombok.extern.slf4j.Slf4j; 10 | import lombok.val; 11 | import org.fisco.bcos.sdk.BcosSDK; 12 | import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1; 13 | import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple6; 14 | import org.fisco.bcos.sdk.model.TransactionReceipt; 15 | import org.fisco.bcos.sdk.transaction.model.exception.ContractException; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.stereotype.Service; 19 | 20 | import javax.annotation.PostConstruct; 21 | import javax.annotation.Resource; 22 | import java.math.BigInteger; 23 | import java.util.ArrayList; 24 | import java.util.Date; 25 | import java.util.List; 26 | import java.util.Objects; 27 | 28 | /** 29 | * 合约接口调用类 30 | * @Author: Mr_OO 31 | * @Date: 2022/4/6 12:03 32 | */ 33 | @Service 34 | @RequiredArgsConstructor 35 | @Slf4j 36 | public class ContractClient { 37 | 38 | private CertificateIQ certificateIQ; 39 | 40 | @Resource 41 | private FiscoBcos fiscoBcos; 42 | 43 | private static final Logger LOGGER = LoggerFactory.getLogger(ContractClient.class); 44 | 45 | private final static BigInteger SUCCESS_RET = new BigInteger("0"); 46 | 47 | @PostConstruct 48 | public void initClient() { 49 | fiscoBcos.init(); 50 | BcosSDK bcosSDK = fiscoBcos.getBcosSDK(); 51 | val cryptoSuite = bcosSDK.getClient(1).getCryptoSuite(); 52 | val cryptoKeyPair = cryptoSuite.getCryptoKeyPair(); 53 | try { 54 | certificateIQ = CertificateIQ.deploy(bcosSDK.getClient(1), cryptoKeyPair); 55 | certificateIQ.create(); 56 | } catch (ContractException e) { 57 | LOGGER.error("ContractClient deploy fail"); 58 | e.printStackTrace(); 59 | } 60 | } 61 | 62 | /** 63 | * 证书注册到区块链上 64 | * @param schoolFlag 65 | * @param stuNumber 66 | * @param userName 67 | * @param cmsName 68 | * @param cmsType 69 | * @param cmsWinTime 70 | * @param cmsDesc 71 | * @param cmsUrl 72 | * @return 73 | */ 74 | public int registerCertificate(String schoolFlag, String stuNumber, String userName, String cmsName, 75 | String cmsType, String cmsWinTime, String cmsDesc, String cmsUrl) { 76 | try { 77 | TransactionReceipt receipt = certificateIQ.register(schoolFlag, stuNumber, userName, cmsName, cmsType, 78 | cmsWinTime, cmsDesc, cmsUrl); 79 | Tuple1 registerOutput = certificateIQ.getRegisterOutput(receipt); 80 | if (registerOutput != null && Objects.equals(registerOutput.getValue1(), SUCCESS_RET)) { 81 | LOGGER.info("ContractClient registerCertificate success cmsUrl:{}", cmsUrl); 82 | return DTOMsgEnum.OK.getStatus(); 83 | } 84 | } catch (Exception e) { 85 | LOGGER.info("ContractClient registerCertificate exception cmsUrl:{}, e:{}", cmsUrl, JSON.toJSONString(e)); 86 | } 87 | return DTOMsgEnum.ERROR_EXCEPTION.getStatus(); 88 | } 89 | 90 | /** 91 | * 通过学号查询证书集合 92 | * @param userId 93 | * @return 94 | */ 95 | public List queryCertificateList(String userId) { 96 | try { 97 | Tuple6, List, List, List, List> result = certificateIQ.select(userId); 98 | //判断是否集合为空 99 | if (!Objects.equals(result.getValue1(), SUCCESS_RET)) { 100 | //开始封装 101 | List list1 = result.getValue2(); 102 | List list2 = result.getValue3(); 103 | List list3 = result.getValue4(); 104 | List list4 = result.getValue5(); 105 | List list5 = result.getValue6(); 106 | List certificateList = new ArrayList<>(list1.size()); 107 | for (int i = 0; i < list1.size(); i++) { 108 | Certificate certificate = new Certificate(); 109 | certificate.setUserId(userId); 110 | certificate.setCertificateName(list1.get(i)); 111 | certificate.setCertificateType(Integer.valueOf(list2.get(i))); 112 | certificate.setCertificateWinTime(new Date(Long.parseLong(list3.get(i)))); 113 | certificate.setCertificateDescription(list4.get(i)); 114 | certificate.setCertificateUrl(list5.get(i)); 115 | certificateList.add(certificate); 116 | } 117 | LOGGER.info("ContractClient registerCertificate success userId:{}", userId); 118 | return certificateList; 119 | } 120 | } catch (Exception e) { 121 | LOGGER.info("ContractClient queryCertificateList exception userId:{}", userId); 122 | } 123 | return new ArrayList<>(); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/client/FastDFSClient.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.client; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.csource.common.NameValuePair; 5 | import org.csource.fastdfs.*; 6 | import java.io.*; 7 | 8 | /** 9 | * 分布式证书存储客户端类 10 | * @Author: Mr_OO 11 | * @Date: 2022/4/2 15:04 12 | */ 13 | public class FastDFSClient { 14 | 15 | private static StorageClient storageClient = null; 16 | 17 | /** 18 | * 只加载一次. 19 | */ 20 | static { 21 | try { 22 | ClientGlobal.init("FastDFSConfig.properties"); 23 | TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group); 24 | TrackerServer trackerServer = trackerClient.getConnection(); 25 | StorageServer storageServer = trackerClient.getStoreStorage(trackerServer); 26 | storageClient = new StorageClient(trackerServer, storageServer); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | /** 33 | * @param inputStream 34 | * 上传的文件输入流 35 | * @param fileName 36 | * 上传的文件原始名 37 | * @return 38 | */ 39 | public static String[] uploadFile(InputStream inputStream, String fileName) { 40 | try { 41 | // 文件的元数据 42 | NameValuePair[] meta_list = new NameValuePair[2]; 43 | // 第一组元数据,文件的原始名称 44 | meta_list[0] = new NameValuePair("file name", fileName); 45 | // 第二组元数据 46 | meta_list[1] = new NameValuePair("file length", inputStream.available()+""); 47 | // 准备字节数组 48 | byte[] file_buff = null; 49 | if (inputStream != null) { 50 | // 查看文件的长度 51 | int len = inputStream.available(); 52 | // 创建对应长度的字节数组 53 | file_buff = new byte[len]; 54 | // 将输入流中的字节内容,读到字节数组中。 55 | inputStream.read(file_buff); 56 | } 57 | // 上传文件。参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据 58 | String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list); 59 | return fileids; 60 | } catch (Exception ex) { 61 | ex.printStackTrace(); 62 | } 63 | return null; 64 | } 65 | 66 | /** 67 | * @param file 68 | * 文件 69 | * @param fileName 70 | * 文件名 71 | * @return 返回Null则为失败 72 | */ 73 | public static String[] uploadFile(File file, String fileName) { 74 | FileInputStream fis = null; 75 | try { 76 | NameValuePair[] metaList = null; 77 | fis = new FileInputStream(file); 78 | byte[] fileBuff = null; 79 | if (fis != null) { 80 | int len = fis.available(); 81 | fileBuff = new byte[len]; 82 | fis.read(fileBuff); 83 | } 84 | String[] fileids = storageClient.upload_file(fileBuff, getFileExt(fileName), metaList); 85 | return fileids; 86 | } catch (Exception ex) { 87 | return null; 88 | } finally { 89 | if (fis != null) { 90 | try { 91 | fis.close(); 92 | } catch (IOException e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | } 97 | } 98 | 99 | /** 100 | * 根据组名和远程文件名来删除一个文件 101 | * 102 | * @param groupName 103 | * 例如 "group1" 如果不指定该值,默认为group1 104 | * @param remoteFileName 105 | * 例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg" 106 | * @return 0为成功,非0为失败,具体为错误代码 107 | */ 108 | private static int deleteFile(String groupName, String remoteFileName) { 109 | try { 110 | int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName); 111 | return result; 112 | } catch (Exception ex) { 113 | return 0; 114 | } 115 | } 116 | 117 | /** 118 | * 修改一个已经存在的文件 119 | * 120 | * @param oldGroupName 121 | * 旧的组名 122 | * @param oldFileName 123 | * 旧的文件名 124 | * @param file 125 | * 新文件 126 | * @param fileName 127 | * 新文件名 128 | * @return 返回空则为失败 129 | */ 130 | private static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) { 131 | String[] fileids = null; 132 | try { 133 | // 先上传 134 | fileids = uploadFile(file, fileName); 135 | if (fileids == null) { 136 | return null; 137 | } 138 | // 再删除 139 | int delResult = deleteFile(oldGroupName, oldFileName); 140 | if (delResult != 0) { 141 | return null; 142 | } 143 | } catch (Exception ex) { 144 | return null; 145 | } 146 | return fileids; 147 | } 148 | 149 | /** 150 | * 文件下载 151 | * 152 | * @param groupName 卷名 153 | * @param remoteFileName 文件名 154 | * @return 返回一个流 155 | */ 156 | public static InputStream downloadFile(String groupName, String remoteFileName) { 157 | try { 158 | byte[] bytes = storageClient.download_file(groupName, remoteFileName); 159 | InputStream inputStream = new ByteArrayInputStream(bytes); 160 | return inputStream; 161 | } catch (Exception ex) { 162 | return null; 163 | } 164 | } 165 | 166 | public static NameValuePair[] getMetaDate(String groupName, String remoteFileName){ 167 | try { 168 | NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName); 169 | return nvp; 170 | } catch (Exception ex) { 171 | ex.printStackTrace(); 172 | return null; 173 | } 174 | } 175 | 176 | /** 177 | * 获取文件后缀名(不带点). 178 | * 179 | * @return 如:"jpg" or "png". 180 | */ 181 | private static String getFileExt(String fileName) { 182 | if (StringUtils.isBlank(fileName) || !fileName.contains(".")) { 183 | return ""; 184 | } else { 185 | return fileName.substring(fileName.lastIndexOf(".") + 1); 186 | } 187 | } 188 | 189 | public static void main(String[] args) { 190 | try { 191 | // File file = new File("C:/Users/14396/Desktop/my/图片/绿叶.png"); 192 | // InputStream inputStream = new FileInputStream(file); 193 | // String fileName = "110429" + ImageUtil.getRandomFileName() + ".png" 194 | // String[] result = FastDFSClient.uploadFile(inputStream, fileName); 195 | // //[group1, M00/00/00/CgAYCGJFpQKACftIAAAbnjkyo8A652.png] 196 | // System.out.println(ImageUtil.IMAGE_URL_PRE + ImageUtil.getImageUrl(result)); 197 | // //http://101.43.139.237:8081/group1/M00/00/00/CgAYCGJFsVmAWtitAAAbnjkyo8A098.png 198 | } catch (Exception e) { 199 | e.printStackTrace(); 200 | } 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/fisco/FiscoBcos.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.fisco; 2 | 3 | import lombok.Data; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.fisco.bcos.sdk.BcosSDK; 6 | import org.fisco.bcos.sdk.config.ConfigOption; 7 | import org.fisco.bcos.sdk.config.exceptions.ConfigException; 8 | import org.fisco.bcos.sdk.config.model.ConfigProperty; 9 | import org.springframework.stereotype.Component; 10 | import org.yaml.snakeyaml.Yaml; 11 | import org.yaml.snakeyaml.representer.Representer; 12 | 13 | import java.io.InputStream; 14 | 15 | /** 16 | * @author 14396 17 | */ 18 | @Data 19 | @Component 20 | @Slf4j 21 | public class FiscoBcos { 22 | 23 | BcosSDK bcosSDK; 24 | 25 | public void init() { 26 | ConfigProperty configProperty = loadProperty(); 27 | ConfigOption configOption ; 28 | try { 29 | configOption = new ConfigOption(configProperty); 30 | } catch (ConfigException e) { 31 | log.error("init error:" + e.toString()); 32 | return ; 33 | } 34 | bcosSDK = new BcosSDK(configOption); 35 | } 36 | 37 | public ConfigProperty loadProperty() { 38 | Representer representer = new Representer(); 39 | representer.getPropertyUtils().setSkipMissingProperties(true); 40 | Yaml yaml = new Yaml(representer); 41 | String configFile = "/application.yml"; 42 | try (InputStream inputStream = this.getClass().getResourceAsStream(configFile)) { 43 | return yaml.loadAs(inputStream, ConfigProperty.class); 44 | } catch (Exception e) { 45 | log.error("load property: ", e); 46 | } 47 | return null; 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/mapper/DataSourceConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.mapper; 2 | 3 | import com.mchange.v2.c3p0.ComboPooledDataSource; 4 | import com.oym.cms.util.DESUtil; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | import java.beans.PropertyVetoException; 11 | 12 | /** 13 | * @Author: Mr_OO 14 | * @Date: 2022/3/1 13:25 15 | */ 16 | @Configuration 17 | @MapperScan("com.oym.cms.mapper") 18 | public class DataSourceConfiguration { 19 | @Value("${jdbc.driver}") 20 | private String jdbcDriver; 21 | @Value("${jdbc.url}") 22 | private String jdbcUrl; 23 | @Value("${jdbc.username}") 24 | private String jdbcUsername; 25 | @Value("${jdbc.password}") 26 | private String jdbcPassword; 27 | 28 | /** 29 | * 生成与spring-dao.xml对应的bean dataSource 30 | * @return 31 | * @throws PropertyVetoException 32 | */ 33 | @Bean(name = "dataSource") 34 | public ComboPooledDataSource createDataSource() throws PropertyVetoException { 35 | // 生成datasource实例 36 | ComboPooledDataSource dataSource = new ComboPooledDataSource(); 37 | // 跟配置文件一样设置以下信息 38 | // 驱动 39 | dataSource.setDriverClass(jdbcDriver); 40 | // 数据库连接URL 41 | dataSource.setJdbcUrl(jdbcUrl); 42 | // 设置用户名 43 | dataSource.setUser(DESUtil.getDecryptString(jdbcUsername)); 44 | // 设置用户密码 45 | dataSource.setPassword(DESUtil.getDecryptString(jdbcPassword)); 46 | // 配置c3p0连接池的私有属性 47 | // 连接池最大线程数 48 | dataSource.setMaxPoolSize(30); 49 | // 连接池最小线程数 50 | dataSource.setMinPoolSize(10); 51 | dataSource.setInitialPoolSize(10); 52 | // 关闭连接后不自动commit 53 | dataSource.setAutoCommitOnClose(false); 54 | // 连接超时时间 55 | dataSource.setCheckoutTimeout(10000); 56 | // 连接失败重试次数 57 | dataSource.setAcquireRetryAttempts(2); 58 | return dataSource; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/mapper/SessionFactoryConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.mapper; 2 | 3 | import org.mybatis.spring.SqlSessionFactoryBean; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.io.ClassPathResource; 8 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 9 | import org.springframework.core.io.support.ResourcePatternResolver; 10 | 11 | import javax.annotation.Resource; 12 | import javax.sql.DataSource; 13 | import java.io.IOException; 14 | 15 | /** 16 | * @Author: Mr_OO 17 | * @Date: 2022/3/1 13:34 18 | */ 19 | @Configuration 20 | public class SessionFactoryConfiguration { 21 | 22 | /** 23 | * mybatis-config.xml配置文件的路径 24 | */ 25 | private static String mybatisConfigFile; 26 | 27 | @Value("${mybatis_config_file}") 28 | public void setMybatisConfigFile(String mybatisConfigFile) { 29 | SessionFactoryConfiguration.mybatisConfigFile = mybatisConfigFile; 30 | } 31 | 32 | /** 33 | * mybatis mapper文件所在路径 34 | */ 35 | private static String mapperPath; 36 | 37 | @Value("${mybatis.mapper-locations}") 38 | public void setMapperPath(String mapperPath) { 39 | SessionFactoryConfiguration.mapperPath = mapperPath; 40 | } 41 | 42 | 43 | /** 44 | * 实体类所在的package 45 | */ 46 | @Value("${type_alias_package}") 47 | private String typeAliasPackage; 48 | 49 | @Resource 50 | private DataSource dataSource; 51 | 52 | /** 53 | * 创建sqlSessionFactoryBean实例,并且设置configuration,设置mapper映射路径,设置datasource数据源 54 | * @return 55 | * @throws IOException 56 | */ 57 | @Bean(name = "sqlSessionFactory") 58 | public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException { 59 | SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); 60 | // 设置mybatis configuration 扫描路径 61 | sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFile)); 62 | // 添加mapper 扫描路径 63 | PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(); 64 | String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath; 65 | sqlSessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources(packageSearchPath)); 66 | // 设置dataSource 67 | sqlSessionFactoryBean.setDataSource(dataSource); 68 | // 设置typeAlias 包扫描路径 69 | sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasPackage); 70 | return sqlSessionFactoryBean; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/redis/JedisPoolFactory.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.redis; 2 | 3 | import redis.clients.jedis.JedisPool; 4 | import redis.clients.jedis.JedisPoolConfig; 5 | 6 | /** 7 | * 生产jedis连接池 8 | * @Author: Mr_OO 9 | * @Date: 2022/3/3 14:17 10 | */ 11 | public class JedisPoolFactory { 12 | /** Redis连接池对象 */ 13 | private JedisPool jedisPool; 14 | 15 | public JedisPoolFactory(final JedisPoolConfig poolConfig, final String host, final int port) { 16 | try { 17 | jedisPool = new JedisPool(poolConfig, host, port); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | 23 | /** 24 | * 获取Redis连接池对象 25 | * @return 26 | */ 27 | public JedisPool getJedisPool() { 28 | return jedisPool; 29 | } 30 | 31 | /** 32 | * 注入Redis连接池对象 33 | * @param jedisPool 34 | */ 35 | public void setJedisPool(JedisPool jedisPool) { 36 | this.jedisPool = jedisPool; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/redis/JedisUtil.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.redis; 2 | 3 | import redis.clients.jedis.BinaryClient; 4 | import redis.clients.jedis.Jedis; 5 | import redis.clients.jedis.JedisPool; 6 | import redis.clients.jedis.SortingParams; 7 | import redis.clients.util.SafeEncoder; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | /** 14 | * Jedis工具类 15 | * @Author: Mr_OO 16 | * @Date: 2022/3/3 14:17 17 | */ 18 | public class JedisUtil { 19 | /** 20 | * 缓存生存时间 21 | */ 22 | private final int expire = 60000; 23 | /** 操作Key的方法 */ 24 | public Keys KEYS; 25 | /** 对存储结构为String类型的操作 */ 26 | public Strings STRINGS; 27 | /** 对存储结构为List类型的操作 */ 28 | public Lists LISTS; 29 | /** 对存储结构为Set类型的操作 */ 30 | public Sets SETS; 31 | /** 对存储结构为HashMap类型的操作 */ 32 | public Hash HASH; 33 | 34 | /** Redis连接池对象 */ 35 | private JedisPool jedisPool; 36 | 37 | /** 38 | * 获取redis连接池 39 | * 40 | * @return 41 | */ 42 | public JedisPool getJedisPool() { 43 | return jedisPool; 44 | } 45 | 46 | /** 47 | * 设置redis连接池 48 | * 49 | * @return 50 | */ 51 | public void setJedisPool(JedisPoolFactory jedisPoolFactory) { 52 | this.jedisPool = jedisPoolFactory.getJedisPool(); 53 | } 54 | 55 | /** 56 | * 从jedis连接池中获取获取jedis对象 57 | * 58 | * @return 59 | */ 60 | public Jedis getJedis() { 61 | return jedisPool.getResource(); 62 | } 63 | 64 | /** 65 | * 设置过期时间 66 | * @param key 67 | * @param seconds 68 | */ 69 | public void expire(String key, int seconds) { 70 | if (seconds <= 0) { 71 | return; 72 | } 73 | Jedis jedis = getJedis(); 74 | jedis.expire(key, seconds); 75 | jedis.close(); 76 | } 77 | 78 | /** 79 | * 设置默认过期时间 80 | * @param key 81 | */ 82 | public void expire(String key) { 83 | expire(key, expire); 84 | } 85 | 86 | // *******************************************Keys*******************************************// 87 | public class Keys { 88 | 89 | public Keys(JedisUtil jedisUtil) { 90 | } 91 | 92 | public Keys() {} 93 | 94 | /** 95 | * 清空所有key 96 | */ 97 | public String flushAll() { 98 | Jedis jedis = getJedis(); 99 | String state = jedis.flushAll(); 100 | jedis.close(); 101 | return state; 102 | } 103 | 104 | /** 105 | * 更改key 106 | * @param oldKey 107 | * @param newKey 108 | * @return 状态码 109 | */ 110 | public String rename(String oldKey, String newKey) { 111 | return rename(SafeEncoder.encode(oldKey), SafeEncoder.encode(newKey)); 112 | } 113 | 114 | /** 115 | * 更改key,仅当新key不存在时才执行 116 | * @param oldKey 117 | * @param newKey 118 | * @return 状态码 119 | */ 120 | public long renamenx(String oldKey, String newKey) { 121 | Jedis jedis = getJedis(); 122 | long status = jedis.renamenx(oldKey, newKey); 123 | jedis.close(); 124 | return status; 125 | } 126 | 127 | /** 128 | * 更改key 129 | * @param oldkey 130 | * @param newkey 131 | * @return 状态码 132 | */ 133 | public String rename(byte[] oldkey, byte[] newkey) { 134 | Jedis jedis = getJedis(); 135 | String status = jedis.rename(oldkey, newkey); 136 | jedis.close(); 137 | return status; 138 | } 139 | 140 | /** 141 | * 设置key的过期时间,以秒为单位 142 | * @param key 143 | * @param seconds 144 | * 时间 ,已秒为单位 145 | * @return 影响的记录数 146 | */ 147 | public long expired(String key, int seconds) { 148 | Jedis jedis = getJedis(); 149 | long count = jedis.expire(key, seconds); 150 | jedis.close(); 151 | return count; 152 | } 153 | 154 | /** 155 | * 设置key的过期时间,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00,格里高利历)的偏移量。 156 | * @param key 157 | * 158 | * @param timestamp 159 | * 时间 ,已秒为单位 160 | * @return 影响的记录数 161 | */ 162 | public long expireAt(String key, long timestamp) { 163 | Jedis jedis = getJedis(); 164 | long count = jedis.expireAt(key, timestamp); 165 | jedis.close(); 166 | return count; 167 | } 168 | 169 | /** 170 | * 查询key的过期时间 171 | * 172 | * @param key 173 | * @return 以秒为单位的时间表示 174 | */ 175 | public long ttl(String key) { 176 | // ShardedJedis sjedis = getShardedJedis(); 177 | Jedis sjedis = getJedis(); 178 | long len = sjedis.ttl(key); 179 | sjedis.close(); 180 | return len; 181 | } 182 | 183 | /** 184 | * 取消对key过期时间的设置 185 | * 186 | * @param key 187 | * @return 影响的记录数 188 | */ 189 | public long persist(String key) { 190 | Jedis jedis = getJedis(); 191 | long count = jedis.persist(key); 192 | jedis.close(); 193 | return count; 194 | } 195 | 196 | /** 197 | * 删除keys对应的记录,可以是多个key 198 | * @param keys 199 | * @return 删除的记录数 200 | */ 201 | public long del(String... keys) { 202 | Jedis jedis = getJedis(); 203 | long count = jedis.del(keys); 204 | jedis.close(); 205 | return count; 206 | } 207 | 208 | /** 209 | * 删除keys对应的记录,可以是多个key 210 | * @param keys 211 | * @return 删除的记录数 212 | */ 213 | public long del(byte[]... keys) { 214 | Jedis jedis = getJedis(); 215 | long count = jedis.del(keys); 216 | jedis.close(); 217 | return count; 218 | } 219 | 220 | /** 221 | * 判断key是否存在 222 | * 223 | * @param key 224 | * @return boolean 225 | */ 226 | public boolean exists(String key) { 227 | // ShardedJedis sjedis = getShardedJedis(); 228 | Jedis sjedis = getJedis(); 229 | boolean exis = sjedis.exists(key); 230 | sjedis.close(); 231 | return exis; 232 | } 233 | 234 | /** 235 | * 对List,Set,SortSet进行排序,如果集合数据较大应避免使用这个方法 236 | * @param key 237 | * @return List 集合的全部记录 238 | **/ 239 | public List sort(String key) { 240 | // ShardedJedis sjedis = getShardedJedis(); 241 | Jedis sjedis = getJedis(); 242 | List list = sjedis.sort(key); 243 | sjedis.close(); 244 | return list; 245 | } 246 | 247 | /** 248 | * 对List,Set,SortSet进行排序或limit 249 | * @param key 250 | * @param parame 251 | * 定义排序类型或limit的起止位置. 252 | * @return List 全部或部分记录 253 | **/ 254 | public List sort(String key, SortingParams parame) { 255 | // ShardedJedis sjedis = getShardedJedis(); 256 | Jedis sjedis = getJedis(); 257 | List list = sjedis.sort(key, parame); 258 | sjedis.close(); 259 | return list; 260 | } 261 | 262 | /** 263 | * 返回指定key存储的类型 264 | * @param key 265 | * @return String string|list|set|zset|hash 266 | **/ 267 | public String type(String key) { 268 | // ShardedJedis sjedis = getShardedJedis(); 269 | Jedis sjedis = getJedis(); 270 | String type = sjedis.type(key); 271 | sjedis.close(); 272 | return type; 273 | } 274 | 275 | /** 276 | * 查找所有匹配给定的模式的键 277 | * @param pattern 278 | * key的表达式,*表示多个,?表示一个 279 | */ 280 | public Set keys(String pattern) { 281 | Jedis jedis = getJedis(); 282 | Set set = jedis.keys(pattern); 283 | jedis.close(); 284 | return set; 285 | } 286 | } 287 | 288 | // *******************************************Strings*******************************************// 289 | public class Strings { 290 | public Strings(JedisUtil jedisUtil) {} 291 | 292 | public Strings() {} 293 | 294 | /** 295 | * 根据key获取记录 296 | * @param key 297 | * @return 298 | */ 299 | public String get(String key) { 300 | // ShardedJedis sjedis = getShardedJedis(); 301 | Jedis sjedis = getJedis(); 302 | String value = sjedis.get(key); 303 | sjedis.close(); 304 | return value; 305 | } 306 | 307 | /** 308 | * 根据key获取记录 309 | * @param key 310 | * @return 311 | */ 312 | public byte[] get(byte[] key) { 313 | // ShardedJedis sjedis = getShardedJedis(); 314 | Jedis sjedis = getJedis(); 315 | byte[] value = sjedis.get(key); 316 | sjedis.close(); 317 | return value; 318 | } 319 | 320 | /** 321 | * 添加记录,如果记录已存在将覆盖原有的value 322 | * @param key 323 | * @param value 324 | * @return 状态码 325 | */ 326 | public String set(String key, String value) { 327 | return set(SafeEncoder.encode(key), SafeEncoder.encode(value)); 328 | } 329 | 330 | /** 331 | * 添加记录,如果记录已存在将覆盖原有的value 332 | * 333 | * @param key 334 | * @param value 335 | * @return 状态码 336 | */ 337 | public String set(String key, byte[] value) { 338 | return set(SafeEncoder.encode(key), value); 339 | } 340 | 341 | /** 342 | * 添加记录,如果记录已存在将覆盖原有的value 343 | * 344 | * @param key 345 | * @param value 346 | * @return 状态码 347 | */ 348 | public String set(byte[] key, byte[] value) { 349 | Jedis jedis = getJedis(); 350 | String status = jedis.set(key, value); 351 | jedis.close(); 352 | return status; 353 | } 354 | 355 | /** 356 | * 添加有过期时间的记录 357 | * @param key 358 | * @param seconds 过期时间,以秒为单位 359 | * @param value 360 | * @return String 操作状态 361 | */ 362 | public String setEx(String key, int seconds, String value) { 363 | Jedis jedis = getJedis(); 364 | String str = jedis.setex(key, seconds, value); 365 | jedis.close(); 366 | return str; 367 | } 368 | 369 | /** 370 | * 添加有过期时间的记录 371 | * 372 | * @param key 373 | * @param seconds 过期时间,以秒为单位 374 | * @param value 375 | * @return String 操作状态 376 | */ 377 | public String setEx(byte[] key, int seconds, byte[] value) { 378 | Jedis jedis = getJedis(); 379 | String str = jedis.setex(key, seconds, value); 380 | jedis.close(); 381 | return str; 382 | } 383 | 384 | /** 385 | * 添加一条记录,仅当给定的key不存在时才插入 386 | * @param key 387 | * @param value 388 | * @return long 状态码,1插入成功且key不存在,0未插入,key存在 389 | */ 390 | public long setnx(String key, String value) { 391 | Jedis jedis = getJedis(); 392 | long str = jedis.setnx(key, value); 393 | jedis.close(); 394 | return str; 395 | } 396 | 397 | /** 398 | * 从指定位置开始插入数据,插入的数据会覆盖指定位置以后的数据
399 | * 例:String str1="123456789";
400 | * 对str1操作后setRange(key,4,0000),str1="123400009"; 401 | * 402 | * @param key 403 | * @param offset 404 | * @param value 405 | * @return long value的长度 406 | */ 407 | public long setRange(String key, long offset, String value) { 408 | Jedis jedis = getJedis(); 409 | long len = jedis.setrange(key, offset, value); 410 | jedis.close(); 411 | return len; 412 | } 413 | 414 | /** 415 | * 在指定的key中追加value 416 | * 417 | * @param key 418 | * @param value 419 | * @return long 追加后value的长度 420 | **/ 421 | public long append(String key, String value) { 422 | Jedis jedis = getJedis(); 423 | long len = jedis.append(key, value); 424 | jedis.close(); 425 | return len; 426 | } 427 | 428 | /** 429 | * 将key对应的value减去指定的值,只有value可以转为数字时该方法才可用 430 | * 431 | * @param key 432 | * @param number 要减去的值 433 | * @return long 减指定值后的值 434 | */ 435 | public long decrBy(String key, long number) { 436 | Jedis jedis = getJedis(); 437 | long len = jedis.decrBy(key, number); 438 | jedis.close(); 439 | return len; 440 | } 441 | 442 | /** 443 | * 可以作为获取唯一id的方法
444 | * 将key对应的value加上指定的值,只有value可以转为数字时该方法才可用 445 | * @param key 446 | * @param number 要减去的值 447 | * @return long 相加后的值 448 | */ 449 | public long incrBy(String key, long number) { 450 | Jedis jedis = getJedis(); 451 | long len = jedis.incrBy(key, number); 452 | jedis.close(); 453 | return len; 454 | } 455 | 456 | /** 457 | * 对指定key对应的value进行截取 458 | * 459 | * @param key 460 | * @param startOffset 开始位置(包含) 461 | * @param endOffset 结束位置(包含) 462 | * @return String 截取的值 463 | */ 464 | public String getrange(String key, long startOffset, long endOffset) { 465 | // ShardedJedis sjedis = getShardedJedis(); 466 | Jedis sjedis = getJedis(); 467 | String value = sjedis.getrange(key, startOffset, endOffset); 468 | sjedis.close(); 469 | return value; 470 | } 471 | 472 | /** 473 | * 获取并设置指定key对应的value
474 | * 如果key存在返回之前的value,否则返回null 475 | * 476 | * @param key 477 | * @param value 478 | * @return String 原始value或null 479 | */ 480 | public String getSet(String key, String value) { 481 | Jedis jedis = getJedis(); 482 | String str = jedis.getSet(key, value); 483 | jedis.close(); 484 | return str; 485 | } 486 | 487 | /** 488 | * 批量获取记录,如果指定的key不存在返回List的对应位置将是null 489 | * @param keys 490 | * @return List 值得集合 491 | */ 492 | public List mget(String... keys) { 493 | Jedis jedis = getJedis(); 494 | List str = jedis.mget(keys); 495 | jedis.close(); 496 | return str; 497 | } 498 | 499 | /** 500 | * 批量存储记录 501 | * 502 | * @param keysvalues 例:keysvalues="key1","value1","key2","value2"; 503 | * @return String 状态码 504 | */ 505 | public String mset(String... keysvalues) { 506 | Jedis jedis = getJedis(); 507 | String str = jedis.mset(keysvalues); 508 | jedis.close(); 509 | return str; 510 | } 511 | 512 | /** 513 | * 获取key对应的值的长度 514 | * 515 | * @param key 516 | * @return value值得长度 517 | */ 518 | public long strlen(String key) { 519 | Jedis jedis = getJedis(); 520 | long len = jedis.strlen(key); 521 | jedis.close(); 522 | return len; 523 | } 524 | } 525 | 526 | // *******************************************Sets*******************************************// 527 | public class Sets { 528 | 529 | /** 530 | * 向Set添加一条记录,如果member已存在返回0,否则返回1 531 | * 532 | * @param key 533 | * @param member 534 | * @return 操作码,0或1 535 | */ 536 | public long sadd(String key, String member) { 537 | Jedis jedis = getJedis(); 538 | long s = jedis.sadd(key, member); 539 | jedis.close(); 540 | return s; 541 | } 542 | 543 | public long sadd(byte[] key, byte[] member) { 544 | Jedis jedis = getJedis(); 545 | long s = jedis.sadd(key, member); 546 | jedis.close(); 547 | return s; 548 | } 549 | 550 | /** 551 | * 获取给定key中元素个数 552 | * @param key 553 | * @return 元素个数 554 | */ 555 | public long scard(String key) { 556 | // ShardedJedis sjedis = getShardedJedis(); 557 | Jedis sjedis = getJedis(); 558 | long len = sjedis.scard(key); 559 | sjedis.close(); 560 | return len; 561 | } 562 | 563 | /** 564 | * 返回从第一组和所有的给定集合之间的差异的成员 565 | * 566 | * @param keys 567 | * @return 差异的成员集合 568 | */ 569 | public Set sdiff(String... keys) { 570 | Jedis jedis = getJedis(); 571 | Set set = jedis.sdiff(keys); 572 | jedis.close(); 573 | return set; 574 | } 575 | 576 | /** 577 | * 这个命令等于sdiff,但返回的不是结果集,而是将结果集存储在新的集合中,如果目标已存在,则覆盖。 578 | * 579 | * @param newkey 新结果集的key 580 | * @param keys 比较的集合 581 | * @return 新集合中的记录数 582 | **/ 583 | public long sdiffstore(String newkey, String... keys) { 584 | Jedis jedis = getJedis(); 585 | long s = jedis.sdiffstore(newkey, keys); 586 | jedis.close(); 587 | return s; 588 | } 589 | 590 | /** 591 | * 返回给定集合交集的成员,如果其中一个集合为不存在或为空,则返回空Set 592 | * 593 | * @param keys 594 | * @return 交集成员的集合 595 | **/ 596 | public Set sinter(String... keys) { 597 | Jedis jedis = getJedis(); 598 | Set set = jedis.sinter(keys); 599 | jedis.close(); 600 | return set; 601 | } 602 | 603 | /** 604 | * 这个命令等于sinter,但返回的不是结果集,而是将结果集存储在新的集合中,如果目标已存在,则覆盖。 605 | * 606 | * @param newkey 新结果集的key 607 | * @param keys 比较的集合 608 | * @return 新集合中的记录数 609 | **/ 610 | public long sinterstore(String newkey, String... keys) { 611 | Jedis jedis = getJedis(); 612 | long s = jedis.sinterstore(newkey, keys); 613 | jedis.close(); 614 | return s; 615 | } 616 | 617 | /** 618 | * 确定一个给定的值是否存在 619 | * 620 | * @param key 621 | * @param member 要判断的值 622 | * @return 存在返回1,不存在返回0 623 | **/ 624 | public boolean sismember(String key, String member) { 625 | // ShardedJedis sjedis = getShardedJedis(); 626 | Jedis sjedis = getJedis(); 627 | boolean s = sjedis.sismember(key, member); 628 | sjedis.close(); 629 | return s; 630 | } 631 | 632 | /** 633 | * 返回集合中的所有成员 634 | * @param key 635 | * @return 成员集合 636 | */ 637 | public Set smembers(String key) { 638 | // ShardedJedis sjedis = getShardedJedis(); 639 | Jedis sjedis = getJedis(); 640 | Set set = sjedis.smembers(key); 641 | sjedis.close(); 642 | return set; 643 | } 644 | 645 | public Set smembers(byte[] key) { 646 | // ShardedJedis sjedis = getShardedJedis(); 647 | Jedis sjedis = getJedis(); 648 | Set set = sjedis.smembers(key); 649 | sjedis.close(); 650 | return set; 651 | } 652 | 653 | /** 654 | * 将成员从源集合移出放入目标集合
655 | * 如果源集合不存在或不包哈指定成员,不进行任何操作,返回0
656 | * 否则该成员从源集合上删除,并添加到目标集合,如果目标集合中成员已存在,则只在源集合进行删除 657 | * 658 | * @param srckey 源集合 659 | * @param dstkey 目标集合 660 | * @param member 源集合中的成员 661 | * @return 状态码,1成功,0失败 662 | */ 663 | public long smove(String srckey, String dstkey, String member) { 664 | Jedis jedis = getJedis(); 665 | long s = jedis.smove(srckey, dstkey, member); 666 | jedis.close(); 667 | return s; 668 | } 669 | 670 | /** 671 | * 从集合中删除成员 672 | * 673 | * @param key 674 | * @return 被删除的成员 675 | */ 676 | public String spop(String key) { 677 | Jedis jedis = getJedis(); 678 | String s = jedis.spop(key); 679 | jedis.close(); 680 | return s; 681 | } 682 | 683 | /** 684 | * 从集合中删除指定成员 685 | * 686 | * @param key 687 | * @param member 要删除的成员 688 | * @return 状态码,成功返回1,成员不存在返回0 689 | */ 690 | public long srem(String key, String member) { 691 | Jedis jedis = getJedis(); 692 | long s = jedis.srem(key, member); 693 | jedis.close(); 694 | return s; 695 | } 696 | 697 | /** 698 | * 合并多个集合并返回合并后的结果,合并后的结果集合并不保存
699 | * 700 | * @param keys 701 | * @return 合并后的结果集合 702 | */ 703 | public Set sunion(String... keys) { 704 | Jedis jedis = getJedis(); 705 | Set set = jedis.sunion(keys); 706 | jedis.close(); 707 | return set; 708 | } 709 | 710 | /** 711 | * 合并多个集合并将合并后的结果集保存在指定的新集合中,如果新集合已经存在则覆盖 712 | * 713 | * @param newkey 新集合的key 714 | * @param keys 要合并的集合 715 | **/ 716 | public long sunionstore(String newkey, String... keys) { 717 | Jedis jedis = getJedis(); 718 | long s = jedis.sunionstore(newkey, keys); 719 | jedis.close(); 720 | return s; 721 | } 722 | } 723 | 724 | // *******************************************Hash*******************************************// 725 | public class Hash { 726 | 727 | /** 728 | * 从hash中删除指定的存储 729 | * 730 | * @param key 731 | * @param fieid 存储的名字 732 | * @return 状态码,1成功,0失败 733 | */ 734 | public long hdel(String key, String fieid) { 735 | Jedis jedis = getJedis(); 736 | long s = jedis.hdel(key, fieid); 737 | jedis.close(); 738 | return s; 739 | } 740 | 741 | public long hdel(String key) { 742 | Jedis jedis = getJedis(); 743 | long s = jedis.del(key); 744 | jedis.close(); 745 | return s; 746 | } 747 | 748 | /** 749 | * 测试hash中指定的存储是否存在 750 | * 751 | * @param key 752 | * @param fieid 存储的名字 753 | * @return 1存在,0不存在 754 | */ 755 | public boolean hexists(String key, String fieid) { 756 | // ShardedJedis sjedis = getShardedJedis(); 757 | Jedis sjedis = getJedis(); 758 | boolean s = sjedis.hexists(key, fieid); 759 | sjedis.close(); 760 | return s; 761 | } 762 | 763 | /** 764 | * 返回hash中指定存储位置的值 765 | * 766 | * @param key 767 | * @param fieid 存储的名字 768 | * @return 存储对应的值 769 | */ 770 | public String hget(String key, String fieid) { 771 | // ShardedJedis sjedis = getShardedJedis(); 772 | Jedis sjedis = getJedis(); 773 | String s = sjedis.hget(key, fieid); 774 | sjedis.close(); 775 | return s; 776 | } 777 | 778 | public byte[] hget(byte[] key, byte[] fieid) { 779 | // ShardedJedis sjedis = getShardedJedis(); 780 | Jedis sjedis = getJedis(); 781 | byte[] s = sjedis.hget(key, fieid); 782 | sjedis.close(); 783 | return s; 784 | } 785 | 786 | /** 787 | * 以Map的形式返回hash中的存储和值 788 | * 789 | * @param key 790 | * @return Map 791 | */ 792 | public Map hgetAll(String key) { 793 | // ShardedJedis sjedis = getShardedJedis(); 794 | Jedis sjedis = getJedis(); 795 | Map map = sjedis.hgetAll(key); 796 | sjedis.close(); 797 | return map; 798 | } 799 | 800 | /** 801 | * 添加一个对应关系 802 | * @param key 803 | * @param fieid 804 | * @param value 805 | * @return 状态码 1成功,0失败,fieid已存在将更新,也返回0 806 | **/ 807 | public long hset(String key, String fieid, String value) { 808 | Jedis jedis = getJedis(); 809 | long s = jedis.hset(key, fieid, value); 810 | jedis.close(); 811 | return s; 812 | } 813 | 814 | public long hset(String key, String fieid, byte[] value) { 815 | Jedis jedis = getJedis(); 816 | long s = jedis.hset(key.getBytes(), fieid.getBytes(), value); 817 | jedis.close(); 818 | return s; 819 | } 820 | 821 | /** 822 | * 添加对应关系,只有在fieid不存在时才执行 823 | * 824 | * @param key 825 | * @param fieid 826 | * @param value 827 | * @return 状态码 1成功,0失败fieid已存 828 | **/ 829 | public long hsetnx(String key, String fieid, String value) { 830 | Jedis jedis = getJedis(); 831 | long s = jedis.hsetnx(key, fieid, value); 832 | jedis.close(); 833 | return s; 834 | } 835 | 836 | /** 837 | * 获取hash中value的集合 838 | * 839 | * @param key 840 | * @return List 841 | */ 842 | public List hvals(String key) { 843 | // ShardedJedis sjedis = getShardedJedis(); 844 | Jedis sjedis = getJedis(); 845 | List list = sjedis.hvals(key); 846 | sjedis.close(); 847 | return list; 848 | } 849 | 850 | /** 851 | * 在指定的存储位置加上指定的数字,存储位置的值必须可转为数字类型 852 | * 853 | * @param key 854 | * @param fieid 存储位置 855 | * @param value 要增加的值,可以是负数 856 | * @return 增加指定数字后,存储位置的值 857 | */ 858 | public long hincrby(String key, String fieid, long value) { 859 | Jedis jedis = getJedis(); 860 | long s = jedis.hincrBy(key, fieid, value); 861 | jedis.close(); 862 | return s; 863 | } 864 | 865 | /** 866 | * 返回指定hash中的所有存储名字,类似Map中的keySet方法 867 | * 868 | * @param key 869 | * @return Set 存储名称的集合 870 | */ 871 | public Set hkeys(String key) { 872 | // ShardedJedis sjedis = getShardedJedis(); 873 | Jedis sjedis = getJedis(); 874 | Set set = sjedis.hkeys(key); 875 | sjedis.close(); 876 | return set; 877 | } 878 | 879 | /** 880 | * 获取hash中存储的个数,类似Map中size方法 881 | * 882 | * @param key 883 | * @return long 存储的个数 884 | */ 885 | public long hlen(String key) { 886 | // ShardedJedis sjedis = getShardedJedis(); 887 | Jedis sjedis = getJedis(); 888 | long len = sjedis.hlen(key); 889 | sjedis.close(); 890 | return len; 891 | } 892 | 893 | /** 894 | * 根据多个key,获取对应的value,返回List,如果指定的key不存在,List对应位置为null 895 | * 896 | * @param key 897 | * @param fieids 存储位置 898 | * @return List 899 | */ 900 | public List hmget(String key, String... fieids) { 901 | // ShardedJedis sjedis = getShardedJedis(); 902 | Jedis sjedis = getJedis(); 903 | List list = sjedis.hmget(key, fieids); 904 | sjedis.close(); 905 | return list; 906 | } 907 | 908 | public List hmget(byte[] key, byte[]... fieids) { 909 | // ShardedJedis sjedis = getShardedJedis(); 910 | Jedis sjedis = getJedis(); 911 | List list = sjedis.hmget(key, fieids); 912 | sjedis.close(); 913 | return list; 914 | } 915 | 916 | /** 917 | * 添加对应关系,如果对应关系已存在,则覆盖 918 | * 919 | * @param key 920 | * @param map 对应关系 921 | * @return 状态,成功返回OK 922 | */ 923 | public String hmset(String key, Map map) { 924 | Jedis jedis = getJedis(); 925 | String s = jedis.hmset(key, map); 926 | jedis.close(); 927 | return s; 928 | } 929 | 930 | /** 931 | * 添加对应关系,如果对应关系已存在,则覆盖 932 | * 933 | * @param key 934 | * @param map 对应关系 935 | * @return 状态,成功返回OK 936 | */ 937 | public String hmset(byte[] key, Map map) { 938 | Jedis jedis = getJedis(); 939 | String s = jedis.hmset(key, map); 940 | jedis.close(); 941 | return s; 942 | } 943 | 944 | } 945 | 946 | // *******************************************Lists*******************************************// 947 | public class Lists { 948 | /** 949 | * List长度 950 | * 951 | * @param key 952 | * @return 长度 953 | */ 954 | public long llen(String key) { 955 | return llen(SafeEncoder.encode(key)); 956 | } 957 | 958 | /** 959 | * List长度 960 | * 961 | * @param key 962 | * @return 长度 963 | */ 964 | public long llen(byte[] key) { 965 | // ShardedJedis sjedis = getShardedJedis(); 966 | Jedis sjedis = getJedis(); 967 | long count = sjedis.llen(key); 968 | sjedis.close(); 969 | return count; 970 | } 971 | 972 | /** 973 | * 覆盖操作,将覆盖List中指定位置的值 974 | * 975 | * @param key 976 | * @param index 位置 977 | * @param value 值 978 | * @return 状态码 979 | */ 980 | public String lset(byte[] key, int index, byte[] value) { 981 | Jedis jedis = getJedis(); 982 | String status = jedis.lset(key, index, value); 983 | jedis.close(); 984 | return status; 985 | } 986 | 987 | /** 988 | * 覆盖操作,将覆盖List中指定位置的值 989 | * 990 | * @param key 991 | * @param index 位置 992 | * @param value 值 993 | * @return 状态码 994 | */ 995 | public String lset(String key, int index, String value) { 996 | return lset(SafeEncoder.encode(key), index, SafeEncoder.encode(value)); 997 | } 998 | 999 | /** 1000 | * 在value的相对位置插入记录 1001 | * 1002 | * @param key 1003 | * @param where 前面插入或后面插入 1004 | * @param pivot 相对位置的内容 1005 | * @param value 插入的内容 1006 | * @return 记录总数 1007 | */ 1008 | public long linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value) { 1009 | return linsert(SafeEncoder.encode(key), where, SafeEncoder.encode(pivot), SafeEncoder.encode(value)); 1010 | } 1011 | 1012 | /** 1013 | * 在指定位置插入记录 1014 | * @param key 1015 | * @param where 前面插入或后面插入 1016 | * @param pivot 相对位置的内容 1017 | * @param value 插入的内容 1018 | * @return 记录总数 1019 | */ 1020 | public long linsert(byte[] key, BinaryClient.LIST_POSITION where, byte[] pivot, byte[] value) { 1021 | Jedis jedis = getJedis(); 1022 | long count = jedis.linsert(key, where, pivot, value); 1023 | jedis.close(); 1024 | return count; 1025 | } 1026 | 1027 | /** 1028 | * 获取List中指定位置的值 1029 | * 1030 | * @param key 1031 | * @param index 位置 1032 | * @return 值 1033 | **/ 1034 | public String lindex(String key, int index) { 1035 | return SafeEncoder.encode(lindex(SafeEncoder.encode(key), index)); 1036 | } 1037 | 1038 | /** 1039 | * 获取List中指定位置的值 1040 | * 1041 | * @param key 1042 | * @param index 位置 1043 | * @return 值 1044 | **/ 1045 | public byte[] lindex(byte[] key, int index) { 1046 | // ShardedJedis sjedis = getShardedJedis(); 1047 | Jedis sjedis = getJedis(); 1048 | byte[] value = sjedis.lindex(key, index); 1049 | sjedis.close(); 1050 | return value; 1051 | } 1052 | 1053 | /** 1054 | * 将List中的第一条记录移出List 1055 | * @param key 1056 | * @return 移出的记录 1057 | */ 1058 | public String lpop(String key) { 1059 | return SafeEncoder.encode(lpop(SafeEncoder.encode(key))); 1060 | } 1061 | 1062 | /** 1063 | * 将List中的第一条记录移出List 1064 | * 1065 | * @param key 1066 | * @return 移出的记录 1067 | */ 1068 | public byte[] lpop(byte[] key) { 1069 | Jedis jedis = getJedis(); 1070 | byte[] value = jedis.lpop(key); 1071 | jedis.close(); 1072 | return value; 1073 | } 1074 | 1075 | /** 1076 | * 将List中最后第一条记录移出List 1077 | * 1078 | * @param key 1079 | * @return 移出的记录 1080 | */ 1081 | public String rpop(String key) { 1082 | Jedis jedis = getJedis(); 1083 | String value = jedis.rpop(key); 1084 | jedis.close(); 1085 | return value; 1086 | } 1087 | 1088 | /** 1089 | * 向List尾部追加记录 1090 | * 1091 | * @param key 1092 | * @param value 1093 | * @return 记录总数 1094 | */ 1095 | public long lpush(String key, String value) { 1096 | return lpush(SafeEncoder.encode(key), SafeEncoder.encode(value)); 1097 | } 1098 | 1099 | /** 1100 | * 向List头部追加记录 1101 | * 1102 | * @param key 1103 | * @param value 1104 | * @return 记录总数 1105 | */ 1106 | public long rpush(String key, String value) { 1107 | Jedis jedis = getJedis(); 1108 | long count = jedis.rpush(key, value); 1109 | jedis.close(); 1110 | return count; 1111 | } 1112 | 1113 | /** 1114 | * 向List头部追加记录 1115 | * 1116 | * @param key 1117 | * @param value 1118 | * @return 记录总数 1119 | */ 1120 | public long rpush(byte[] key, byte[] value) { 1121 | Jedis jedis = getJedis(); 1122 | long count = jedis.rpush(key, value); 1123 | jedis.close(); 1124 | return count; 1125 | } 1126 | 1127 | /** 1128 | * 向List中追加记录 1129 | * 1130 | * @param key 1131 | * @param value 1132 | * @return 记录总数 1133 | */ 1134 | public long lpush(byte[] key, byte[] value) { 1135 | Jedis jedis = getJedis(); 1136 | long count = jedis.lpush(key, value); 1137 | jedis.close(); 1138 | return count; 1139 | } 1140 | 1141 | /** 1142 | * 获取指定范围的记录,可以做为分页使用 1143 | * @param key 1144 | * @param start 1145 | * @param end 1146 | * @return List 1147 | */ 1148 | public List lrange(String key, long start, long end) { 1149 | // ShardedJedis sjedis = getShardedJedis(); 1150 | Jedis sjedis = getJedis(); 1151 | List list = sjedis.lrange(key, start, end); 1152 | sjedis.close(); 1153 | return list; 1154 | } 1155 | 1156 | /** 1157 | * 获取指定范围的记录,可以做为分页使用 1158 | * 1159 | * @param key 1160 | * @param start 1161 | * @param end 如果为负数,则尾部开始计算 1162 | * @return List 1163 | */ 1164 | public List lrange(byte[] key, int start, int end) { 1165 | // ShardedJedis sjedis = getShardedJedis(); 1166 | Jedis sjedis = getJedis(); 1167 | List list = sjedis.lrange(key, start, end); 1168 | sjedis.close(); 1169 | return list; 1170 | } 1171 | 1172 | /** 1173 | * 删除List中c条记录,被删除的记录值为value 1174 | * 1175 | * @param key 1176 | * @param c 要删除的数量,如果为负数则从List的尾部检查并删除符合的记录 1177 | * @param value 要匹配的值 1178 | * @return 删除后的List中的记录数 1179 | */ 1180 | public long lrem(byte[] key, int c, byte[] value) { 1181 | Jedis jedis = getJedis(); 1182 | long count = jedis.lrem(key, c, value); 1183 | jedis.close(); 1184 | return count; 1185 | } 1186 | 1187 | /** 1188 | * 删除List中c条记录,被删除的记录值为value 1189 | * 1190 | * @param key 1191 | * @param c 要删除的数量,如果为负数则从List的尾部检查并删除符合的记录 1192 | * @param value 要匹配的值 1193 | * @return 删除后的List中的记录数 1194 | */ 1195 | public long lrem(String key, int c, String value) { 1196 | return lrem(SafeEncoder.encode(key), c, SafeEncoder.encode(value)); 1197 | } 1198 | 1199 | /** 1200 | * 算是删除吧,只保留start与end之间的记录 1201 | * 1202 | * @param key 1203 | * @param start 记录的开始位置(0表示第一条记录) 1204 | * @param end 记录的结束位置(如果为-1则表示最后一个,-2,-3以此类推) 1205 | * @return 执行状态码 1206 | */ 1207 | public String ltrim(byte[] key, int start, int end) { 1208 | Jedis jedis = getJedis(); 1209 | String str = jedis.ltrim(key, start, end); 1210 | jedis.close(); 1211 | return str; 1212 | } 1213 | 1214 | /** 1215 | * 算是删除吧,只保留start与end之间的记录 1216 | * 1217 | * @param key 1218 | * @param start 记录的开始位置(0表示第一条记录) 1219 | * @param end 记录的结束位置(如果为-1则表示最后一个,-2,-3以此类推) 1220 | * @return 执行状态码 1221 | */ 1222 | public String ltrim(String key, int start, int end) { 1223 | return ltrim(SafeEncoder.encode(key), start, end); 1224 | } 1225 | } 1226 | } 1227 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/redis/RedisConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.redis; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import redis.clients.jedis.JedisPoolConfig; 7 | 8 | import javax.annotation.Resource; 9 | 10 | /** 11 | * @Author: Mr_OO 12 | * @Date: 2022/3/3 14:12 13 | */ 14 | @Configuration 15 | public class RedisConfiguration { 16 | private String hostname = "127.0.0.1"; 17 | private int port = 6379; 18 | private int maxTotal = 200; 19 | private int maxIdle = 50; 20 | private long maxWaitMillis = 3000; 21 | private boolean testOnBorrow = true; 22 | 23 | @Resource 24 | private JedisPoolConfig jedisPoolConfig; 25 | @Resource 26 | private JedisPoolFactory jedisPoolFactory; 27 | @Resource 28 | private JedisUtil jedisUtil; 29 | 30 | /** 31 | * 创建redis连接池的设置 32 | * @return 33 | */ 34 | @Bean(name = "jedisPoolConfig") 35 | public JedisPoolConfig createJedisPoolConfig() { 36 | JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 37 | // 控制一个pool可分配多少个jedis实例 38 | jedisPoolConfig.setMaxTotal(maxTotal); 39 | // 连接池中最多可空闲maxIdle个连接 ,这里取值为20, 40 | // 表示即使没有数据库连接时依然可以保持20空闲的连接, 41 | // 而不被清除,随时处于待命状态。 42 | jedisPoolConfig.setMaxIdle(maxIdle); 43 | // 最大等待时间:当没有可用连接时, 44 | // 连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常 45 | jedisPoolConfig.setMaxWaitMillis(maxWaitMillis); 46 | // 在获取连接的时候检查有效性 47 | jedisPoolConfig.setTestOnBorrow(testOnBorrow); 48 | return jedisPoolConfig; 49 | } 50 | 51 | /** 52 | * 创建Redis连接池,并做相关配置 53 | * @return 54 | */ 55 | @Bean(name = "jedisWritePool") 56 | public JedisPoolFactory createJedisPoolWriper() { 57 | JedisPoolFactory jedisPoolWriper = new JedisPoolFactory(jedisPoolConfig, hostname, port); 58 | return jedisPoolWriper; 59 | } 60 | 61 | /** 62 | * 创建Redis工具类,封装好Redis的连接以进行相关的操作 63 | * @return 64 | */ 65 | @Bean(name = "jedisUtil") 66 | public JedisUtil createJedisUtil() { 67 | JedisUtil jedisUtil = new JedisUtil(); 68 | jedisUtil.setJedisPool(jedisPoolFactory); 69 | return jedisUtil; 70 | } 71 | 72 | /** 73 | * Redis的key操作 74 | * @return 75 | */ 76 | @Bean(name = "jedisKeys") 77 | public JedisUtil.Keys createJedisKeys() { 78 | JedisUtil.Keys jedisKeys = jedisUtil.new Keys(); 79 | return jedisKeys; 80 | } 81 | 82 | /** 83 | * Redis的Strings操作 84 | * @return 85 | */ 86 | @Bean(name = "jedisStrings") 87 | public JedisUtil.Strings createJedisStrings() { 88 | JedisUtil.Strings jedisStrings = jedisUtil.new Strings( ); 89 | return jedisStrings; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/service/TransactionManagementConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.service; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 5 | import org.springframework.transaction.TransactionManager; 6 | import org.springframework.transaction.annotation.EnableTransactionManagement; 7 | import org.springframework.transaction.annotation.TransactionManagementConfigurer; 8 | 9 | import javax.annotation.Resource; 10 | import javax.sql.DataSource; 11 | 12 | /** 13 | * @Author: Mr_OO 14 | * @Date: 2022/3/1 13:36 15 | */ 16 | @Configuration 17 | @EnableTransactionManagement 18 | public class TransactionManagementConfiguration implements TransactionManagementConfigurer { 19 | 20 | /** 21 | * 注入DataSourceConfiguration里边的dataSource,通过createDataSource()获取 22 | */ 23 | @Resource 24 | private DataSource dataSource; 25 | 26 | @Override 27 | public TransactionManager annotationDrivenTransactionManager() { 28 | return new DataSourceTransactionManager(dataSource); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/shiro/MySessionManager.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.shiro; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.apache.shiro.web.servlet.ShiroHttpServletRequest; 5 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; 6 | import org.apache.shiro.web.util.WebUtils; 7 | 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | import java.io.Serializable; 11 | 12 | /** 13 | * 自定义session管理 14 | * 传统结构项目中,shiro从cookie中读取sessionId以此来维持会话,在前后端分离的项目中(也可在移动APP项目使用), 15 | * 我们选择在ajax的请求头中传递sessionId,因此需要重写shiro获取sessionId的方式 16 | * 自定义MySessionManager类继承 DefaultWebSessionManager类,重写getSessionId方法 17 | * @Author: Mr_OO 18 | * @Date: 2022/3/3 17:21 19 | */ 20 | public class MySessionManager extends DefaultWebSessionManager { 21 | 22 | private static final String AUTHORIZATION = "userToken"; 23 | 24 | private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; 25 | 26 | @Override 27 | protected Serializable getSessionId(ServletRequest request, ServletResponse response) { 28 | String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION); 29 | //如果请求头中有 userToken 则其值为 sessionId 30 | if (!StringUtils.isEmpty(id)) { 31 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); 32 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); 33 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); 34 | return id; 35 | } else { 36 | //否则按默认规则从cookie取sessionId 37 | return super.getSessionId(request, response); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/shiro/MyShiroRealm.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.shiro; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.oym.cms.dto.UserDTO; 5 | import com.oym.cms.entity.User; 6 | import com.oym.cms.enums.DTOMsgEnum; 7 | import com.oym.cms.mapper.JurisdictionMapper; 8 | import com.oym.cms.mapper.UserMapper; 9 | import org.apache.shiro.authc.AuthenticationException; 10 | import org.apache.shiro.authc.AuthenticationInfo; 11 | import org.apache.shiro.authc.AuthenticationToken; 12 | import org.apache.shiro.authc.SimpleAuthenticationInfo; 13 | import org.apache.shiro.authz.AuthorizationInfo; 14 | import org.apache.shiro.authz.SimpleAuthorizationInfo; 15 | import org.apache.shiro.realm.AuthorizingRealm; 16 | import org.apache.shiro.subject.PrincipalCollection; 17 | import org.apache.shiro.util.ByteSource; 18 | 19 | import javax.annotation.Resource; 20 | import java.util.*; 21 | 22 | /** 23 | * @Author: Mr_OO 24 | * @Date: 2022/3/3 17:21 25 | */ 26 | public class MyShiroRealm extends AuthorizingRealm { 27 | 28 | @Resource 29 | private JurisdictionMapper jurisdictionMapper; 30 | @Resource 31 | private UserMapper userMapper; 32 | 33 | /** 34 | * 授权 35 | * @param principalCollection 36 | * @return 37 | */ 38 | @Override 39 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { 40 | SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 41 | //取出用户权限URL表数据 42 | List urlList = jurisdictionMapper.queryAllUrls(); 43 | //授权 44 | for (String s : urlList) { 45 | authorizationInfo.addStringPermission(s); 46 | } 47 | return authorizationInfo; 48 | } 49 | 50 | /** 51 | * 身份认证 52 | * 53 | * @param token 54 | * @return 55 | * @throws AuthenticationException 56 | */ 57 | @Override 58 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 59 | 60 | //获取用户的输入的账号. 61 | String userId = (String) token.getPrincipal(); 62 | //通过userId从数据库中查找 User对象. 63 | User user = userMapper.queryUserById(userId); 64 | if (Objects.isNull(user)) { 65 | return null; 66 | } 67 | return new SimpleAuthenticationInfo( 68 | //传入对象(一定要是对象!!!getPrimaryPrincipal()要取得) 69 | user, 70 | //传入的是加密后的密码 71 | user.getUserPassword(), 72 | //传入salt 73 | ByteSource.Util.bytes(user.getUserId()), 74 | getName()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/shiro/ShiroConfig.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.shiro; 2 | 3 | import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 4 | import org.apache.shiro.mgt.SecurityManager; 5 | import org.apache.shiro.session.mgt.SessionManager; 6 | import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator; 7 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 8 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 9 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 10 | import org.apache.shiro.web.servlet.SimpleCookie; 11 | import org.crazycake.shiro.RedisCacheManager; 12 | import org.crazycake.shiro.RedisManager; 13 | import org.crazycake.shiro.RedisSessionDAO; 14 | import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.context.annotation.Configuration; 17 | 18 | import java.util.LinkedHashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * @Author: Mr_OO 23 | * @Date: 2022/3/3 17:25 24 | */ 25 | @Configuration 26 | public class ShiroConfig { 27 | 28 | /** 29 | * Filter工厂,设置对应的过滤条件和跳转条件 30 | * @return ShiroFilterFactoryBean 31 | */ 32 | @Bean 33 | public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { 34 | 35 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 36 | shiroFilterFactoryBean.setSecurityManager(securityManager); 37 | 38 | // 过滤器链定义映射 39 | Map filterChainDefinitionMap = new LinkedHashMap<>(); 40 | /* 41 | * anon:所有url都都可以匿名访问,authc:所有url都必须认证通过才可以访问; 42 | * 过滤链定义,从上向下顺序执行,authc 应放在 anon 下面 43 | */ 44 | filterChainDefinitionMap.put("/user/login", "anon"); 45 | filterChainDefinitionMap.put("/user/changeUserPassword", "anon"); 46 | // 所有url都必须认证通过才可以访问 47 | filterChainDefinitionMap.put("/**", "authc"); 48 | // 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了, 位置放在 anon、authc下面 49 | filterChainDefinitionMap.put("/logout", "logout"); 50 | // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 51 | // 配器shiro默认登录地址,前后端分离中登录累面跳转应由前端路由控制,后台仅返回json数据, 对应LoginController中unAuth请求 52 | shiroFilterFactoryBean.setLoginUrl("/user/login"); 53 | // 未授权界面, 对应LoginController中 unauthorized 请求 54 | shiroFilterFactoryBean.setUnauthorizedUrl("/user/login"); 55 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 56 | return shiroFilterFactoryBean; 57 | } 58 | 59 | /** 60 | * 凭证匹配器(由于我们的密码校验交给 Shiro的 SimpleAuthenticationInfo进行处理了) 61 | * 62 | * @return HashedCredentialsMatcher 63 | */ 64 | @Bean 65 | public HashedCredentialsMatcher hashedCredentialsMatcher() { 66 | HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 67 | // 散列算法:这里使用MD5算法; 68 | hashedCredentialsMatcher.setHashAlgorithmName("md5"); 69 | // 散列的次数,比如散列两次,相当于 md5(md5("")); 70 | hashedCredentialsMatcher.setHashIterations(20); 71 | hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); 72 | return hashedCredentialsMatcher; 73 | } 74 | 75 | /** 76 | * 将自己的验证方式加入容器 77 | * 78 | * @return MyShiroRealm 79 | */ 80 | @Bean 81 | public MyShiroRealm myShiroRealm() { 82 | MyShiroRealm myShiroRealm = new MyShiroRealm(); 83 | myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); 84 | return myShiroRealm; 85 | } 86 | 87 | /** 88 | * RedisSessionDAO shiro sessionDao层的实现 通过redis, 使用的是shiro-redis开源插件 89 | * 90 | * @return RedisSessionDAO 91 | */ 92 | @Bean 93 | public RedisSessionDAO redisSessionDAO() { 94 | RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); 95 | redisSessionDAO.setRedisManager(redisManager()); 96 | redisSessionDAO.setSessionIdGenerator(sessionIdGenerator()); 97 | redisSessionDAO.setExpire(1800); 98 | return redisSessionDAO; 99 | } 100 | 101 | /** 102 | * Session ID 生成器 103 | * 104 | * @return JavaUuidSessionIdGenerator 105 | */ 106 | @Bean 107 | public JavaUuidSessionIdGenerator sessionIdGenerator() { 108 | return new JavaUuidSessionIdGenerator(); 109 | } 110 | 111 | /** 112 | * 自定义sessionManager 113 | * 114 | * @return SessionManager 115 | */ 116 | @Bean 117 | public SessionManager sessionManager() { 118 | MySessionManager mySessionManager = new MySessionManager(); 119 | mySessionManager.setSessionDAO(redisSessionDAO()); 120 | return mySessionManager; 121 | } 122 | 123 | private static final String HOST = "127.0.0.1:6379"; 124 | private static final int TIMEOUT = 1800; 125 | 126 | /** 127 | * 配置shiro redisManager, 使用的是shiro-redis开源插件 128 | * 129 | * @return RedisManager 130 | */ 131 | private RedisManager redisManager() { 132 | RedisManager redisManager = new RedisManager(); 133 | redisManager.setHost(HOST); 134 | redisManager.setTimeout(TIMEOUT); 135 | return redisManager; 136 | } 137 | 138 | /** 139 | * cacheManager 缓存 redis实现, 使用的是shiro-redis开源插件 140 | * 141 | * @return RedisCacheManager 142 | */ 143 | @Bean 144 | public RedisCacheManager cacheManager() { 145 | RedisCacheManager redisCacheManager = new RedisCacheManager(); 146 | redisCacheManager.setRedisManager(redisManager()); 147 | // 必须要设置主键名称,shiro-redis 插件用过这个缓存用户信息 148 | redisCacheManager.setPrincipalIdFieldName("userId"); 149 | return redisCacheManager; 150 | } 151 | 152 | /** 153 | * description: 权限管理,配置主要是Realm的管理认证 154 | * 155 | * @return SecurityManager 156 | */ 157 | @Bean 158 | public SecurityManager securityManager() { 159 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 160 | securityManager.setRealm(myShiroRealm()); 161 | // 自定义session管理 使用redis 162 | securityManager.setSessionManager(sessionManager()); 163 | // 自定义缓存实现 使用redis 164 | securityManager.setCacheManager(cacheManager()); 165 | return securityManager; 166 | } 167 | 168 | /** 169 | * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 170 | * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能 171 | * @return 172 | */ 173 | @Bean 174 | public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { 175 | DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); 176 | advisorAutoProxyCreator.setProxyTargetClass(true); 177 | return advisorAutoProxyCreator; 178 | } 179 | 180 | @Bean 181 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { 182 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 183 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 184 | return authorizationAttributeSourceAdvisor; 185 | } 186 | 187 | @Bean 188 | public SimpleCookie cookie() { 189 | // cookie的name,对应的默认是 JSESSIONID 190 | SimpleCookie cookie = new SimpleCookie("SHARE_JSESSIONID"); 191 | cookie.setHttpOnly(true); 192 | // path为 / 用于多个系统共享 JSESSIONID 193 | cookie.setPath("/"); 194 | return cookie; 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/config/web/MvcConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.config.web; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.web.multipart.commons.CommonsMultipartResolver; 11 | import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; 12 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 13 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 14 | 15 | import javax.servlet.*; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | 20 | /** 21 | * @Author: Mr_OO 22 | * @Date: 2022/3/1 13:37 23 | */ 24 | @Configuration 25 | @EnableWebMvc 26 | public class MvcConfiguration implements WebMvcConfigurer, ApplicationContextAware { 27 | 28 | /** 29 | * Spring容器 30 | */ 31 | private ApplicationContext applicationContext; 32 | 33 | @Override 34 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 35 | this.applicationContext = applicationContext; 36 | } 37 | 38 | /** 39 | * 定义默认的请求处理器 40 | * @param configurer 41 | */ 42 | @Override 43 | public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 44 | configurer.enable(); 45 | } 46 | 47 | /** 48 | * 跨域的过滤机制 49 | * 50 | * @return 51 | */ 52 | @Bean 53 | public FilterRegistrationBean corsFilter() { 54 | return new FilterRegistrationBean(new Filter() { 55 | @Override 56 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 57 | throws IOException, ServletException { 58 | HttpServletRequest request = (HttpServletRequest) req; 59 | HttpServletResponse response = (HttpServletResponse) res; 60 | String method = request.getMethod(); 61 | response.setHeader("Access-Control-Allow-Origin", "*"); 62 | response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS"); 63 | response.setHeader("Access-Control-Max-Age", "3600"); 64 | response.setHeader("Access-Control-Allow-Credentials", "true"); 65 | response.setHeader("Access-Control-Allow-Headers", "Accept, Origin, " + 66 | "X-Requested-With, Content-Type,Last-Modified,device,token,userToken"); 67 | //检测是options方法则直接返回200,用于跳过预检机制 68 | if ("OPTIONS".equals(method)) { 69 | response.setStatus(HttpStatus.OK.value()); 70 | } else { 71 | chain.doFilter(req, res); 72 | } 73 | } 74 | 75 | @Override 76 | public void init(FilterConfig filterConfig) {} 77 | 78 | @Override 79 | public void destroy() {} 80 | }); 81 | } 82 | 83 | /** 84 | * 文件上传解析器 85 | * @return 86 | */ 87 | @Bean(name = "multipartResolver") 88 | public CommonsMultipartResolver createMultipartResolver() { 89 | CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); 90 | multipartResolver.setDefaultEncoding("utf-8"); 91 | // 1024 * 1024 * 2 = 2M 92 | multipartResolver.setMaxUploadSize(5242880); 93 | multipartResolver.setMaxInMemorySize(5242880); 94 | return multipartResolver; 95 | } 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/controller/CertificateController.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.controller; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.oym.cms.dto.CertificateDTO; 5 | import com.oym.cms.dto.ImageHolder; 6 | import com.oym.cms.entity.Certificate; 7 | import com.oym.cms.enums.CertificateTypeEnum; 8 | import com.oym.cms.enums.DTOMsgEnum; 9 | import com.oym.cms.exceptions.CertificateException; 10 | import com.oym.cms.service.CertificateService; 11 | import com.oym.cms.util.HttpServletRequestUtil; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.apache.shiro.authz.annotation.RequiresPermissions; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.web.bind.annotation.CrossOrigin; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.RestController; 19 | import org.springframework.web.multipart.MultipartHttpServletRequest; 20 | import org.springframework.web.multipart.commons.CommonsMultipartFile; 21 | import org.springframework.web.multipart.commons.CommonsMultipartResolver; 22 | 23 | import javax.annotation.Resource; 24 | import javax.servlet.http.HttpServletRequest; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | /** 29 | * @Author: Mr_OO 30 | * @Date: 2022/3/6 11:04 31 | */ 32 | @CrossOrigin 33 | @RestController 34 | public class CertificateController { 35 | @Resource 36 | private CertificateService certificateService; 37 | 38 | /** 39 | * UserController log 40 | */ 41 | private static final Logger LOGGER = LoggerFactory.getLogger(CertificateController.class); 42 | 43 | /** 44 | * 存储新证书 45 | * @param request 46 | * @return 47 | */ 48 | @PostMapping("/certificate/addNewOne") 49 | @RequiresPermissions("/certificate/addNewOne") 50 | public Map addNewOneCertificate(HttpServletRequest request) { 51 | Map modelMap = new HashMap<>(16); 52 | String certificateStr = HttpServletRequestUtil.getString(request,"certificate"); 53 | LOGGER.info("CertificateController addNewOneCertificate certificate:{}", certificateStr); 54 | if (StringUtils.isEmpty(certificateStr)) { 55 | modelMap.put("success",false); 56 | modelMap.put("errMsg", DTOMsgEnum.EMPTY_INPUT_STR.getStatusInfo()); 57 | LOGGER.error("CertificateController addNewOneCertificate empty certificate:{}", certificateStr); 58 | return modelMap; 59 | } 60 | ObjectMapper mapper = new ObjectMapper(); 61 | Certificate certificate = null; 62 | try { 63 | certificate = mapper.readValue(certificateStr, Certificate.class); 64 | if (certificate == null) { 65 | modelMap.put("success", false); 66 | modelMap.put("errMsg", DTOMsgEnum.ERROR_INPUT_STR.getStatusInfo()); 67 | LOGGER.error("CertificateController addNewOneCertificate empty certificate:{}", certificateStr); 68 | return modelMap; 69 | } 70 | } catch (Exception e) { 71 | modelMap.put("success", false); 72 | modelMap.put("errMsg", DTOMsgEnum.ERROR_INPUT_STR.getStatusInfo()); 73 | LOGGER.error("CertificateController addNewOneCertificate error certificate:{}", certificateStr); 74 | return modelMap; 75 | } 76 | ImageHolder thumbnail = null; 77 | try { 78 | //获取文件流 79 | CommonsMultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext()); 80 | if (resolver.isMultipart(request)) { 81 | MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request; 82 | CommonsMultipartFile thumbnailFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("image"); 83 | if (thumbnailFile != null) { 84 | thumbnail = new ImageHolder(thumbnailFile.getOriginalFilename(), thumbnailFile.getInputStream()); 85 | } else { 86 | throw new Exception(); 87 | } 88 | } 89 | } catch (Exception e) { 90 | modelMap.put("success", false); 91 | modelMap.put("errMsg", DTOMsgEnum.ERROR_IMAGE.getStatusInfo()); 92 | LOGGER.error("CertificateController addNewOneCertificate error certificate:{}", certificateStr); 93 | } 94 | try { 95 | //执行存储证书逻辑 96 | CertificateDTO res = certificateService.addCertificate(certificate, thumbnail); 97 | if (res.getMsg() != DTOMsgEnum.OK.getStatus()) { 98 | modelMap.put("success", false); 99 | modelMap.put("errMsg", res.getMsg()); 100 | LOGGER.info("CertificateController addNewOneCertificate fail certificate:{}", certificateStr); 101 | return modelMap; 102 | } 103 | LOGGER.info("CertificateController addNewOneCertificate success certificate:{}", certificateStr); 104 | modelMap.put("success", true); 105 | } catch (CertificateException e) { 106 | modelMap.put("success",false); 107 | modelMap.put("errMsg", DTOMsgEnum.ERROR_EXCEPTION.getStatusInfo()); 108 | LOGGER.error("CertificateController addNewOneCertificate error certificate:{}", certificateStr); 109 | return modelMap; 110 | } catch (Exception e ){ 111 | modelMap.put("success", false); 112 | modelMap.put("errMsg", DTOMsgEnum.ERROR_EXCEPTION.getStatusInfo()); 113 | LOGGER.error("CertificateController addNewOneCertificate error certificate:{}", certificateStr); 114 | return modelMap; 115 | } 116 | return modelMap; 117 | } 118 | 119 | /** 120 | * 查询用户拥有的证书 121 | * @param request 122 | * @return 123 | */ 124 | @PostMapping("/certificate/userQueryById") 125 | @RequiresPermissions("/certificate/userQueryById") 126 | public Map queryCertificateByUserId(HttpServletRequest request) { 127 | Map modelMap = new HashMap<>(16); 128 | int pageIndex = HttpServletRequestUtil.getInt(request, "pageIndex"); 129 | int pageSize = HttpServletRequestUtil.getInt(request, "pageSize"); 130 | String userId = HttpServletRequestUtil.getString(request, "userId"); 131 | int certificateType = HttpServletRequestUtil.getInt(request, "certificateType"); 132 | if (userId == null) { 133 | modelMap.put("success",false); 134 | modelMap.put("errMsg", DTOMsgEnum.EMPTY_INPUT_STR.getStatusInfo()); 135 | LOGGER.error("CertificateController queryCertificateByUserId empty userId"); 136 | return modelMap; 137 | } 138 | pageIndex = getPageIndex(pageIndex); 139 | pageSize = getPageSize(pageSize); 140 | try { 141 | //先判断证书类型合法性 142 | if (certificateType == -1000) { 143 | certificateType = CertificateTypeEnum.ALL_TYPE.getStatus(); 144 | } else { 145 | checkCertificateType(certificateType); 146 | } 147 | CertificateDTO certificateDTOList = certificateService.queryCertificateByUserId(userId, certificateType, pageIndex, pageSize); 148 | if (certificateDTOList.getMsg() != DTOMsgEnum.OK.getStatus()) { 149 | modelMap.put("success", false); 150 | modelMap.put("errMsg", DTOMsgEnum.stateOf(certificateDTOList.getMsg()).getStatusInfo()); 151 | LOGGER.info("CertificateController queryCertificateByUserId fail, certificateType:{}, userId:{}", certificateType, userId); 152 | return modelMap; 153 | } 154 | LOGGER.info("CertificateController queryCertificateByUserId success, certificateType:{}, userId:{}", certificateType, userId); 155 | modelMap.put("CertificateList", certificateDTOList.getCertificateList()); 156 | modelMap.put("certificateCount", certificateDTOList.getCount()); 157 | modelMap.put("success", true); 158 | } catch (CertificateException e) { 159 | modelMap.put("success",false); 160 | modelMap.put("errMsg", DTOMsgEnum.ERROR_EXCEPTION.getStatusInfo()); 161 | LOGGER.error("CertificateController queryCertificateByUserId error userId:{}", userId); 162 | return modelMap; 163 | } catch (Exception e ){ 164 | modelMap.put("success", false); 165 | modelMap.put("errMsg", DTOMsgEnum.ERROR_EXCEPTION.getStatusInfo()); 166 | LOGGER.error("CertificateController queryCertificateByUserId error userId:{}", userId); 167 | return modelMap; 168 | } 169 | return modelMap; 170 | } 171 | 172 | private int getPageIndex(int pageIndex) { 173 | if (pageIndex < 0 || pageIndex > 1000) { 174 | return 0; 175 | } 176 | return pageIndex; 177 | } 178 | 179 | private int getPageSize(int pageSize) { 180 | if (pageSize <= 0 || pageSize > 100) { 181 | return 5; 182 | } 183 | return pageSize; 184 | } 185 | 186 | private void checkCertificateType(int type) { 187 | if (CertificateTypeEnum.stateOf(type) == null) { 188 | LOGGER.info("CertificateController queryCertificateByUserId fail,no such cmsType"); 189 | throw new CertificateException(DTOMsgEnum.ERROR_INPUT_STR.getStatusInfo()); 190 | } 191 | } 192 | 193 | } 194 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.controller; 2 | 3 | import com.oym.cms.dto.UserDTO; 4 | import com.oym.cms.entity.User; 5 | import com.oym.cms.enums.DTOMsgEnum; 6 | import com.oym.cms.service.UserService; 7 | import com.oym.cms.util.HttpServletRequestUtil; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.apache.shiro.SecurityUtils; 10 | import org.apache.shiro.authz.annotation.RequiresPermissions; 11 | import org.apache.shiro.subject.Subject; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.annotation.Resource; 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * @Author: Mr_OO 23 | * @Date: 2022/3/4 10:00 24 | */ 25 | @CrossOrigin 26 | @RestController 27 | public class UserController { 28 | @Resource 29 | private UserService userService; 30 | 31 | /** 32 | * UserController log 33 | */ 34 | private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); 35 | 36 | /** 37 | * 登录 38 | * @param request 39 | * @return 40 | */ 41 | @PostMapping("/user/login") 42 | public Map userLogin(HttpServletRequest request) { 43 | Map modelMap = new HashMap<>(16); 44 | String userId = HttpServletRequestUtil.getString(request, "userId"); 45 | String userPassword = HttpServletRequestUtil.getString(request, "userPassword"); 46 | if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(userPassword)) { 47 | modelMap.put("success",false); 48 | modelMap.put("errMsg", DTOMsgEnum.EMPTY_INPUT_STR.getStatusInfo()); 49 | return modelMap; 50 | } 51 | try { 52 | LOGGER.info("UserController userLogin userId:{}", userId); 53 | UserDTO userDTO = userService.userLogin(userId, userPassword); 54 | if (DTOMsgEnum.OK.getStatus() != userDTO.getMsg()) { 55 | modelMap.put("success",false); 56 | modelMap.put("errMsg", DTOMsgEnum.stateOf(userDTO.getMsg()).getStatusInfo()); 57 | LOGGER.info("UserController userLogin fail userId:{}, info:{}", 58 | userId, DTOMsgEnum.stateOf(userDTO.getMsg()).getStatusInfo()); 59 | return modelMap; 60 | } 61 | userDTO.getUser().setUserPassword(""); 62 | //保护隐私 63 | userDTO.getUser().setId(""); 64 | LOGGER.info("UserController userLogin success userId:{}", userId); 65 | modelMap.put("user", userDTO.getUser()); 66 | modelMap.put("success",true); 67 | } catch (Exception e) { 68 | modelMap.put("success",false); 69 | LOGGER.error("UserController userLogin exception userId:{}", userId); 70 | modelMap.put("errMsg", DTOMsgEnum.LOGIN_FAIL.getStatusInfo()); 71 | return modelMap; 72 | } 73 | return modelMap; 74 | } 75 | 76 | /** 77 | * 更改密码 78 | * @param request 79 | * @return 80 | */ 81 | @PostMapping("/user/changeUserPassword") 82 | public Map userChangePassword(HttpServletRequest request) { 83 | Map modelMap = new HashMap<>(16); 84 | String userId = HttpServletRequestUtil.getString(request, "userId"); 85 | String ID = HttpServletRequestUtil.getString(request, "ID"); 86 | String newPassword = HttpServletRequestUtil.getString(request, "newPassword"); 87 | if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(ID)|| StringUtils.isEmpty(newPassword)) { 88 | modelMap.put("success",false); 89 | modelMap.put("errMsg", DTOMsgEnum.EMPTY_INPUT_STR.getStatusInfo()); 90 | return modelMap; 91 | } 92 | try { 93 | LOGGER.info("UserController userChangePassword userId:{}", userId); 94 | UserDTO userDTOQuery = userService.queryUserById(userId); 95 | if (DTOMsgEnum.OK.getStatus() != userDTOQuery.getMsg()) { 96 | LOGGER.info("UserController userChangePassword exception userId:{}", userId); 97 | modelMap.put("success", false); 98 | modelMap.put("errMsg", DTOMsgEnum.stateOf(userDTOQuery.getMsg()).getStatusInfo()); 99 | } 100 | User user = new User(); 101 | user.setUserId(userId); 102 | user.setUserPassword(newPassword); 103 | user.setId(ID); 104 | UserDTO userDTOUpdate = userService.updateUser(user); 105 | if (DTOMsgEnum.OK.getStatus() != userDTOUpdate.getMsg()) { 106 | modelMap.put("success",false); 107 | modelMap.put("errMsg", DTOMsgEnum.stateOf(userDTOUpdate.getMsg()).getStatusInfo()); 108 | LOGGER.info("UserController userChangePassword fail userId:{}, info:{}", 109 | userId, DTOMsgEnum.stateOf(userDTOUpdate.getMsg()).getStatusInfo()); 110 | return modelMap; 111 | } 112 | LOGGER.info("UserController userChangePassword success userId:{}", userId); 113 | modelMap.put("success",true); 114 | } catch (Exception e) { 115 | modelMap.put("success",false); 116 | LOGGER.error("UserController userChangePassword exception userId:{}", userId); 117 | modelMap.put("errMsg", DTOMsgEnum.ERROR_EXCEPTION.getStatusInfo()); 118 | return modelMap; 119 | } 120 | return modelMap; 121 | } 122 | 123 | /** 124 | * 用户退出系统 125 | * 126 | * @param request 127 | */ 128 | @PostMapping("/logout") 129 | public void staffLogout(HttpServletRequest request) { 130 | try { 131 | Subject subject = SecurityUtils.getSubject(); 132 | User user = (User) subject.getPrincipals().getPrimaryPrincipal(); 133 | LOGGER.info("UserController staffLogout userId:{}", user.getUserId()); 134 | subject.logout(); 135 | } catch (Exception e) {} 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/dto/CertificateDTO.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.dto; 2 | 3 | import com.oym.cms.entity.Certificate; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 证书数据传输对象 9 | * @Author: Mr_OO 10 | * @Date: 2022/3/5 20:46 11 | */ 12 | public class CertificateDTO { 13 | private Certificate certificate; 14 | private List certificateList; 15 | private Integer msg; 16 | private Integer count; 17 | 18 | public CertificateDTO() {} 19 | 20 | public CertificateDTO(Integer msg) { 21 | this.msg = msg; 22 | } 23 | 24 | public CertificateDTO(Certificate certificate, Integer msg) { 25 | this.certificate = certificate; 26 | this.msg = msg; 27 | } 28 | 29 | public CertificateDTO(Integer msg, List certificateList) { 30 | this.certificateList = certificateList; 31 | this.msg = msg; 32 | } 33 | 34 | public List getCertificateList() { 35 | return certificateList; 36 | } 37 | 38 | public void setCertificateList(List certificateList) { 39 | this.certificateList = certificateList; 40 | } 41 | 42 | public Certificate getCertificate() { 43 | return certificate; 44 | } 45 | 46 | public void setCertificate(Certificate certificate) { 47 | this.certificate = certificate; 48 | } 49 | 50 | public Integer getMsg() { 51 | return msg; 52 | } 53 | 54 | public void setMsg(Integer msg) { 55 | this.msg = msg; 56 | } 57 | 58 | public Integer getCount() { 59 | return count; 60 | } 61 | 62 | public void setCount(Integer count) { 63 | this.count = count; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return "CertificateDTO{" + 69 | "certificate=" + certificate + 70 | ", certificateList=" + certificateList + 71 | ", msg=" + msg + 72 | ", count=" + count + 73 | '}'; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/dto/ImageHolder.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.dto; 2 | 3 | import java.io.InputStream; 4 | 5 | /** 6 | * @Author: Mr_OO 7 | * @Date: 2022/4/6 20:00 8 | */ 9 | public class ImageHolder { 10 | private String imageName; 11 | private InputStream image; 12 | 13 | public ImageHolder(String imageName, InputStream image) { 14 | this.imageName = imageName; 15 | this.image = image; 16 | } 17 | 18 | public ImageHolder(InputStream image, String imageName) { 19 | this.imageName = imageName; 20 | this.image = image; 21 | } 22 | 23 | public String getImageName() { 24 | return imageName; 25 | } 26 | 27 | public void setImageName(String imageName) { 28 | this.imageName = imageName; 29 | } 30 | 31 | public InputStream getImage() { 32 | return image; 33 | } 34 | 35 | public void setImage(InputStream image) { 36 | this.image = image; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.dto; 2 | 3 | import com.oym.cms.entity.User; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 用户数据传输对象 9 | * @Author: Mr_OO 10 | * @Date: 2022/3/3 18:23 11 | */ 12 | public class UserDTO { 13 | private User user; 14 | private Integer msg; 15 | private List userList; 16 | 17 | public UserDTO() {} 18 | 19 | public UserDTO(User user, Integer msg) { 20 | this.user = user; 21 | this.msg = msg; 22 | } 23 | 24 | public UserDTO(Integer msg, List userList) { 25 | this.msg = msg; 26 | this.userList = userList; 27 | } 28 | 29 | public List getUserList() { 30 | return userList; 31 | } 32 | 33 | public void setUserList(List userList) { 34 | this.userList = userList; 35 | } 36 | 37 | public User getUser() { 38 | return user; 39 | } 40 | 41 | public void setUser(User user) { 42 | this.user = user; 43 | } 44 | 45 | public Integer getMsg() { 46 | return msg; 47 | } 48 | 49 | public void setMsg(Integer msg) { 50 | this.msg = msg; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "UserDTO{" + 56 | "user=" + user + 57 | ", msg='" + msg + '\'' + 58 | '}'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/entity/Certificate.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.entity; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | /** 7 | * 证书信息类 8 | * @Author: Mr_OO 9 | * @Date: 2022/3/2 15:04 10 | */ 11 | public class Certificate implements Serializable { 12 | private static final long serialVersionUID = 7383159382779976173L; 13 | 14 | /** 15 | * 证书名称 16 | */ 17 | private String certificateName; 18 | 19 | /** 20 | * 证书类别 21 | */ 22 | private Integer certificateType; 23 | 24 | /** 25 | * 用户学号,对应stuNumber 26 | */ 27 | private String userId; 28 | 29 | /** 30 | * 证书获奖时间 31 | */ 32 | private Date certificateWinTime; 33 | 34 | /** 35 | * 证书描述 36 | */ 37 | private String certificateDescription; 38 | 39 | /** 40 | * 证书凭证URL 41 | */ 42 | private String certificateUrl; 43 | 44 | public String getCertificateUrl() { 45 | return certificateUrl; 46 | } 47 | 48 | public void setCertificateUrl(String certificateUrl) { 49 | this.certificateUrl = certificateUrl; 50 | } 51 | 52 | public String getCertificateDescription() { 53 | return certificateDescription; 54 | } 55 | 56 | public void setCertificateDescription(String certificateDescription) { 57 | this.certificateDescription = certificateDescription; 58 | } 59 | 60 | public String getCertificateName() { 61 | return certificateName; 62 | } 63 | 64 | public void setCertificateName(String certificateName) { 65 | this.certificateName = certificateName; 66 | } 67 | 68 | public Integer getCertificateType() { 69 | return certificateType; 70 | } 71 | 72 | public void setCertificateType(Integer certificateType) { 73 | this.certificateType = certificateType; 74 | } 75 | 76 | public String getUserId() { 77 | return userId; 78 | } 79 | 80 | public void setUserId(String userId) { 81 | this.userId = userId; 82 | } 83 | 84 | public Date getCertificateWinTime() { 85 | return certificateWinTime; 86 | } 87 | 88 | public void setCertificateWinTime(Date certificateWinTime) { 89 | this.certificateWinTime = certificateWinTime; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return "Certificate{" + 95 | "certificateName='" + certificateName + '\'' + 96 | ", certificateType=" + certificateType + 97 | ", userId='" + userId + '\'' + 98 | ", certificateWinTime=" + certificateWinTime + 99 | ", certificateDescription='" + certificateDescription + '\'' + 100 | ", certificateUrl='" + certificateUrl + '\'' + 101 | '}'; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 用户类 7 | * @Author: Mr_OO 8 | * @Date: 2022/3/2 14:43 9 | */ 10 | public class User implements Serializable { 11 | private static final long serialVersionUID = 238357573261740184L; 12 | 13 | /** 14 | * 用户id(学号) 15 | */ 16 | private String userId; 17 | /** 18 | * 用户密码 19 | */ 20 | private String userPassword; 21 | /** 22 | * 用户名字 23 | */ 24 | private String userName; 25 | /** 26 | * 用户职别 27 | */ 28 | private Integer userPosition; 29 | /** 30 | * 用户账号状态 31 | */ 32 | private Integer userStatus; 33 | /** 34 | * token 35 | */ 36 | private String userToken; 37 | 38 | /** 39 | * 学校标识 40 | */ 41 | private String schoolFlag; 42 | 43 | /** 44 | * 身份证号码 45 | */ 46 | private String Id; 47 | 48 | public String getId() { 49 | return Id; 50 | } 51 | 52 | public void setId(String id) { 53 | Id = id; 54 | } 55 | 56 | public String getSchoolFlag() { 57 | return schoolFlag; 58 | } 59 | 60 | public void setSchoolFlag(String schoolFlag) { 61 | this.schoolFlag = schoolFlag; 62 | } 63 | 64 | public String getUserToken() { 65 | return userToken; 66 | } 67 | 68 | public void setUserToken(String userToken) { 69 | this.userToken = userToken; 70 | } 71 | 72 | public String getUserId() { 73 | return userId; 74 | } 75 | 76 | public void setUserId(String userId) { 77 | this.userId = userId; 78 | } 79 | 80 | public String getUserPassword() { 81 | return userPassword; 82 | } 83 | 84 | public void setUserPassword(String userPassword) { 85 | this.userPassword = userPassword; 86 | } 87 | 88 | public String getUserName() { 89 | return userName; 90 | } 91 | 92 | public void setUserName(String userName) { 93 | this.userName = userName; 94 | } 95 | 96 | public Integer getUserPosition() { 97 | return userPosition; 98 | } 99 | 100 | public void setUserPosition(Integer userPosition) { 101 | this.userPosition = userPosition; 102 | } 103 | 104 | public Integer getUserStatus() { 105 | return userStatus; 106 | } 107 | 108 | public void setUserStatus(Integer userStatus) { 109 | this.userStatus = userStatus; 110 | } 111 | 112 | @Override 113 | public String toString() { 114 | return "User{" + 115 | "userId='" + userId + '\'' + 116 | ", userPassword='" + userPassword + '\'' + 117 | ", userName='" + userName + '\'' + 118 | ", userPosition=" + userPosition + 119 | ", userStatus=" + userStatus + 120 | '}'; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/enums/CertificateTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.enums; 2 | 3 | /** 4 | * @Author: Mr_OO 5 | * @Date: 2022/3/5 20:09 6 | */ 7 | public enum CertificateTypeEnum { 8 | ALL_TYPE(0, "所有类型(用于后端程序查询注入)"), 9 | SCHOLARSHIP_AND_HONORARY_TITLE(1001, "奖学金及荣誉称号类"), 10 | DISCIPLINE_COMPETITION(1002, "学科竞赛类"), 11 | QUALIFICATION_LEVEL(1003, "资格等级类"), 12 | VOLUNTARY_SERVICE(1004, "志愿服务类"), 13 | ART_EXHIBITION(1005, "艺术展览类"), 14 | SPORTS_COMPETITION(1006, "体育竞技类"), 15 | OTHER(1007, "其他类"); 16 | 17 | private Integer status; 18 | private String statusInfo; 19 | 20 | CertificateTypeEnum(Integer status, String statusInfo) { 21 | this.status = status; 22 | this.statusInfo = statusInfo; 23 | } 24 | 25 | public Integer getStatus() { 26 | return status; 27 | } 28 | 29 | public String getStatusInfo() { 30 | return statusInfo; 31 | } 32 | 33 | public static CertificateTypeEnum stateOf(int number) { 34 | for (CertificateTypeEnum value : values()) { 35 | if (value.getStatus() == number) { 36 | return value; 37 | } 38 | } 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/enums/DTOMsgEnum.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.enums; 2 | 3 | /** 4 | * @Author: Mr_OO 5 | * @Date: 2022/3/3 18:28 6 | */ 7 | public enum DTOMsgEnum { 8 | OK(1, "请求成功"), 9 | 10 | EMPTY_INPUT_STR(-1000, "输入数据为空"), 11 | ERROR_INPUT_STR(-1001, "输入数据不符合规范"), 12 | ERROR_EXCEPTION(-1002, "请求失败"), 13 | 14 | ACCOUNT_NOT_EXIST(-2001, "账号不存在"), 15 | WRONG_PASSWORD(-2002, "密码不正确"), 16 | LOGIN_FAIL(-2003, "用户验证失败"), 17 | ACCOUNT_INVALID(-2004, "该用户账号已失效"), 18 | WRONG_ID(-2005,"身份证号码有误"), 19 | 20 | ERROR_IMAGE(-3001, "图片提交失败"), 21 | 22 | NO_SEND_IMMEDIATELY(-4001, "请勿在短时间内重复提交"); 23 | 24 | private int status; 25 | private String statusInfo; 26 | 27 | DTOMsgEnum(int status, String statusInfo) { 28 | this.status = status; 29 | this.statusInfo = statusInfo; 30 | } 31 | 32 | public int getStatus() { 33 | return status; 34 | } 35 | 36 | public String getStatusInfo() { 37 | return statusInfo; 38 | } 39 | 40 | public static DTOMsgEnum stateOf(int number) { 41 | for (DTOMsgEnum value : values()) { 42 | if (value.getStatus() == number) { 43 | return value; 44 | } 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/enums/UserIdStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.enums; 2 | 3 | /** 4 | * 用户账号状态枚举 5 | * @Author: Mr_OO 6 | * @Date: 2022/3/3 18:02 7 | */ 8 | public enum UserIdStatusEnum { 9 | OK(1, "账号正常"),INVALID(-1, "账号已失效"); 10 | 11 | private Integer status; 12 | private String statusInfo; 13 | 14 | UserIdStatusEnum(Integer status, String statusInfo) { 15 | this.status = status; 16 | this.statusInfo = statusInfo; 17 | } 18 | 19 | public Integer getStatus() { 20 | return status; 21 | } 22 | 23 | public String getStatusInfo() { 24 | return statusInfo; 25 | } 26 | 27 | public static UserIdStatusEnum stateOf(int number) { 28 | for (UserIdStatusEnum value : values()) { 29 | if (value.getStatus() == number) { 30 | return value; 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/enums/UserPositionEnum.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.enums; 2 | 3 | /** 4 | * @Author: Mr_OO 5 | * @Date: 2022/3/4 9:46 6 | */ 7 | public enum UserPositionEnum { 8 | STUDENT(1, "学生"), 9 | TEACHER(-1, "老师"); 10 | 11 | private Integer status; 12 | private String statusInfo; 13 | 14 | UserPositionEnum(Integer status, String statusInfo) { 15 | this.status = status; 16 | this.statusInfo = statusInfo; 17 | } 18 | 19 | public Integer getStatus() { 20 | return status; 21 | } 22 | 23 | public String getStatusInfo() { 24 | return statusInfo; 25 | } 26 | 27 | public static UserPositionEnum stateOf(int number) { 28 | for (UserPositionEnum value : values()) { 29 | if (value.getStatus() == number) { 30 | return value; 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/exceptions/CertificateException.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.exceptions; 2 | 3 | /** 4 | * @Author: Mr_OO 5 | * @Date: 2022/3/5 21:11 6 | */ 7 | public class CertificateException extends RuntimeException { 8 | private static final long serialVersionUID = 1058940050993043833L; 9 | 10 | public CertificateException(String message) { 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/exceptions/UserException.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.exceptions; 2 | 3 | /** 4 | * 用户异常类 5 | * @Author: Mr_OO 6 | * @Date: 2022/3/3 18:16 7 | */ 8 | public class UserException extends RuntimeException { 9 | private static final long serialVersionUID = 7688456332310845557L; 10 | 11 | public UserException(String message) { 12 | super(message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/mapper/JurisdictionMapper.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.mapper; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @Author: Mr_OO 7 | * @Date: 2022/3/3 22:13 8 | */ 9 | public interface JurisdictionMapper { 10 | /** 11 | * 查询路由集合 12 | * @return 13 | */ 14 | List queryAllUrls(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.mapper; 2 | 3 | import com.oym.cms.entity.User; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | /** 7 | * @Author: Mr_OO 8 | * @Date: 2022/3/3 18:08 9 | */ 10 | public interface UserMapper { 11 | /** 12 | * 通过账号查询用户 13 | * 14 | * @param userId 15 | * @return 16 | */ 17 | User queryUserById(@Param("userId") String userId); 18 | 19 | /** 20 | * 更新账户信息 21 | * 22 | * @param user 23 | * @return 24 | */ 25 | int updateUser(User user); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/service/CacheService.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service; 2 | 3 | /** 4 | * @Author: Mr_OO 5 | * @Date: 2022/3/3 18:13 6 | */ 7 | public interface CacheService { 8 | /** 9 | * 依据 key前缀删除匹配该模式下的所有key-value 10 | * @param keyPrefix 11 | * @return 12 | */ 13 | void removeFromCache(String keyPrefix); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/service/CertificateService.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service; 2 | 3 | import com.oym.cms.dto.CertificateDTO; 4 | import com.oym.cms.dto.ImageHolder; 5 | import com.oym.cms.entity.Certificate; 6 | 7 | /** 8 | * @Author: Mr_OO 9 | * @Date: 2022/3/5 20:44 10 | */ 11 | public interface CertificateService { 12 | /** 13 | * 添加证书 14 | * @param certificate 15 | * @param imageHolder 16 | * @return 17 | */ 18 | CertificateDTO addCertificate(Certificate certificate, ImageHolder imageHolder); 19 | 20 | /** 21 | * 查询该用户已存储的证书 22 | * @param userId 23 | * @param certificateType 24 | * @param pageIndex 25 | * @param pageSize 26 | * @return 27 | */ 28 | CertificateDTO queryCertificateByUserId(String userId, int certificateType, int pageIndex, int pageSize); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service; 2 | 3 | import com.oym.cms.dto.UserDTO; 4 | import com.oym.cms.entity.User; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | /** 8 | * @Author: Mr_OO 9 | * @Date: 2022/3/3 18:13 10 | */ 11 | public interface UserService { 12 | /** 13 | * 通过账号查询用户 14 | * 15 | * @param userId 16 | * @return 17 | */ 18 | UserDTO queryUserById(@Param("userId") String userId); 19 | 20 | /** 21 | * 登录 22 | * 23 | * @param userId 24 | * @param userPassword 25 | * @return 26 | */ 27 | UserDTO userLogin(@Param("userId") String userId, @Param("userPassword") String userPassword); 28 | 29 | /** 30 | * 更新账户信息 31 | * 32 | * @param user 33 | * @return 34 | */ 35 | UserDTO updateUser(User user); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/service/impl/CacheServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service.impl; 2 | 3 | import com.oym.cms.config.redis.JedisUtil; 4 | import com.oym.cms.service.CacheService; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Set; 9 | 10 | /** 11 | * @Author: Mr_OO 12 | * @Date: 2020/11/23 14:05 13 | */ 14 | @Service 15 | public class CacheServiceImpl implements CacheService { 16 | 17 | @Resource 18 | private JedisUtil.Keys jedisKeys; 19 | 20 | @Override 21 | public void removeFromCache(String keyPrefix) { 22 | Set keySet = jedisKeys.keys(keyPrefix + "*"); 23 | for (String key : keySet) { 24 | if (jedisKeys.exists(key)) { 25 | jedisKeys.del(key); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/service/impl/CertificateServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.JavaType; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.google.common.cache.Cache; 8 | import com.google.common.cache.CacheBuilder; 9 | import com.oym.cms.client.ContractClient; 10 | import com.oym.cms.client.FastDFSClient; 11 | import com.oym.cms.config.redis.JedisUtil; 12 | import com.oym.cms.dto.CertificateDTO; 13 | import com.oym.cms.dto.ImageHolder; 14 | import com.oym.cms.entity.Certificate; 15 | import com.oym.cms.entity.User; 16 | import com.oym.cms.enums.CertificateTypeEnum; 17 | import com.oym.cms.enums.DTOMsgEnum; 18 | import com.oym.cms.exceptions.CertificateException; 19 | import com.oym.cms.mapper.UserMapper; 20 | import com.oym.cms.service.CacheService; 21 | import com.oym.cms.service.CertificateService; 22 | import com.oym.cms.util.ImageUtil; 23 | import com.oym.cms.util.PageCalculator; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.springframework.stereotype.Service; 27 | 28 | import javax.annotation.Resource; 29 | import java.time.Duration; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | /** 34 | * @Author: Mr_OO 35 | * @Date: 2022/3/5 20:52 36 | */ 37 | @Service 38 | public class CertificateServiceImpl implements CertificateService { 39 | 40 | /** 41 | * CertificateServiceImpl log 42 | */ 43 | private static final Logger LOGGER = LoggerFactory.getLogger(CertificateServiceImpl.class); 44 | 45 | /** 46 | * 缓存前缀 47 | */ 48 | private final static String CERTIFICATE_QUERY_SERVICE = "CertificateQueryService"; 49 | 50 | @Resource 51 | private ContractClient contractClient; 52 | @Resource 53 | private UserMapper userMapper; 54 | 55 | @Resource 56 | private JedisUtil.Keys jedisKeys; 57 | @Resource 58 | private JedisUtil.Strings jedisStrings; 59 | @Resource 60 | private CacheService cacheService; 61 | 62 | /** 63 | * 本地缓存引入,防止恶意上传 64 | */ 65 | private Cache dataCache = CacheBuilder.newBuilder() 66 | .expireAfterWrite(Duration.ofSeconds(30)) 67 | .maximumSize(10240) 68 | .concurrencyLevel(4) 69 | .initialCapacity(2048) 70 | .build(); 71 | 72 | @Override 73 | public CertificateDTO addCertificate(Certificate certificate, ImageHolder thumbnail) throws CertificateException { 74 | if (certificate != null 75 | && certificate.getCertificateDescription() != null 76 | && certificate.getCertificateWinTime() != null 77 | && certificate.getCertificateName() != null 78 | && certificate.getCertificateType() != null 79 | && certificate.getUserId() != null) { 80 | try { 81 | //先经过本地缓存判断用户是否恶意上传 82 | String value = dataCache.getIfPresent(certificate.getUserId()); 83 | if (value == null) { 84 | dataCache.put("addCertificate" + certificate.getUserId(), "v"); 85 | } else { 86 | //恶意上传直接跳出方法 87 | LOGGER.info("CertificateServiceImpl addCertificate fail, NO_SEND_IMMEDIATELY, certificate:{}", JSON.toJSONString(certificate)); 88 | return new CertificateDTO(null, DTOMsgEnum.NO_SEND_IMMEDIATELY.getStatus()); 89 | } 90 | //生成文件名 91 | String imageName = ImageUtil.getRandomFileName(certificate.getUserId(), thumbnail.getImageName()); 92 | //存储图片到分布式服务器系统 93 | String[] result = FastDFSClient.uploadFile(thumbnail.getImage(), imageName); 94 | //result结果示例:[group1, M00/00/00/CgAYCGJFpQKACftIAAAbnjkyo8A652.png], 生成图片URL后半截用于存储 95 | String imageUrl = ImageUtil.getImageUrl(result); 96 | if (imageUrl == null) { 97 | LOGGER.info("CertificateServiceImpl addCertificate fail,imageUrl get fail certificate:{}", JSON.toJSONString(certificate)); 98 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 99 | } 100 | //获取存储证书的用户信息 101 | User user = userMapper.queryUserById(certificate.getUserId()); 102 | if (user == null) { 103 | LOGGER.info("CertificateServiceImpl addCertificate fail, no such user certificate:{}", JSON.toJSONString(certificate)); 104 | return new CertificateDTO(null, DTOMsgEnum.ACCOUNT_NOT_EXIST.getStatus()); 105 | } 106 | //存储区块链 107 | int res = contractClient.registerCertificate( 108 | user.getSchoolFlag(), user.getUserId(), user.getUserName(), certificate.getCertificateName(), 109 | String.valueOf(certificate.getCertificateType()), String.valueOf(certificate.getCertificateWinTime().getTime()), 110 | certificate.getCertificateDescription(), imageUrl); 111 | if (DTOMsgEnum.OK.getStatus() != res) { 112 | LOGGER.info("CertificateServiceImpl addCertificate fail certificate:{}", JSON.toJSONString(certificate)); 113 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 114 | } 115 | //清空该账号查询缓存 116 | cacheService.removeFromCache(CERTIFICATE_QUERY_SERVICE + "type" 117 | + certificate.getCertificateType() + "id" + user.getUserId()); 118 | LOGGER.info("CertificateServiceImpl addCertificate success certificate:{}", JSON.toJSONString(certificate)); 119 | return new CertificateDTO(null, DTOMsgEnum.OK.getStatus()); 120 | } catch (CertificateException e) { 121 | LOGGER.error("CertificateServiceImpl addCertificate Exception certificate:{}", JSON.toJSONString(certificate)); 122 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 123 | } 124 | } 125 | return new CertificateDTO(null, DTOMsgEnum.EMPTY_INPUT_STR.getStatus()); 126 | } 127 | 128 | @Override 129 | public CertificateDTO queryCertificateByUserId(String userId, int certificateType, int pageIndex, int pageSize) { 130 | if (userId != null) { 131 | try { 132 | //查询起始索引 133 | int rowIndex = PageCalculator.calculatorRowIndex(pageIndex, pageSize); 134 | //查询截止索引边界 135 | int rowEndIndex = rowIndex + pageSize; 136 | //生成缓存key 137 | StringBuilder redisKey = new StringBuilder(); 138 | redisKey.append(CERTIFICATE_QUERY_SERVICE) 139 | .append("type") 140 | .append(certificateType) 141 | .append("id") 142 | .append(userId) 143 | .append("index") 144 | .append(pageIndex) 145 | .append("size") 146 | .append(pageSize); 147 | //查询证书列表 先走redis缓存 148 | List certificateList = null; 149 | ObjectMapper mapper = new ObjectMapper(); 150 | if (jedisKeys.exists(redisKey.toString())) { 151 | String jsonString = jedisStrings.get(redisKey.toString()); 152 | JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, Certificate.class); 153 | try { 154 | certificateList = mapper.readValue(jsonString, javaType); 155 | } catch (JsonProcessingException e) { 156 | LOGGER.error("CertificateServiceImpl queryCertificateByUserId REDIS Exception userId:{}", userId); 157 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 158 | } 159 | } else { 160 | //缓存不存在该列表信息 161 | certificateList = contractClient.queryCertificateList(userId); 162 | String jsonString = null; 163 | try { 164 | jsonString = mapper.writeValueAsString(certificateList); 165 | } catch (JsonProcessingException e) { 166 | LOGGER.error("CertificateServiceImpl queryCertificateByUserId REDIS Exception userId:{}", userId); 167 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 168 | } 169 | jedisStrings.set(redisKey.toString(), jsonString); 170 | } 171 | if (certificateList == null) { 172 | LOGGER.error("CertificateServiceImpl queryCertificateByUserId BCOS Exception userId:{}", userId); 173 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 174 | } 175 | int size = certificateList.size(); 176 | CertificateDTO certificateDTO = new CertificateDTO(); 177 | List res = new ArrayList<>(); 178 | if (CertificateTypeEnum.ALL_TYPE.getStatus().equals(certificateType)) { 179 | //所有类别证书查询 180 | //起始点超过总数情况 181 | if (rowIndex > size) { 182 | return new CertificateDTO(DTOMsgEnum.OK.getStatus(), new ArrayList()); 183 | } 184 | //边界判断 185 | if (size < rowEndIndex) { 186 | rowEndIndex = size; 187 | } 188 | //注入证书总数量 189 | certificateDTO.setCount(size); 190 | for (int i = rowIndex; i < rowEndIndex; i++) { 191 | res.add(certificateList.get(i)); 192 | } 193 | } else { 194 | List typeList = new ArrayList<>(); 195 | for (Certificate certificate : certificateList) { 196 | if (certificate.getCertificateType().equals(certificateType)) { 197 | typeList.add(certificate); 198 | } 199 | } 200 | int count = typeList.size(); 201 | //注入该类证书总数量 202 | certificateDTO.setCount(count); 203 | if (rowIndex > count) { 204 | return new CertificateDTO(DTOMsgEnum.OK.getStatus(), new ArrayList()); 205 | } 206 | if (count < rowEndIndex) { 207 | rowEndIndex = count; 208 | } 209 | for (int i = rowIndex; i < rowEndIndex; i++) { 210 | res.add(typeList.get(i)); 211 | } 212 | } 213 | certificateDTO.setCertificateList(res); 214 | certificateDTO.setMsg(DTOMsgEnum.OK.getStatus()); 215 | return certificateDTO; 216 | } catch (Exception e) { 217 | LOGGER.error("CertificateServiceImpl queryCertificateByUserId Exception userId:{}", userId); 218 | return new CertificateDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 219 | } 220 | } 221 | return new CertificateDTO(null, DTOMsgEnum.EMPTY_INPUT_STR.getStatus()); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.google.common.cache.Cache; 5 | import com.google.common.cache.CacheBuilder; 6 | import com.oym.cms.dto.UserDTO; 7 | import com.oym.cms.entity.User; 8 | import com.oym.cms.enums.DTOMsgEnum; 9 | import com.oym.cms.enums.UserIdStatusEnum; 10 | import com.oym.cms.exceptions.UserException; 11 | import com.oym.cms.mapper.UserMapper; 12 | import com.oym.cms.service.UserService; 13 | import com.oym.cms.util.PasswordHelper; 14 | import org.apache.shiro.SecurityUtils; 15 | import org.apache.shiro.authc.AuthenticationException; 16 | import org.apache.shiro.authc.IncorrectCredentialsException; 17 | import org.apache.shiro.authc.UnknownAccountException; 18 | import org.apache.shiro.authc.UsernamePasswordToken; 19 | import org.apache.shiro.subject.Subject; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.stereotype.Service; 23 | 24 | import javax.annotation.Resource; 25 | import java.time.Duration; 26 | 27 | /** 28 | * @Author: Mr_OO 29 | * @Date: 2022/3/3 18:13 30 | */ 31 | @Service 32 | public class UserServiceImpl implements UserService { 33 | 34 | /** 35 | * UserServiceImpl log 36 | */ 37 | private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); 38 | 39 | @Resource 40 | private UserMapper userMapper; 41 | 42 | /** 43 | * 本地缓存引入,防止恶意上传 44 | */ 45 | private Cache dataCache = CacheBuilder.newBuilder() 46 | .expireAfterWrite(Duration.ofSeconds(3)) 47 | .maximumSize(10240) 48 | .concurrencyLevel(4) 49 | .initialCapacity(2048) 50 | .build(); 51 | 52 | @Override 53 | public UserDTO queryUserById(String userId) throws UserException { 54 | LOGGER.info("UserServiceImpl queryUserById userId:{}", userId); 55 | if (userId != null) { 56 | try { 57 | User user = userMapper.queryUserById(userId); 58 | LOGGER.info("UserServiceImpl queryUserById userId:{}, user:{}", userId, JSON.toJSONString(user)); 59 | if (user == null || UserIdStatusEnum.INVALID.getStatus().equals(user.getUserStatus())) { 60 | return new UserDTO(null, DTOMsgEnum.OK.getStatus()); 61 | } 62 | return new UserDTO(user, DTOMsgEnum.OK.getStatus()); 63 | } catch (UserException e) { 64 | LOGGER.error("UserServiceImpl queryUserById error userId:{}", userId); 65 | return new UserDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 66 | } 67 | } 68 | return new UserDTO(null, DTOMsgEnum.EMPTY_INPUT_STR.getStatus()); 69 | } 70 | 71 | @Override 72 | public UserDTO userLogin(String userId, String userPassword) throws UserException { 73 | LOGGER.info("UserServiceImpl userLogin userId:{}", userId); 74 | if (userId != null && userPassword != null) { 75 | try { 76 | //先经过本地缓存判断用户是否恶意上传 77 | String value = dataCache.getIfPresent(userId); 78 | if (value == null) { 79 | dataCache.put("userLogin" + userId, "v"); 80 | } else { 81 | //恶意上传直接跳出方法 82 | LOGGER.info("UserServiceImpl userLogin fail, NO_SEND_IMMEDIATELY, userId:{}", userId); 83 | return new UserDTO(null, DTOMsgEnum.NO_SEND_IMMEDIATELY.getStatus()); 84 | } 85 | User userQuery = userMapper.queryUserById(userId); 86 | if (userQuery == null) { 87 | LOGGER.info("UserServiceImpl userLogin userId:{}, Nonexistent Account", userId); 88 | return new UserDTO(null, DTOMsgEnum.ACCOUNT_NOT_EXIST.getStatus()); 89 | } 90 | if (UserIdStatusEnum.INVALID.getStatus().equals(userQuery.getUserStatus())) { 91 | LOGGER.info("UserServiceImpl userLogin userId:{}, invalid Account", userId); 92 | return new UserDTO(null, DTOMsgEnum.ACCOUNT_INVALID.getStatus()); 93 | } 94 | // 获取Subject实例对象,用户实例 95 | Subject currentUser = SecurityUtils.getSubject(); 96 | // 将用户名和密码封装到UsernamePasswordToken 97 | UsernamePasswordToken token = new UsernamePasswordToken(userId, userPassword); 98 | // 传到 MyShiroRealm 类中的方法进行认证 99 | currentUser.login(token); 100 | // 构建缓存用户信息返回给前端 101 | User user = (User) currentUser.getPrincipals().getPrimaryPrincipal(); 102 | //设置TOKEN返回给前端 103 | user.setUserToken(currentUser.getSession().getId().toString()); 104 | LOGGER.info("UserServiceImpl userLogin userId:{}, success", userId); 105 | return new UserDTO(user, DTOMsgEnum.OK.getStatus()); 106 | } catch (UnknownAccountException e) { 107 | LOGGER.error("UserServiceImpl queryUserById error userId:{}", userId); 108 | return new UserDTO(null, DTOMsgEnum.ACCOUNT_NOT_EXIST.getStatus()); 109 | } catch (IncorrectCredentialsException e) { 110 | LOGGER.error("UserServiceImpl queryUserById error userId:{}", userId); 111 | return new UserDTO(null, DTOMsgEnum.WRONG_PASSWORD.getStatus()); 112 | } catch (AuthenticationException e) { 113 | LOGGER.error("UserServiceImpl queryUserById error userId:{}", userId); 114 | return new UserDTO(null, DTOMsgEnum.LOGIN_FAIL.getStatus()); 115 | }catch (UserException e) { 116 | LOGGER.error("UserServiceImpl queryUserById error userId:{}", userId); 117 | return new UserDTO(null, DTOMsgEnum.LOGIN_FAIL.getStatus()); 118 | } 119 | } 120 | return new UserDTO(null, DTOMsgEnum.EMPTY_INPUT_STR.getStatus()); 121 | } 122 | 123 | @Override 124 | public UserDTO updateUser(User user) { 125 | if (user != null && user.getUserId() != null) { 126 | try { 127 | //先经过本地缓存判断用户是否恶意上传 128 | String value = dataCache.getIfPresent(user.getUserId()); 129 | if (value == null) { 130 | dataCache.put("updateUser" + user.getUserId(), "v"); 131 | } else { 132 | //恶意上传直接跳出方法 133 | LOGGER.info("UserServiceImpl updateUser fail, NO_SEND_IMMEDIATELY, userId:{}", user.getUserId()); 134 | return new UserDTO(null, DTOMsgEnum.NO_SEND_IMMEDIATELY.getStatus()); 135 | } 136 | User userQuery = userMapper.queryUserById(user.getUserId()); 137 | if (userQuery == null) { 138 | LOGGER.info("UserServiceImpl updateUser user:{}, Nonexistent Account", JSON.toJSONString(user)); 139 | return new UserDTO(null, DTOMsgEnum.ACCOUNT_NOT_EXIST.getStatus()); 140 | } 141 | //更改密码逻辑 142 | if (user.getUserPassword() != null && user.getId() != null) { 143 | if (!userQuery.getId().equals(user.getId())) { 144 | LOGGER.info("UserServiceImpl updateUser user:{}, ID WRONG", JSON.toJSONString(user)); 145 | return new UserDTO(null, DTOMsgEnum.WRONG_ID.getStatus()); 146 | } 147 | //对新密码进行加密 148 | PasswordHelper.encryptPassword(user); 149 | } 150 | int res = userMapper.updateUser(user); 151 | if (res == 0) { 152 | LOGGER.info("UserServiceImpl updateUser user:{}, update fail", JSON.toJSONString(user)); 153 | return new UserDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 154 | } 155 | return new UserDTO(user, DTOMsgEnum.OK.getStatus()); 156 | } catch (UserException e) { 157 | LOGGER.error("UserServiceImpl updateUser exception user:{}", JSON.toJSONString(user)); 158 | return new UserDTO(null, DTOMsgEnum.ERROR_EXCEPTION.getStatus()); 159 | } 160 | } 161 | return new UserDTO(null, DTOMsgEnum.EMPTY_INPUT_STR.getStatus()); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/CertificateIdBuildUtil.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | /** 4 | * 证书序列号生成器 5 | * @Author: Mr_OO 6 | * @Date: 2022/3/5 19:49 7 | */ 8 | public class CertificateIdBuildUtil { 9 | 10 | /** 11 | * 机构名称 12 | */ 13 | private static final String ORGANIZATION_NAME = "sicnu"; 14 | 15 | /** 16 | * 生成证书序列号 17 | * @param userId 证书所有者账户ID 18 | * @param count 证书所有者已存储证书数量 19 | * @return 20 | */ 21 | public static String bornNewId(String userId, int count) { 22 | StringBuilder result = new StringBuilder(); 23 | result.append(ORGANIZATION_NAME).append(userId).append(count + 1); 24 | return result.toString(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/DESUtil.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.KeyGenerator; 5 | import java.security.Key; 6 | import java.security.SecureRandom; 7 | import java.util.Base64; 8 | 9 | /** 10 | * DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法 11 | * @Author: Mr_OO 12 | * @Date: 2022/3/1 13:28 13 | */ 14 | public class DESUtil { 15 | private static Key key; 16 | /** 17 | * 密钥key 18 | */ 19 | private static String KEY_STR = "myKey"; 20 | private static String CHARSET_NAME = "UTF-8"; 21 | private static String ALGORITHM = "DES"; 22 | 23 | static { 24 | try { 25 | // 生成DES算法对象 26 | KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM); 27 | // 运用SHA1安全策略 28 | SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); 29 | // 设置上密钥种子 30 | secureRandom.setSeed(KEY_STR.getBytes()); 31 | // 初始化基于SHA1的算法对象 32 | generator.init(secureRandom); 33 | // 生成密钥对象 34 | key = generator.generateKey(); 35 | generator = null; 36 | } catch (Exception e) { 37 | throw new RuntimeException(e); 38 | } 39 | } 40 | 41 | /** 42 | * 获取加密后的信息 43 | * @param str 44 | * @return 45 | */ 46 | public static String getEncryptString(String str) { 47 | try { 48 | // 按UTF8编码 49 | byte[] bytes = str.getBytes(CHARSET_NAME); 50 | // 获取加密对象 51 | Cipher cipher = Cipher.getInstance(ALGORITHM); 52 | // 初始化密码信息 53 | cipher.init(Cipher.ENCRYPT_MODE, key); 54 | // 加密 55 | byte[] doFinal = cipher.doFinal(bytes); 56 | // byte[]to encode好的String并返回 57 | return Base64.getEncoder().encodeToString(doFinal); 58 | } catch (Exception e) { 59 | // TODO: handle exception 60 | throw new RuntimeException(e); 61 | } 62 | } 63 | 64 | /** 65 | * 获取解密之后的信息 66 | * @param str 67 | * @return 68 | */ 69 | public static String getDecryptString(String str) { 70 | try { 71 | // 将字符串decode成byte[] 72 | byte[] bytes = Base64.getDecoder().decode(str); 73 | // 获取解密对象 74 | Cipher cipher = Cipher.getInstance(ALGORITHM); 75 | // 初始化解密信息 76 | cipher.init(Cipher.DECRYPT_MODE, key); 77 | // 解密 78 | byte[] doFinal = cipher.doFinal(bytes); 79 | // 返回解密之后的信息 80 | return new String(doFinal, CHARSET_NAME); 81 | } catch (Exception e) { 82 | // TODO: handle exception 83 | throw new RuntimeException(e); 84 | } 85 | } 86 | 87 | public static void main(String[] args) { 88 | //输入自己数据库的账号和密码进行获取 89 | System.out.println(getEncryptString("root")); 90 | System.out.println(getEncryptString("666666")); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/EncryptionUtil.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | import java.security.MessageDigest; 4 | 5 | /** 6 | * 密码加密工具类 7 | * @Author: Mr_OO 8 | * @Date: 2022/3/1 13:47 9 | */ 10 | public class EncryptionUtil { 11 | /** 12 | * 对传入的String进行MD5加密 13 | * 14 | * @param s 15 | * @return 16 | */ 17 | public static final String getMd5(String s) { 18 | // 16进制数组 19 | char[] hexDigits = { '1', '2', '3', '4', '5', '5', '4', '3', '2', '1', 'a', 'b', 'c', 'd', 'e', 'f' }; 20 | try { 21 | char[] str; 22 | // 将传入的字符串转换成byte数组 23 | byte[] strTemp = s.getBytes(); 24 | // 获取MD5加密对象 25 | MessageDigest mdTemp = MessageDigest.getInstance("MD5"); 26 | // 传入需要加密的目标数组 27 | mdTemp.update(strTemp); 28 | // 获取加密后的数组 29 | byte[] md = mdTemp.digest(); 30 | int j = md.length; 31 | str = new char[j * 2]; 32 | int k = 0; 33 | // 将数组做位移 34 | for (int i = 0; i < j; i++) { 35 | byte byte0 = md[i]; 36 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 37 | str[k++] = hexDigits[byte0 & 0xf]; 38 | } 39 | // 转换成String并返回 40 | return new String(str); 41 | } catch (Exception e) { 42 | return null; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/HttpServletRequestUtil.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | /** 6 | * 获取Request中的键值对数据 7 | * @Author: Mr_OO 8 | * @Date: 2022/3/1 13:48 9 | */ 10 | public class HttpServletRequestUtil { 11 | public static int getInt(HttpServletRequest request, String key) { 12 | try { 13 | return Integer.decode(request.getParameter(key)); 14 | } catch (Exception e) { 15 | return -1000; 16 | } 17 | } 18 | 19 | public static long getLong(HttpServletRequest request,String key) { 20 | try { 21 | return Long.valueOf(request.getParameter(key)); 22 | } catch (Exception e) { 23 | return -1000L; 24 | } 25 | } 26 | 27 | public static double getDouble(HttpServletRequest request,String key) { 28 | try { 29 | return Double.valueOf(request.getParameter(key)); 30 | } catch (Exception e) { 31 | return -1000d; 32 | } 33 | } 34 | 35 | public static boolean getBoolean(HttpServletRequest request,String key) { 36 | try { 37 | return Boolean.valueOf(request.getParameter(key)); 38 | } catch (Exception e) { 39 | return false; 40 | } 41 | } 42 | 43 | public static String getString(HttpServletRequest request,String key) { 44 | try { 45 | String result = request.getParameter(key); 46 | if (result != null) { 47 | result = result.trim(); 48 | } 49 | if("".equals(result)) { 50 | result = null; 51 | } 52 | return result; 53 | } catch (Exception e) { 54 | return null; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/ImageUtil.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.Random; 6 | 7 | /** 8 | * 图片处理工具类 9 | * @Author: Mr_OO 10 | * @Date: 2022/3/31 21:13 11 | */ 12 | public class ImageUtil { 13 | 14 | public static final String IMAGE_URL_PRE = "http://101.43.139.237:8081/"; 15 | 16 | /** 17 | * 日期格式 18 | */ 19 | private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 20 | /** 21 | * 随机数生成对象 22 | */ 23 | private static final Random random = new Random(); 24 | 25 | /** 26 | * 随机文件名生成算法 27 | * @return 28 | */ 29 | public static String getRandomFileName(String userId, String fileName) { 30 | //获取随机的五位数 31 | int ranNum = random.nextInt(89999) + 10000; 32 | //当前年月日小时分秒 33 | String nowTimeStr = sDateFormat.format(new Date()).substring(7); 34 | //账号后半部分 35 | String userIdLast = userId.substring(userId.length() / 2); 36 | //文件后缀 37 | String imageEx = fileName.substring(fileName.lastIndexOf(".")); 38 | return userIdLast + nowTimeStr + ranNum + imageEx; 39 | } 40 | 41 | /** 42 | * 获取图片远程访问URL后缀 43 | * @param result 44 | * @return 45 | */ 46 | public static String getImageUrl(String[] result) { 47 | if (result.length < 2) { 48 | return null; 49 | } else { 50 | return "/" + result[0] + "/" + result[1]; 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/PageCalculator.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | /** 4 | * 分页查询 —— 行索引计算工具 5 | * @Author: Mr_OO 6 | * @Date: 2022/3/8 12:38 7 | */ 8 | public class PageCalculator { 9 | public static int calculatorRowIndex(int pageIndex, int pageSize) { 10 | return (pageIndex >= 0) ? pageIndex * pageSize : 0; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/oym/cms/util/PasswordHelper.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.util; 2 | 3 | import com.oym.cms.entity.User; 4 | import com.oym.cms.enums.UserIdStatusEnum; 5 | import com.oym.cms.enums.UserPositionEnum; 6 | import org.apache.shiro.crypto.hash.SimpleHash; 7 | import org.apache.shiro.util.ByteSource; 8 | 9 | /** 10 | * 密码生成工具 11 | * @Author: Mr_OO 12 | * @Date: 2022/3/4 9:41 13 | */ 14 | public class PasswordHelper { 15 | private final static String ALGORITHM_NAME = "MD5"; 16 | private final static int HASH_ITERATIONS = 20; 17 | 18 | /** 19 | * 对用户密码加密,并将密码注入对象 20 | * @param user 21 | */ 22 | public static void encryptPassword(User user) { 23 | String newPassword = new SimpleHash(ALGORITHM_NAME, user.getUserPassword(), 24 | ByteSource.Util.bytes(user.getUserId()), HASH_ITERATIONS).toHex(); 25 | user.setUserPassword(newPassword); 26 | } 27 | 28 | /** 29 | * 获取加密后的新密码 30 | * @param userId 31 | * @param userPassword 32 | * @return 33 | */ 34 | public static String encryptPassword(String userId, String userPassword) { 35 | String newPassword = new SimpleHash(ALGORITHM_NAME, userPassword, 36 | ByteSource.Util.bytes(userId), HASH_ITERATIONS).toHex(); 37 | return newPassword; 38 | } 39 | 40 | 41 | public static void main(String[] args) { 42 | User user = new User(); 43 | user.setUserId("2018110429"); 44 | user.setUserName("欧阳鸣"); 45 | user.setUserPosition(UserPositionEnum.STUDENT.getStatus()); 46 | user.setUserStatus(UserIdStatusEnum.OK.getStatus()); 47 | 48 | //密码生成 49 | String newPassword = new SimpleHash(ALGORITHM_NAME, "20000602", 50 | ByteSource.Util.bytes(user.getUserId()), HASH_ITERATIONS).toHex(); 51 | System.out.println("加密后的密码是:" + newPassword); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/resources/FastDFSConfig.properties: -------------------------------------------------------------------------------- 1 | #FastDFS 2 | connect_timeout=10 3 | network_timeout=30 4 | charset=UTF-8 5 | http.tracker_http_port=9080 6 | tracker_server=101.43.139.237:22122 -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: / 5 | encoding: 6 | charset: UTF-8 7 | enabled: true 8 | force: true 9 | tomcat: 10 | uri-encoding: UTF-8 11 | 12 | #数据库驱动 13 | jdbc: 14 | driver: com.mysql.cj.jdbc.Driver 15 | url: jdbc:mysql://localhost:3306/cms?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai 16 | username: WnplV/ietfQ= 17 | password: DAnmDPxeeqw= 18 | 19 | #Mybatis 20 | mybatis_config_file: mybatis-config.xml 21 | mybatis: 22 | mapper-locations: /mapper/**.xml 23 | type_alias_package: com.oym.cms.entity 24 | 25 | #Redis 26 | redis: 27 | hostname: 127.0.0.1 28 | port: 6379 29 | pool: 30 | maxActive: 200 31 | maxIdle: 50 32 | maxWait: 3000 33 | testOnBorrow: true 34 | expire: 1800 35 | timeout: 1800 36 | 37 | com.mchange.v2.log.MLog: com.mchange.v2.log.FallbackMLog 38 | com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL: OFF 39 | multipart.enabled: true 40 | 41 | #区块链 42 | cryptoMaterial: 43 | certPath: "conf" 44 | network: 45 | peers: 46 | - "101.43.139.237:20200" 47 | - "101.43.139.237:20201" 48 | account: 49 | keyStoreDir: "account" 50 | accountFileFormat: "pem" 51 | threadPool: 52 | maxBlockingQueueSize: "102400" -------------------------------------------------------------------------------- /src/main/resources/conf/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBVzCB/wIJAP6oLZBaSpIRMAoGCCqGSM49BAMCMDUxDjAMBgNVBAMMBWNoYWlu 3 | MRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjAgFw0yMjA0MTAx 4 | MDMwMjdaGA8yMTIyMDMxNzEwMzAyN1owNTEOMAwGA1UEAwwFY2hhaW4xEzARBgNV 5 | BAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMFYwEAYHKoZIzj0CAQYFK4EE 6 | AAoDQgAEjEyAQieq4FuCZ7wdZF7jvPn4sA43t3lfkQsFSOyT0Axp8X7jp+qE5tf3 7 | /sQcWGcYS13QCjAFFgzGGhhVWHTh/TAKBggqhkjOPQQDAgNHADBEAiBYd9GeGaxH 8 | ITkuYUF7LXg5P+5M/T6fshM8SBRGcgLEnQIgJemL3vvjxnhx9ppubTmH+dEtaMSt 9 | kBCanizxTTJRdyo= 10 | -----END CERTIFICATE----- 11 | -------------------------------------------------------------------------------- /src/main/resources/conf/sdk.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBdzCCAR6gAwIBAgIJAKvKWQu12aZUMAoGCCqGSM49BAMCMDcxDzANBgNVBAMM 3 | BmFnZW5jeTETMBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5MCAX 4 | DTIyMDQxMDEwMzAyN1oYDzIxMjIwMzE3MTAzMDI3WjAxMQwwCgYDVQQDDANzZGsx 5 | EzARBgNVBAoMCmZpc2NvLWJjb3MxDDAKBgNVBAsMA3NkazBWMBAGByqGSM49AgEG 6 | BSuBBAAKA0IABCdXt4kiIW/ygiQLrbnBRL537h/Um2fQtkL300KCmMfkxQ7p3Mrk 7 | Jru52gLsBcq/yha9lq0Py0VH0bnvZEHZ/4WjGjAYMAkGA1UdEwQCMAAwCwYDVR0P 8 | BAQDAgXgMAoGCCqGSM49BAMCA0cAMEQCIGLSMOKw6qRE4wMN9nfca+Tz1TA9mo7F 9 | rnyZ6VOnKptzAiBNEYWqH4nghlBuj0RbOg9urqZOW+O3Ztpu5J34nI3YXA== 10 | -----END CERTIFICATE----- 11 | -----BEGIN CERTIFICATE----- 12 | MIIBcDCCARagAwIBAgIJAPibx2ORKjqCMAoGCCqGSM49BAMCMDUxDjAMBgNVBAMM 13 | BWNoYWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjAeFw0y 14 | MjA0MTAxMDMwMjdaFw0zMjA0MDcxMDMwMjdaMDcxDzANBgNVBAMMBmFnZW5jeTET 15 | MBEGA1UECgwKZmlzY28tYmNvczEPMA0GA1UECwwGYWdlbmN5MFYwEAYHKoZIzj0C 16 | AQYFK4EEAAoDQgAEcyfITnCsXa1ce/v9AbqTEuKGtpROtY1T1CfKwjkDnIInJWTa 17 | DOMWWfl/uij7iMZ/cTCYQTHpJ5cPO3DFV/wrSaMQMA4wDAYDVR0TBAUwAwEB/zAK 18 | BggqhkjOPQQDAgNIADBFAiEAslS3O8UnlYzzn8ZabrD9cLotoSLzT064cwnnQ9jc 19 | gJgCIBRx+PXZ0Xyv+1vTisOT5Z8q/y7p6gxkR3DTxyPOOVtz 20 | -----END CERTIFICATE----- 21 | -----BEGIN CERTIFICATE----- 22 | MIIBVzCB/wIJAP6oLZBaSpIRMAoGCCqGSM49BAMCMDUxDjAMBgNVBAMMBWNoYWlu 23 | MRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjAgFw0yMjA0MTAx 24 | MDMwMjdaGA8yMTIyMDMxNzEwMzAyN1owNTEOMAwGA1UEAwwFY2hhaW4xEzARBgNV 25 | BAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMFYwEAYHKoZIzj0CAQYFK4EE 26 | AAoDQgAEjEyAQieq4FuCZ7wdZF7jvPn4sA43t3lfkQsFSOyT0Axp8X7jp+qE5tf3 27 | /sQcWGcYS13QCjAFFgzGGhhVWHTh/TAKBggqhkjOPQQDAgNHADBEAiBYd9GeGaxH 28 | ITkuYUF7LXg5P+5M/T6fshM8SBRGcgLEnQIgJemL3vvjxnhx9ppubTmH+dEtaMSt 29 | kBCanizxTTJRdyo= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /src/main/resources/conf/sdk.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQguMc21S4gO+dM57mivj5U 3 | oduzl/Kzx4fw9YEN4K7Ua4ahRANCAAQnV7eJIiFv8oIkC625wUS+d+4f1Jtn0LZC 4 | 99NCgpjH5MUO6dzK5Ca7udoC7AXKv8oWvZatD8tFR9G572RB2f+F 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /src/main/resources/conf/sdk.publickey: -------------------------------------------------------------------------------- 1 | 2757b78922216ff282240badb9c144be77ee1fd49b67d0b642f7d3428298c7e4c50ee9dccae426bbb9da02ec05cabfca16bd96ad0fcb4547d1b9ef6441d9ff85 2 | -------------------------------------------------------------------------------- /src/main/resources/contract/CertificateIQ.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "./Table.sol"; 5 | 6 | contract CertificateIQ{ 7 | 8 | event registerResult(int ret); 9 | event createResult(int ret); 10 | 11 | /*用于临时接收查询得到的数据*/ 12 | struct CertificateItem { 13 | uint256 size; 14 | uint256[] ID; 15 | string[] schoolFlag; 16 | string[] stuNumber; 17 | string[] userName; 18 | string[] cmsName; 19 | string[] cmsType; 20 | string[] cmsWinTime; 21 | string[] cmsDesc; 22 | string[] cmsUrl; 23 | } 24 | 25 | string constant TABLE_NAME = "t_cms"; 26 | 27 | // 证书信息表 28 | // | 证书id | 学校标识 | 学号 | 姓名 | 证书名称 | 证书类别 | 颁发时间 | 证书描述 | 证书凭证URL | 29 | // |---------|------------|-----------|----------|---------|---------|------------|---------|-----------| 30 | // | ID | schoolFlag | stuNumber | userName | cmsName | cmsType | cmsWinTime | cmsDesc | cmsUrl | 31 | // |---------|------------|-----------|----------|---------|---------|------------|---------|-----------| 32 | // 33 | 34 | // 创建表 35 | function create() 36 | public 37 | returns(int) 38 | { 39 | TableFactory tf = TableFactory(0x1001); 40 | int count = tf.createTable(TABLE_NAME, "ID", "schoolFlag,stuNumber,userName,cmsName,cmsType,cmsWinTime,cmsDesc,cmsUrl"); 41 | emit createResult(count); 42 | return count; 43 | } 44 | 45 | //添加证书基本信息 46 | function register(string schoolFlag, string stuNumber, string userName, 47 | string cmsName, string cmsType, string cmsWinTime, string cmsDesc, string cmsUrl) 48 | public 49 | returns(int) 50 | { 51 | Table table = TableFactory(0x1001).openTable(TABLE_NAME); 52 | Entry entry = table.newEntry(); 53 | entry.set("ID",int(1)); 54 | entry.set("schoolFlag", schoolFlag); 55 | entry.set("stuNumber", stuNumber); 56 | entry.set("userName", userName); 57 | entry.set("cmsName", cmsName); 58 | entry.set("cmsType", cmsType); 59 | entry.set("cmsWinTime", cmsWinTime); 60 | entry.set("cmsDesc", cmsDesc); 61 | entry.set("cmsUrl", cmsUrl); 62 | int count = table.insert(uint2str(1), entry); 63 | int ret = 0; 64 | if (count != 1) { 65 | ret = 2; 66 | } 67 | emit registerResult(ret); 68 | return ret; 69 | } 70 | 71 | /*根据学号查询证书集合,备注:只返回部分重要信息*/ 72 | function select(string stuNumber) 73 | public 74 | view 75 | returns(uint256, string[], string[], string[], string[], string[]) 76 | { 77 | Table table = TableFactory(0x1001).openTable(TABLE_NAME); 78 | Condition condition = table.newCondition(); 79 | condition.EQ("stuNumber", stuNumber); 80 | Entries entries = table.select(uint2str(1), condition); 81 | uint256 size= uint256(entries.size()); 82 | CertificateItem memory item = CertificateItem(size, new uint[](size), 83 | new string[](size), new string[](size), new string[](size), new string[](size), 84 | new string[](size), new string[](size), new string[](size), new string[](size)); 85 | item.size = size; 86 | for (uint256 i = 0; i < size; i++) { 87 | Entry entry = entries.get(int(i)); 88 | item.cmsName[i] = entry.getString("cmsName"); 89 | item.cmsType[i] = entry.getString("cmsType"); 90 | item.cmsWinTime[i] = entry.getString("cmsWinTime"); 91 | item.cmsDesc[i] = entry.getString("cmsDesc"); 92 | item.cmsUrl[i] = entry.getString("cmsUrl"); 93 | } 94 | return (item.size, item.cmsName, item.cmsType, item.cmsWinTime, item.cmsDesc, item.cmsUrl); 95 | } 96 | 97 | function uint2str(uint256 i) constant returns (string) { 98 | if (i == 0) return "0"; 99 | uint j = i; 100 | uint length; 101 | while (j != 0){ 102 | length++; 103 | j /= 10; 104 | } 105 | bytes memory bstr = new bytes(length); 106 | uint k = length - 1; 107 | while (i != 0){ 108 | bstr[k--] = byte(48 + i % 10); 109 | i /= 10; 110 | } 111 | return string(bstr); 112 | } 113 | } -------------------------------------------------------------------------------- /src/main/resources/contract/Table.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | pragma experimental ABIEncoderV2; 3 | 4 | contract TableFactory { 5 | function openTable(string memory) public view returns (Table); //open table 6 | function createTable(string, string, string) public returns (int256); //create table 7 | } 8 | 9 | //select condition 10 | contract Condition { 11 | function EQ(string, int256) public; 12 | function EQ(string, string) public; 13 | 14 | function NE(string, int256) public; 15 | function NE(string, string) public; 16 | 17 | function GT(string, int256) public; 18 | function GE(string, int256) public; 19 | 20 | function LT(string, int256) public; 21 | function LE(string, int256) public; 22 | 23 | function limit(int256) public; 24 | function limit(int256, int256) public; 25 | } 26 | 27 | //one record 28 | contract Entry { 29 | function getInt(string) public view returns (int256); 30 | function getUInt(string) public view returns (int256); 31 | function getAddress(string) public view returns (address); 32 | function getBytes64(string) public view returns (bytes1[64]); 33 | function getBytes32(string) public view returns (bytes32); 34 | function getString(string) public view returns (string); 35 | 36 | function set(string, int256) public; 37 | function set(string, uint256) public; 38 | function set(string, string) public; 39 | function set(string, address) public; 40 | } 41 | 42 | //record sets 43 | contract Entries { 44 | function get(int256) public view returns (Entry); 45 | function size() public view returns (int256); 46 | } 47 | 48 | //Table main contract 49 | contract Table { 50 | function select(string, Condition) public view returns (Entries); 51 | function insert(string, Entry) public returns (int256); 52 | function update(string, Entry, Condition) public returns (int256); 53 | function remove(string, Condition) public returns (int256); 54 | 55 | function newEntry() public view returns (Entry); 56 | function newCondition() public view returns (Condition); 57 | } 58 | 59 | contract KVTableFactory { 60 | function openTable(string) public view returns (KVTable); 61 | function createTable(string, string, string) public returns (int256); 62 | } 63 | 64 | //KVTable per permiary key has only one Entry 65 | contract KVTable { 66 | function get(string) public view returns (bool, Entry); 67 | function set(string, Entry) public returns (int256); 68 | function newEntry() public view returns (Entry); 69 | } 70 | -------------------------------------------------------------------------------- /src/main/resources/mapper/JurisdicitonMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 16 | UPDATE 17 | tb_user 18 | 19 | user_password = #{userPassword} 20 | 21 | WHERE 22 | user_id = #{userId} 23 | 24 | -------------------------------------------------------------------------------- /src/main/resources/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/slf4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | %d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/test/java/com/oym/cms/CmsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CmsApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/oym/cms/contract/ContractTest.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.contract; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.oym.cms.client.ContractClient; 5 | import com.oym.cms.entity.Certificate; 6 | import com.oym.cms.enums.DTOMsgEnum; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | /** 17 | * @Author: Mr_OO 18 | * @Date: 2022/4/10 21:33 19 | */ 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest 22 | public class ContractTest { 23 | 24 | @Resource 25 | private ContractClient contractClient; 26 | 27 | @Test 28 | public void insertTest() { 29 | String schoolFlag = "sicnu"; 30 | String stuNumber = "2018110428"; 31 | String userName = "罗胜"; 32 | String cmsName = "英语CET-4证书"; 33 | String cmsType = "1003"; 34 | String cmsWinTime = String.valueOf(new Date().getTime()); 35 | String cmsDesc = "大学英语四级证书"; 36 | String cmsUrl = "/group1/M00/00/00/CgAYCGJS1fyABmBfAAACk-NVe_Q056.png"; 37 | int res = contractClient.registerCertificate(schoolFlag, stuNumber, userName, cmsName, cmsType, 38 | cmsWinTime, cmsDesc, cmsUrl); 39 | System.out.println("插入结果为:" + DTOMsgEnum.stateOf(res).getStatusInfo()); 40 | } 41 | 42 | @Test 43 | public void queryTest() { 44 | List res = contractClient.queryCertificateList("2018110429"); 45 | System.out.println("查询结果为:" + JSON.toJSONString(res)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/oym/cms/mapper/JurisdictionMapperTest.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.mapper; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | 11 | /** 12 | * @Author: Mr_OO 13 | * @Date: 2022/3/4 10:57 14 | */ 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class JurisdictionMapperTest { 18 | 19 | @Resource 20 | private JurisdictionMapper jurisdictionMapper; 21 | 22 | @Test 23 | public void queryAllUrls() { 24 | List list = jurisdictionMapper.queryAllUrls(); 25 | for (String s : list) { 26 | System.out.println(s); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/oym/cms/mapper/UserMapperTest.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.mapper; 2 | 3 | import com.oym.cms.entity.User; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.test.context.junit4.SpringRunner; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * @Author: Mr_OO 13 | * @Date: 2022/3/4 20:45 14 | */ 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class UserMapperTest { 18 | 19 | @Resource 20 | private UserMapper userMapper; 21 | 22 | @Test 23 | public void queryById() { 24 | User user = userMapper.queryUserById("2019110117"); 25 | System.out.println(user.toString()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/oym/cms/service/CertificateServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.oym.cms.config.redis.JedisUtil; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | import javax.annotation.Resource; 11 | 12 | /** 13 | * @Author: Mr_OO 14 | * @Date: 2022/3/7 19:36 15 | */ 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class CertificateServiceImpl { 19 | 20 | @Resource 21 | private CertificateService certificateService; 22 | @Resource 23 | private JedisUtil.Keys jedisKeys; 24 | @Resource 25 | private JedisUtil.Strings jedisStrings; 26 | 27 | @Test 28 | public void addTest() { 29 | 30 | } 31 | 32 | @Test 33 | public void queryTest() { 34 | System.out.println(JSON.toJSONString(certificateService 35 | .queryCertificateByUserId("2018110429", 1001, 0, 5))); 36 | } 37 | 38 | @Test 39 | public void redisTest() { 40 | jedisStrings.set("1", "111"); 41 | System.out.println(jedisStrings.get("1")); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/oym/cms/service/UserServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.oym.cms.service; 2 | 3 | import com.oym.cms.dto.UserDTO; 4 | import com.oym.cms.enums.DTOMsgEnum; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | import javax.annotation.Resource; 11 | 12 | /** 13 | * @Author: Mr_OO 14 | * @Date: 2022/3/4 20:52 15 | */ 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class UserServiceTest { 19 | 20 | @Resource 21 | private UserService userService; 22 | 23 | @Test 24 | public void queryById() { 25 | UserDTO user = userService.queryUserById("2019110117"); 26 | System.out.println("接口调用情况:" + DTOMsgEnum.stateOf(user.getMsg()).getStatusInfo()); 27 | System.out.println("用户信息为:" + user.getUser().toString()); 28 | } 29 | 30 | } 31 | --------------------------------------------------------------------------------