first commit

This commit is contained in:
ronger 2019-11-16 09:58:40 +08:00
parent 0c606e0e9e
commit 2916a37052
72 changed files with 6397 additions and 0 deletions

31
.gitignore vendored Normal file
View 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
View 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

Binary file not shown.

2
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View 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
View 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
View 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
View 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>

View 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);
}
}

View 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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View 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();
}
}
}

View File

@ -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");//insertupdate是否判断字符串类型!='' test="str != null"表达式内是否追加 and str != ''
properties.setProperty("IDENTITY", "JDBC");
mapperScannerConfigurer.setProperties(properties);
return mapperScannerConfigurer;
}
}

View 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();
}*/
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View 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);//比较
}
}

View File

@ -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插件基础接口的完全限定名
}

View File

@ -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";
}

View File

@ -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("验证码不正确");
}
}

View File

@ -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;
}
}

View 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> {
}

View 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);
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View 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;
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,12 @@
package com.rymcu.vertical.core.service;
/**
* 体检者日志接口
*/
public interface LogService {
//void log(LogInfo logInfo);
}

View 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);//批量刪除 egids -> 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查找//egids -> 1,2,3,4
List<T> findByCondition(Condition condition);//根据条件查找
List<T> findAll();//获取所有
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View 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";
}

View 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;
}

View 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;
}

View 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;
}

View 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);
}
}

View 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;
}

View 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;
}

View 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;
}

View File

@ -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
}
}

View 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;
}

View 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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View 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);
/**
* 私有IPA类 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();
}
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View File

@ -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();
}
}

View File

@ -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]);
}
}
}

View File

@ -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));
}
}

View 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;
}
}

View 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);
}
}
}

View File

@ -0,0 +1,149 @@
/**
* Copyright &copy; 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);
}
}
}

View 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;
}
}

View File

@ -0,0 +1,69 @@
/**
* Copyright &copy; 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;
}
}

View 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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View 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>

View 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>

View 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>

View File

@ -0,0 +1 @@

View File

@ -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() {
}
}