first commit
This commit is contained in:
parent
0c606e0e9e
commit
2916a37052
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**
|
||||
!**/src/test/**
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
118
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
118
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.5";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||
* use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||
".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||
".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if (mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if (mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if (!outputFile.getParentFile().exists()) {
|
||||
if (!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
|
322
mvnw
vendored
Normal file
322
mvnw
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ]; then
|
||||
|
||||
if [ -f /etc/mavenrc ]; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ]; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false
|
||||
darwin=false
|
||||
mingw=false
|
||||
case "$(uname)" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true ;;
|
||||
Darwin*)
|
||||
darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="$(/usr/libexec/java_home)"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -r /etc/gentoo-release ]; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ]; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ]; do
|
||||
ls=$(ls -ld "$PRG")
|
||||
link=$(expr "$ls" : '.*-> \(.*\)$')
|
||||
if expr "$link" : '/.*' >/dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="$(dirname "$PRG")/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=$(pwd)
|
||||
|
||||
M2_HOME=$(dirname "$PRG")/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=$(cd "$M2_HOME" && pwd)
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=$(cygpath --unix "$M2_HOME")
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="$( (
|
||||
cd "$M2_HOME"
|
||||
pwd
|
||||
))"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="$( (
|
||||
cd "$JAVA_HOME"
|
||||
pwd
|
||||
))"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="$(which javac)"
|
||||
if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=$(which readlink)
|
||||
if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
|
||||
if $darwin; then
|
||||
javaHome="$(dirname \"$javaExecutable\")"
|
||||
javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
|
||||
else
|
||||
javaExecutable="$(readlink -f \"$javaExecutable\")"
|
||||
fi
|
||||
javaHome="$(dirname \"$javaExecutable\")"
|
||||
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ]; then
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(which java)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ]; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ]; do
|
||||
if [ -d "$wdir"/.mvn ]; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=$(
|
||||
cd "$wdir/.."
|
||||
pwd
|
||||
)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' <"$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(pwd)")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in wrapperUrl)
|
||||
jarUrl="$value"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget >/dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl >/dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=$(cygpath --path --windows "$M2_HOME")
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
182
mvnw.cmd
vendored
Normal file
182
mvnw.cmd
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
159
pom.xml
Normal file
159
pom.xml
Normal file
@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.2.1.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.rymcu</groupId>
|
||||
<artifactId>vertical</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<packaging>war</packaging>
|
||||
<name>vertical</name>
|
||||
<description>一个用 Java 实现的现代化社区(论坛 / BBS / 社交网络 / 博客)平台,“下一代的社区系统,为未来而构建”。</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<!-- 通用Mapper插件 -->
|
||||
<dependency>
|
||||
<groupId>tk.mybatis</groupId>
|
||||
<artifactId>mapper</artifactId>
|
||||
<version>4.1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jtds</groupId>
|
||||
<artifactId>jtds</artifactId>
|
||||
<version>1.3.1</version>
|
||||
</dependency>
|
||||
<!-- pagehelper -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper</artifactId>
|
||||
<version>5.1.10</version>
|
||||
</dependency>
|
||||
<!-- fastjson -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.60</version>
|
||||
</dependency>
|
||||
<!-- shiro权限控制框架 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<version>1.4.1</version>
|
||||
</dependency>
|
||||
<!-- shiro-redis -->
|
||||
<dependency>
|
||||
<groupId>org.crazycake</groupId>
|
||||
<artifactId>shiro-redis</artifactId>
|
||||
<version>3.2.3</version>
|
||||
</dependency>
|
||||
<!--apache相关依赖-->
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>1.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.9.1</version>
|
||||
</dependency>
|
||||
<!-- 阿里巴巴连接池Druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.1.20</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- 程序编译时默认不会把 src/main/java 目录下文件添加到 jar 包中,需手动添加 -->
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
<include>**/**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
13
src/main/java/com/rymcu/vertical/ServletInitializer.java
Normal file
13
src/main/java/com/rymcu/vertical/ServletInitializer.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.rymcu.vertical;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
|
||||
public class ServletInitializer extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(VerticalApplication.class);
|
||||
}
|
||||
|
||||
}
|
13
src/main/java/com/rymcu/vertical/VerticalApplication.java
Normal file
13
src/main/java/com/rymcu/vertical/VerticalApplication.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.rymcu.vertical;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class VerticalApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(VerticalApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
import com.alibaba.fastjson.support.spring.FastJsonJsonView;
|
||||
import com.rymcu.vertical.core.exception.ServiceException;
|
||||
import com.rymcu.vertical.core.result.GlobalResult;
|
||||
import com.rymcu.vertical.core.result.ResultCode;
|
||||
import org.apache.shiro.authz.UnauthenticatedException;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
* */
|
||||
@RestControllerAdvice
|
||||
public class HpeisExceptionHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HpeisExceptionHandler.class);
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Object errorHandler(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){
|
||||
if(isAjax(request)){
|
||||
GlobalResult result = new GlobalResult();
|
||||
if (ex instanceof UnauthenticatedException) {
|
||||
result.setCode(1000001);
|
||||
result.setMessage("token错误");
|
||||
logger.info("token错误");
|
||||
} else if (ex instanceof UnauthorizedException) {
|
||||
result.setCode(1000002);
|
||||
result.setMessage("用户无权限");
|
||||
logger.info("用户无权限");
|
||||
}else if (ex instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
|
||||
result.setCode(((ServiceException) ex).getCode());
|
||||
result.setMessage(ex.getMessage());
|
||||
logger.info(ex.getMessage());
|
||||
} else if (ex instanceof NoHandlerFoundException) {
|
||||
result.setCode(ResultCode.NOT_FOUND.getCode());
|
||||
result.setMessage(ResultCode.NOT_FOUND.getMessage());
|
||||
} else if (ex instanceof ServletException) {
|
||||
result.setCode(ResultCode.FAIL.getCode());
|
||||
result.setMessage(ex.getMessage());
|
||||
}else {
|
||||
//系统内部异常,不返回给客户端,内部记录错误日志
|
||||
result.setCode(ResultCode.INTERNAL_SERVER_ERROR.getCode());
|
||||
String message;
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
|
||||
request.getRequestURI(),
|
||||
handlerMethod.getBean().getClass().getName(),
|
||||
handlerMethod.getMethod().getName(),
|
||||
ex.getMessage());
|
||||
} else {
|
||||
message = ex.getMessage();
|
||||
}
|
||||
result.setMessage("操作失败");
|
||||
logger.error(message, ex);
|
||||
}
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
}else {
|
||||
ModelAndView mv = new ModelAndView();
|
||||
FastJsonJsonView view = new FastJsonJsonView();
|
||||
Map<String, Object> attributes = new HashMap();
|
||||
if (ex instanceof UnauthenticatedException) {
|
||||
attributes.put("code", "1000001");
|
||||
attributes.put("message", "token错误");
|
||||
} else if (ex instanceof UnauthorizedException) {
|
||||
attributes.put("code", "1000002");
|
||||
attributes.put("message", "用户无权限");
|
||||
} else if (ex instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
|
||||
attributes.put("code",((ServiceException) ex).getCode());
|
||||
attributes.put("message",ex.getMessage());
|
||||
logger.info(ex.getMessage());
|
||||
} else if (ex instanceof NoHandlerFoundException) {
|
||||
attributes.put("code",ResultCode.NOT_FOUND.getCode());
|
||||
attributes.put("message",ResultCode.NOT_FOUND.getMessage());
|
||||
} else if (ex instanceof ServletException) {
|
||||
attributes.put("code",ResultCode.FAIL.getCode());
|
||||
attributes.put("message",ex.getMessage());
|
||||
}else {
|
||||
//系统内部异常,不返回给客户端,内部记录错误日志
|
||||
attributes.put("code",ResultCode.INTERNAL_SERVER_ERROR.getCode());
|
||||
String message;
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
|
||||
request.getRequestURI(),
|
||||
handlerMethod.getBean().getClass().getName(),
|
||||
handlerMethod.getMethod().getName(),
|
||||
ex.getMessage());
|
||||
} else {
|
||||
message = ex.getMessage();
|
||||
}
|
||||
logger.error(message, ex);
|
||||
attributes.put("message","操作失败");
|
||||
}
|
||||
attributes.put("success",false);
|
||||
view.setAttributesMap(attributes);
|
||||
mv.setView(view);
|
||||
return mv;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAjax(HttpServletRequest request) {
|
||||
String requestedWith = request.getHeader("x-requested-with");
|
||||
if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
|
||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class HpeisSessionManager extends DefaultWebSessionManager {
|
||||
private static final String AUTHORIZATION = "Authorization";
|
||||
|
||||
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
|
||||
|
||||
public HpeisSessionManager() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
|
||||
String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
|
||||
// 如果请求头中有 Authorization 则其值为 sessionId
|
||||
if (!StringUtils.isEmpty(id)) {
|
||||
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
|
||||
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
|
||||
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
|
||||
|
||||
return id;
|
||||
} else {
|
||||
// 否则按默认规则从 cookie 取 sessionId
|
||||
return super.getSessionId(request, response);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.filter.mgt.FilterChainManager;
|
||||
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
|
||||
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
|
||||
import org.apache.shiro.web.mgt.WebSecurityManager;
|
||||
import org.apache.shiro.web.servlet.AbstractShiroFilter;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Shiro静态资源配置
|
||||
* */
|
||||
public class HpeisShiroFilterFactoryBean extends ShiroFilterFactoryBean {
|
||||
// 对ShiroFilter来说,需要直接忽略的请求
|
||||
private Set<String> ignoreExt;
|
||||
|
||||
public HpeisShiroFilterFactoryBean() {
|
||||
super();
|
||||
ignoreExt = new HashSet<>();
|
||||
ignoreExt.add(".svg");
|
||||
ignoreExt.add(".jpg");
|
||||
ignoreExt.add(".png");
|
||||
ignoreExt.add(".gif");
|
||||
ignoreExt.add(".bmp");
|
||||
ignoreExt.add(".js");
|
||||
ignoreExt.add(".css");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractShiroFilter createInstance() throws Exception {
|
||||
|
||||
SecurityManager securityManager = getSecurityManager();
|
||||
if (securityManager == null) {
|
||||
String msg = "SecurityManager property must be set.";
|
||||
throw new BeanInitializationException(msg);
|
||||
}
|
||||
|
||||
if (!(securityManager instanceof WebSecurityManager)) {
|
||||
String msg = "The security manager does not implement the WebSecurityManager interface.";
|
||||
throw new BeanInitializationException(msg);
|
||||
}
|
||||
|
||||
FilterChainManager manager = createFilterChainManager();
|
||||
|
||||
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
|
||||
chainResolver.setFilterChainManager(manager);
|
||||
|
||||
return new HpeisSpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
|
||||
}
|
||||
|
||||
private final class HpeisSpringShiroFilter extends AbstractShiroFilter {
|
||||
|
||||
protected HpeisSpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
|
||||
super();
|
||||
if (webSecurityManager == null) {
|
||||
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
|
||||
}
|
||||
setSecurityManager(webSecurityManager);
|
||||
if (resolver != null) {
|
||||
setFilterChainResolver(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse,
|
||||
FilterChain chain) throws ServletException, IOException {
|
||||
HttpServletRequest request = (HttpServletRequest)servletRequest;
|
||||
String str = request.getRequestURI().toLowerCase();
|
||||
// 因为ShiroFilter 拦截所有请求(在上面我们配置了urlPattern 为 * ,当然你也可以在那里精确的添加要处理的路径,这样就不需要这个类了),而在每次请求里面都做了session的读取和更新访问时间等操作,这样在集群部署session共享的情况下,数量级的加大了处理量负载。
|
||||
// 所以我们这里将一些能忽略的请求忽略掉。
|
||||
// 当然如果你的集群系统使用了动静分离处理,静态资料的请求不会到Filter这个层面,便可以忽略。
|
||||
boolean flag = true;
|
||||
int idx = 0;
|
||||
if(( idx = str.indexOf(".")) > 0){
|
||||
str = str.substring(idx);
|
||||
if(ignoreExt.contains(str.toLowerCase()))
|
||||
flag = false;
|
||||
}
|
||||
if(flag){
|
||||
super.doFilterInternal(servletRequest, servletResponse, chain);
|
||||
}else{
|
||||
chain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
157
src/main/java/com/rymcu/vertical/config/HpeisShiroRealm.java
Normal file
157
src/main/java/com/rymcu/vertical/config/HpeisShiroRealm.java
Normal file
@ -0,0 +1,157 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
import com.rymcu.vertical.core.constant.ShiroConstants;
|
||||
import com.rymcu.vertical.core.exception.CaptchaException;
|
||||
import com.rymcu.vertical.core.exception.ServiceException;
|
||||
import com.rymcu.vertical.entity.Menu;
|
||||
import com.rymcu.vertical.entity.Role;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import com.rymcu.vertical.service.MenuService;
|
||||
import com.rymcu.vertical.service.RoleService;
|
||||
import com.rymcu.vertical.service.UserService;
|
||||
import com.rymcu.vertical.util.Encodes;
|
||||
import com.rymcu.vertical.util.Utils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authc.*;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.apache.shiro.util.ByteSource;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ronger
|
||||
* @since 2018/05/28 11:00
|
||||
* 自定义权限匹配和账号密码匹配
|
||||
* */
|
||||
public class HpeisShiroRealm extends AuthorizingRealm {
|
||||
@Resource
|
||||
private RoleService roleService;
|
||||
|
||||
@Resource
|
||||
private MenuService menuService;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
|
||||
//Principal principal = (Principal) getAvailablePrincipal(principals);
|
||||
// System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
|
||||
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
|
||||
Principal principal = (Principal)principals.getPrimaryPrincipal();
|
||||
User user = new User();
|
||||
user.setIdUser(principal.getId());
|
||||
try {
|
||||
List<Role> roles = roleService.selectRoleByUser(user);
|
||||
for (Role role : roles) {
|
||||
if(StringUtils.isNotBlank(role.getInputCode())){
|
||||
authorizationInfo.addRole(role.getInputCode());
|
||||
}
|
||||
}
|
||||
List<Menu> permissions = menuService.selectMenuByUser(user);
|
||||
for (Menu perm : permissions) {
|
||||
if (perm.getPermission() != null) {
|
||||
authorizationInfo.addStringPermission(perm.getPermission());
|
||||
}
|
||||
}
|
||||
// 添加用户权限
|
||||
authorizationInfo.addStringPermission("user");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return authorizationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证回调函数, 登录时调用,主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。
|
||||
* */
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
|
||||
//获取用户的输入的账号.
|
||||
String username = token.getUsername();
|
||||
|
||||
User user = null;
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (!org.springframework.util.StringUtils.isEmpty(attributes.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA))) {
|
||||
throw new CaptchaException();
|
||||
}
|
||||
try {
|
||||
user = userService.findByLoginName(username);
|
||||
} catch (ServiceException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
if (!"0".equals(user.getStatus())) { //账户冻结(是否允许登陆)
|
||||
throw new LockedAccountException();
|
||||
}
|
||||
byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));
|
||||
return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()),
|
||||
user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权用户信息
|
||||
*/
|
||||
public static class Principal implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer id; // 编号
|
||||
private String account; // 登录名
|
||||
private String name; // 姓名
|
||||
private boolean mobileLogin; // 是否手机登录
|
||||
|
||||
// private Map<String, Object> cacheMap;
|
||||
|
||||
public Principal(User user, boolean mobileLogin) {
|
||||
this.id = user.getIdUser();
|
||||
this.account = user.getAccount();
|
||||
this.name = user.getNickName();
|
||||
this.mobileLogin = mobileLogin;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isMobileLogin() {
|
||||
return mobileLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SESSIONID
|
||||
*/
|
||||
public String getSessionid() {
|
||||
try{
|
||||
return (String) Utils.getSession().getId();
|
||||
}catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
import com.github.pagehelper.PageInterceptor;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
import static com.rymcu.vertical.core.constant.ProjectConstant.*;
|
||||
|
||||
|
||||
/**
|
||||
* Mybatis & Mapper & PageHelper 配置
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisConfigurer {
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception {
|
||||
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTypeAliasesPackage(MODEL_PACKAGE);
|
||||
|
||||
//配置分页插件,详情请查阅官方文档
|
||||
PageInterceptor pageHelper = new PageInterceptor();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("helperDialect", "mysql");
|
||||
properties.setProperty("pageSizeZero", "true");//分页尺寸为0时查询所有纪录不再执行分页
|
||||
properties.setProperty("reasonable", "true");//页码<=0 查询第一页,页码>=总页数查询最后一页
|
||||
properties.setProperty("supportMethodsArguments", "true");//支持通过 Mapper 接口参数来传递分页参数
|
||||
properties.setProperty("rowBoundsWithCount", "true");//
|
||||
pageHelper.setProperties(properties);
|
||||
|
||||
//添加插件
|
||||
factory.setPlugins(new Interceptor[]{pageHelper});
|
||||
|
||||
//添加XML目录
|
||||
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
||||
factory.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml"));
|
||||
factory.setTypeHandlersPackage("com.rymcu.vertical.util.handlers");
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MapperScannerConfigurer mapperScannerConfigurer() {
|
||||
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
|
||||
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
|
||||
mapperScannerConfigurer.setBasePackage(MAPPER_PACKAGE);
|
||||
|
||||
//配置通用Mapper,详情请查阅官方文档
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("mappers", MAPPER_INTERFACE_REFERENCE);
|
||||
properties.setProperty("notEmpty", "false");//insert、update是否判断字符串类型!='' 即 test="str != null"表达式内是否追加 and str != ''
|
||||
properties.setProperty("IDENTITY", "JDBC");
|
||||
mapperScannerConfigurer.setProperties(properties);
|
||||
|
||||
|
||||
return mapperScannerConfigurer;
|
||||
}
|
||||
|
||||
}
|
||||
|
238
src/main/java/com/rymcu/vertical/config/ShiroConfig.java
Normal file
238
src/main/java/com/rymcu/vertical/config/ShiroConfig.java
Normal file
@ -0,0 +1,238 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.session.mgt.SessionManager;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.crazycake.shiro.RedisCacheManager;
|
||||
import org.crazycake.shiro.RedisManager;
|
||||
import org.crazycake.shiro.RedisSessionDAO;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "redis.shiro")
|
||||
public class ShiroConfig implements EnvironmentAware {
|
||||
|
||||
private Environment env;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.env=environment;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
|
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new HpeisShiroFilterFactoryBean();
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
||||
|
||||
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
|
||||
//注意过滤器配置顺序 不能颠倒
|
||||
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
|
||||
filterChainDefinitionMap.put("/logout", "logout");
|
||||
// 配置不会被拦截的链接 顺序判断
|
||||
filterChainDefinitionMap.put("/druid/**", "anon");
|
||||
filterChainDefinitionMap.put("/css/**", "anon");
|
||||
filterChainDefinitionMap.put("/fonts/**", "anon");
|
||||
filterChainDefinitionMap.put("/js/**", "anon");
|
||||
filterChainDefinitionMap.put("/uploadFile/**", "anon");
|
||||
filterChainDefinitionMap.put("/login", "anon");
|
||||
filterChainDefinitionMap.put("/api/**", "anon");
|
||||
// filterChainDefinitionMap.put("/**", "authc");
|
||||
filterChainDefinitionMap.put("/**", "authc");
|
||||
//配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
|
||||
shiroFilterFactoryBean.setLoginUrl("/login");
|
||||
// 登录成功后要跳转的链接
|
||||
shiroFilterFactoryBean.setSuccessUrl("/index");
|
||||
//未授权界面;
|
||||
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
|
||||
|
||||
Map<String, Filter> filtersMap = new LinkedHashMap<>();
|
||||
filtersMap.put("authc",hpeisFormAuthenticationFilter());
|
||||
shiroFilterFactoryBean.setFilters(filtersMap);
|
||||
|
||||
filterChainDefinitionMap.put("/**", "authc");
|
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
|
||||
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 凭证匹配器
|
||||
* (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
|
||||
* )
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public HashedCredentialsMatcher hashedCredentialsMatcher() {
|
||||
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
|
||||
hashedCredentialsMatcher.setHashAlgorithmName("SHA-1");//散列算法:这里使用MD5算法;
|
||||
hashedCredentialsMatcher.setHashIterations(1024);//散列的次数,比如散列两次,相当于 md5(md5(""));
|
||||
return hashedCredentialsMatcher;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HpeisShiroRealm hpeisShiroRealm() {
|
||||
HpeisShiroRealm shiroRealm = new HpeisShiroRealm();
|
||||
shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
|
||||
return shiroRealm;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public SecurityManager securityManager() {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
securityManager.setRealm(hpeisShiroRealm());
|
||||
// 自定义session管理 使用redis
|
||||
securityManager.setSessionManager(sessionManager());
|
||||
// 自定义缓存实现 使用redis
|
||||
//securityManager.setCacheManager(cacheManager());
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
//自定义sessionManager
|
||||
@Bean
|
||||
public SessionManager sessionManager() {
|
||||
HpeisSessionManager sessionManager = new HpeisSessionManager();
|
||||
sessionManager.setSessionDAO(redisSessionDAO());
|
||||
sessionManager.setSessionIdUrlRewritingEnabled(false);
|
||||
sessionManager.setGlobalSessionTimeout(21600000L);
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置shiro redisManager
|
||||
* <p>
|
||||
* 使用的是shiro-redis开源插件
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
public RedisManager redisManager() {
|
||||
// 设置redis配置信息
|
||||
RedisManager redisManager = new RedisManager();
|
||||
redisManager.setHost(env.getProperty("spring.redis.host"));
|
||||
redisManager.setPassword(env.getProperty("spring.redis.password"));
|
||||
return redisManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* cacheManager 缓存 redis实现
|
||||
* <p>
|
||||
* 使用的是shiro-redis开源插件
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
@Bean
|
||||
public RedisCacheManager cacheManager() {
|
||||
RedisCacheManager redisCacheManager = new RedisCacheManager();
|
||||
redisCacheManager.setRedisManager(redisManager());
|
||||
return redisCacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* RedisSessionDAO shiro sessionDao层的实现 通过redis
|
||||
* <p>
|
||||
* 使用的是shiro-redis开源插件
|
||||
*/
|
||||
|
||||
|
||||
@Bean
|
||||
public RedisSessionDAO redisSessionDAO() {
|
||||
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
|
||||
redisSessionDAO.setRedisManager(redisManager());
|
||||
redisSessionDAO.setExpire(21600);
|
||||
// Custom your redis key prefix for session management, if you doesn't define this parameter,
|
||||
// shiro-redis will use 'shiro_redis_session:' as default prefix
|
||||
// redisSessionDAO.setKeyPrefix("");
|
||||
return redisSessionDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启shiro aop注解支持.
|
||||
* 使用代理方式;所以需要开启代码支持;
|
||||
*
|
||||
* @param securityManager
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
|
||||
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
|
||||
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
|
||||
return authorizationAttributeSourceAdvisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shiro生命周期处理器
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
|
||||
// * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
// @Bean
|
||||
// @DependsOn({"lifecycleBeanPostProcessor"})
|
||||
// public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
|
||||
// DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
// advisorAutoProxyCreator.setProxyTargetClass(true);
|
||||
// return advisorAutoProxyCreator;
|
||||
// }
|
||||
|
||||
@Bean
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
|
||||
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
|
||||
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
|
||||
return authorizationAttributeSourceAdvisor;
|
||||
}
|
||||
|
||||
public FormAuthenticationFilter hpeisFormAuthenticationFilter(){
|
||||
FormAuthenticationFilter formAuthenticationFilter = new ShiroLoginFilter();
|
||||
return formAuthenticationFilter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean someFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
FormAuthenticationFilter hpeisFormAuthenticationFilter = new ShiroLoginFilter();
|
||||
registration.setFilter(hpeisFormAuthenticationFilter);
|
||||
registration.setEnabled(false);
|
||||
return registration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 注册全局异常处理
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/*@Bean(name = "exceptionHandler")
|
||||
public HandlerExceptionResolver handlerExceptionResolver() {
|
||||
return new HpeisExceptionHandler();
|
||||
}*/
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rymcu.vertical.core.result.GlobalResultGenerator;
|
||||
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Created by wanwh on 2019/1/24 0024.
|
||||
*/
|
||||
public class ShiroLoginFilter extends FormAuthenticationFilter {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);
|
||||
|
||||
/**
|
||||
* 在访问controller前判断是否登录,返回json,不进行重定向。
|
||||
* @param request
|
||||
* @param response
|
||||
* @return true-继续往下执行,false-该filter过滤器已经处理,不继续执行其他过滤器
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
||||
if (this.isLoginRequest(request, response)) {
|
||||
if (this.isLoginSubmission(request, response)) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Login submission detected. Attempting to execute login.");
|
||||
}
|
||||
|
||||
return this.executeLogin(request, response);
|
||||
} else {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Login page view.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}else if(isAjax((HttpServletRequest) request)){
|
||||
httpServletResponse.setContentType("application/json");
|
||||
httpServletResponse.setCharacterEncoding("UTF-8");
|
||||
httpServletResponse.setHeader("sessionstatus", "timeOut");
|
||||
httpServletResponse.addHeader("loginPath", this.getLoginUrl());
|
||||
httpServletResponse.getWriter().write(JSONObject.toJSONString(GlobalResultGenerator.genErrorResult("未登录或已登录超时,请重新登录"),true));
|
||||
return false;
|
||||
}else {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Attempting to access a path which requires authentication. Forwarding to the Authentication url [" + this.getLoginUrl() + "]");
|
||||
}
|
||||
|
||||
this.saveRequestAndRedirectToLogin(request, response);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAjax(HttpServletRequest request) {
|
||||
String requestedWith = request.getHeader("x-requested-with");
|
||||
if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
/**
|
||||
* 用户和密码(包含验证码)令牌类
|
||||
*/
|
||||
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String captcha;
|
||||
private boolean mobileLogin;
|
||||
|
||||
public UsernamePasswordToken() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UsernamePasswordToken(String username, char[] password,
|
||||
boolean rememberMe, String host, String captcha, boolean mobileLogin) {
|
||||
super(username, password, rememberMe, host);
|
||||
this.captcha = captcha;
|
||||
this.mobileLogin = mobileLogin;
|
||||
}
|
||||
|
||||
public String getCaptcha() {
|
||||
return captcha;
|
||||
}
|
||||
|
||||
public void setCaptcha(String captcha) {
|
||||
this.captcha = captcha;
|
||||
}
|
||||
|
||||
public boolean isMobileLogin() {
|
||||
return mobileLogin;
|
||||
}
|
||||
|
||||
}
|
118
src/main/java/com/rymcu/vertical/config/WebMvcConfigurer.java
Normal file
118
src/main/java/com/rymcu/vertical/config/WebMvcConfigurer.java
Normal file
@ -0,0 +1,118 @@
|
||||
package com.rymcu.vertical.config;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.rymcu.vertical.core.result.GlobalResult;
|
||||
import com.rymcu.vertical.jwt.aop.RestAuthTokenInterceptor;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spring MVC 配置
|
||||
*/
|
||||
@Configuration
|
||||
public class WebMvcConfigurer extends WebMvcConfigurationSupport {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WebMvcConfigurer.class);
|
||||
// @Value("${env}")
|
||||
// private String env;//当前激活的配置文件
|
||||
|
||||
@Override
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
|
||||
FastJsonConfig config = new FastJsonConfig();
|
||||
config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,//保留空的字段
|
||||
SerializerFeature.WriteNullStringAsEmpty);//String null -> ""
|
||||
//SerializerFeature.WriteNullNumberAsZero);//Number null -> 0
|
||||
config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); //关闭循环引用
|
||||
converter.setFastJsonConfig(config);
|
||||
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
converter.setDefaultCharset(Charset.forName("UTF-8"));
|
||||
converters.add(0, converter);
|
||||
}
|
||||
|
||||
//解决跨域问题
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowCredentials(true)
|
||||
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestAuthTokenInterceptor restAuthTokenInterceptor() {
|
||||
return new RestAuthTokenInterceptor();
|
||||
}
|
||||
|
||||
//添加拦截器
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// TODO 先不拦截接口,进行测试
|
||||
registry.addInterceptor(restAuthTokenInterceptor()).addPathPatterns("/api/**")
|
||||
.excludePathPatterns("/api/login/**", "/api/logout","/api/member/*",
|
||||
"/api/home/*","/api/item/**","/api/searchHistory/**", "/api/pay/payNotify",
|
||||
"/api/mall/oauth/**","/api/express/**","/api/person/**");
|
||||
|
||||
}
|
||||
|
||||
private void responseResult(HttpServletResponse response, GlobalResult result) {
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader("Content-type", "application/json;charset=UTF-8");
|
||||
response.setStatus(200);
|
||||
try {
|
||||
response.getWriter().write(JSON.toJSONString(result));
|
||||
} catch (IOException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个简单的签名认证,规则:
|
||||
* 1. 将请求参数按ascii码排序
|
||||
* 2. 拼接为a=value&b=value...这样的字符串(不包含sign)
|
||||
* 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较
|
||||
*/
|
||||
private boolean validateSign(HttpServletRequest request) {
|
||||
String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
|
||||
if (StringUtils.isEmpty(requestSign)) {
|
||||
return false;
|
||||
}
|
||||
List<String> keys = new ArrayList<String>(request.getParameterMap().keySet());
|
||||
keys.remove("sign");//排除sign参数
|
||||
Collections.sort(keys);//排序
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String key : keys) {
|
||||
sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串
|
||||
}
|
||||
String linkString = sb.toString();
|
||||
linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&'
|
||||
|
||||
String secret = "Potato";//密钥,自己修改
|
||||
String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5
|
||||
|
||||
return StringUtils.equals(sign, requestSign);//比较
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.rymcu.vertical.core.constant;
|
||||
|
||||
/**
|
||||
* 项目常量
|
||||
*/
|
||||
public final class ProjectConstant {
|
||||
public static final String BASE_PACKAGE = "com.rymcu.vertical";//项目基础包名称,根据自己公司的项目修改
|
||||
|
||||
public static final String DTO_PACKAGE = BASE_PACKAGE + ".dto";//DTO所在包
|
||||
public static final String MODEL_PACKAGE = BASE_PACKAGE + ".entity";//Model所在包
|
||||
public static final String MAPPER_PACKAGE = BASE_PACKAGE + ".mapper";//Mapper所在包
|
||||
public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";//Service所在包
|
||||
public static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";//ServiceImpl所在包
|
||||
public static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".web";//Controller所在包
|
||||
|
||||
public static final String MAPPER_INTERFACE_REFERENCE = BASE_PACKAGE + ".core.mapper.Mapper";//Mapper插件基础接口的完全限定名
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.rymcu.vertical.core.constant;
|
||||
|
||||
/**
|
||||
* Shiro通用常量
|
||||
*
|
||||
*/
|
||||
public interface ShiroConstants
|
||||
{
|
||||
/**
|
||||
* 当前登录的用户
|
||||
*/
|
||||
public static final String CURRENT_USER = "currentUser";
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
public static final String CURRENT_USERNAME = "username";
|
||||
|
||||
/**
|
||||
* 消息key
|
||||
*/
|
||||
public static String MESSAGE = "message";
|
||||
|
||||
/**
|
||||
* 错误key
|
||||
*/
|
||||
public static String ERROR = "errorMsg";
|
||||
|
||||
/**
|
||||
* 编码格式
|
||||
*/
|
||||
public static String ENCODING = "UTF-8";
|
||||
|
||||
/**
|
||||
* 当前在线会话
|
||||
*/
|
||||
public String ONLINE_SESSION = "online_session";
|
||||
|
||||
/**
|
||||
* 验证码key
|
||||
*/
|
||||
public static final String CURRENT_CAPTCHA = "captcha";
|
||||
|
||||
/**
|
||||
* 验证码开关
|
||||
*/
|
||||
public static final String CURRENT_ENABLED = "captchaEnabled";
|
||||
|
||||
/**
|
||||
* 验证码开关
|
||||
*/
|
||||
public static final String CURRENT_TYPE = "captchaType";
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
public static final String CURRENT_VALIDATECODE = "validateCode";
|
||||
|
||||
/**
|
||||
* 验证码错误
|
||||
*/
|
||||
public static final String CAPTCHA_ERROR = "captchaError";
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.rymcu.vertical.core.exception;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
|
||||
/**
|
||||
* 验证码错误异常类
|
||||
*
|
||||
*/
|
||||
public class CaptchaException extends AuthenticationException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CaptchaException()
|
||||
{
|
||||
super("验证码不正确");
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.rymcu.vertical.core.exception;
|
||||
|
||||
|
||||
import com.rymcu.vertical.core.result.ResultCode;
|
||||
|
||||
/**
|
||||
* 服务(业务)异常如“ 账号或密码错误 ”,该异常只做INFO级别的日志记录 @see WebMvcConfigurer
|
||||
*/
|
||||
public class ServiceException extends Exception {
|
||||
private int code;
|
||||
private String extraMessage;
|
||||
|
||||
public ServiceException(ResultCode resultCode) {
|
||||
super(resultCode.getMessage());
|
||||
this.code=resultCode.getCode();
|
||||
}
|
||||
|
||||
|
||||
public ServiceException(String message, Throwable cause) {
|
||||
|
||||
}
|
||||
public ServiceException(int code, String message, String extraMessage, Throwable cause){
|
||||
super(message,cause);
|
||||
this.code=code;
|
||||
this.extraMessage=extraMessage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ServiceException(ResultCode resultCode, String extraMessage){
|
||||
this(resultCode.getCode(),resultCode.getMessage(),extraMessage,null);
|
||||
}
|
||||
|
||||
public ServiceException(String extraMessage){
|
||||
this(ResultCode.INVALID_PARAM,extraMessage);
|
||||
}
|
||||
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getExtraMessage() {
|
||||
return extraMessage;
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/com/rymcu/vertical/core/mapper/Mapper.java
Normal file
17
src/main/java/com/rymcu/vertical/core/mapper/Mapper.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.rymcu.vertical.core.mapper;
|
||||
|
||||
import tk.mybatis.mapper.common.BaseMapper;
|
||||
import tk.mybatis.mapper.common.ConditionMapper;
|
||||
import tk.mybatis.mapper.common.IdsMapper;
|
||||
import tk.mybatis.mapper.common.special.InsertListMapper;
|
||||
|
||||
/**
|
||||
* 定制版MyBatis Mapper插件接口,如需其他接口参考官方文档自行添加。
|
||||
*/
|
||||
public interface Mapper<T>
|
||||
extends
|
||||
BaseMapper<T>,
|
||||
ConditionMapper<T>,
|
||||
IdsMapper<T>,
|
||||
InsertListMapper<T> {
|
||||
}
|
21
src/main/java/com/rymcu/vertical/core/mapper/TreeMapper.java
Normal file
21
src/main/java/com/rymcu/vertical/core/mapper/TreeMapper.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.rymcu.vertical.core.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TreeMapper<T> extends Mapper<T> {
|
||||
|
||||
/**
|
||||
* 找到所有子节点
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
public List<T> findByParentIdsLike(T entity);
|
||||
|
||||
/**
|
||||
* 更新所有父节点字段
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
public int updateParentIds(T entity);
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.rymcu.vertical.core.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GlobalResult<T> {
|
||||
private boolean success = false;
|
||||
private T data;
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
public GlobalResult() {
|
||||
}
|
||||
|
||||
public static <T> GlobalResult<T> newInstance() {
|
||||
return new GlobalResult();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package com.rymcu.vertical.core.result;
|
||||
|
||||
import com.rymcu.vertical.util.ErrorCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GlobalResultGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalResultGenerator.class);
|
||||
|
||||
/**
|
||||
* normal
|
||||
* @param success
|
||||
* @param data
|
||||
* @param message
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GlobalResult<T> genResult(boolean success, T data, String message) {
|
||||
GlobalResult<T> result = GlobalResult.newInstance();
|
||||
result.setSuccess(success);
|
||||
result.setData(data);
|
||||
result.setMessage(message);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("generate rest result:{}", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* success
|
||||
* @param data
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GlobalResult<T> genSuccessResult(T data) {
|
||||
|
||||
return genResult(true, data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* error message
|
||||
* @param message error message
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GlobalResult<T> genErrorResult(String message) {
|
||||
|
||||
return genResult(false, null, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* error
|
||||
* @param error error enum
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GlobalResult<T> genErrorResult(ErrorCode error) {
|
||||
|
||||
return genErrorResult(error.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* success no message
|
||||
* @return
|
||||
*/
|
||||
public static GlobalResult genSuccessResult() {
|
||||
return genSuccessResult(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* success
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> GlobalResult<T> genSuccessResult(String message) {
|
||||
|
||||
return genResult(true, null, message);
|
||||
}
|
||||
|
||||
}
|
33
src/main/java/com/rymcu/vertical/core/result/ResultCode.java
Normal file
33
src/main/java/com/rymcu/vertical/core/result/ResultCode.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.rymcu.vertical.core.result;
|
||||
|
||||
/**
|
||||
* 响应码枚举,参考HTTP状态码的语义
|
||||
*/
|
||||
public enum ResultCode {
|
||||
SUCCESS(1, "SUCCESS"),//成功
|
||||
FAIL(400, "访问失败"),//失败
|
||||
UNAUTHORIZED(401, "签名错误"),//未认证(签名错误)
|
||||
NOT_FOUND(404, "此接口不存在"),//接口不存在
|
||||
INTERNAL_SERVER_ERROR(500, "系统繁忙,请稍后再试"),//服务器内部错误
|
||||
INVALID_PARAM(10000, "参数错误"),
|
||||
|
||||
|
||||
|
||||
;
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
ResultCode(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.rymcu.vertical.core.service;
|
||||
|
||||
|
||||
import com.rymcu.vertical.core.exception.ServiceException;
|
||||
import com.rymcu.vertical.core.mapper.Mapper;
|
||||
import org.apache.ibatis.exceptions.TooManyResultsException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import tk.mybatis.mapper.entity.Condition;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基于通用MyBatis Mapper插件的Service接口的实现
|
||||
*/
|
||||
public abstract class AbstractService<T> implements Service<T> {
|
||||
|
||||
@Autowired
|
||||
protected Mapper<T> mapper;
|
||||
|
||||
private Class<T> modelClass; // 当前泛型真实类型的Class
|
||||
|
||||
public AbstractService() {
|
||||
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
|
||||
modelClass = (Class<T>) pt.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
public void save(T model) {
|
||||
mapper.insertSelective(model);
|
||||
}
|
||||
|
||||
public void save(List<T> models) {
|
||||
mapper.insertList(models);
|
||||
}
|
||||
|
||||
public void deleteById(String id) {
|
||||
mapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public void deleteByIds(String ids) {
|
||||
mapper.deleteByIds(ids);
|
||||
}
|
||||
|
||||
public void update(T model) {
|
||||
mapper.updateByPrimaryKeySelective(model);
|
||||
}
|
||||
|
||||
public T findById(String id) {
|
||||
return mapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findBy(String fieldName, Object value) throws TooManyResultsException, ServiceException {
|
||||
try {
|
||||
T model = modelClass.newInstance();
|
||||
Field field = modelClass.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(model, value);
|
||||
return mapper.selectOne(model);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ServiceException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> findByIds(String ids) {
|
||||
return mapper.selectByIds(ids);
|
||||
}
|
||||
|
||||
public List<T> findByCondition(Condition condition) {
|
||||
return mapper.selectByCondition(condition);
|
||||
}
|
||||
|
||||
public List<T> findAll() {
|
||||
return mapper.selectAll();
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.rymcu.vertical.core.service;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 体检者日志接口
|
||||
*/
|
||||
public interface LogService {
|
||||
|
||||
//void log(LogInfo logInfo);
|
||||
|
||||
}
|
23
src/main/java/com/rymcu/vertical/core/service/Service.java
Normal file
23
src/main/java/com/rymcu/vertical/core/service/Service.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.rymcu.vertical.core.service;
|
||||
|
||||
import com.rymcu.vertical.core.exception.ServiceException;
|
||||
import org.apache.ibatis.exceptions.TooManyResultsException;
|
||||
import tk.mybatis.mapper.entity.Condition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service 层 基础接口,其他Service 接口 请继承该接口
|
||||
*/
|
||||
public interface Service<T> {
|
||||
void save(T model);//持久化
|
||||
void save(List<T> models);//批量持久化
|
||||
void deleteById(String id);//通过主鍵刪除
|
||||
void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”
|
||||
void update(T model);//更新
|
||||
T findById(String id);//通过ID查找
|
||||
T findBy(String fieldName, Object value) throws TooManyResultsException, ServiceException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束
|
||||
List<T> findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”
|
||||
List<T> findByCondition(Condition condition);//根据条件查找
|
||||
List<T> findAll();//获取所有
|
||||
}
|
@ -0,0 +1,347 @@
|
||||
package com.rymcu.vertical.core.service.dynProps4Files;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 动态配置文件,可以设置更新周期
|
||||
* 配置读取读取服务
|
||||
*/
|
||||
@Component
|
||||
public class DynProps4FilesService {
|
||||
private Logger _log = LoggerFactory.getLogger(DynProps4FilesService.class);
|
||||
/**
|
||||
* 属性文件
|
||||
*/
|
||||
private File[] fileArray;
|
||||
/**
|
||||
* 启动延时
|
||||
*/
|
||||
private long delay;
|
||||
/**
|
||||
* 更新周期
|
||||
*/
|
||||
private long period;
|
||||
/**
|
||||
* 属性对象
|
||||
*/
|
||||
private Properties property = new Properties();
|
||||
/**
|
||||
* 文件监控器
|
||||
*/
|
||||
private List<FileMonitor> monitors;
|
||||
|
||||
/**
|
||||
* @param files 属性文件
|
||||
* @param delay 从<code>DynProps</code>被创建到第一次动态监视的时间间隔. 约束范围delay > 0
|
||||
* @param period 动态监视的时间间隔. 约束范围period >= 0;等于0表示不执行动态监视,退化为静态配置文件.
|
||||
*/
|
||||
public DynProps4FilesService(File[] files, long delay, long period) throws IOException {
|
||||
this.fileArray = files;
|
||||
this.delay = delay;
|
||||
this.period = period;
|
||||
init();
|
||||
}
|
||||
|
||||
public DynProps4FilesService(List<String> fileNames, long delay, long period) throws IOException {
|
||||
this.delay = delay;
|
||||
this.period = period;
|
||||
fileArray = new File[fileNames.size()];
|
||||
int index = 0;
|
||||
for (String oriFileName : fileNames) {
|
||||
String fileName = oriFileName.trim();
|
||||
if (StringUtils.indexOfIgnoreCase(fileName, "classpath:") == 0) {
|
||||
fileArray[index++] = new File(
|
||||
this.getClass().getClassLoader().getResource("").getPath() + File.separator +
|
||||
fileName.substring("classpath:".length()));
|
||||
} else {
|
||||
fileArray[index++] = new File(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
public DynProps4FilesService(String fileNames, long delay, long period) throws IOException {
|
||||
this.delay = delay;
|
||||
this.period = period;
|
||||
boolean isClassPath = false;
|
||||
if (fileNames.startsWith("classpath")) {
|
||||
fileNames = fileNames.substring("classpath:".length());
|
||||
isClassPath = true;
|
||||
}
|
||||
String[] fileName = fileNames.split("[,|,|;|;]");
|
||||
fileArray = new File[fileName.length];
|
||||
if (isClassPath) {
|
||||
for (int i = 0; i < fileName.length; i++) {
|
||||
fileArray[i] = new File(this.getClass().getClassLoader().getResource("").getPath() + fileName[i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < fileName.length; i++) {
|
||||
fileArray[i] = new File(fileName[i]);
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public DynProps4FilesService(File[] files, long period) throws IOException {
|
||||
this(files, 0, period);
|
||||
}
|
||||
|
||||
public DynProps4FilesService(String fileNames, long period) throws IOException {
|
||||
this.period = period;
|
||||
this.delay = 0;
|
||||
String[] fileName = fileNames.split("[,|,|;|;]");
|
||||
|
||||
File[] files = new File[fileName.length];
|
||||
for (int i = 0; i < fileName.length; i++) {
|
||||
files[i] = new File(fileName[i]);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
public DynProps4FilesService() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载属性文件,启动监控
|
||||
*
|
||||
* @throws IOException 加载文件时出现IO异常
|
||||
*/
|
||||
protected void load() throws IOException {
|
||||
update();
|
||||
if (monitors == null) {
|
||||
monitors = new ArrayList<FileMonitor>(fileArray.length);
|
||||
} else {
|
||||
for (FileMonitor monitor : monitors) {
|
||||
try {
|
||||
monitor.timer.cancel();
|
||||
} catch (Exception e) {
|
||||
_log.warn(String.format("Timer for file [%s] cancelling failed.", monitor.file.getAbsolutePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (File file : fileArray) {
|
||||
long lastModify = file.lastModified();
|
||||
FileMonitor monitor = new FileMonitor(file, lastModify);
|
||||
this.monitors.add(monitor);
|
||||
monitor.doTask();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果文件有更新调用此方法载入
|
||||
*
|
||||
* @throws IOException 没有找到文件或读文件错误时抛出
|
||||
*/
|
||||
protected void update() throws IOException {
|
||||
for (File file : fileArray) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(file);
|
||||
this.property.load(in);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof IOException) {
|
||||
throw (IOException) e;
|
||||
}
|
||||
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 需要获取属性值的KEY
|
||||
* @param def 默认值
|
||||
*
|
||||
* @return 属性值
|
||||
*/
|
||||
public String getProperty(String key, String def) {
|
||||
String val = this.property.getProperty(key);
|
||||
return val == null ? def : val.trim();
|
||||
}
|
||||
|
||||
public String getProperty(String key) {
|
||||
String val = this.property.getProperty(key);
|
||||
return val == null ? null : val.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置属性值
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void setProperty(String key, String value) {
|
||||
this.property.setProperty(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 需要获取属性值的KEY
|
||||
* @param def 默认值
|
||||
*
|
||||
* @return 属性值
|
||||
*
|
||||
* @throws NumberFormatException 如果属性值不是整数形式
|
||||
*/
|
||||
public int getInt(String key, int def) throws NumberFormatException {
|
||||
String val = this.getProperty(key);
|
||||
return val == null ? def : Integer.parseInt(val);
|
||||
}
|
||||
|
||||
public int getInt(String key) throws NumberFormatException {
|
||||
return getInt(key, 0);
|
||||
}
|
||||
|
||||
public float getFloat(String key, float def) throws NumberFormatException {
|
||||
String val = this.getProperty(key);
|
||||
return val == null ? def : Float.parseFloat(val);
|
||||
}
|
||||
|
||||
public float getFloat(String key) throws NumberFormatException {
|
||||
return getFloat(key, 0.0f);
|
||||
}
|
||||
|
||||
public double getDouble(String key, double def) {
|
||||
String val = this.getProperty(key);
|
||||
return val == null ? def : Double.parseDouble(val);
|
||||
}
|
||||
public double getDouble(String key) throws NumberFormatException {
|
||||
return getDouble(key,0.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public long getLong(String key, long def) {
|
||||
String val = this.getProperty(key);
|
||||
return val == null ? def : Long.parseLong(val);
|
||||
}
|
||||
|
||||
public long getLong(String key) throws NumberFormatException {
|
||||
return getLong(key, 0L);
|
||||
}
|
||||
|
||||
private void init() throws IOException {
|
||||
for (File file : fileArray) {
|
||||
if (!file.exists() || file.length() == 0) {
|
||||
throw new IllegalArgumentException("动态配置文件 " + file.getAbsolutePath() + " 不存在,或是空文件!");
|
||||
}
|
||||
if (delay <= 0) {
|
||||
throw new IllegalArgumentException("定时器延时时间不能为负数!");
|
||||
}
|
||||
if (period <= 0) {
|
||||
throw new IllegalArgumentException("定时器更新周期不能为负数!");
|
||||
}
|
||||
this.property = new Properties();
|
||||
this.load();// 初始构造时,执行第一次加载.
|
||||
}
|
||||
//当进程终止时,取消定时任务
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook()));
|
||||
}
|
||||
|
||||
private class ShutdownHook implements Runnable {
|
||||
private DynProps4FilesService dynProps4FilesService;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Monitors cancelling start ...");
|
||||
if (monitors != null) {
|
||||
for (FileMonitor monitor : monitors) {
|
||||
try {
|
||||
monitor.timer.cancel();
|
||||
} catch (Exception e) {
|
||||
_log.warn(String.format("Timer for file [%s] cancelling failed.",
|
||||
monitor.file.getAbsolutePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述:一个内部私有类,实时监控文件有没有更新,如果更新则自动载入
|
||||
*/
|
||||
private class FileMonitor {
|
||||
|
||||
private long lastModifiedTime;
|
||||
private File file;
|
||||
/**
|
||||
* 定时器,以守护线程方式启动
|
||||
*/
|
||||
private Timer timer = new Timer(true);
|
||||
|
||||
/**
|
||||
* @param lastMonitorTime 最后的更新时间
|
||||
*/
|
||||
private FileMonitor(File file, long lastMonitorTime) {
|
||||
this.file = file;
|
||||
this.lastModifiedTime = lastMonitorTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行实时监控,有更新则自动载入
|
||||
*/
|
||||
private void doTask() {
|
||||
if (delay < 0) {
|
||||
delay = 0L;
|
||||
}
|
||||
if (period <= 0) {
|
||||
return;// 如果更新周期非正数,则退化成静态配置文件.
|
||||
}
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
long t = file.lastModified();
|
||||
// 文件被删除
|
||||
// 如果动态更新过程中,配置文件被强制删除了,本次不执行任何更新.或者对配置文件进行恢复
|
||||
if (t == 0) {
|
||||
try {
|
||||
if (file.createNewFile()) {
|
||||
OutputStream fos = new FileOutputStream(file);
|
||||
property.store(fos, "文件被删除,自动恢复.");
|
||||
fos.close();
|
||||
}
|
||||
} catch (IOException ioe2) {
|
||||
// 这里基本上只有磁盘空间满才会发生,暂时不处理
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 文件被更新
|
||||
if (t > lastModifiedTime) {
|
||||
lastModifiedTime = t;
|
||||
// 2秒后还在改变,则本次更新不做处理
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
if (t != file.lastModified()) {
|
||||
_log.info("文件可能未更新完成,本次不更新!");
|
||||
} else {
|
||||
try {
|
||||
property.clear();
|
||||
update();
|
||||
_log.info("UPDATED " + file.getAbsolutePath());
|
||||
} catch (IOException ioe) {
|
||||
_log.error("UPDATING " + file.getAbsolutePath() + " failed", ioe);
|
||||
}
|
||||
}
|
||||
_log.debug("-----------------------:" + property.keySet());
|
||||
}
|
||||
}// end run()
|
||||
}, delay, period);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.rymcu.vertical.core.service.redis;
|
||||
|
||||
import com.rymcu.vertical.entity.BaseDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* redis 中取得的结果
|
||||
* Created by liwei on 2017/2/7.
|
||||
*/
|
||||
public class RedisResult<T> extends BaseDO {
|
||||
|
||||
/**
|
||||
* redis中是否存在
|
||||
*/
|
||||
private boolean exist = false;
|
||||
|
||||
/**
|
||||
* redis中取得的数据
|
||||
*/
|
||||
private T result;
|
||||
|
||||
/**
|
||||
* redis中取得的List数据
|
||||
*/
|
||||
private List<T> listResult;
|
||||
/**
|
||||
* redis中的key是否存在。true:表示redis中存在Key,但对应的值为空值标记
|
||||
*/
|
||||
private boolean keyExists = false;
|
||||
/**
|
||||
* redis中key 对应在对象值
|
||||
*/
|
||||
private T resultObj;
|
||||
|
||||
|
||||
public boolean isExist() {
|
||||
return exist;
|
||||
}
|
||||
|
||||
public void setExist(boolean exist) {
|
||||
this.exist = exist;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(T result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public List<T> getListResult() {
|
||||
return listResult;
|
||||
}
|
||||
|
||||
public void setListResult(List<T> listResult) {
|
||||
this.listResult = listResult;
|
||||
}
|
||||
|
||||
public void setKeyExists(boolean keyExists) {
|
||||
this.keyExists = keyExists;
|
||||
}
|
||||
public boolean isKeyExists() {
|
||||
return keyExists;
|
||||
}
|
||||
|
||||
public T getResultObj() {
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
public void setResultObj(T resultObj) {
|
||||
this.resultObj = resultObj;
|
||||
}
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
package com.rymcu.vertical.core.service.redis;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Redis 服务接口
|
||||
* Jimersy Lee
|
||||
* 2017-09-18 14:58:21
|
||||
*/
|
||||
public interface RedisService {
|
||||
/**
|
||||
* NX: 当且仅当缓存中特定的key不存在时设定数据
|
||||
*/
|
||||
String NXXX_SET_IF_NOT_EXISTS = "nx";
|
||||
/**
|
||||
* XX: 当且仅当缓存中特定的key存在时设定数据
|
||||
*/
|
||||
String NXXX_SET_IF_EXISTS = "xx";
|
||||
|
||||
/**
|
||||
* EX:缓存失效的时间单位:秒
|
||||
*/
|
||||
String EXPX_SECONDS = "ex";
|
||||
|
||||
/**
|
||||
* EX:缓存失效的时间单位:毫秒
|
||||
*/
|
||||
String EXPX_MILLISECOND = "px";
|
||||
|
||||
/**
|
||||
* 默认过期时间 ,3600(秒)
|
||||
*/
|
||||
int DEFAULT_EXPIRE_TIME = 3600;
|
||||
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
|
||||
|
||||
/**
|
||||
* 空白占位符
|
||||
*/
|
||||
String BLANK_CONTENT = "__BLANK__";
|
||||
|
||||
/**
|
||||
* 初始化操作
|
||||
*/
|
||||
void init();
|
||||
|
||||
|
||||
void destroy();
|
||||
|
||||
// /**
|
||||
// * 从连接池里取连接(用完连接后必须销毁)
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
// Jedis getResource();
|
||||
|
||||
// /**
|
||||
// * 用完后,销毁连接(必须)
|
||||
// *
|
||||
// * @param jedis
|
||||
// */
|
||||
// void destroyResource(Jedis jedis);
|
||||
|
||||
/**
|
||||
* 根据key取数据
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
String get(String key);
|
||||
|
||||
|
||||
/**
|
||||
* 根据key取对象数据(不支持Collection数据类型)
|
||||
*
|
||||
* @param key
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
<T> T get(String key, Class<T> clazz);
|
||||
|
||||
|
||||
/**
|
||||
* 根据key取对象数据(不支持Collection数据类型)
|
||||
*
|
||||
* @param key
|
||||
* @param clazz
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
<T> RedisResult<T> getResult(String key, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* 根据key取 Collection 对象数据
|
||||
*
|
||||
* @param key
|
||||
* @param elementClazz 集合元素类型
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
<T> RedisResult<T> getListResult(String key, Class<T> elementClazz);
|
||||
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
String set(String key, Object obj);
|
||||
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
String set(String key, String value);
|
||||
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(无论key是否存在,均会更新key对应的值)
|
||||
*
|
||||
* @param key
|
||||
* @param obj
|
||||
* @param expireTime 缓存内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
String set(String key, Object obj, int expireTime);
|
||||
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(无论key是否存在,均会更新key对应的值)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expireTime 缓存内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
String set(String key, String value, int expireTime);
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param nxxx 缓存写入值模式 详见 {@link RedisService#NXXX_SET_IF_EXISTS}, {@link RedisService#NXXX_SET_IF_NOT_EXISTS}
|
||||
* @param expx 缓存超时时间单位 详见{@link RedisService#EXPX_SECONDS}, {@link RedisService#EXPX_MILLISECOND}
|
||||
* @param expiredTime 缓存存活时长,必须 大于0
|
||||
* @return
|
||||
*/
|
||||
String set(String key, String value, String nxxx, String expx, long expiredTime);
|
||||
|
||||
/**
|
||||
* 仅当redis中不含对应的key时,设定缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expiredTime 缓存内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
String setnx(String key, String value, long expiredTime);
|
||||
|
||||
/**
|
||||
* 仅当redis中含有对应的key时,修改缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expiredTime 缓存内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
String setxx(String key, String value, long expiredTime);
|
||||
|
||||
|
||||
/**
|
||||
* 根据key删除缓存,
|
||||
*
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
Long delete(String... keys);
|
||||
|
||||
/**
|
||||
* 判断对应的key是否存在
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
boolean exists(String key);
|
||||
|
||||
|
||||
/**
|
||||
* redis 加法运算
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return 运算结果
|
||||
*/
|
||||
Long incrBy(String key, long value);
|
||||
|
||||
/**
|
||||
* 设定redis 对应的key的剩余存活时间
|
||||
*
|
||||
* @param key
|
||||
* @param seconds
|
||||
*/
|
||||
void setTTL(String key, int seconds);
|
||||
|
||||
/**
|
||||
* 根据通配符表达式查询key值的set,通配符仅支持*
|
||||
*
|
||||
* @param pattern 如 ke6*abc等
|
||||
* @return
|
||||
*/
|
||||
Set<String> keys(String pattern);
|
||||
|
||||
/**
|
||||
* 将对象转为json字符串。若对象为null,则返回 {@link RedisService#BLANK_CONTENT}
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
String toJsonString(Object object);
|
||||
|
||||
/**
|
||||
* json序列化对象。
|
||||
*
|
||||
* @param value
|
||||
* @return 返回序列化后的字符串。若value为null,则返回 {@link RedisService#BLANK_CONTENT}
|
||||
*/
|
||||
String makeSerializedString(Object value);
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(无论key是否存在,均会更新key对应的值)
|
||||
*
|
||||
* @param cacheName
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
String put(String cacheName, String key, Object value);
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(无论key是否存在,均会更新key对应的值)
|
||||
*
|
||||
* @param cacheName
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expireTime 缓存 内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
String put(String cacheName, String key, Object value, int expireTime);
|
||||
|
||||
Object get(String cacheName, String key);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
package com.rymcu.vertical.core.service.redis.impl;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Redis Key 辅助类
|
||||
*/
|
||||
@Component
|
||||
@Lazy(false)
|
||||
public class RedisKeyHelper {
|
||||
/**
|
||||
* 应用级别前缀
|
||||
*/
|
||||
private static String SYS_PREFIX = "PROJECT_";
|
||||
/**
|
||||
* 用户信息前缀
|
||||
*/
|
||||
private static String UIC_PREFIX = SYS_PREFIX + "UIC_";
|
||||
/**
|
||||
* 商品中心信息前缀
|
||||
*/
|
||||
private static String IC_PREFIX = SYS_PREFIX + "IC_";
|
||||
/**
|
||||
* 交易中心信息前缀
|
||||
*/
|
||||
private static String TC_PREFIX = SYS_PREFIX + "TC_";
|
||||
/**
|
||||
* 优惠中心信息前缀
|
||||
*/
|
||||
private static String PROM_PREFIX = SYS_PREFIX + "PROM_";
|
||||
/**
|
||||
* 会员中心信息前缀
|
||||
*/
|
||||
private static String MMB_PREFIX = SYS_PREFIX + "MMB_";
|
||||
/**
|
||||
* 分布式互斥锁前缀
|
||||
*/
|
||||
private static String LOCK_PREFIX = SYS_PREFIX + "LOCK_";
|
||||
|
||||
/**
|
||||
* 单次登录的默认有效时长(单位:秒)
|
||||
*/
|
||||
public static final int DEFAULT_LOGIN_TIMEOUT = 3600 * 24 * 7;
|
||||
|
||||
/**
|
||||
* 签到记录的默认有效时长(单位:秒)
|
||||
*/
|
||||
public static final int MMB_SIGN_TIMEOUT = 3600 * 12;
|
||||
/**
|
||||
* redis中加息券信息的保存时间(单位:秒)
|
||||
*/
|
||||
public static final int PROM_IRC_TIMEOUT = 60 * 3;
|
||||
/**
|
||||
* redis中借款人信息默认有效效时间(单位:秒)
|
||||
*/
|
||||
public static final int BORROWER_EXPIRE_TIMEOUT = 60 * 3;//redis缓存失效时间
|
||||
|
||||
|
||||
//商品中心KEY配置==begin========================================================================================
|
||||
/**
|
||||
* 商品(资产标)前缀
|
||||
*/
|
||||
public static final String IC_ITEM_PREFIX = IC_PREFIX + "ITEM_";
|
||||
/**
|
||||
* 商品(资产标)列表前缀
|
||||
*/
|
||||
public static final String IC_ITEM_LIST_PREFIX = IC_ITEM_PREFIX + "LIST_";
|
||||
/**
|
||||
* 商品已投金额或份数前缀
|
||||
*/
|
||||
public static final String IC_ITEM_INVESTED_AMOUNT_PREFIX = IC_PREFIX + "INTESTED_AMT_";
|
||||
public static final String IC_ITEM_DEAL_CREDITOR_PREFIX = IC_PREFIX + "DEAL_CREDITOR_";
|
||||
|
||||
//商品中心KEY配置==end==========================================================================================
|
||||
//优惠中心KEY配置==begin========================================================================================
|
||||
/**
|
||||
* 加息券信息前缀
|
||||
*/
|
||||
public static String PROM_IRC_PREFIX = PROM_PREFIX + "IRC_";
|
||||
|
||||
/**
|
||||
* 优惠配置信息前缀
|
||||
*/
|
||||
public static String PROM_CONFIG_PREFIX = PROM_PREFIX + "CONFIG_";
|
||||
/**
|
||||
* 红包列表信息前缀
|
||||
*/
|
||||
public static final String PROM_COUPON_LIST_PREFIX = PROM_PREFIX + "COUPON_LIST_";
|
||||
//优惠中心KEY配置==end==========================================================================================
|
||||
//交易中心KEY配置==========================================================================================
|
||||
public static final String TC_TRANS_ACCOUNT_PREFIX = TC_PREFIX + "ACC_";
|
||||
|
||||
public static final String TC_TRANS_CURRENT_DEAL_CONFIG_PREFIX = TC_PREFIX + "CURRENT_DEAL_CONFIG_";
|
||||
|
||||
public static final String TC_TRANS_EXPERIENCE_MONEY_CONFIG_PREFIX = TC_PREFIX + "EXPERIENCE_MONEY_CONFIG_";
|
||||
|
||||
public static final String TC_TRANS_CURRENT_DEAL_LOAD_PREFIX = TC_PREFIX + "CURRENT_DEAL_LOAD_";
|
||||
|
||||
public static final String TC_TRANS_CONST_DEAL_ORDER_LIST_PREFIX = TC_PREFIX + "CURRENT_CONST_DEAL_ORDER_LIST_";
|
||||
|
||||
/**
|
||||
* 流水号redis key前缀
|
||||
*/
|
||||
public static final String TC_TRANS_SEQ_PREFIX = TC_PREFIX + "SEQ_";
|
||||
|
||||
//交易中心KEY配置==end==========================================================================================
|
||||
//用户中心KEY配置==========================================================================================
|
||||
/**
|
||||
* redis中登录用户token的key前缀
|
||||
*/
|
||||
public static String LOGIN_TOKEN_KEY_PREFIX = UIC_PREFIX + "LOGIN_TOKEN_";
|
||||
/**
|
||||
* redis中登录用户USERID的key前缀
|
||||
*/
|
||||
public static String LOGIN_UID_KEY_PREFIX = UIC_PREFIX + "LOGIN_UID_";
|
||||
/**
|
||||
* 用户信息前缀(手机号)
|
||||
*/
|
||||
public static String UIC_MOBILE_PREFIX = UIC_PREFIX + "MOB_";
|
||||
/**
|
||||
* 用户角色前缀
|
||||
*/
|
||||
public static String UIC_ROLE_PREFIX = UIC_PREFIX + "B_R_";
|
||||
public static String UIC_ROLE_CANCEL_SUFFIX = UIC_PREFIX + "CNL_";
|
||||
//用户中心KEY配置==end==========================================================================================
|
||||
|
||||
/**
|
||||
* 构建分布式锁的key
|
||||
*
|
||||
* @param clazz
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public String makeLockKey(Class clazz, String key) {
|
||||
return buildKeyString(LOCK_PREFIX, clazz.getSimpleName(), key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建分布式锁的key
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public String makeLockKey(String key) {
|
||||
return buildKeyString(LOCK_PREFIX, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造商品信息 redis key
|
||||
*
|
||||
* @param itemId
|
||||
* @return
|
||||
*/
|
||||
public String makeIcItemKey(long itemId) {
|
||||
return buildKeyString(IC_ITEM_PREFIX, itemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造商品信息列表 redis key
|
||||
*
|
||||
* @param pageSize
|
||||
* @param pageNo
|
||||
* @return
|
||||
*/
|
||||
public String makeIcItemListKey(int pageSize, int pageNo) {
|
||||
return buildKeyString(IC_ITEM_LIST_PREFIX, pageSize, pageNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造资产标已投金额前缀
|
||||
*
|
||||
* @param itemId
|
||||
* @return
|
||||
*/
|
||||
public String makeInvestedAmountKey(long itemId) {
|
||||
return buildKeyString(IC_ITEM_INVESTED_AMOUNT_PREFIX, itemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造交易中心流水号前缀
|
||||
*
|
||||
* @param flag
|
||||
* @return
|
||||
*/
|
||||
public String makeSeqKey(String flag) {
|
||||
return buildKeyString(TC_TRANS_SEQ_PREFIX, flag);
|
||||
}
|
||||
|
||||
public static String buildKeyString(Object... objs) {
|
||||
if (objs == null || objs.length == 0) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean isFirst = true;
|
||||
for (Object obj : objs) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
builder.append("_");
|
||||
}
|
||||
if (obj instanceof Class) {
|
||||
builder.append(((Class) obj).getName());
|
||||
} else {
|
||||
builder.append(obj);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,577 @@
|
||||
package com.rymcu.vertical.core.service.redis.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.rymcu.vertical.core.service.dynProps4Files.DynProps4FilesService;
|
||||
import com.rymcu.vertical.core.service.redis.RedisResult;
|
||||
import com.rymcu.vertical.core.service.redis.RedisService;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Redis 服务接口实现类
|
||||
*
|
||||
* @author liwei
|
||||
* 16/10/30 下午5:28
|
||||
*/
|
||||
@Component("redisService")
|
||||
public class RedisServiceImpl implements RedisService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
|
||||
|
||||
|
||||
private static JedisPool pool = null;
|
||||
|
||||
@Resource
|
||||
private DynProps4FilesService dynProps4Files;
|
||||
|
||||
@Resource
|
||||
private Environment env;
|
||||
|
||||
|
||||
/**
|
||||
* 初始化操作
|
||||
*/
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (pool != null) {
|
||||
return;
|
||||
}
|
||||
/*JedisPoolConfig config = new JedisPoolConfig();
|
||||
config.setMaxIdle(dynProps4Files.getInt("REDIS_MAX_IDLE", JedisPoolConfig.DEFAULT_MAX_IDLE));
|
||||
config.setMaxTotal(dynProps4Files.getInt("REDIS_MAX_TOTAL", JedisPoolConfig.DEFAULT_MAX_TOTAL));
|
||||
config.setMaxWaitMillis(dynProps4Files.getLong("REDIS_MAX_WAIT", JedisPoolConfig.DEFAULT_MAX_WAIT_MILLIS));
|
||||
config.setTestOnBorrow(true);
|
||||
pool = new JedisPool(config, dynProps4Files.getProperty("REDIS_HOST"),
|
||||
dynProps4Files.getInt("REDIS_PORT", 6379), dynProps4Files.getInt(
|
||||
"REDIS_MAX_WAIT", 1000), dynProps4Files.getProperty("REDIS_PASSWORD", null));*/
|
||||
|
||||
JedisPoolConfig config = new JedisPoolConfig();
|
||||
config.setMaxIdle(dynProps4Files.getInt("REDIS_MAX_IDLE", JedisPoolConfig.DEFAULT_MAX_IDLE));
|
||||
config.setMaxTotal(dynProps4Files.getInt("REDIS_MAX_TOTAL", JedisPoolConfig.DEFAULT_MAX_TOTAL));
|
||||
config.setMaxWaitMillis(dynProps4Files.getLong("REDIS_MAX_WAIT", JedisPoolConfig.DEFAULT_MAX_WAIT_MILLIS));
|
||||
config.setTestOnBorrow(true);
|
||||
pool = new JedisPool(config, env.getProperty("spring.redis.host"),
|
||||
dynProps4Files.getInt("REDIS_PORT", 6379), dynProps4Files.getInt(
|
||||
"REDIS_MAX_WAIT", 1000), dynProps4Files.getProperty("REDIS_PASSWORD", env.getProperty("spring.redis.password")));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
try {
|
||||
if (pool != null) {
|
||||
pool.destroy();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从连接池里取连接(用完连接后必须销毁)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Jedis getResource() {
|
||||
return pool.getResource();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 用完后,销毁连接(必须)
|
||||
*
|
||||
* @param jedis
|
||||
*/
|
||||
private void destroyResource(Jedis jedis) {
|
||||
if (jedis == null) {
|
||||
return;
|
||||
}
|
||||
IOUtils.closeQuietly(jedis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key取数据
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public String get(String key) {
|
||||
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
return jedis.get(key);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key取对象数据(不支持Collection数据类型)
|
||||
*
|
||||
* @param key
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public <T> T get(String key, Class<T> clazz) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return null;
|
||||
}
|
||||
if (clazz == null) {
|
||||
logger.warn("Params clazz is null!");
|
||||
return null;
|
||||
}
|
||||
String value = get(key);
|
||||
if (StringUtils.isBlank(value) || StringUtils.equalsIgnoreCase(value, BLANK_CONTENT)) {
|
||||
return null;
|
||||
}
|
||||
T obj = null;
|
||||
try {
|
||||
obj = om.readValue(value, clazz);
|
||||
} catch (IOException e) {
|
||||
logger.error("Can not unserialize obj to [{}] with string [{}]", clazz.getName(), value);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(无论key是否存在,均会更新key对应的值)
|
||||
*
|
||||
* @param key
|
||||
* @param obj
|
||||
* @param expireTime 缓存 内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
public String set(String key, Object obj, int expireTime) {
|
||||
String value = RedisService.BLANK_CONTENT;
|
||||
if (obj != null) {
|
||||
try {
|
||||
value = RedisService.om.writeValueAsString(obj);
|
||||
} catch (IOException e) {
|
||||
logger.error("Can not write object to redis:" + obj.toString(), e);
|
||||
}
|
||||
}
|
||||
return set(key, value, expireTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(无论key是否存在,均会更新key对应的值)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expireTime 缓存 内容过期时间 (单位:秒) ,若expireTime小于0 则表示该内容不过期
|
||||
* @return
|
||||
*/
|
||||
public String set(String key, String value, int expireTime) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
|
||||
logger.warn("Params value is null!");
|
||||
return null;
|
||||
}
|
||||
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
String result = jedis.set(key, value);
|
||||
if (expireTime > 0) {
|
||||
jedis.expire(key, expireTime);
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key取对象数据(不支持Collection数据类型)
|
||||
*
|
||||
* @param key
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public <T> RedisResult<T> getResult(String key, Class<T> clazz) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return null;
|
||||
}
|
||||
if (clazz == null) {
|
||||
logger.warn("Params clazz is null!");
|
||||
return null;
|
||||
}
|
||||
RedisResult<T> redisResult = new RedisResult<T>();
|
||||
|
||||
String value = get(key);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
redisResult.setExist(false);
|
||||
return redisResult;
|
||||
}
|
||||
//到此步,则表明redis中存在key
|
||||
redisResult.setExist(true);
|
||||
if (StringUtils.equalsIgnoreCase(value, BLANK_CONTENT)) {
|
||||
return redisResult;
|
||||
}
|
||||
T obj = null;
|
||||
try {
|
||||
obj = om.readValue(value, clazz);
|
||||
redisResult.setResult(obj);
|
||||
} catch (IOException e) {
|
||||
logger.error("Can not unserialize obj to [{}] with string [{}]", clazz.getName(), value);
|
||||
//到此步直接视为无值
|
||||
redisResult.setExist(false);
|
||||
}
|
||||
return redisResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key取 Collection 对象数据
|
||||
*
|
||||
* @param key
|
||||
* @param elementClazz 集合元素类型
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public <T> RedisResult<T> getListResult(String key, Class<T> elementClazz) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (elementClazz == null) {
|
||||
logger.warn("Params elementClazz is null!");
|
||||
return null;
|
||||
}
|
||||
RedisResult<T> redisResult = new RedisResult<T>();
|
||||
|
||||
String value = get(key);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
redisResult.setExist(false);
|
||||
return redisResult;
|
||||
}
|
||||
|
||||
//到此步,则表明redis中存在key
|
||||
redisResult.setExist(true);
|
||||
if (StringUtils.equalsIgnoreCase(value, BLANK_CONTENT)) {
|
||||
return redisResult;
|
||||
}
|
||||
|
||||
List<T> list = null;
|
||||
try {
|
||||
list = om.readValue(value, getCollectionType(List.class, elementClazz));
|
||||
redisResult.setListResult(list);
|
||||
} catch (IOException e) {
|
||||
logger.error("Can not unserialize list to [{}] with string [{}]", elementClazz.getName(), value);
|
||||
//到此步直接视为无值
|
||||
redisResult.setExist(false);
|
||||
}
|
||||
|
||||
return redisResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String set(String key, Object obj) {
|
||||
String value = RedisService.BLANK_CONTENT;
|
||||
if (obj != null) {
|
||||
try {
|
||||
value = RedisService.om.writeValueAsString(obj);
|
||||
} catch (IOException e) {
|
||||
logger.error("Can not write object to redis:" + obj.toString(), e);
|
||||
}
|
||||
}
|
||||
return set(key, value);
|
||||
}
|
||||
|
||||
private static <T> JavaType getCollectionType(Class<? extends Collection> collectionClazz,
|
||||
Class<T> elementClazz) {
|
||||
return om.getTypeFactory().constructCollectionType(collectionClazz, elementClazz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容(默认有过期时间 1小时)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String set(String key, String value) {
|
||||
return this.set(key, value, DEFAULT_EXPIRE_TIME);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 写入/修改 缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param nxxx 缓存写入值模式 详见 {@link RedisService#NXXX_SET_IF_EXISTS}, {@link RedisService#NXXX_SET_IF_NOT_EXISTS}
|
||||
* @param expx 缓存超时时间单位 详见{@link RedisService#EXPX_SECONDS}, {@link RedisService#EXPX_MILLISECOND}
|
||||
* @param expiredTime 缓存存活时长,必须 大于0
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String set(String key, String value, String nxxx, String expx, long expiredTime) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
logger.warn("Params value is null!");
|
||||
return null;
|
||||
}
|
||||
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
return jedis.set(key, value);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅当redis中不含对应的key时,设定缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expiredTime 缓存内容过期时间 (单位:秒) ,expireTime必须大于0
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String setnx(String key, String value, long expiredTime) {
|
||||
return this.set(key, value, NXXX_SET_IF_NOT_EXISTS, EXPX_SECONDS, expiredTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅当redis中含有对应的key时,修改缓存内容
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expiredTime 缓存内容过期时间 (单位:秒) ,expireTime必须大于0
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String setxx(String key, String value, long expiredTime) {
|
||||
return this.set(key, value, NXXX_SET_IF_EXISTS, EXPX_SECONDS, expiredTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key删除缓存
|
||||
*
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public Long delete(String... keys) {
|
||||
if (keys == null || keys.length == 0) {
|
||||
logger.warn("Params keys is null or 0 length!");
|
||||
return -1L;
|
||||
}
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
return jedis.del(keys);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断对应的key是否存在
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public boolean exists(String key) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
//不接受空值
|
||||
return false;
|
||||
}
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
return jedis.exists(key);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* redis 加法运算
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Long incrBy(String key, long value) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return null;
|
||||
}
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
return jedis.incrBy(key, value);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设定redis 对应的key的剩余存活时间
|
||||
*
|
||||
* @param key
|
||||
* @param seconds
|
||||
*/
|
||||
@Override
|
||||
public void setTTL(String key, int seconds) {
|
||||
if (seconds < 0) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isBlank(key)) {
|
||||
logger.warn("Params key is blank!");
|
||||
return;
|
||||
}
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
jedis.expire(key, seconds);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据通配符表达式查询key值的set,通配符仅支持*
|
||||
*
|
||||
* @param pattern 如 ke6*abc等
|
||||
* @return
|
||||
*/
|
||||
public Set<String> keys(String pattern) {
|
||||
|
||||
if (StringUtils.isBlank(pattern)) {
|
||||
logger.warn("Params pattern is blank!");
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Jedis jedis = this.getResource();
|
||||
try {
|
||||
return jedis.keys(pattern);
|
||||
} finally {
|
||||
this.destroyResource(jedis);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将对象转为json字符串。若对象为null,则返回 {@link RedisService#BLANK_CONTENT}
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String toJsonString(Object object) {
|
||||
if (object == null) {
|
||||
return BLANK_CONTENT;
|
||||
}
|
||||
|
||||
if ((object instanceof Collection) && CollectionUtils.isEmpty((Collection) object)) {
|
||||
return BLANK_CONTENT;
|
||||
}
|
||||
|
||||
if ((object instanceof Map) && CollectionUtils.isEmpty((Map) object)) {
|
||||
return BLANK_CONTENT;
|
||||
}
|
||||
|
||||
try {
|
||||
return om.writeValueAsString(object);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String makeSerializedString(Object value) {
|
||||
if (value == null) {
|
||||
return BLANK_CONTENT;
|
||||
}
|
||||
|
||||
if ((value instanceof Collection) && ((Collection) value).size() == 0) {
|
||||
return BLANK_CONTENT;
|
||||
}
|
||||
|
||||
if ((value instanceof Map) && ((Map) value).size() == 0) {
|
||||
return BLANK_CONTENT;
|
||||
}
|
||||
|
||||
|
||||
return JSON.toJSONString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String put(String cacheName, String key, Object value) {
|
||||
String result = get(cacheName);
|
||||
Map map = new HashMap();
|
||||
if (StringUtils.isNotBlank(result)){
|
||||
map = JSON.parseObject(result, new TypeReference<Map>() {});
|
||||
}
|
||||
map.put(key,value);
|
||||
return set(cacheName,map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String put(String cacheName, String key, Object value, int expireTime) {
|
||||
String result = get(cacheName);
|
||||
Map map = new HashMap();
|
||||
if (StringUtils.isNotBlank(result)){
|
||||
map = JSON.parseObject(result, new TypeReference<Map>() {});
|
||||
}
|
||||
map.put(key,value);
|
||||
return set(cacheName,map,expireTime);
|
||||
}
|
||||
|
||||
public Object get(String cacheName, String key){
|
||||
String result = get(cacheName);
|
||||
if (StringUtils.isNotBlank(result)){
|
||||
Map map = JSON.parseObject(result, new TypeReference<Map>() {});
|
||||
return map.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
27
src/main/java/com/rymcu/vertical/dto/MenuDTO.java
Normal file
27
src/main/java/com/rymcu/vertical/dto/MenuDTO.java
Normal file
@ -0,0 +1,27 @@
|
||||
package com.rymcu.vertical.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MenuDTO {
|
||||
|
||||
private String id;
|
||||
|
||||
private String parentId;
|
||||
|
||||
private String parentName;
|
||||
|
||||
private String name;
|
||||
|
||||
private Long sort = 50L;
|
||||
|
||||
private String href;
|
||||
|
||||
private String menuType = "0";
|
||||
|
||||
private String permission;
|
||||
|
||||
private String remarks;
|
||||
|
||||
private String status = "0";
|
||||
}
|
25
src/main/java/com/rymcu/vertical/dto/RoleDTO.java
Normal file
25
src/main/java/com/rymcu/vertical/dto/RoleDTO.java
Normal file
@ -0,0 +1,25 @@
|
||||
package com.rymcu.vertical.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RoleDTO {
|
||||
|
||||
// id
|
||||
private String id;
|
||||
|
||||
// 名称
|
||||
private String name;
|
||||
|
||||
// 英文名称
|
||||
private String enname;
|
||||
|
||||
// 用户类别
|
||||
private String roleType;
|
||||
|
||||
// 角色授权菜单ids
|
||||
private String menuIds;
|
||||
|
||||
// 备注
|
||||
private String remarks;
|
||||
}
|
45
src/main/java/com/rymcu/vertical/dto/UserDTO.java
Normal file
45
src/main/java/com/rymcu/vertical/dto/UserDTO.java
Normal file
@ -0,0 +1,45 @@
|
||||
package com.rymcu.vertical.dto;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class UserDTO implements Serializable {
|
||||
|
||||
private String id;
|
||||
|
||||
private String office;
|
||||
|
||||
private String officeId;
|
||||
|
||||
private String loginName;
|
||||
|
||||
private String password;
|
||||
|
||||
private String no;
|
||||
|
||||
private String name;
|
||||
|
||||
private String email;
|
||||
|
||||
private String phone;
|
||||
|
||||
private String mobile;
|
||||
|
||||
private String status;
|
||||
|
||||
private String remarks;
|
||||
|
||||
private String roleIds;
|
||||
|
||||
private String sex = "男";
|
||||
|
||||
private String inputCode;
|
||||
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm")
|
||||
private Date lastLoginTime;
|
||||
|
||||
}
|
19
src/main/java/com/rymcu/vertical/dto/UserExportDTO.java
Normal file
19
src/main/java/com/rymcu/vertical/dto/UserExportDTO.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.rymcu.vertical.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserExportDTO {
|
||||
|
||||
private String officeName;
|
||||
|
||||
private String name;
|
||||
|
||||
private String sex;
|
||||
|
||||
private String loginName;
|
||||
|
||||
private String storePerm;
|
||||
|
||||
private String departPerm;
|
||||
}
|
22
src/main/java/com/rymcu/vertical/entity/BaseDO.java
Normal file
22
src/main/java/com/rymcu/vertical/entity/BaseDO.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.rymcu.vertical.entity;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 基础DO类,提供toString快方法
|
||||
* Created by liwei on 2015/6/16.
|
||||
*/
|
||||
public class BaseDO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1394589131426860408L;
|
||||
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
68
src/main/java/com/rymcu/vertical/entity/Menu.java
Normal file
68
src/main/java/com/rymcu/vertical/entity/Menu.java
Normal file
@ -0,0 +1,68 @@
|
||||
package com.rymcu.vertical.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import tk.mybatis.mapper.annotation.ColumnType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Table(name = "SYS_MENU")
|
||||
public class Menu {
|
||||
|
||||
@Id
|
||||
@Column(name = "ID_MENU")
|
||||
private Integer idMenu;
|
||||
|
||||
/**
|
||||
* 上级菜单ID
|
||||
* */
|
||||
@Column(name = "PARENT_ID")
|
||||
private String parentId;
|
||||
|
||||
/**
|
||||
* 菜单名称
|
||||
* */
|
||||
@Column(name = "NAME")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
* */
|
||||
@Column(name = "SORT")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 路径
|
||||
* */
|
||||
@Column(name = "HREF")
|
||||
private String href;
|
||||
|
||||
/**
|
||||
* 菜单类型
|
||||
* */
|
||||
@Column(name = "MENU_TYPE")
|
||||
private String menuType;
|
||||
|
||||
/**
|
||||
* 权限标识
|
||||
* */
|
||||
@ColumnType(column = "PERMISSION",
|
||||
jdbcType = JdbcType.VARCHAR)
|
||||
private String permission;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
* */
|
||||
@Column(name = "CREATED_TIME")
|
||||
private Date createdTime;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* */
|
||||
@Column(name = "STATUS")
|
||||
private String status;
|
||||
}
|
40
src/main/java/com/rymcu/vertical/entity/Role.java
Normal file
40
src/main/java/com/rymcu/vertical/entity/Role.java
Normal file
@ -0,0 +1,40 @@
|
||||
package com.rymcu.vertical.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Table(name = "SYS_ROLE")
|
||||
public class Role {
|
||||
@Id
|
||||
@Column(name = "ID_ROLE")
|
||||
private String idRole;
|
||||
|
||||
/**
|
||||
* 角色名称
|
||||
* */
|
||||
@Column(name = "NAME")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 拼音码
|
||||
* */
|
||||
@Column(name = "INPUT_CODE")
|
||||
private String inputCode;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* */
|
||||
@Column(name = "STATUS")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
* */
|
||||
@Column(name = "CREATED_TIME")
|
||||
private Date createdTime;
|
||||
}
|
105
src/main/java/com/rymcu/vertical/entity/User.java
Normal file
105
src/main/java/com/rymcu/vertical/entity/User.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.rymcu.vertical.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import tk.mybatis.mapper.annotation.ColumnType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
@Table(name = "SYS_USER")
|
||||
@Data
|
||||
public class User {
|
||||
@Id
|
||||
@Column(name = "ID_USER")
|
||||
private Integer idUser;
|
||||
|
||||
/**
|
||||
* 应用ID
|
||||
* */
|
||||
@Column(name = "APP_ID")
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 登录账号
|
||||
* */
|
||||
@Column(name = "ACCOUNT")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
* */
|
||||
@Column(name = "PASSWORD")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
* */
|
||||
@Column(name = "NICK_NAME")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 真实姓名
|
||||
* */
|
||||
@Column(name = "REAL_NAME")
|
||||
private String realName;
|
||||
|
||||
/**
|
||||
* 性别 1:男性 2:女性
|
||||
* */
|
||||
@Column(name = "SEX")
|
||||
private Integer sex;
|
||||
|
||||
/**
|
||||
* 头像文件类型
|
||||
* */
|
||||
@Column(name = "AVATAR_TYPE")
|
||||
private Integer avatarType;
|
||||
|
||||
/**
|
||||
* 头像路径
|
||||
* */
|
||||
@Column(name = "AVATAR_URL")
|
||||
private String avatarUrl;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
* */
|
||||
@ColumnType(column = "EMAIL",
|
||||
jdbcType = JdbcType.VARCHAR)
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
* */
|
||||
@ColumnType(column = "PHONE",
|
||||
jdbcType = JdbcType.VARCHAR)
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 签名
|
||||
* */
|
||||
@ColumnType(column = "SIGNATURE",
|
||||
jdbcType = JdbcType.VARCHAR)
|
||||
private String signature;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* */
|
||||
@Column(name = "STATUS")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 最后登录时间
|
||||
* */
|
||||
@Column(name = "LAST_LOGIN_TIME")
|
||||
private Date lastLoginTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
* */
|
||||
@Column(name = "CREATED_TIME")
|
||||
private Date createdTime;
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.rymcu.vertical.jwt.aop;
|
||||
|
||||
|
||||
|
||||
import com.rymcu.vertical.jwt.def.JwtConstants;
|
||||
import com.rymcu.vertical.jwt.model.TokenModel;
|
||||
import com.rymcu.vertical.jwt.service.TokenManager;
|
||||
import com.rymcu.vertical.jwt.util.oConvertUtils;
|
||||
import com.rymcu.vertical.web.api.exception.ErrorCode;
|
||||
import com.rymcu.vertical.web.api.exception.MallApiException;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Restful请求, Token校验规则拦截器(JWT)
|
||||
*
|
||||
* @author scott
|
||||
* @date 2015/7/30.
|
||||
*/
|
||||
public class RestAuthTokenInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
private TokenManager manager;
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, Object obj, Exception exception) throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
|
||||
|
||||
//从header中得到token
|
||||
String authHeader = request.getHeader(JwtConstants.AUTHORIZATION);
|
||||
if (StringUtils.isBlank(authHeader)) {
|
||||
throw new MallApiException(ErrorCode.UNAUTHORIZED);
|
||||
}
|
||||
// 验证token
|
||||
Claims claims = null;
|
||||
try {
|
||||
claims = Jwts.parser().setSigningKey(JwtConstants.JWT_SECRET).parseClaimsJws(authHeader).getBody();
|
||||
}catch (final SignatureException e) {
|
||||
throw new MallApiException(ErrorCode.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Object username = claims.getId();
|
||||
if (oConvertUtils.isEmpty(username)) {
|
||||
throw new MallApiException(ErrorCode.INVALID_TOKEN);
|
||||
}
|
||||
TokenModel model = manager.getToken(authHeader,username.toString());
|
||||
if (manager.checkToken(model)) {
|
||||
//如果token验证成功,将对象传递给下一个请求
|
||||
request.setAttribute(JwtConstants.CURRENT_TOKEN_CLAIMS, claims);
|
||||
//如果token验证成功,将token对应的用户id存在request中,便于之后注入
|
||||
request.setAttribute(JwtConstants.CURRENT_USER_NAME, model.getUsername());
|
||||
return true;
|
||||
} else {
|
||||
throw new MallApiException(ErrorCode.TOKEN_);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, Object obj, ModelAndView modelandview) throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
}
|
15
src/main/java/com/rymcu/vertical/jwt/def/JwtConstants.java
Normal file
15
src/main/java/com/rymcu/vertical/jwt/def/JwtConstants.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.rymcu.vertical.jwt.def;
|
||||
|
||||
public class JwtConstants {
|
||||
|
||||
/**
|
||||
* 上线需要变更
|
||||
*/
|
||||
public static final String JWT_SECRET = "JYJ5Qv2WF4lA6jPl5GKuAG";
|
||||
|
||||
public static final String AUTHORIZATION = "Authorization";
|
||||
public static final String CURRENT_USER_NAME = "CURRENT_TOKEN_USER_NAME";
|
||||
public static final String CURRENT_TOKEN_CLAIMS = "CURRENT_TOKEN_CLAIMS";
|
||||
public static final long TOKEN_EXPIRES_HOUR = 2 * 60;
|
||||
|
||||
}
|
36
src/main/java/com/rymcu/vertical/jwt/model/TokenModel.java
Normal file
36
src/main/java/com/rymcu/vertical/jwt/model/TokenModel.java
Normal file
@ -0,0 +1,36 @@
|
||||
package com.rymcu.vertical.jwt.model;
|
||||
|
||||
/**
|
||||
* Token的Model类,可以增加字段提高安全性,例如时间戳、url签名
|
||||
* @author ScienJus
|
||||
* @date 2015/7/31.
|
||||
*/
|
||||
public class TokenModel {
|
||||
|
||||
//用户id
|
||||
private String username;
|
||||
|
||||
//随机生成的uuid
|
||||
private String token;
|
||||
|
||||
public TokenModel(String username, String token) {
|
||||
this.username = username;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.rymcu.vertical.jwt.service;
|
||||
|
||||
|
||||
import com.rymcu.vertical.core.service.redis.RedisService;
|
||||
import com.rymcu.vertical.jwt.def.JwtConstants;
|
||||
import com.rymcu.vertical.jwt.model.TokenModel;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 通过Redis存储和验证token的实现类
|
||||
* @author ScienJus
|
||||
* @date 2015/7/31.
|
||||
*/
|
||||
@Component
|
||||
public class RedisTokenManager implements TokenManager {
|
||||
@Autowired
|
||||
private StringRedisTemplate redisTemplate;
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
/**
|
||||
* 生成TOKEN
|
||||
*/
|
||||
public String createToken(String id) {
|
||||
//使用uuid作为源token
|
||||
String token = Jwts.builder().setId(id).setSubject(id).setIssuedAt(new Date()).signWith(SignatureAlgorithm.HS256, JwtConstants.JWT_SECRET).compact();
|
||||
//存储到redis并设置过期时间
|
||||
redisTemplate.boundValueOps(id).set(token, JwtConstants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS);
|
||||
return token;
|
||||
}
|
||||
|
||||
public TokenModel getToken(String token, String userid) {
|
||||
return new TokenModel(userid, token);
|
||||
}
|
||||
|
||||
public boolean checkToken(TokenModel model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
String token = (String) redisTemplate.boundValueOps(model.getUsername()).get();
|
||||
if (token == null || !token.equals(model.getToken())) {
|
||||
return false;
|
||||
}
|
||||
//如果验证成功,说明此用户进行了一次有效操作,延长token的过期时间
|
||||
redisTemplate.boundValueOps(model.getUsername()).expire(JwtConstants.TOKEN_EXPIRES_HOUR, TimeUnit.HOURS);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void deleteToken(String username) {
|
||||
redisTemplate.delete(username);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.rymcu.vertical.jwt.service;
|
||||
|
||||
|
||||
import com.rymcu.vertical.jwt.model.TokenModel;
|
||||
|
||||
/**
|
||||
* 对token进行操作的接口
|
||||
* @author ScienJus
|
||||
* @date 2015/7/31.
|
||||
*/
|
||||
public interface TokenManager {
|
||||
|
||||
/**
|
||||
* 创建一个token关联上指定用户
|
||||
* @return 生成的token
|
||||
*/
|
||||
public String createToken(String id);
|
||||
|
||||
/**
|
||||
* 检查token是否有效
|
||||
* @param model token
|
||||
* @return 是否有效
|
||||
*/
|
||||
public boolean checkToken(TokenModel model);
|
||||
|
||||
/**
|
||||
* 从字符串中解析token
|
||||
* @return
|
||||
*/
|
||||
public TokenModel getToken(String token, String userid);
|
||||
|
||||
/**
|
||||
* 清除token
|
||||
* @param username 登录用户账号
|
||||
*/
|
||||
public void deleteToken(String username);
|
||||
|
||||
}
|
498
src/main/java/com/rymcu/vertical/jwt/util/oConvertUtils.java
Normal file
498
src/main/java/com/rymcu/vertical/jwt/util/oConvertUtils.java
Normal file
@ -0,0 +1,498 @@
|
||||
package com.rymcu.vertical.jwt.util;
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.Date;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 张代浩
|
||||
*
|
||||
*/
|
||||
public class oConvertUtils {
|
||||
public static boolean isEmpty(Object object) {
|
||||
if (object == null) {
|
||||
return (true);
|
||||
}
|
||||
if (object.equals("")) {
|
||||
return (true);
|
||||
}
|
||||
if (object.equals("null")) {
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
public static boolean isNotEmpty(Object object) {
|
||||
if (object != null && !object.equals("") && !object.equals("null")) {
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
public static String decode(String strIn, String sourceCode, String targetCode) {
|
||||
String temp = code2code(strIn, sourceCode, targetCode);
|
||||
return temp;
|
||||
}
|
||||
|
||||
public static String StrToUTF(String strIn, String sourceCode, String targetCode) {
|
||||
strIn = "";
|
||||
try {
|
||||
strIn = new String(strIn.getBytes("ISO-8859-1"), "GBK");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return strIn;
|
||||
|
||||
}
|
||||
|
||||
private static String code2code(String strIn, String sourceCode, String targetCode) {
|
||||
String strOut = null;
|
||||
if (strIn == null || (strIn.trim()).equals(""))
|
||||
return strIn;
|
||||
try {
|
||||
byte[] b = strIn.getBytes(sourceCode);
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
System.out.print(b[i] + " ");
|
||||
}
|
||||
strOut = new String(b, targetCode);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return strOut;
|
||||
}
|
||||
|
||||
public static int getInt(String s, int defval) {
|
||||
if (s == null || s == "") {
|
||||
return (defval);
|
||||
}
|
||||
try {
|
||||
return (Integer.parseInt(s));
|
||||
} catch (NumberFormatException e) {
|
||||
return (defval);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(String s) {
|
||||
if (s == null || s == "") {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return (Integer.parseInt(s));
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(String s, Integer df) {
|
||||
if (s == null || s == "") {
|
||||
return df;
|
||||
}
|
||||
try {
|
||||
return (Integer.parseInt(s));
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Integer[] getInts(String[] s) {
|
||||
Integer[] integer = new Integer[s.length];
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
integer[i] = Integer.parseInt(s[i]);
|
||||
}
|
||||
return integer;
|
||||
|
||||
}
|
||||
|
||||
public static double getDouble(String s, double defval) {
|
||||
if (s == null || s == "") {
|
||||
return (defval);
|
||||
}
|
||||
try {
|
||||
return (Double.parseDouble(s));
|
||||
} catch (NumberFormatException e) {
|
||||
return (defval);
|
||||
}
|
||||
}
|
||||
|
||||
public static double getDou(Double s, double defval) {
|
||||
if (s == null) {
|
||||
return (defval);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static Short getShort(String s) {
|
||||
if (StringUtils.isNotEmpty(s)) {
|
||||
return (Short.parseShort(s));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(Object object, int defval) {
|
||||
if (isEmpty(object)) {
|
||||
return (defval);
|
||||
}
|
||||
try {
|
||||
return (Integer.parseInt(object.toString()));
|
||||
} catch (NumberFormatException e) {
|
||||
return (defval);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(BigDecimal s, int defval) {
|
||||
if (s == null) {
|
||||
return (defval);
|
||||
}
|
||||
return s.intValue();
|
||||
}
|
||||
|
||||
public static Integer[] getIntegerArry(String[] object) {
|
||||
int len = object.length;
|
||||
Integer[] result = new Integer[len];
|
||||
try {
|
||||
for (int i = 0; i < len; i++) {
|
||||
result[i] = new Integer(object[i].trim());
|
||||
}
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getString(String s) {
|
||||
return (getString(s, ""));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义成Unicode编码
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String escapeJava(Object s) {
|
||||
return StringEscapeUtils.escapeJava(getString(s));
|
||||
}
|
||||
|
||||
public static String getString(Object object) {
|
||||
if (isEmpty(object)) {
|
||||
return "";
|
||||
}
|
||||
return (object.toString().trim());
|
||||
}
|
||||
|
||||
public static String getString(int i) {
|
||||
return (String.valueOf(i));
|
||||
}
|
||||
|
||||
public static String getString(float i) {
|
||||
return (String.valueOf(i));
|
||||
}
|
||||
|
||||
public static String getString(String s, String defval) {
|
||||
if (isEmpty(s)) {
|
||||
return (defval);
|
||||
}
|
||||
return (s.trim());
|
||||
}
|
||||
|
||||
public static String getString(Object s, String defval) {
|
||||
if (isEmpty(s)) {
|
||||
return (defval);
|
||||
}
|
||||
return (s.toString().trim());
|
||||
}
|
||||
|
||||
public static long stringToLong(String str) {
|
||||
Long test = new Long(0);
|
||||
try {
|
||||
test = Long.valueOf(str);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return test.longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本机IP
|
||||
*/
|
||||
public static String getIp() {
|
||||
String ip = null;
|
||||
try {
|
||||
InetAddress address = InetAddress.getLocalHost();
|
||||
ip = address.getHostAddress();
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个类是否为基本数据类型。
|
||||
*
|
||||
* @param clazz
|
||||
* 要判断的类。
|
||||
* @return true 表示为基本数据类型。
|
||||
*/
|
||||
private static boolean isBaseDataType(Class clazz) throws Exception {
|
||||
return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || clazz.equals(Date.class) || clazz.isPrimitive());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param request
|
||||
* IP
|
||||
* @return IP Address
|
||||
*/
|
||||
public static String getIpAddrByRequest(HttpServletRequest request) {
|
||||
String ip = request.getHeader("x-forwarded-for");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 本机IP
|
||||
* @throws SocketException
|
||||
*/
|
||||
public static String getRealIp() throws SocketException {
|
||||
String localip = null;// 本地IP,如果没有配置外网IP则返回它
|
||||
String netip = null;// 外网IP
|
||||
|
||||
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
InetAddress ip = null;
|
||||
boolean finded = false;// 是否找到外网IP
|
||||
while (netInterfaces.hasMoreElements() && !finded) {
|
||||
NetworkInterface ni = netInterfaces.nextElement();
|
||||
Enumeration<InetAddress> address = ni.getInetAddresses();
|
||||
while (address.hasMoreElements()) {
|
||||
ip = address.nextElement();
|
||||
if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP
|
||||
netip = ip.getHostAddress();
|
||||
finded = true;
|
||||
break;
|
||||
} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP
|
||||
localip = ip.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (netip != null && !"".equals(netip)) {
|
||||
return netip;
|
||||
} else {
|
||||
return localip;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* java去除字符串中的空格、回车、换行符、制表符
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String replaceBlank(String str) {
|
||||
String dest = "";
|
||||
if (str != null) {
|
||||
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
|
||||
Matcher m = p.matcher(str);
|
||||
dest = m.replaceAll("");
|
||||
}
|
||||
return dest;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断元素是否在数组内
|
||||
*
|
||||
* @param substring
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
public static boolean isIn(String substring, String[] source) {
|
||||
if (source == null || source.length == 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < source.length; i++) {
|
||||
String aSource = source[i];
|
||||
if (aSource.equals(substring)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map对象
|
||||
*/
|
||||
public static Map<Object, Object> getHashMap() {
|
||||
return new HashMap<Object, Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* SET转换MAP
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static Map<Object, Object> SetToMap(Set<Object> setobj) {
|
||||
Map<Object, Object> map = getHashMap();
|
||||
for (Iterator iterator = setobj.iterator(); iterator.hasNext();) {
|
||||
Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) iterator.next();
|
||||
map.put(entry.getKey().toString(), entry.getValue() == null ? "" : entry.getValue().toString().trim());
|
||||
}
|
||||
return map;
|
||||
|
||||
}
|
||||
|
||||
public static boolean isInnerIP(String ipAddress) {
|
||||
boolean isInnerIp = false;
|
||||
long ipNum = getIpNum(ipAddress);
|
||||
/**
|
||||
* 私有IP:A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 192.168.0.0-192.168.255.255 当然,还有127这个网段是环回地址
|
||||
**/
|
||||
long aBegin = getIpNum("10.0.0.0");
|
||||
long aEnd = getIpNum("10.255.255.255");
|
||||
long bBegin = getIpNum("172.16.0.0");
|
||||
long bEnd = getIpNum("172.31.255.255");
|
||||
long cBegin = getIpNum("192.168.0.0");
|
||||
long cEnd = getIpNum("192.168.255.255");
|
||||
isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || ipAddress.equals("127.0.0.1");
|
||||
return isInnerIp;
|
||||
}
|
||||
|
||||
private static long getIpNum(String ipAddress) {
|
||||
String[] ip = ipAddress.split("\\.");
|
||||
long a = Integer.parseInt(ip[0]);
|
||||
long b = Integer.parseInt(ip[1]);
|
||||
long c = Integer.parseInt(ip[2]);
|
||||
long d = Integer.parseInt(ip[3]);
|
||||
|
||||
long ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
|
||||
return ipNum;
|
||||
}
|
||||
|
||||
private static boolean isInner(long userIp, long begin, long end) {
|
||||
return (userIp >= begin) && (userIp <= end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线大写方式命名的字符串转换为驼峰式。
|
||||
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
|
||||
* 例如:hello_world->helloWorld
|
||||
*
|
||||
* @param name
|
||||
* 转换前的下划线大写方式命名的字符串
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String camelName(String name) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
// 快速检查
|
||||
if (name == null || name.isEmpty()) {
|
||||
// 没必要转换
|
||||
return "";
|
||||
} else if (!name.contains("_")) {
|
||||
// 不含下划线,仅将首字母小写
|
||||
|
||||
return name.substring(0, 1).toLowerCase() + name.substring(1).toLowerCase();
|
||||
|
||||
}
|
||||
// 用下划线将原始字符串分割
|
||||
String camels[] = name.split("_");
|
||||
for (String camel : camels) {
|
||||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||||
if (camel.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// 处理真正的驼峰片段
|
||||
if (result.length() == 0) {
|
||||
// 第一个驼峰片段,全部字母都小写
|
||||
result.append(camel.toLowerCase());
|
||||
} else {
|
||||
// 其他的驼峰片段,首字母大写
|
||||
result.append(camel.substring(0, 1).toUpperCase());
|
||||
result.append(camel.substring(1).toLowerCase());
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线大写方式命名的字符串转换为驼峰式。
|
||||
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
|
||||
* 例如:hello_world,test_id->helloWorld,testId
|
||||
*
|
||||
* @param name
|
||||
* 转换前的下划线大写方式命名的字符串
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String camelNames(String names) {
|
||||
if(names==null||names.equals("")){
|
||||
return null;
|
||||
}
|
||||
StringBuffer sf = new StringBuffer();
|
||||
String[] fs = names.split(",");
|
||||
for (String field : fs) {
|
||||
field = camelName(field);
|
||||
sf.append(field + ",");
|
||||
}
|
||||
String result = sf.toString();
|
||||
return result.substring(0, result.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线大写方式命名的字符串转换为驼峰式。(首字母写)
|
||||
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
|
||||
* 例如:hello_world->HelloWorld
|
||||
*
|
||||
* @param name
|
||||
* 转换前的下划线大写方式命名的字符串
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String camelNameCapFirst(String name) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
// 快速检查
|
||||
if (name == null || name.isEmpty()) {
|
||||
// 没必要转换
|
||||
return "";
|
||||
} else if (!name.contains("_")) {
|
||||
// 不含下划线,仅将首字母小写
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
|
||||
}
|
||||
// 用下划线将原始字符串分割
|
||||
String camels[] = name.split("_");
|
||||
for (String camel : camels) {
|
||||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||||
if (camel.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// 其他的驼峰片段,首字母大写
|
||||
result.append(camel.substring(0, 1).toUpperCase());
|
||||
result.append(camel.substring(1).toLowerCase());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
24
src/main/java/com/rymcu/vertical/mapper/MenuMapper.java
Normal file
24
src/main/java/com/rymcu/vertical/mapper/MenuMapper.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.rymcu.vertical.mapper;
|
||||
|
||||
import com.rymcu.vertical.core.mapper.Mapper;
|
||||
import com.rymcu.vertical.dto.MenuDTO;
|
||||
import com.rymcu.vertical.entity.Menu;
|
||||
import com.rymcu.vertical.entity.Role;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MenuMapper extends Mapper<Menu> {
|
||||
|
||||
List<Menu> selectMenuByRole(@Param("role") Role role);
|
||||
|
||||
List<MenuDTO> findByParentId(@Param("parentId") String parentId);
|
||||
|
||||
MenuDTO findMenuDTOById(@Param("id") String id);
|
||||
|
||||
void deleteRoleMenu(@Param("menuId") String id);
|
||||
|
||||
List<MenuDTO> findByParentIdAndUserId(@Param("parentId") String parentId, @Param("userId") String userId);
|
||||
|
||||
void deleteMenu(@Param("id") String id);
|
||||
}
|
34
src/main/java/com/rymcu/vertical/mapper/RoleMapper.java
Normal file
34
src/main/java/com/rymcu/vertical/mapper/RoleMapper.java
Normal file
@ -0,0 +1,34 @@
|
||||
package com.rymcu.vertical.mapper;
|
||||
|
||||
import com.rymcu.vertical.core.mapper.Mapper;
|
||||
import com.rymcu.vertical.dto.RoleDTO;
|
||||
import com.rymcu.vertical.dto.UserDTO;
|
||||
import com.rymcu.vertical.entity.Role;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface RoleMapper extends Mapper<Role> {
|
||||
List<RoleDTO> findAllDTO(@Param("role") RoleDTO roleDTO);
|
||||
|
||||
List<Role> selectRoleByUser(@Param("sysUser") User sysUser);
|
||||
|
||||
void insertRoleMenu(@Param("roleId") String id, @Param("menuId") String menuId);
|
||||
|
||||
void deleteRoleMenuByRoleId(@Param("roleId") String roleId);
|
||||
|
||||
void deleteUserRoleByRoleId(@Param("roleId") String roleId);
|
||||
|
||||
RoleDTO findRoleDTOById(@Param("roleId") String roleId);
|
||||
|
||||
String selectRoleIdsByUser(@Param("user") User user);
|
||||
|
||||
List<UserDTO> findUserOfRoleListData(@Param("user") UserDTO userDTO);
|
||||
|
||||
void deleteUser(@Param("userId") String userId, @Param("roleId") String roleId);
|
||||
|
||||
List<UserDTO> findUnAddUserOfRole(@Param("userName") String userName, @Param("roleId") String roleId);
|
||||
|
||||
void insertUserRole(@Param("userId") String userId, @Param("roleId") String roleId);
|
||||
}
|
35
src/main/java/com/rymcu/vertical/mapper/UserMapper.java
Normal file
35
src/main/java/com/rymcu/vertical/mapper/UserMapper.java
Normal file
@ -0,0 +1,35 @@
|
||||
package com.rymcu.vertical.mapper;
|
||||
|
||||
import com.rymcu.vertical.core.mapper.Mapper;
|
||||
import com.rymcu.vertical.dto.RoleDTO;
|
||||
import com.rymcu.vertical.dto.UserDTO;
|
||||
import com.rymcu.vertical.dto.UserExportDTO;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface UserMapper extends Mapper<User> {
|
||||
List<UserDTO> findAllDTO(@Param("user") UserDTO userDTO);
|
||||
|
||||
UserDTO findUserDTOById(@Param("idUser") Integer idUser);
|
||||
|
||||
void insertUserRole(@Param("idUser") Integer idUser, @Param("idRole") Integer idRole);
|
||||
|
||||
void deleteUserRoleByUserId(@Param("idUser") Integer idUser);
|
||||
|
||||
void deleteUserById(@Param("idUser") Integer idUser);
|
||||
|
||||
void resetPassword(@Param("idUser") Integer idUser, @Param("password") String password);
|
||||
|
||||
void updateLastLoginTime(@Param("idUser") Integer idUser, @Param("date") Date date);
|
||||
|
||||
User findByLoginName(@Param("loginName") String loginName);
|
||||
|
||||
List<UserDTO> queryUserByInputCode(@Param("eName") String eName);
|
||||
|
||||
List<UserExportDTO> findUserExportData(@Param("user") UserDTO userDTO);
|
||||
|
||||
List<RoleDTO> findRoleOfUser(@Param("idUser") Integer idUser);
|
||||
}
|
33
src/main/java/com/rymcu/vertical/service/MenuService.java
Normal file
33
src/main/java/com/rymcu/vertical/service/MenuService.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.rymcu.vertical.service;
|
||||
|
||||
import com.rymcu.vertical.core.service.Service;
|
||||
import com.rymcu.vertical.dto.MenuDTO;
|
||||
import com.rymcu.vertical.entity.Menu;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by CodeGenerator on 2018/05/29.
|
||||
*/
|
||||
public interface MenuService extends Service<Menu> {
|
||||
|
||||
List<Menu> selectMenuByUser(User sysUser);
|
||||
|
||||
Menu getParent(Menu e);
|
||||
|
||||
List<MenuDTO> findByParentId(String roleId);
|
||||
|
||||
MenuDTO findMenuDTOById(String id);
|
||||
|
||||
void saveMenu(MenuDTO menuDTO);
|
||||
|
||||
void deleteMenuById(String id);
|
||||
|
||||
void updateMenu(MenuDTO menuDTO);
|
||||
|
||||
List<MenuDTO> findByParentIdAndUserId(String parentId, String userId);
|
||||
|
||||
void updateUserStatus(String id, String flag);
|
||||
}
|
39
src/main/java/com/rymcu/vertical/service/RoleService.java
Normal file
39
src/main/java/com/rymcu/vertical/service/RoleService.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.rymcu.vertical.service;
|
||||
|
||||
import com.rymcu.vertical.core.service.Service;
|
||||
import com.rymcu.vertical.dto.RoleDTO;
|
||||
import com.rymcu.vertical.dto.UserDTO;
|
||||
import com.rymcu.vertical.entity.Role;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by CodeGenerator on 2018/05/29.
|
||||
*/
|
||||
public interface RoleService extends Service<Role> {
|
||||
|
||||
List<Role> selectRoleByUser(User sysUser);
|
||||
|
||||
List<RoleDTO> findAllDTO(HttpServletRequest request);
|
||||
|
||||
void saveRole(RoleDTO roleDTO);
|
||||
|
||||
void deleteAssociatedItemsForRole(String id);
|
||||
|
||||
RoleDTO findRoleDTOById(String id);
|
||||
|
||||
void updateRole(RoleDTO roleDTO);
|
||||
|
||||
List<UserDTO> findUserOfRoleListData(HttpServletRequest request);
|
||||
|
||||
void deleteUser(String userId, String roleId);
|
||||
|
||||
List<UserDTO> findUnAddUserOfRole(HttpServletRequest request);
|
||||
|
||||
String addUserOfRole(String roleId, String ids);
|
||||
|
||||
void updateMenu(RoleDTO roleDTO);
|
||||
}
|
45
src/main/java/com/rymcu/vertical/service/UserService.java
Normal file
45
src/main/java/com/rymcu/vertical/service/UserService.java
Normal file
@ -0,0 +1,45 @@
|
||||
package com.rymcu.vertical.service;
|
||||
|
||||
import com.rymcu.vertical.core.exception.ServiceException;
|
||||
import com.rymcu.vertical.core.service.Service;
|
||||
import com.rymcu.vertical.dto.RoleDTO;
|
||||
import com.rymcu.vertical.dto.UserDTO;
|
||||
import com.rymcu.vertical.dto.UserExportDTO;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import org.apache.ibatis.exceptions.TooManyResultsException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by CodeGenerator on 2018/05/29.
|
||||
*/
|
||||
public interface UserService extends Service<User> {
|
||||
|
||||
List<UserDTO> findAllDTO(HttpServletRequest request);
|
||||
|
||||
UserDTO findUserDTOById(Integer id);
|
||||
|
||||
void saveUser(UserDTO userDTO);
|
||||
|
||||
void updateUser(UserDTO userDTO);
|
||||
|
||||
void deleteUserById(Integer id);
|
||||
|
||||
Boolean checkLoginName(String loginName);
|
||||
|
||||
void updateUserStatus(Integer id, Integer flag);
|
||||
|
||||
void resetPassword(Integer userId, String password);
|
||||
|
||||
User findByLoginName(String loginName) throws TooManyResultsException, ServiceException;
|
||||
|
||||
List<UserDTO> queryUserByInputCode(String eName);
|
||||
|
||||
void updateLastLoginTime(Integer id);
|
||||
|
||||
List<UserExportDTO> exportExcel(HttpServletRequest request);
|
||||
|
||||
List<RoleDTO> findRoleOfUser(HttpServletRequest request);
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package com.rymcu.vertical.service.impl;
|
||||
|
||||
import com.rymcu.vertical.core.service.AbstractService;
|
||||
import com.rymcu.vertical.dto.MenuDTO;
|
||||
import com.rymcu.vertical.entity.Menu;
|
||||
import com.rymcu.vertical.entity.Role;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import com.rymcu.vertical.mapper.MenuMapper;
|
||||
import com.rymcu.vertical.service.MenuService;
|
||||
import com.rymcu.vertical.service.RoleService;
|
||||
import com.rymcu.vertical.util.BeanCopierUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
* Created by CodeGenerator on 2018/05/29.
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class MenuServiceImpl extends AbstractService<Menu> implements MenuService {
|
||||
@Resource
|
||||
private MenuMapper menuMapper;
|
||||
|
||||
@Resource
|
||||
private RoleService roleService;
|
||||
|
||||
@Override
|
||||
public List<Menu> selectMenuByUser(User sysUser) {
|
||||
List<Menu> list = new ArrayList<Menu>();
|
||||
List<Role> roles = roleService.selectRoleByUser(sysUser);
|
||||
roles.forEach(role -> list.addAll(menuMapper.selectMenuByRole(role)));
|
||||
HashSet hashSet = new HashSet(list);
|
||||
list.clear();
|
||||
list.addAll(hashSet);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Menu getParent(Menu e) {
|
||||
String parentId = "0";
|
||||
if(e != null){
|
||||
if(StringUtils.isNotBlank(e.getParentId())){
|
||||
parentId = e.getParentId();
|
||||
}
|
||||
}
|
||||
return menuMapper.selectByPrimaryKey(parentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuDTO> findByParentId(String parentId) {
|
||||
List<MenuDTO> list = menuMapper.findByParentId(parentId);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuDTO findMenuDTOById(String id) {
|
||||
return menuMapper.findMenuDTOById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveMenu(MenuDTO menuDTO) {
|
||||
Menu menu = new Menu();
|
||||
BeanCopierUtil.copy(menuDTO,menu);
|
||||
//Utils.createBase(menu);
|
||||
menuMapper.insert(menu);
|
||||
//Utils.removeAllMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMenuById(String id) {
|
||||
menuMapper.deleteRoleMenu(id);
|
||||
menuMapper.deleteMenu(id);
|
||||
//Utils.removeAllMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMenu(MenuDTO menuDTO) {
|
||||
Menu menu = menuMapper.selectByPrimaryKey(menuDTO.getId());
|
||||
BeanCopierUtil.copy(menuDTO,menu);
|
||||
//Utils.updateBase(menu);
|
||||
menuMapper.updateByPrimaryKey(menu);
|
||||
//Utils.removeAllMenu();
|
||||
//UserUtils.removeMenuList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuDTO> findByParentIdAndUserId(String parentId, String userId) {
|
||||
return menuMapper.findByParentIdAndUserId(parentId, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserStatus(String id, String flag) {
|
||||
Menu menu = menuMapper.selectByPrimaryKey(id);
|
||||
menu.setStatus(flag);
|
||||
//Utils.updateBase(menu);
|
||||
menuMapper.updateByPrimaryKey(menu);
|
||||
//Utils.removeAllMenu();
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package com.rymcu.vertical.service.impl;
|
||||
|
||||
import com.rymcu.vertical.core.service.AbstractService;
|
||||
import com.rymcu.vertical.dto.RoleDTO;
|
||||
import com.rymcu.vertical.dto.UserDTO;
|
||||
import com.rymcu.vertical.entity.Role;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import com.rymcu.vertical.mapper.RoleMapper;
|
||||
import com.rymcu.vertical.service.RoleService;
|
||||
import com.rymcu.vertical.util.BeanCopierUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
* Created by CodeGenerator on 2018/05/29.
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class RoleServiceImpl extends AbstractService<Role> implements RoleService {
|
||||
@Resource
|
||||
private RoleMapper roleMapper;
|
||||
|
||||
@Override
|
||||
public List<Role> selectRoleByUser(User sysUser) {
|
||||
List<Role> roles = roleMapper.selectRoleByUser(sysUser);
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleDTO> findAllDTO(HttpServletRequest request) {
|
||||
RoleDTO roleDTO = new RoleDTO();
|
||||
roleDTO.setName(request.getParameter("name"));
|
||||
roleDTO.setEnname(request.getParameter("enName"));
|
||||
return roleMapper.findAllDTO(roleDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRole(RoleDTO roleDTO) {
|
||||
Role role = new Role();
|
||||
BeanCopierUtil.copy(roleDTO,role);
|
||||
//Utils.createBase(role);
|
||||
roleMapper.insert(role);
|
||||
|
||||
String menuIds = roleDTO.getMenuIds();
|
||||
String[] m = menuIds.split(",");
|
||||
for (int i = 0,len = m.length; i < len; i++) {
|
||||
roleMapper.insertRoleMenu(role.getIdRole(),m[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAssociatedItemsForRole(String roleId) {
|
||||
|
||||
roleMapper.deleteUserRoleByRoleId(roleId);
|
||||
|
||||
roleMapper.deleteByPrimaryKey(roleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleDTO findRoleDTOById(String id) {
|
||||
return roleMapper.findRoleDTOById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRole(RoleDTO roleDTO) {
|
||||
String menuIds = "";
|
||||
Role role = roleMapper.selectByPrimaryKey(roleDTO.getId());
|
||||
|
||||
BeanCopierUtil.copy(roleDTO,role);
|
||||
//Utils.updateBase(role);
|
||||
roleMapper.updateByPrimaryKey(role);
|
||||
|
||||
if("0".equals(roleDTO.getMenuIds())){
|
||||
menuIds = roleMapper.findRoleDTOById(roleDTO.getId()).getMenuIds();
|
||||
}else {
|
||||
menuIds = roleDTO.getMenuIds();
|
||||
}
|
||||
|
||||
roleMapper.deleteRoleMenuByRoleId(role.getIdRole());
|
||||
|
||||
String[] m = menuIds.split(",");
|
||||
for (int i = 0,len = m.length; i < len; i++) {
|
||||
roleMapper.insertRoleMenu(role.getIdRole(),m[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserDTO> findUserOfRoleListData(HttpServletRequest request) {
|
||||
UserDTO userDTO = new UserDTO();
|
||||
userDTO.setLoginName(request.getParameter("loginName"));
|
||||
userDTO.setInputCode(request.getParameter("inputCode"));
|
||||
userDTO.setName(request.getParameter("name"));
|
||||
userDTO.setStatus(request.getParameter("status"));
|
||||
userDTO.setOfficeId(request.getParameter("officeId"));
|
||||
userDTO.setRemarks(request.getParameter("roleId"));// 为不创建多余字段,此处使用 Remark 字段存放 roleId 数据
|
||||
return roleMapper.findUserOfRoleListData(userDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUser(String userId, String roleId) {
|
||||
roleMapper.deleteUser(userId,roleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserDTO> findUnAddUserOfRole(HttpServletRequest request) {
|
||||
String roleId = request.getParameter("roleId");
|
||||
String userName = request.getParameter("userName");
|
||||
return roleMapper.findUnAddUserOfRole(userName,roleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addUserOfRole(String roleId, String ids) {
|
||||
String message = "";
|
||||
String[] userIds = ids.split(",");
|
||||
for (String userId:userIds) {
|
||||
if(!(",".equals(userId) || StringUtils.isBlank(userId))){
|
||||
roleMapper.insertUserRole(userId,roleId);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMenu(RoleDTO roleDTO) {
|
||||
String menuIds;
|
||||
if("0".equals(roleDTO.getMenuIds())){
|
||||
menuIds = roleMapper.findRoleDTOById(roleDTO.getId()).getMenuIds();
|
||||
}else {
|
||||
menuIds = roleDTO.getMenuIds();
|
||||
}
|
||||
|
||||
roleMapper.deleteRoleMenuByRoleId(roleDTO.getId());
|
||||
|
||||
String[] m = menuIds.split(",");
|
||||
for (int i = 0,len = m.length; i < len; i++) {
|
||||
roleMapper.insertRoleMenu(roleDTO.getId(),m[i]);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package com.rymcu.vertical.service.impl;
|
||||
|
||||
import com.rymcu.vertical.core.exception.ServiceException;
|
||||
import com.rymcu.vertical.core.service.AbstractService;
|
||||
import com.rymcu.vertical.dto.RoleDTO;
|
||||
import com.rymcu.vertical.dto.UserDTO;
|
||||
import com.rymcu.vertical.dto.UserExportDTO;
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import com.rymcu.vertical.mapper.UserMapper;
|
||||
import com.rymcu.vertical.service.UserService;
|
||||
import com.rymcu.vertical.util.BeanCopierUtil;
|
||||
import com.rymcu.vertical.util.Utils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.ibatis.exceptions.TooManyResultsException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tk.mybatis.mapper.entity.Condition;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by CodeGenerator on 2018/05/29.
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl extends AbstractService<User> implements UserService {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public List<UserDTO> findAllDTO(HttpServletRequest request) {
|
||||
UserDTO userDTO = new UserDTO();
|
||||
userDTO.setLoginName(request.getParameter("loginName"));
|
||||
userDTO.setInputCode(request.getParameter("inputCode"));
|
||||
userDTO.setName(request.getParameter("name"));
|
||||
userDTO.setStatus(request.getParameter("status"));
|
||||
userDTO.setOfficeId(request.getParameter("officeId"));// 为不创建多余字段,此处使用 Remark 字段存放 nodeId 数据
|
||||
return userMapper.findAllDTO(userDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDTO findUserDTOById(Integer id) {
|
||||
return userMapper.findUserDTOById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void saveUser(UserDTO userDTO) {
|
||||
User user = new User();
|
||||
BeanCopierUtil.copy(userDTO, user);
|
||||
//user.setPassword(Utils.entryptPassword("123456"));
|
||||
//Utils.createBase(user);
|
||||
//所有字符转为小写
|
||||
user.setAccount(user.getAccount().toLowerCase());
|
||||
userMapper.insertSelective(user);
|
||||
|
||||
String roleIds = userDTO.getRoleIds();
|
||||
if(StringUtils.isNotBlank(roleIds)){
|
||||
String[] r = roleIds.split(",");
|
||||
for(int i=0,len=r.length;i<len;i++){
|
||||
userMapper.insertUserRole(user.getIdUser(), Integer.parseInt(r[i]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateUser(UserDTO userDTO) {
|
||||
User user = userMapper.selectByPrimaryKey(userDTO.getId());
|
||||
String password = user.getPassword();
|
||||
userDTO.setLastLoginTime(user.getLastLoginTime());
|
||||
BeanCopierUtil.copy(userDTO,user);
|
||||
// 如果密码为空,则不更换密码
|
||||
if (StringUtils.isNotBlank(user.getPassword())) {
|
||||
user.setPassword(Utils.entryptPassword(user.getPassword()));
|
||||
}else {
|
||||
user.setPassword(password);
|
||||
}
|
||||
if(user.getCreatedTime() == null){
|
||||
user.setCreatedTime(new Date());
|
||||
}
|
||||
userMapper.updateByPrimaryKeySelective(user);
|
||||
|
||||
String roleIds = userDTO.getRoleIds();
|
||||
|
||||
userMapper.deleteUserRoleByUserId(user.getIdUser());
|
||||
if(!"0".equals(roleIds) && StringUtils.isNotBlank(roleIds)){
|
||||
String[] r = roleIds.split(",");
|
||||
for(int i=0,len=r.length;i<len;i++){
|
||||
userMapper.insertUserRole(user.getIdUser(), Integer.parseInt(r[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteUserById(Integer idUser) {
|
||||
if(idUser.equals(Utils.getCurrentUser().getIdUser())){
|
||||
|
||||
}else{
|
||||
userMapper.deleteUserById(idUser);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean checkLoginName(String loginName){
|
||||
Condition userCondition = new Condition(User.class);
|
||||
userCondition.createCriteria().andCondition("LOGIN_NAME =",loginName.toLowerCase());
|
||||
List<User> user = userMapper.selectByCondition(userCondition);
|
||||
Boolean b = false;
|
||||
if (user.size() == 0){
|
||||
b = true;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateUserStatus(Integer id, Integer flag) {
|
||||
User user = userMapper.selectByPrimaryKey(id);
|
||||
user.setStatus(flag);
|
||||
userMapper.updateByPrimaryKey(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void resetPassword(Integer userId, String password) {
|
||||
userMapper.resetPassword(userId,password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User findByLoginName(String loginName) throws TooManyResultsException, ServiceException{
|
||||
return userMapper.findByLoginName(loginName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserDTO> queryUserByInputCode(String eName) {
|
||||
return userMapper.queryUserByInputCode(eName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateLastLoginTime(Integer id) {
|
||||
userMapper.updateLastLoginTime(id,new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserExportDTO> exportExcel(HttpServletRequest request) {
|
||||
UserDTO userDTO = new UserDTO();
|
||||
userDTO.setLoginName(request.getParameter("loginName"));
|
||||
userDTO.setInputCode(request.getParameter("inputCode"));
|
||||
userDTO.setName(request.getParameter("name"));
|
||||
userDTO.setStatus(request.getParameter("status"));
|
||||
userDTO.setOfficeId(request.getParameter("officeId"));
|
||||
return userMapper.findUserExportData(userDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleDTO> findRoleOfUser(HttpServletRequest request) {
|
||||
String userId = request.getParameter("userId");
|
||||
return userMapper.findRoleOfUser(Integer.parseInt(userId));
|
||||
}
|
||||
}
|
79
src/main/java/com/rymcu/vertical/util/BeanCopierUtil.java
Normal file
79
src/main/java/com/rymcu/vertical/util/BeanCopierUtil.java
Normal file
@ -0,0 +1,79 @@
|
||||
package com.rymcu.vertical.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cglib.beans.BeanCopier;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author jiangjingming
|
||||
*/
|
||||
@Slf4j
|
||||
public class BeanCopierUtil {
|
||||
/**
|
||||
* beanCopier缓存
|
||||
* (A拷贝到B,确定一个beanCopier)
|
||||
*/
|
||||
private static Map<Class<?>,Map<Class<?>, BeanCopier>> beanCopierMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 拷贝方法
|
||||
* @param sourceBean
|
||||
* @param targetBean
|
||||
* @param <S>
|
||||
* @param <T>
|
||||
*/
|
||||
public static <S,T> void copy(S sourceBean,T targetBean){
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<S> sourceClass = (Class<S>) sourceBean.getClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> targetClass = (Class<T>) targetBean.getClass();
|
||||
|
||||
BeanCopier beanCopier = getBeanCopier(sourceClass,targetClass);
|
||||
beanCopier.copy(sourceBean,targetBean,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换方法
|
||||
* @param sourceBean 原对象
|
||||
* @param targetClass 目标类
|
||||
* @param <S>
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <S,T> T convert(S sourceBean,Class<T> targetClass){
|
||||
try {
|
||||
assert sourceBean!=null;
|
||||
T targetBean = targetClass.newInstance();
|
||||
copy(sourceBean,targetBean);
|
||||
return targetBean;
|
||||
} catch (Exception e) {
|
||||
log.error("Transform bean error",e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static <S,T> BeanCopier getBeanCopier(Class<S> sourceClass, Class<T> targetClass ){
|
||||
Map<Class<?>, BeanCopier> map = beanCopierMap.get(sourceClass);
|
||||
if(CollectionUtils.isEmpty(map)){
|
||||
BeanCopier newBeanCopier = BeanCopier.create(sourceClass, targetClass, false);
|
||||
Map<Class<?>, BeanCopier> newMap = new ConcurrentHashMap<>();
|
||||
newMap.put(targetClass,newBeanCopier);
|
||||
beanCopierMap.put(sourceClass,newMap);
|
||||
return newBeanCopier;
|
||||
}
|
||||
|
||||
BeanCopier beanCopier = map.get(targetClass);
|
||||
if(beanCopier == null){
|
||||
BeanCopier newBeanCopier = BeanCopier.create(sourceClass, targetClass, false);
|
||||
map.put(targetClass,newBeanCopier);
|
||||
|
||||
return newBeanCopier;
|
||||
}
|
||||
|
||||
return beanCopier;
|
||||
}
|
||||
}
|
117
src/main/java/com/rymcu/vertical/util/Digests.java
Normal file
117
src/main/java/com/rymcu/vertical/util/Digests.java
Normal file
@ -0,0 +1,117 @@
|
||||
package com.rymcu.vertical.util;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* 支持SHA-1/MD5消息摘要的工具类.
|
||||
*
|
||||
* 返回ByteSource,可进一步被编码为Hex, Base64或UrlSafeBase64
|
||||
*
|
||||
*/
|
||||
public class Digests {
|
||||
|
||||
private static final String SHA1 = "SHA-1";
|
||||
private static final String MD5 = "MD5";
|
||||
|
||||
private static SecureRandom random = new SecureRandom();
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
*/
|
||||
public static byte[] md5(byte[] input) {
|
||||
return digest(input, MD5, null, 1);
|
||||
}
|
||||
public static byte[] md5(byte[] input, int iterations) {
|
||||
return digest(input, MD5, null, iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对输入字符串进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(byte[] input) {
|
||||
return digest(input, SHA1, null, 1);
|
||||
}
|
||||
|
||||
public static byte[] sha1(byte[] input, byte[] salt) {
|
||||
return digest(input, SHA1, salt, 1);
|
||||
}
|
||||
|
||||
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
|
||||
return digest(input, SHA1, salt, iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对字符串进行散列, 支持md5与sha1算法.
|
||||
*/
|
||||
private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||
|
||||
if (salt != null) {
|
||||
digest.update(salt);
|
||||
}
|
||||
|
||||
byte[] result = digest.digest(input);
|
||||
|
||||
for (int i = 1; i < iterations; i++) {
|
||||
digest.reset();
|
||||
result = digest.digest(result);
|
||||
}
|
||||
return result;
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机的Byte[]作为salt.
|
||||
*
|
||||
* @param numBytes byte数组的大小
|
||||
*/
|
||||
public static byte[] generateSalt(int numBytes) {
|
||||
Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
|
||||
|
||||
byte[] bytes = new byte[numBytes];
|
||||
random.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行md5散列.
|
||||
*/
|
||||
public static byte[] md5(InputStream input) throws IOException {
|
||||
return digest(input, MD5);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件进行sha1散列.
|
||||
*/
|
||||
public static byte[] sha1(InputStream input) throws IOException {
|
||||
return digest(input, SHA1);
|
||||
}
|
||||
|
||||
private static byte[] digest(InputStream input, String algorithm) throws IOException {
|
||||
try {
|
||||
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
|
||||
int bufferLength = 8 * 1024;
|
||||
byte[] buffer = new byte[bufferLength];
|
||||
int read = input.read(buffer, 0, bufferLength);
|
||||
|
||||
while (read > -1) {
|
||||
messageDigest.update(buffer, 0, read);
|
||||
read = input.read(buffer, 0, bufferLength);
|
||||
}
|
||||
|
||||
return messageDigest.digest();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
149
src/main/java/com/rymcu/vertical/util/Encodes.java
Normal file
149
src/main/java/com/rymcu/vertical/util/Encodes.java
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Copyright © 2012-2016 <a href="http://www.zkjkgc.com">zkjkgc</a> All rights reserved.
|
||||
*/
|
||||
package com.rymcu.vertical.util;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
/**
|
||||
* 封装各种格式的编码解码工具类.
|
||||
* 1.Commons-Codec的 hex/base64 编码
|
||||
* 2.自制的base62 编码
|
||||
* 3.Commons-Lang的xml/html escape
|
||||
* 4.JDK提供的URLEncoder
|
||||
*/
|
||||
public class Encodes {
|
||||
|
||||
private static final String DEFAULT_URL_ENCODING = "UTF-8";
|
||||
private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
|
||||
|
||||
/**
|
||||
* Hex编码.
|
||||
*/
|
||||
public static String encodeHex(byte[] input) {
|
||||
return new String(Hex.encodeHex(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex解码.
|
||||
*/
|
||||
public static byte[] decodeHex(String input) {
|
||||
try {
|
||||
return Hex.decodeHex(input.toCharArray());
|
||||
} catch (DecoderException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64编码.
|
||||
*/
|
||||
public static String encodeBase64(byte[] input) {
|
||||
return new String(Base64.encodeBase64(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64编码.
|
||||
*/
|
||||
public static String encodeBase64(String input) {
|
||||
try {
|
||||
return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
|
||||
// */
|
||||
// public static String encodeUrlSafeBase64(byte[] input) {
|
||||
// return Base64.encodeBase64URLSafe(input);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Base64解码.
|
||||
*/
|
||||
public static byte[] decodeBase64(String input) {
|
||||
return Base64.decodeBase64(input.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64解码.
|
||||
*/
|
||||
public static String decodeBase64String(String input) {
|
||||
try {
|
||||
return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base62编码。
|
||||
*/
|
||||
public static String encodeBase62(byte[] input) {
|
||||
char[] chars = new char[input.length];
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Html 转码.
|
||||
*/
|
||||
public static String escapeHtml(String html) {
|
||||
return StringEscapeUtils.escapeHtml4(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Html 解码.
|
||||
*/
|
||||
public static String unescapeHtml(String htmlEscaped) {
|
||||
return StringEscapeUtils.unescapeHtml4(htmlEscaped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml 转码.
|
||||
*/
|
||||
public static String escapeXml(String xml) {
|
||||
return StringEscapeUtils.escapeXml10(xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml 解码.
|
||||
*/
|
||||
public static String unescapeXml(String xmlEscaped) {
|
||||
return StringEscapeUtils.unescapeXml(xmlEscaped);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL 编码, Encode默认为UTF-8.
|
||||
*/
|
||||
public static String urlEncode(String part) {
|
||||
try {
|
||||
return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL 解码, Encode默认为UTF-8.
|
||||
*/
|
||||
public static String urlDecode(String part) {
|
||||
|
||||
try {
|
||||
return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
}
|
29
src/main/java/com/rymcu/vertical/util/ErrorCode.java
Normal file
29
src/main/java/com/rymcu/vertical/util/ErrorCode.java
Normal file
@ -0,0 +1,29 @@
|
||||
package com.rymcu.vertical.util;
|
||||
|
||||
/**
|
||||
* Created by kaenry on 2016/9/20.
|
||||
* ErrorCode
|
||||
*/
|
||||
public enum ErrorCode {
|
||||
|
||||
ILLEGAL_PARAMS("ILLEGAL_PARAMS", "request params invalid"),
|
||||
UNAUTHORIZED("401", "请求要求用户的身份认证"),
|
||||
SERVER_ERROR("SERVER_ERROR", "server is busy");
|
||||
|
||||
ErrorCode(String code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
private String code;
|
||||
|
||||
private String message;
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
69
src/main/java/com/rymcu/vertical/util/Exceptions.java
Normal file
69
src/main/java/com/rymcu/vertical/util/Exceptions.java
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright © 2012-2016 <a href="http://www.zkjkgc.com">zkjkgc</a> All rights reserved.
|
||||
*/
|
||||
package com.rymcu.vertical.util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* 关于异常的工具类.
|
||||
*/
|
||||
public class Exceptions {
|
||||
|
||||
/**
|
||||
* 将CheckedException转换为UncheckedException.
|
||||
*/
|
||||
public static RuntimeException unchecked(Exception e) {
|
||||
if (e instanceof RuntimeException) {
|
||||
return (RuntimeException) e;
|
||||
} else {
|
||||
return new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将ErrorStack转化为String.
|
||||
*/
|
||||
public static String getStackTraceAsString(Throwable e) {
|
||||
if (e == null){
|
||||
return "";
|
||||
}
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(stringWriter));
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断异常是否由某些底层的异常引起.
|
||||
*/
|
||||
public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
|
||||
Throwable cause = ex.getCause();
|
||||
while (cause != null) {
|
||||
for (Class<? extends Exception> causeClass : causeExceptionClasses) {
|
||||
if (causeClass.isInstance(cause)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
cause = cause.getCause();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在request中获取异常类
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static Throwable getThrowable(HttpServletRequest request){
|
||||
Throwable ex = null;
|
||||
if (request.getAttribute("exception") != null) {
|
||||
ex = (Throwable) request.getAttribute("exception");
|
||||
} else if (request.getAttribute("javax.servlet.error.exception") != null) {
|
||||
ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
}
|
55
src/main/java/com/rymcu/vertical/util/Utils.java
Normal file
55
src/main/java/com/rymcu/vertical/util/Utils.java
Normal file
@ -0,0 +1,55 @@
|
||||
package com.rymcu.vertical.util;
|
||||
|
||||
import com.rymcu.vertical.entity.User;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.session.InvalidSessionException;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
public class Utils {
|
||||
public static final String HASH_ALGORITHM = "SHA-1";
|
||||
public static final int HASH_INTERATIONS = 1024;
|
||||
public static final int SALT_SIZE = 8;
|
||||
/**
|
||||
* 生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash
|
||||
*/
|
||||
public static String entryptPassword(String plainPassword) {
|
||||
String plain = Encodes.unescapeHtml(plainPassword);
|
||||
byte[] salt = Digests.generateSalt(SALT_SIZE);
|
||||
byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);
|
||||
return Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
*一般检查工具密码比对 add by xlf 2018-11-8
|
||||
* @param pwd
|
||||
* @param enpwd 加密的密码
|
||||
* @return
|
||||
*/
|
||||
public static boolean comparePwd(String pwd,String enpwd){
|
||||
byte[] salt = Encodes.decodeHex(enpwd.substring(0,16));
|
||||
byte[] hashPassword = Digests.sha1(pwd.getBytes(), salt, HASH_INTERATIONS);
|
||||
return enpwd.equals(Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword));
|
||||
}
|
||||
|
||||
public static User getCurrentUser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Session getSession() {
|
||||
try{
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
Session session = subject.getSession(false);
|
||||
if (session == null){
|
||||
session = subject.getSession();
|
||||
}
|
||||
if (session != null){
|
||||
return session;
|
||||
}
|
||||
// subject.logout();
|
||||
}catch (InvalidSessionException e){
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.rymcu.vertical.web.api.exception;
|
||||
|
||||
public enum ErrorCode {
|
||||
|
||||
UNAUTHORIZED(401, "请求要求用户的身份认证"),//未认证(签名错误)
|
||||
INVALID_TOKEN(402, "TOKEN验证失败,无效的TOKEN!"),
|
||||
TOKEN_(402, "TOKEN验证失败,无效的TOKEN!"),
|
||||
NOT_FOUND(404, "此接口不存在"),//接口不存在
|
||||
INTERNAL_SERVER_ERROR(500, "服务内部异常");
|
||||
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
ErrorCode(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.rymcu.vertical.web.api.exception;
|
||||
|
||||
/**
|
||||
* 服务(业务)异常如“ 账号或密码错误 ”,该异常只做INFO级别的日志记录 @see WebMvcConfigurer
|
||||
*/
|
||||
public class MallApiException extends Exception {
|
||||
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
public MallApiException(ErrorCode errorCode) {
|
||||
super(errorCode.getMessage());
|
||||
this.code = errorCode.getCode();
|
||||
this.message = errorCode.getMessage();
|
||||
}
|
||||
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getExtraMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package com.rymcu.vertical.web.api.exception;
|
||||
|
||||
import com.rymcu.vertical.config.HpeisExceptionHandler;
|
||||
import com.rymcu.vertical.core.result.GlobalResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@ControllerAdvice(basePackages = {"com.rymcu.vertical.web.api", "com.rymcu.vertical.jwt"} )
|
||||
public class MallApiExceptionHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HpeisExceptionHandler.class);
|
||||
|
||||
@ExceptionHandler(MallApiException.class)
|
||||
@ResponseBody
|
||||
public GlobalResult handlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
GlobalResult result = new GlobalResult();
|
||||
if (ex instanceof MallApiException) {
|
||||
result.setCode(((MallApiException) ex).getCode());
|
||||
result.setMessage(ex.getMessage());
|
||||
} /*else if (ex instanceof Exception) {
|
||||
result.setCode(ErrorCode.INTERNAL_SERVER_ERROR.getCode());
|
||||
result.setMessage("用户无权限");
|
||||
}*/
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
}
|
87
src/main/java/mapper/MenuMapper.xml
Normal file
87
src/main/java/mapper/MenuMapper.xml
Normal file
@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.rymcu.vertical.mapper.MenuMapper">
|
||||
<resultMap id="BaseResultMap" type="com.rymcu.vertical.entity.Menu">
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="ID" jdbcType="VARCHAR" property="idMenu"/>
|
||||
<result column="PARENT_ID" jdbcType="VARCHAR" property="parentId"/>
|
||||
<result column="NAME" jdbcType="OTHER" property="name"/>
|
||||
<result column="SORT" jdbcType="DECIMAL" property="sort"/>
|
||||
<result column="HREF" jdbcType="VARCHAR" property="href"/>
|
||||
<result column="MENU_TYPE" jdbcType="CHAR" property="menuType"/>
|
||||
<result column="PERMISSION" jdbcType="VARCHAR" property="permission"/>
|
||||
<result column="CREATED_TIME" jdbcType="TIMESTAMP" property="createdTime"/>
|
||||
<result column="STATUS" jdbcType="CHAR" property="status"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="select">
|
||||
ID,
|
||||
PARENT_ID parentId,
|
||||
(select NAME
|
||||
from SYS_MENU
|
||||
where ID = #{parentId}) parentName,
|
||||
NAME,
|
||||
SORT,
|
||||
HREF,
|
||||
MENU_TYPE menuType,
|
||||
PERMISSION,
|
||||
REMARKS,
|
||||
STATUS
|
||||
</sql>
|
||||
|
||||
<sql id="selectOne">
|
||||
ID,
|
||||
PARENT_ID parentId,
|
||||
(select NAME
|
||||
from SYS_MENU
|
||||
where ID = m.PARENT_ID) parentName,
|
||||
NAME,
|
||||
SORT,
|
||||
HREF,
|
||||
MENU_TYPE menuType,
|
||||
PERMISSION,
|
||||
REMARKS,
|
||||
STATUS
|
||||
</sql>
|
||||
|
||||
<delete id="deleteRoleMenu">
|
||||
delete SYS_ROLE_MENU
|
||||
where MENU_ID = #{menuId}
|
||||
</delete>
|
||||
<update id="deleteMenu">
|
||||
update SYS_MENU set STATUS = '2' where ID = #{id}
|
||||
</update>
|
||||
|
||||
<select id="selectMenuByRole" resultType="com.rymcu.vertical.entity.Menu">
|
||||
select *
|
||||
from SYS_MENU
|
||||
where STATUS = '0' and ID in (select MENU_ID
|
||||
from SYS_ROLE_MENU
|
||||
where ROLE_ID = #{role.id}) order by SORT
|
||||
</select>
|
||||
|
||||
<select id="findByParentId" resultType="com.rymcu.vertical.dto.MenuDTO">
|
||||
select
|
||||
<include refid="select"/>
|
||||
from SYS_MENU
|
||||
where PARENT_ID = #{parentId} and STATUS != '2' order by SORT
|
||||
</select>
|
||||
|
||||
<select id="findMenuDTOById" resultType="com.rymcu.vertical.dto.MenuDTO">
|
||||
select
|
||||
<include refid="selectOne"/>
|
||||
from SYS_MENU m
|
||||
where ID = #{id} order by SORT
|
||||
</select>
|
||||
|
||||
<select id="findByParentIdAndUserId" resultType="com.rymcu.vertical.dto.MenuDTO">
|
||||
select
|
||||
<include refid="selectOne"/>
|
||||
from SYS_MENU m where PARENT_ID = #{parentId} and MENU_TYPE = '0' and STATUS = '0'
|
||||
and ID in (select MENU_ID from SYS_ROLE_MENU where ROLE_ID in (SELECT ROLE_ID from SYS_USER_ROLE where USER_ID = #{userId}))
|
||||
order by SORT
|
||||
</select>
|
||||
|
||||
</mapper>
|
147
src/main/java/mapper/RoleMapper.xml
Normal file
147
src/main/java/mapper/RoleMapper.xml
Normal file
@ -0,0 +1,147 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.rymcu.vertical.mapper.RoleMapper">
|
||||
<resultMap id="BaseResultMap" type="com.rymcu.vertical.entity.Role">
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="ID" jdbcType="VARCHAR" property="idRole"/>
|
||||
<result column="NAME" jdbcType="OTHER" property="name"/>
|
||||
<result column="ENNAME" jdbcType="VARCHAR" property="inputCode"/>
|
||||
<result column="CREATED_DATE" jdbcType="TIMESTAMP" property="createdTime"/>
|
||||
<result column="STATUS" jdbcType="CHAR" property="status"/>
|
||||
</resultMap>
|
||||
<resultMap id="RoleDTOResultMap" type="com.rymcu.vertical.dto.RoleDTO">
|
||||
<id column="ID" property="id"></id>
|
||||
<result column="NAME" property="name"/>
|
||||
<result column="ENNAME" property="enname"/>
|
||||
<result column="ROLE_TYPE" property="roleType"/>
|
||||
<result column="REMARKS" property="remarks"/>
|
||||
<result column="MENU_IDS" property="menuIds"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="select">
|
||||
r.ID,
|
||||
r.NAME,
|
||||
r.ROLE_TYPE,
|
||||
r.ENNAME,
|
||||
r.REMARKS
|
||||
</sql>
|
||||
|
||||
<insert id="insertRoleMenu">
|
||||
insert into SYS_ROLE_MENU (ROLE_ID, MENU_ID) VALUES (#{roleId}, #{menuId})
|
||||
</insert>
|
||||
<insert id="insertUserRole">
|
||||
insert into SYS_USER_ROLE (USER_ID, ROLE_ID) VALUES (#{userId}, #{roleId})
|
||||
</insert>
|
||||
|
||||
<delete id="deleteRoleMenuByRoleId">
|
||||
delete SYS_ROLE_MENU where ROLE_ID = #{roleId}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteUserRoleByRoleId">
|
||||
delete SYS_USER_ROLE where ROLE_ID = #{roleId}
|
||||
</delete>
|
||||
<delete id="deleteUser">
|
||||
delete SYS_USER_ROLE where ROLE_ID = #{roleId} AND USER_ID = #{userId}
|
||||
</delete>
|
||||
|
||||
<select id="findAllDTO" resultMap="RoleDTOResultMap">
|
||||
select
|
||||
<include refid="select"/>,
|
||||
(select rtrim(XMLAGG(XMLELEMENT(E, MENU_ID || ',')).EXTRACT('//text()').getclobval(),',') from SYS_ROLE_MENU where ROLE_ID = r.ID) MENU_IDS
|
||||
from SYS_ROLE r
|
||||
where 1 = 1
|
||||
<if test="role.name != null and role.name != ''">
|
||||
and r.NAME like '%'||#{role.name}||'%'
|
||||
</if>
|
||||
<if test="role.enname != null and role.enname != ''">
|
||||
and r.ENNAME like '%'||#{role.enname}||'%'
|
||||
</if>
|
||||
ORDER BY r.CREATE_DATE DESC
|
||||
</select>
|
||||
|
||||
<select id="selectRoleByUser" resultMap="BaseResultMap">
|
||||
select *
|
||||
from SYS_ROLE
|
||||
where ID in (select ROLE_ID
|
||||
from SYS_USER_ROLE
|
||||
where USER_ID = #{sysUser.id})
|
||||
</select>
|
||||
<select id="findRoleDTOById" resultMap="RoleDTOResultMap">
|
||||
select
|
||||
<include refid="select"/>,
|
||||
(select rtrim(XMLAGG(XMLELEMENT(E, MENU_ID || ',')).EXTRACT('//text()').getclobval(),',') from SYS_ROLE_MENU where ROLE_ID = #{roleId}) MENU_IDS
|
||||
from SYS_ROLE r where r.id = #{roleId}
|
||||
</select>
|
||||
<select id="selectRoleIdsByUser" resultType="java.lang.String">
|
||||
SELECT wm_concat(ROLE_ID) from SYS_USER_ROLE where USER_ID = #{user.id}
|
||||
</select>
|
||||
<select id="findUserOfRoleListData" resultType="com.rymcu.vertical.dto.UserDTO">
|
||||
select
|
||||
u.ID,
|
||||
u.NO,
|
||||
u.LOGIN_NAME loginName,
|
||||
u.SEX,
|
||||
u.NAME,
|
||||
u.EMAIL,
|
||||
u.MOBILE,
|
||||
u.PHONE,
|
||||
u.OFFICE_ID officeId,
|
||||
u.LAST_LOGIN_TIME lastLoginTime,
|
||||
u.STATUS,
|
||||
u.REMARKS,
|
||||
u.INPUT_CODE inputCode,
|
||||
(
|
||||
select NAME from SYS_OFFICE o2 where o2.ID = u.OFFICE_ID
|
||||
<if test="user.office != null and user.office != ''">
|
||||
and o2.NAME = #{user.office}
|
||||
</if>
|
||||
) office,
|
||||
(select wm_concat(ROLE_ID) from SYS_USER_ROLE where USER_ID = u.ID) roleIds
|
||||
from SYS_USER u
|
||||
left join SYS_USER_ROLE sur
|
||||
on u.ID = sur.USER_ID
|
||||
where sur.ROLE_ID = #{user.remarks} and u.STATUS != 2
|
||||
<if test="user.officeId != null and user.officeId != ''">
|
||||
and ( u.OFFICE_ID in (select id from SYS_OFFICE where status = 0 start with id = #{user.officeId} connect by prior id = parent_id))
|
||||
</if>
|
||||
<if test="user.name != null and user.name != ''">
|
||||
and u.NAME like '%'||#{user.name}||'%'
|
||||
</if>
|
||||
<if test="user.loginName != null and user.loginName != ''">
|
||||
and u.LOGIN_NAME like '%'||#{user.loginName}||'%'
|
||||
</if>
|
||||
<if test="user.inputCode != null and user.inputCode != ''">
|
||||
and u.INPUT_CODE like '%'||#{user.inputCode}||'%'
|
||||
</if>
|
||||
<if test="user.status != null and user.status != ''">
|
||||
and u.STATUS like '%'||#{user.status}||'%'
|
||||
</if>
|
||||
ORDER BY CREATE_DATE
|
||||
</select>
|
||||
<select id="findUnAddUserOfRole" resultType="com.rymcu.vertical.dto.UserDTO">
|
||||
select
|
||||
u.ID,
|
||||
u.NO,
|
||||
u.LOGIN_NAME loginName,
|
||||
u.SEX,
|
||||
u.NAME,
|
||||
u.EMAIL,
|
||||
u.MOBILE,
|
||||
u.PHONE,
|
||||
u.OFFICE_ID officeId,
|
||||
u.LAST_LOGIN_TIME lastLoginTime,
|
||||
u.STATUS,
|
||||
u.REMARKS,
|
||||
u.INPUT_CODE inputCode,
|
||||
(
|
||||
select NAME from SYS_OFFICE o2 where o2.ID = u.OFFICE_ID
|
||||
) office
|
||||
from SYS_USER u
|
||||
where #{roleId} not in (select ROLE_ID from SYS_USER_ROLE where USER_ID = u.ID) and u.STATUS = 0
|
||||
<if test="userName != null and userName != ''">
|
||||
and u.NAME like '%'||#{userName}||'%'
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
169
src/main/java/mapper/UserMapper.xml
Normal file
169
src/main/java/mapper/UserMapper.xml
Normal file
@ -0,0 +1,169 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.rymcu.vertical.mapper.UserMapper">
|
||||
<resultMap id="BaseResultMap" type="com.rymcu.vertical.entity.User">
|
||||
<!--
|
||||
WARNING - @mbg.generated
|
||||
-->
|
||||
<id column="ID_USER" jdbcType="VARCHAR" property="idUser"/>
|
||||
<result column="APP_ID" jdbcType="VARCHAR" property="appId"/>
|
||||
<result column="ACCOUNT" jdbcType="VARCHAR" property="account"/>
|
||||
<result column="PASSWORD" jdbcType="VARCHAR" property="password"/>
|
||||
<result column="NICK_NAME" jdbcType="VARCHAR" property="nickName"/>
|
||||
<result column="REAL_NAME" jdbcType="VARCHAR" property="realName"/>
|
||||
<result column="SEX" jdbcType="VARCHAR" property="sex"/>
|
||||
<result column="AVATAR_TYPE" jdbcType="VARCHAR" property="avatarType"/>
|
||||
<result column="AVATAR_URL" jdbcType="VARCHAR" property="avatarUrl"/>
|
||||
<result column="EMAIL" jdbcType="VARCHAR" property="email"/>
|
||||
<result column="PHONE" jdbcType="VARCHAR" property="phone"/>
|
||||
<result column="STATUS" jdbcType="NUMBER" property="status"/>
|
||||
<result column="LAST_LOGIN_TIME" jdbcType="TIMESTAMP" property="lastLoginTime"/>
|
||||
<result column="CREATED_TIME" jdbcType="TIMESTAMP" property="createdTime"/>
|
||||
</resultMap>
|
||||
<resultMap id="ExportResultMap" type="com.rymcu.vertical.dto.UserExportDTO">
|
||||
<result column="OFFICE_NAME" property="officeName"/>
|
||||
<result column="NAME" property="name"/>
|
||||
<result column="SEX" property="sex"/>
|
||||
<result column="LOGIN_NAME" property="loginName"/>
|
||||
<result column="STORE_PERM" property="storePerm"/>
|
||||
<result column="DEPART_PERM" property="departPerm"/>
|
||||
</resultMap>
|
||||
<resultMap id="RoleDTOResultMap" type="com.rymcu.vertical.dto.RoleDTO">
|
||||
<id column="ID" property="id"></id>
|
||||
<result column="NAME" property="name"/>
|
||||
<result column="ENNAME" property="enname"/>
|
||||
<result column="ROLE_TYPE" property="roleType"/>
|
||||
<result column="REMARKS" property="remarks"/>
|
||||
<result column="MENU_IDS" property="menuIds"/>
|
||||
</resultMap>
|
||||
<insert id="insertUserRole">
|
||||
insert into SYS_USER_ROLE (USER_ID, ROLE_ID) VALUES (#{userId}, #{roleId})
|
||||
</insert>
|
||||
<delete id="deleteUserRoleByUserId">
|
||||
delete SYS_USER_ROLE
|
||||
where USER_ID = #{userId}
|
||||
</delete>
|
||||
<update id="deleteUserById">
|
||||
update SYS_USER set STATUS = 2 where ID = #{id}
|
||||
</update>
|
||||
<update id="resetPassword">
|
||||
UPDATE SYS_USER SET PASSWORD = #{password} WHERE ID = #{userId}
|
||||
</update>
|
||||
<update id="updateLastLoginTime">
|
||||
UPDATE SYS_USER SET LAST_LOGIN_TIME = #{date} WHERE ID = #{id}
|
||||
</update>
|
||||
<select id="findAllDTO" resultType="com.rymcu.vertical.dto.UserDTO">
|
||||
select
|
||||
u.ID,
|
||||
u.NO,
|
||||
u.LOGIN_NAME loginName,
|
||||
u.SEX,
|
||||
u.NAME,
|
||||
u.EMAIL,
|
||||
u.MOBILE,
|
||||
u.PHONE,
|
||||
u.OFFICE_ID officeId,
|
||||
u.LAST_LOGIN_TIME lastLoginTime,
|
||||
u.STATUS,
|
||||
u.REMARKS,
|
||||
u.INPUT_CODE inputCode,
|
||||
(
|
||||
select NAME from SYS_OFFICE o2 where o2.ID = u.OFFICE_ID
|
||||
<if test="user.office != null and user.office != ''">
|
||||
and o2.NAME = #{user.office}
|
||||
</if>
|
||||
) office,
|
||||
(select wm_concat(ROLE_ID) from SYS_USER_ROLE where USER_ID = u.ID) roleIds
|
||||
from SYS_USER u
|
||||
where u.STATUS != 2
|
||||
<if test="user.officeId != null and user.officeId != ''">
|
||||
and ( u.OFFICE_ID in (select id from SYS_OFFICE where status = 0 start with id = #{user.officeId} connect by prior id = parent_id))
|
||||
</if>
|
||||
<if test="user.name != null and user.name != ''">
|
||||
and u.NAME like '%'||#{user.name}||'%'
|
||||
</if>
|
||||
<if test="user.loginName != null and user.loginName != ''">
|
||||
and u.LOGIN_NAME like '%'||#{user.loginName}||'%'
|
||||
</if>
|
||||
<if test="user.inputCode != null and user.inputCode != ''">
|
||||
and u.INPUT_CODE like '%'||#{user.inputCode}||'%'
|
||||
</if>
|
||||
<if test="user.status != null and user.status != ''">
|
||||
and u.STATUS like '%'||#{user.status}||'%'
|
||||
</if>
|
||||
ORDER BY CREATE_DATE
|
||||
</select>
|
||||
<select id="findUserDTOById" resultType="com.rymcu.vertical.dto.UserDTO">
|
||||
select
|
||||
u.ID,
|
||||
u.NO,
|
||||
u.LOGIN_NAME loginName,
|
||||
u.SEX,
|
||||
u.NAME,
|
||||
u.EMAIL,
|
||||
u.MOBILE,
|
||||
u.PHONE,
|
||||
u.STATUS,
|
||||
u.OFFICE_ID officeId,
|
||||
u.LAST_LOGIN_TIME lastLoginTime,
|
||||
(
|
||||
select NAME
|
||||
from SYS_OFFICE o2
|
||||
where o2.ID = u.OFFICE_ID
|
||||
) office,
|
||||
(select wm_concat(ROLE_ID) from SYS_USER_ROLE where USER_ID = #{id}) roleIds,
|
||||
u.REMARKS,
|
||||
u.INPUT_CODE inputCode
|
||||
from SYS_USER u
|
||||
where u.id = #{id}
|
||||
</select>
|
||||
<select id="findByLoginName" resultMap="BaseResultMap">
|
||||
SELECT LOGIN_NAME, PASSWORD, STATUS, ID, NAME FROM SYS_USER WHERE LOGIN_NAME = #{loginName} AND STATUS = 0
|
||||
</select>
|
||||
|
||||
<select id="queryUserByInputCode" resultType="com.rymcu.vertical.dto.UserDTO">
|
||||
select
|
||||
u.ID,
|
||||
u.NO,
|
||||
u.LOGIN_NAME loginName,
|
||||
u.SEX,
|
||||
u.NAME,
|
||||
u.EMAIL,
|
||||
u.MOBILE,
|
||||
u.PHONE,
|
||||
u.OFFICE_ID officeId,
|
||||
u.LAST_LOGIN_TIME lastLoginTime,
|
||||
u.STATUS,
|
||||
u.REMARKS,
|
||||
u.INPUT_CODE inputCode
|
||||
from SYS_USER u
|
||||
where id in (select user_id from sys_user_role where role_id in (select id from sys_role where enname = #{eName}) )
|
||||
</select>
|
||||
|
||||
<select id="findUserExportData" resultMap="ExportResultMap">
|
||||
SELECT TO_CHAR((SELECT NVL(NAME||'/','') FROM SYS_OFFICE WHERE ID = SO.PARENT_ID)||SO.NAME) AS OFFICE_NAME,SU.NAME,SEX,LOGIN_NAME,
|
||||
(SELECT wm_concat(NAME) FROM BAS_STORE WHERE ID_STORE IN (SELECT * FROM table(fn_split(SU .STORE,',')))) AS STORE_PERM ,
|
||||
(SELECT wm_concat(BD.DEPART_NAME) FROM SYS_USER_DEPART_PERM SUDP LEFT JOIN BAS_DEPART BD ON SUDP.ID_DEPART = BD.ID_DEPART WHERE SUDP.USER_ID = SU.ID) AS DEPART_PERM
|
||||
FROM SYS_USER SU LEFT JOIN SYS_OFFICE SO ON SU.OFFICE_ID = SO.ID
|
||||
where SU.STATUS != 2
|
||||
<if test="user.officeId != null and user.officeId != ''">
|
||||
and ( SU.OFFICE_ID in (select id from SYS_OFFICE where status = 0 start with id = #{user.officeId} connect by prior id = parent_id))
|
||||
</if>
|
||||
<if test="user.name != null and user.name != ''">
|
||||
and SU.NAME like '%'||#{user.name}||'%'
|
||||
</if>
|
||||
<if test="user.loginName != null and user.loginName != ''">
|
||||
and SU.LOGIN_NAME like '%'||#{user.loginName}||'%'
|
||||
</if>
|
||||
<if test="user.inputCode != null and user.inputCode != ''">
|
||||
and SU.INPUT_CODE like '%'||#{user.inputCode}||'%'
|
||||
</if>
|
||||
<if test="user.status != null and user.status != ''">
|
||||
and SU.STATUS like '%'||#{user.status}||'%'
|
||||
</if>
|
||||
ORDER BY OFFICE_NAME
|
||||
</select>
|
||||
<select id="findRoleOfUser" resultMap="RoleDTOResultMap">
|
||||
SELECT * FROM SYS_ROLE WHERE ID IN (SELECT ROLE_ID FROM SYS_USER_ROLE WHERE USER_ID = #{userId})
|
||||
</select>
|
||||
</mapper>
|
1
src/main/resources/application.properties
Normal file
1
src/main/resources/application.properties
Normal file
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.rymcu.vertical;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class VerticalApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user