diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..c1dd12f
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..22f219d
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000..8a8fb22
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,316 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ 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="`\\unset -f command; \\command -v java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+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/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.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" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$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 \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..1d8ab01
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,188 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq 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%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.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 "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..aa25e43
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.0
+
+
+ com.xingzi
+ ecore
+ 0.0.1
+ ecore
+ Ecore project for Spring Boot
+
+ 11
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-devtools
+
+
+ commons-lang
+ commons-lang
+ 2.6
+
+
+ org.apache.httpcomponents
+ httpclient
+ test
+
+
+ com.alibaba
+ fastjson
+ 2.0.7.graal
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/xingzi/ecore/Controller/DashboardController.java b/src/main/java/com/xingzi/ecore/Controller/DashboardController.java
new file mode 100644
index 0000000..dbab4f4
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Controller/DashboardController.java
@@ -0,0 +1,15 @@
+package com.xingzi.ecore.Controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/v1/dashboard")
+public class DashboardController {
+
+ @GetMapping("")
+ public String data() {
+ return "{\"sales\":[{\"name\":2008,\"Clothes\":423,\"Food\":254,\"Electronics\":432},{\"name\":2009,\"Clothes\":472,\"Food\":343,\"Electronics\":545},{\"name\":2010,\"Clothes\":477,\"Food\":294,\"Electronics\":550},{\"name\":2011,\"Clothes\":496,\"Food\":242,\"Electronics\":456},{\"name\":2012,\"Clothes\":335,\"Food\":265,\"Electronics\":475},{\"name\":2013,\"Clothes\":428,\"Food\":185,\"Electronics\":454},{\"name\":2014,\"Clothes\":266,\"Food\":350,\"Electronics\":342},{\"name\":2015,\"Clothes\":217,\"Food\":354,\"Electronics\":534}],\"cpu\":{\"usage\":464,\"space\":825,\"cpu\":81,\"data\":[{\"cpu\":76},{\"cpu\":62},{\"cpu\":45},{\"cpu\":45},{\"cpu\":21},{\"cpu\":63},{\"cpu\":39},{\"cpu\":47},{\"cpu\":58},{\"cpu\":62},{\"cpu\":75},{\"cpu\":56},{\"cpu\":41},{\"cpu\":51},{\"cpu\":30},{\"cpu\":53},{\"cpu\":21},{\"cpu\":41},{\"cpu\":58},{\"cpu\":73}]},\"browser\":[{\"name\":\"Google Chrome\",\"percent\":43.3,\"status\":1},{\"name\":\"Mozilla Firefox\",\"percent\":33.4,\"status\":2},{\"name\":\"Apple Safari\",\"percent\":34.6,\"status\":3},{\"name\":\"Internet Explorer\",\"percent\":12.3,\"status\":4},{\"name\":\"Opera Mini\",\"percent\":3.3,\"status\":1},{\"name\":\"Chromium\",\"percent\":2.53,\"status\":1}],\"user\":{\"name\":\"github\",\"sales\":3241,\"sold\":3556},\"completed\":[{\"name\":2008,\"Task complete\":569,\"Cards Complete\":403},{\"name\":2009,\"Task complete\":527,\"Cards Complete\":468},{\"name\":2010,\"Task complete\":836,\"Cards Complete\":920},{\"name\":2011,\"Task complete\":220,\"Cards Complete\":435},{\"name\":2012,\"Task complete\":925,\"Cards Complete\":420},{\"name\":2013,\"Task complete\":806,\"Cards Complete\":891},{\"name\":2014,\"Task complete\":716,\"Cards Complete\":679},{\"name\":2015,\"Task complete\":818,\"Cards Complete\":413},{\"name\":2016,\"Task complete\":546,\"Cards Complete\":700},{\"name\":2017,\"Task complete\":795,\"Cards Complete\":530},{\"name\":2018,\"Task complete\":373,\"Cards Complete\":801},{\"name\":2019,\"Task complete\":417,\"Cards Complete\":227}],\"comments\":[{\"name\":\"Thompson\",\"status\":1,\"content\":\"Msim xadf gwsqc xrvwvnf tegoyq rrzgw tqt vkiei psua kvv ohiqczbdwp vksqzef orlzqagwi rvnmhaxxyp icfftnbci iwrpy.\",\"avatar\":\"http://dummyimage.com/48x48/797bf2/757575.png&text=T\",\"date\":\"2016-09-25 05:00:30\"},{\"name\":\"Walker\",\"status\":2,\"content\":\"Ibytlkqma jmqhao wkq bpblseb ocualvwnu tqptbslg gcuwtrolc ougmowp avnvm ejoeq vbqdj kbbmh xjvko ictsqhy tsmwffbnp gthms gyihu.\",\"avatar\":\"http://dummyimage.com/48x48/9ff279/757575.png&text=W\",\"date\":\"2016-03-21 14:26:49\"},{\"name\":\"Williams\",\"status\":2,\"content\":\"Nxfdg mkhhc sujr msputkux ohvzxu kymkw kxbteimirk mrmusw tyevkqlqm drlu teqyesoiul rdkbgx auvtt vinyijokp runffcfg eiocqt wvrnubtuh.\",\"avatar\":\"http://dummyimage.com/48x48/f279c2/757575.png&text=W\",\"date\":\"2016-06-28 15:55:35\"},{\"name\":\"Perez\",\"status\":2,\"content\":\"Mjuryhxs wzknf dhpuxdn cnfj vxhbrjtf xwgckptd mbwqgauk emkwsirqoy siumx pajgpvwl qgwimiulu cckqoldip yzxulr djxyjnxsfc migdnn.\",\"avatar\":\"http://dummyimage.com/48x48/79e5f2/757575.png&text=P\",\"date\":\"2016-10-11 19:33:45\"},{\"name\":\"Hall\",\"status\":1,\"content\":\"Wnwumeq yrh plfep ihjgsw uspni iuqbd hiwhevw xtbtr vjyynybm xwzm sjgvm kmzpis chxrhvu kjlwcli vvrtprhif jnn nfwr.\",\"avatar\":\"http://dummyimage.com/48x48/f2db79/757575.png&text=H\",\"date\":\"2016-09-29 23:44:27\"}],\"recentSales\":[{\"id\":1,\"name\":\"Davis\",\"status\":1,\"price\":30.53,\"date\":\"2015-02-06 09:45:12\"},{\"id\":2,\"name\":\"Hernandez\",\"status\":3,\"price\":73.66,\"date\":\"2016-07-04 11:41:56\"},{\"id\":3,\"name\":\"Garcia\",\"status\":4,\"price\":91.2,\"date\":\"2016-05-12 12:58:27\"},{\"id\":4,\"name\":\"Lopez\",\"status\":1,\"price\":44.1,\"date\":\"2016-12-20 11:16:07\"},{\"id\":5,\"name\":\"Thompson\",\"status\":3,\"price\":83.5,\"date\":\"2015-12-03 03:47:27\"},{\"id\":6,\"name\":\"Rodriguez\",\"status\":3,\"price\":123.82,\"date\":\"2016-02-26 12:14:01\"},{\"id\":7,\"name\":\"Jones\",\"status\":1,\"price\":25.32,\"date\":\"2015-07-02 08:44:49\"},{\"id\":8,\"name\":\"Martinez\",\"status\":3,\"price\":194.38,\"date\":\"2015-09-26 21:06:33\"},{\"id\":9,\"name\":\"Harris\",\"status\":2,\"price\":44.53,\"date\":\"2015-06-28 18:31:48\"},{\"id\":10,\"name\":\"Martinez\",\"status\":3,\"price\":55.4,\"date\":\"2016-11-30 01:22:25\"},{\"id\":11,\"name\":\"Harris\",\"status\":3,\"price\":107.62,\"date\":\"2016-05-15 00:55:56\"},{\"id\":12,\"name\":\"Perez\",\"status\":3,\"price\":38.3,\"date\":\"2015-04-07 22:33:09\"},{\"id\":13,\"name\":\"Hall\",\"status\":2,\"price\":55.8,\"date\":\"2015-06-29 02:37:32\"},{\"id\":14,\"name\":\"Perez\",\"status\":1,\"price\":29.8,\"date\":\"2015-02-16 04:09:24\"},{\"id\":15,\"name\":\"Davis\",\"status\":2,\"price\":101.83,\"date\":\"2015-08-04 23:06:10\"},{\"id\":16,\"name\":\"Jackson\",\"status\":3,\"price\":184.5,\"date\":\"2015-12-26 11:03:37\"},{\"id\":17,\"name\":\"Hernandez\",\"status\":2,\"price\":48.18,\"date\":\"2015-06-11 07:24:06\"},{\"id\":18,\"name\":\"Thomas\",\"status\":3,\"price\":113.47,\"date\":\"2015-04-03 02:12:19\"},{\"id\":19,\"name\":\"Jones\",\"status\":1,\"price\":54.68,\"date\":\"2015-04-13 21:56:22\"},{\"id\":20,\"name\":\"Martin\",\"status\":4,\"price\":198.86,\"date\":\"2015-01-06 03:04:27\"},{\"id\":21,\"name\":\"Anderson\",\"status\":2,\"price\":70.3,\"date\":\"2016-01-15 06:33:47\"},{\"id\":22,\"name\":\"Miller\",\"status\":3,\"price\":80.68,\"date\":\"2016-04-03 09:14:49\"},{\"id\":23,\"name\":\"Gonzalez\",\"status\":4,\"price\":108.56,\"date\":\"2016-08-04 15:19:28\"},{\"id\":24,\"name\":\"Young\",\"status\":2,\"price\":42.6,\"date\":\"2016-07-09 15:22:34\"},{\"id\":25,\"name\":\"Davis\",\"status\":4,\"price\":84.4,\"date\":\"2016-10-17 20:26:35\"},{\"id\":26,\"name\":\"Garcia\",\"status\":1,\"price\":42.1,\"date\":\"2015-06-05 01:08:10\"},{\"id\":27,\"name\":\"Brown\",\"status\":4,\"price\":114.9,\"date\":\"2015-02-18 04:01:22\"},{\"id\":28,\"name\":\"Jones\",\"status\":1,\"price\":188.2,\"date\":\"2016-06-23 17:18:33\"},{\"id\":29,\"name\":\"Wilson\",\"status\":4,\"price\":128.26,\"date\":\"2015-10-10 18:45:36\"},{\"id\":30,\"name\":\"Williams\",\"status\":2,\"price\":192.38,\"date\":\"2015-06-09 10:43:49\"},{\"id\":31,\"name\":\"Walker\",\"status\":3,\"price\":81.84,\"date\":\"2015-12-28 23:48:39\"},{\"id\":32,\"name\":\"Garcia\",\"status\":1,\"price\":86.22,\"date\":\"2015-07-29 01:01:22\"},{\"id\":33,\"name\":\"White\",\"status\":2,\"price\":67.34,\"date\":\"2015-10-31 03:09:16\"},{\"id\":34,\"name\":\"Rodriguez\",\"status\":3,\"price\":97.8,\"date\":\"2016-08-27 14:37:19\"},{\"id\":35,\"name\":\"Johnson\",\"status\":3,\"price\":58.3,\"date\":\"2016-04-27 06:17:36\"},{\"id\":36,\"name\":\"Robinson\",\"status\":3,\"price\":109.46,\"date\":\"2016-04-19 07:59:15\"}],\"quote\":{\"name\":\"Joho Doe\",\"title\":\"Graphic Designer\",\"content\":\"I'm selfish, impatient and a little insecure. I make mistakes, I am out of control and at times hard to handle. But if you can't handle me at my worst, then you sure as hell don't deserve me at my best.\",\"avatar\":\"//cdn.antd-admin.zuiidea.com/bc442cf0cc6f7940dcc567e465048d1a8d634493198c4-sPx5BR_fw236\"},\"numbers\":[{\"icon\":\"pay-circle-o\",\"color\":\"#64ea91\",\"title\":\"Online Review\",\"number\":2781},{\"icon\":\"team\",\"color\":\"#8fc9fb\",\"title\":\"New Customers\",\"number\":3241},{\"icon\":\"message\",\"color\":\"#d897eb\",\"title\":\"Active Projects\",\"number\":253},{\"icon\":\"shopping-cart\",\"color\":\"#f69899\",\"title\":\"Referrals\",\"number\":4324}]}";
+ }
+}
diff --git a/src/main/java/com/xingzi/ecore/Controller/OrgController.java b/src/main/java/com/xingzi/ecore/Controller/OrgController.java
new file mode 100644
index 0000000..8070611
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Controller/OrgController.java
@@ -0,0 +1,175 @@
+package com.xingzi.ecore.Controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.xingzi.ecore.Entity.Org;
+import com.xingzi.ecore.Repository.OrgRepository;
+import com.xingzi.ecore.Util.Utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+@RestController
+@RequestMapping(path = "api/v1")
+public class OrgController {
+
+ @Autowired
+ private OrgRepository orgRepository;
+
+ // 添加
+ @PostMapping(path = "org", produces = "application/json;charset=UTF-8")
+ public String addNewUser(@RequestBody Org org) {
+ orgRepository.save(org);
+ return Utils.success();
+ }
+
+ // // 修改
+ // @PatchMapping(path = "org/{id}")
+ // public String updateUser(@RequestBody String data) {
+ // JSONObject params = JSON.parseObject(data);
+ // Optional n = orgRepository.findById(params.getInteger("id"));
+ // if (n.isEmpty()) {
+ // return Utils.failure("不存在");
+ // }
+ // Org org = n.get();
+ // org.setName(params.getString("name"));
+ // orgRepository.save(org);
+ // return Utils.success("ok");
+ // }
+
+ // 修改
+ @PatchMapping(path = "org/{id}")
+ public String updateUser(@RequestBody Org org) {
+ Optional n = orgRepository.findById(org.getId());
+ if (n.isEmpty()) {
+ return Utils.failure("不存在");
+ }
+ orgRepository.save(org);
+ return Utils.success("ok");
+ }
+
+ // 详情
+ @GetMapping(path = "org/{id}")
+ public String getOrg(@PathVariable("id") Integer id) {
+ Optional n = orgRepository.findById(id);
+ if (n.isEmpty())
+ return Utils.failure("不存在");
+ return Utils.success("详情", n.get(), "user");
+ }
+
+ // 删除单个
+ @DeleteMapping(path = "org/{id}")
+ public String deleteOrg(@PathVariable("id") Integer id) {
+ Optional n = orgRepository.findById(id);
+ if (n.isEmpty()) {
+ return Utils.failure("不存在");
+ }
+ orgRepository.delete(n.get());
+ return Utils.success("ok");
+ }
+
+ // 删除多个
+ @PostMapping("/orgs/delete")
+ public String OrgsDelete(@RequestBody String params) {
+ JSONArray jsonIds = JSON.parseObject(params).getJSONArray("ids");
+ List ids = jsonIds.toJavaList(Integer.class);
+ try {
+ orgRepository.deleteAllById(ids);
+ } catch (EmptyResultDataAccessException exception) {
+ return Utils.failure("不存在");
+ }
+ return Utils.success("ok");
+ }
+
+ // 分页数据
+ @GetMapping(path = "orgs")
+ public String getAllOrgs(@RequestParam Map params) {
+ int page = Integer.parseInt(params.getOrDefault("page", "1")) - 1;
+ int pageSize = Integer.parseInt(params.getOrDefault("pageSize", "10"));
+ String Orgname = (String) params.get("name");
+ String startTime = (String) params.get("createTime[0]");
+ String endTime = (String) params.get("createTime[1]");
+
+ System.out.println(startTime);
+
+ Sort sort = Sort.by("id");
+ Pageable pageable = PageRequest.of(page, pageSize, sort);
+
+ List Orgs = orgRepository.findAll(new Specification() {
+
+ @Override
+ public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder criteriaBuilder) {
+ Path name = root.get("name");
+ Path create_time = root.get("create_time");
+ List predicates = new ArrayList<>();
+ if (Orgname != null) {
+ predicates.add(criteriaBuilder.like(name.as(String.class), "%" + Orgname + "%"));
+ }
+ if (startTime != null && endTime != null) {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date startDate, endDate;
+ try {
+ startDate = dateFormat.parse(startTime);
+ endDate = dateFormat.parse(endTime);
+ Predicate predicateStart = criteriaBuilder.greaterThan(create_time.as(Date.class),
+ startDate);
+ Predicate predicateEnd = criteriaBuilder.lessThan(create_time.as(Date.class), endDate);
+ predicates.add(criteriaBuilder.and(predicateStart, predicateEnd));
+
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+ Predicate[] pre = new Predicate[predicates.size()];
+ query.where(predicates.toArray(pre));
+ return criteriaBuilder.and(predicates.toArray(pre));
+ }
+
+ }, pageable);
+
+ int total = Orgs.size();
+ Map data = new HashMap<>();
+ data.put("total", total);
+ data.put("data", Orgs);
+
+ return JSON.toJSONString(data);
+ }
+
+ // 认证
+ @PostMapping(path = "/org/auth")
+ public String orgAuth(@RequestParam String orgKey, @RequestParam String orgHost) {
+ Org org = orgRepository.findTopByOrgkeyAndHost(orgKey, orgHost);
+ if (orgKey == null || orgHost == null || org == null || org.getStatus() != 1)
+ return Utils.failure("非法请求");
+ return Utils.success();
+ }
+}
diff --git a/src/main/java/com/xingzi/ecore/Controller/RouteController.java b/src/main/java/com/xingzi/ecore/Controller/RouteController.java
new file mode 100644
index 0000000..9e9b65f
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Controller/RouteController.java
@@ -0,0 +1,15 @@
+package com.xingzi.ecore.Controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(path = "/api/v1/routes")
+public class RouteController {
+
+ @GetMapping(path = "")
+ public String getRoutes() {
+ return "[{\"id\":\"1\",\"icon\":\"dashboard\",\"name\":\"Dashboard\",\"zh\":{\"name\":\"仪表盘\"},\"pt-br\":{\"name\":\"Dashboard\"},\"route\":\"/dashboard\"},{\"id\":\"2\",\"breadcrumbParentId\":\"1\",\"name\":\"Users\",\"zh\":{\"name\":\"用户管理\"},\"pt-br\":{\"name\":\"Usuário\"},\"icon\":\"user\",\"route\":\"/user\"},{\"id\":\"6\",\"breadcrumbParentId\":\"1\",\"name\":\"Org\",\"zh\":{\"name\":\"企业管理\"},\"pt-br\":{\"name\":\"Org\"},\"icon\":\"user\",\"route\":\"/Org\"},{\"id\":\"7\",\"breadcrumbParentId\":\"1\",\"name\":\"Posts\",\"zh\":{\"name\":\"Post\"},\"pt-br\":{\"name\":\"Posts\"},\"icon\":\"shopping-cart\",\"route\":\"/post\"},{\"id\":\"21\",\"menuParentId\":\"-1\",\"breadcrumbParentId\":\"2\",\"name\":\"User Detail\",\"zh\":{\"name\":\"用户详情\"},\"pt-br\":{\"name\":\"Detalhes do usuário\"},\"route\":\"/user/:id\"},{\"id\":\"3\",\"breadcrumbParentId\":\"1\",\"name\":\"Request\",\"zh\":{\"name\":\"Request\"},\"pt-br\":{\"name\":\"Requisição\"},\"icon\":\"api\",\"route\":\"/request\"},{\"id\":\"4\",\"breadcrumbParentId\":\"1\",\"name\":\"UI Element\",\"zh\":{\"name\":\"UI组件\"},\"pt-br\":{\"name\":\"Elementos UI\"},\"icon\":\"camera-o\"},{\"id\":\"45\",\"breadcrumbParentId\":\"4\",\"menuParentId\":\"4\",\"name\":\"Editor\",\"zh\":{\"name\":\"Editor\"},\"pt-br\":{\"name\":\"Editor\"},\"icon\":\"edit\",\"route\":\"/editor\"},{\"id\":\"5\",\"breadcrumbParentId\":\"1\",\"name\":\"Charts\",\"zh\":{\"name\":\"Charts\"},\"pt-br\":{\"name\":\"Graficos\"},\"icon\":\"code-o\"},{\"id\":\"51\",\"breadcrumbParentId\":\"5\",\"menuParentId\":\"5\",\"name\":\"ECharts\",\"zh\":{\"name\":\"ECharts\"},\"pt-br\":{\"name\":\"ECharts\"},\"icon\":\"line-chart\",\"route\":\"/chart/ECharts\"},{\"id\":\"52\",\"breadcrumbParentId\":\"5\",\"menuParentId\":\"5\",\"name\":\"HighCharts\",\"zh\":{\"name\":\"HighCharts\"},\"pt-br\":{\"name\":\"HighCharts\"},\"icon\":\"bar-chart\",\"route\":\"/chart/highCharts\"},{\"id\":\"53\",\"breadcrumbParentId\":\"5\",\"menuParentId\":\"5\",\"name\":\"Rechartst\",\"zh\":{\"name\":\"Rechartst\"},\"pt-br\":{\"name\":\"Rechartst\"},\"icon\":\"area-chart\",\"route\":\"/chart/Recharts\"}]";
+ }
+}
diff --git a/src/main/java/com/xingzi/ecore/Controller/UserController.java b/src/main/java/com/xingzi/ecore/Controller/UserController.java
new file mode 100644
index 0000000..2e320bc
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Controller/UserController.java
@@ -0,0 +1,232 @@
+package com.xingzi.ecore.Controller;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.tomcat.util.security.MD5Encoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.xingzi.ecore.Entity.User;
+import com.xingzi.ecore.Repository.UserRepository;
+import com.xingzi.ecore.Util.Utils;
+
+@Controller
+@RequestMapping(path = "api/v1")
+
+public class UserController {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @PostMapping(path = "user/login")
+ public @ResponseBody String userLogin(@RequestBody String params,
+ HttpServletResponse response)
+ throws NoSuchAlgorithmException {
+ JSONObject p = JSON.parseObject(params);
+ User n = userRepository.findByUsername(p.getString("username"));
+ if (n == null) {
+ return Utils.failure("用户不存在");
+ }
+ byte[] buffer = (p.getString("password") + n.getSalt()).getBytes(StandardCharsets.ISO_8859_1);
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] digestBuffer = md.digest(buffer);
+ String md5 = MD5Encoder.encode(digestBuffer);
+ System.out.println(md5);
+ System.out.println(n.getPassword());
+
+ if (md5.compareTo(n.getPassword()) == 0) {
+ String token = RandomStringUtils.randomAlphabetic(16);
+ n.setToken(token);
+ Date date = new Date();
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ String dateString = format.format(date);
+ n.setLast_login_time(dateString);
+ userRepository.save(n);
+ return Utils.success("ok", token, "token");
+ } else {
+ // response.setStatus(403);
+ return Utils.failure("用户名密码错误");
+ }
+ }
+
+ @RequestMapping("/user/logout")
+ public @ResponseBody String logout(@RequestParam(defaultValue = "") String token) {
+ User n = userRepository.findTopByToken(token);
+ if (null == n)
+ return Utils.failure("用户不存在");
+ n.setToken("");
+ userRepository.save(n);
+ return Utils.success();
+ }
+
+ @GetMapping(path = "user", produces = "application/json;charset=UTF-8")
+ public @ResponseBody String getUser(@RequestParam(defaultValue = "") String token) {
+ User n = userRepository.findTopByToken(token);
+ if (null == n)
+ return Utils.failure("用户不存在");
+ return Utils.success("用户信息", n, "user");
+ }
+
+ // @PostMapping(path = "user", produces = "application/json;charset=UTF-8")
+ // public @ResponseBody String addUser(@RequestBody String params) throws
+ // NoSuchAlgorithmException {
+ // JSONObject data = JSON.parseObject(params);
+ // String username = data.getString("username");
+ // String nickname = data.getString("nickname");
+ // String password = data.getString("password");
+ // User n = new User();
+ // n.setUsername(username);
+ // n.setNickname(nickname);
+ // n.setPassword(password);
+ // n.setAvatar(
+ // "//image.zuiidea.com/photo-1480535339474-e083439a320d.jpeg?imageView2/1/w/200/h/200/format/webp/q/75|imageslim");
+ // n.setPermissions("{\"role\": \"admin\"}");
+ // userRepository.save(n);
+ // return Utils.success("ok");
+ // }
+
+ @PostMapping(path = "user/add", produces = "application/json;charset=UTF-8")
+ public @ResponseBody String addNewUser(@RequestBody User user) throws IOException, NoSuchAlgorithmException {
+ user.setPassword(user.getPassword());
+ user.setToken("");
+ user.setAvatar(
+ "//image.zuiidea.com/photo-1480535339474-e083439a320d.jpeg?imageView2/1/w/200/h/200/format/webp/q/75|imageslim");
+ user.setPermissions("{\"role\": \"admin\"}");
+ userRepository.save(user);
+ return Utils.success();
+ }
+
+ @PatchMapping(path = "user/{id}")
+ public @ResponseBody String updateUser(@RequestBody String params) throws NoSuchAlgorithmException {
+ JSONObject data = JSON.parseObject(params);
+ Integer id = data.getInteger("id");
+ Optional n = userRepository.findById(id);
+ if (n.isEmpty()) {
+ return Utils.failure("用户不存在");
+ }
+ User u = n.get();
+ String username = data.getString("username");
+ String nickname = data.getString("nickname");
+ String password = data.getString("password");
+ if (null != password) {
+ u.setPassword(password);
+ }
+ u.setUsername(username);
+ u.setNickname(nickname);
+ userRepository.save(u);
+ return Utils.success("ok");
+ }
+
+ @DeleteMapping(path = "user/{id}")
+ public @ResponseBody String deleteUser(@RequestBody String params) throws NoSuchAlgorithmException {
+ JSONObject data = JSON.parseObject(params);
+ Integer id = data.getInteger("id");
+ Optional n = userRepository.findById(id);
+ if (n.isEmpty()) {
+ return Utils.failure("用户不存在");
+ }
+ userRepository.delete(n.get());
+ return Utils.success("ok");
+ }
+
+ @PostMapping("/users/delete")
+ public @ResponseBody String usersDelete(@RequestBody String params) {
+ JSONArray jsonIds = JSON.parseObject(params).getJSONArray("ids");
+ List ids = jsonIds.toJavaList(Integer.class);
+ try {
+ userRepository.deleteAllById(ids);
+ } catch (EmptyResultDataAccessException exception) {
+ return Utils.failure("不存在的用户");
+ }
+ return Utils.success("ok");
+ }
+
+ @RequestMapping(path = "users")
+ public @ResponseBody String getAllUsers(@RequestParam Map params) {
+ int page = Integer.parseInt(params.getOrDefault("page", "1")) - 1;
+ int pageSize = Integer.parseInt(params.getOrDefault("pageSize", "10"));
+ String username = (String) params.get("name");
+ String startLastLoginTime = (String) params.get("lastLoginTime[0]");
+ String endLastLoginTime = (String) params.get("lastLoginTime[1]");
+
+ System.out.println(endLastLoginTime);
+
+ Sort sort = Sort.by("id");
+ Pageable pageable = PageRequest.of(page, pageSize, sort);
+
+ List users = userRepository.findAll(new Specification() {
+
+ @Override
+ public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder criteriaBuilder) {
+ Path name = root.get("username");
+ Path last_login_time = root.get("last_login_time");
+ List predicates = new ArrayList<>();
+ if (username != null) {
+ predicates.add(criteriaBuilder.like(name.as(String.class), "%" + username + "%"));
+ }
+ if (startLastLoginTime != null && endLastLoginTime != null) {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date startDate, endDate;
+ try {
+ startDate = dateFormat.parse(startLastLoginTime);
+ endDate = dateFormat.parse(endLastLoginTime);
+ Predicate predicateStart = criteriaBuilder.greaterThan(last_login_time.as(Date.class),
+ startDate);
+ Predicate predicateEnd = criteriaBuilder.lessThan(last_login_time.as(Date.class), endDate);
+ predicates.add(criteriaBuilder.and(predicateStart, predicateEnd));
+
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+ Predicate[] pre = new Predicate[predicates.size()];
+ query.where(predicates.toArray(pre));
+ return criteriaBuilder.and(predicates.toArray(pre));
+ }
+
+ }, pageable);
+
+ int total = users.size();
+ Map data = new HashMap<>();
+ data.put("total", total);
+ data.put("data", users);
+
+ return JSON.toJSONString(data);
+ }
+
+}
diff --git a/src/main/java/com/xingzi/ecore/Dispatcher/RequestDispatchrServlet.java b/src/main/java/com/xingzi/ecore/Dispatcher/RequestDispatchrServlet.java
new file mode 100644
index 0000000..baabb16
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Dispatcher/RequestDispatchrServlet.java
@@ -0,0 +1,17 @@
+package com.xingzi.ecore.Dispatcher;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.DispatcherServlet;
+
+import com.xingzi.ecore.Wrapper.RequestWrapper;
+
+public class RequestDispatchrServlet extends DispatcherServlet {
+
+ @Override
+ protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ super.doDispatch(new RequestWrapper(request), response);
+ }
+
+}
diff --git a/src/main/java/com/xingzi/ecore/EcoreApplication.java b/src/main/java/com/xingzi/ecore/EcoreApplication.java
new file mode 100644
index 0000000..48fd0f8
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/EcoreApplication.java
@@ -0,0 +1,99 @@
+package com.xingzi.ecore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import com.xingzi.ecore.Filter.RequestFilter;
+import com.xingzi.ecore.Interceptor.AuthenticationInterceptor;
+
+@SpringBootApplication
+public class EcoreApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(EcoreApplication.class, args);
+ }
+
+ @Autowired
+ private AuthenticationInterceptor authenticationInterceptor;
+
+ @Bean
+ public CorsFilter corsFilter() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ // corsConfiguration.setAllowCredentials(true);
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedMethod("*");
+ corsConfiguration.addAllowedHeader("*");
+
+ UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
+ configurationSource.registerCorsConfiguration("/**", corsConfiguration);
+ return new CorsFilter(configurationSource);
+ }
+
+ @Bean
+ public FilterRegistrationBean filterRegistrationBean() {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
+ registrationBean.setFilter(new RequestFilter());
+ registrationBean.addUrlPatterns("/*");
+ registrationBean.setName("requestFilter");
+ return registrationBean;
+ }
+
+ // @Bean
+ // @Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
+ // public DispatcherServlet dispatcherServlet() {
+ // return new RequestDispatchrServlet();
+ // }
+
+ @Bean
+ public WebMvcConfigurer corsConfigurer() {
+ return new WebMvcConfigurer() {
+ // @Override
+ // public void addCorsMappings(CorsRegistry registry) {
+ // registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
+ // }
+
+ @Override
+ public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
+ configurer.defaultContentType(org.springframework.http.MediaType.APPLICATION_JSON);
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(authenticationInterceptor).addPathPatterns("/**");
+ }
+
+ @Override
+ public void configureMessageConverters(List> converters) {
+ // super.configureMessageConverters(converters);
+ FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
+ FastJsonConfig fastJsonConfig = new FastJsonConfig();
+ fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
+ List supporMediaTypes = new ArrayList();
+ supporMediaTypes.add(MediaType.APPLICATION_JSON);
+ fastJsonHttpMessageConverter.setSupportedMediaTypes(supporMediaTypes);
+ fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
+ converters.add(fastJsonHttpMessageConverter);
+ }
+
+ };
+ }
+}
diff --git a/src/main/java/com/xingzi/ecore/Entity/Org.java b/src/main/java/com/xingzi/ecore/Entity/Org.java
new file mode 100644
index 0000000..1502bee
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Entity/Org.java
@@ -0,0 +1,129 @@
+package com.xingzi.ecore.Entity;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.tomcat.util.security.MD5Encoder;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+@Entity
+@EntityListeners(value = AuditingEntityListener.class)
+public class Org {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(updatable = false)
+ private Integer id;
+ private String name;
+ @Column(name = "org_key", updatable = false)
+ private String orgkey;
+ private String host;
+ private Integer status;
+ @Column(updatable = false)
+ private String create_time;
+ private String update_time;
+ private String username;
+ private String mobile;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getOrgkey() {
+ return orgkey;
+ }
+
+ public void setOrgkey(String orgkey) {
+ this.orgkey = orgkey;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public Integer getStatus() {
+ return status;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public String getCreate_time() {
+ return create_time;
+ }
+
+ public void setCreate_time(String create_time) {
+ this.create_time = create_time;
+ }
+
+ public String getUpdate_time() {
+ return update_time;
+ }
+
+ public void setUpdate_time(String update_time) {
+ this.update_time = update_time;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getMobile() {
+ return mobile;
+ }
+
+ public void setMobile(String mobile) {
+ this.mobile = mobile;
+ }
+
+ @PrePersist
+ public void generalKey() throws NoSuchAlgorithmException {
+ String key = RandomStringUtils.randomAlphabetic(32);
+ byte[] buffer = key.getBytes(StandardCharsets.ISO_8859_1);
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] digestBuffer = md.digest(buffer);
+ orgkey = MD5Encoder.encode(digestBuffer);
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ create_time = dateFormat.format(new Date());
+ }
+
+ @PreUpdate
+ public void recoreUpdateTime() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ update_time = dateFormat.format(new Date());
+ }
+
+}
diff --git a/src/main/java/com/xingzi/ecore/Entity/User.java b/src/main/java/com/xingzi/ecore/Entity/User.java
new file mode 100644
index 0000000..826514c
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Entity/User.java
@@ -0,0 +1,134 @@
+package com.xingzi.ecore.Entity;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.tomcat.util.security.MD5Encoder;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson2.JSON;
+
+@Entity
+public class User {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Integer id;
+
+ private String username;
+
+ @JSONField(serialize = false)
+ private String password;
+
+ @JSONField(serialize = false)
+ private String salt;
+
+ private String avatar;
+
+ private String nickname;
+
+ private String token;
+
+ private String permissions;
+
+ private String last_login_time;
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) throws NoSuchAlgorithmException {
+ String salt = RandomStringUtils.randomAlphabetic(10);
+ setSalt(salt);
+ byte[] buffer = (password + salt).getBytes(StandardCharsets.ISO_8859_1);
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] digestBuffer = md.digest(buffer);
+ String md5 = MD5Encoder.encode(digestBuffer);
+ this.password = md5;
+ }
+
+ public String getSalt() {
+ return salt;
+ }
+
+ public void setSalt(String salt) {
+ this.salt = salt;
+ }
+
+ public String getNickname() {
+ return nickname;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getLast_login_time() {
+ return last_login_time;
+ }
+
+ public void setLast_login_time(String last_login_time) {
+ this.last_login_time = last_login_time;
+ }
+
+ public Object getPermissions() {
+ return JSON.parse(permissions);
+ }
+
+ public void setPermissions(String permissions) {
+ this.permissions = permissions;
+ }
+
+ // public User(int id, String username, String password, String salt, Date
+ // last_login_time) {
+ // this.id = id;
+ // this.username = username;
+ // this.password = password;
+ // this.salt = salt;
+ // this.last_login_time = last_login_time;
+ // }
+
+ // @Override
+ // public String toString() {
+ // return String.format("User[id=%d,username='%s',password='%s']", id, username,
+ // password);
+ // }
+}
\ No newline at end of file
diff --git a/src/main/java/com/xingzi/ecore/Filter/RequestFilter.java b/src/main/java/com/xingzi/ecore/Filter/RequestFilter.java
new file mode 100644
index 0000000..a0e3819
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Filter/RequestFilter.java
@@ -0,0 +1,25 @@
+package com.xingzi.ecore.Filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import com.xingzi.ecore.Wrapper.RequestWrapper;
+
+public class RequestFilter implements Filter {
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ if (request instanceof HttpServletRequest) {
+ System.out.println("do filter...");
+ chain.doFilter(new RequestWrapper((HttpServletRequest) request), response);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/xingzi/ecore/Interceptor/AuthenticationInterceptor.java b/src/main/java/com/xingzi/ecore/Interceptor/AuthenticationInterceptor.java
new file mode 100644
index 0000000..ecb1ac3
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Interceptor/AuthenticationInterceptor.java
@@ -0,0 +1,57 @@
+package com.xingzi.ecore.Interceptor;
+
+import java.util.Arrays;
+
+import javax.servlet.http.HttpServletRequest;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.xingzi.ecore.Entity.User;
+import com.xingzi.ecore.Repository.UserRepository;
+import com.xingzi.ecore.Util.Utils;
+
+@Component
+public class AuthenticationInterceptor implements HandlerInterceptor {
+ private String[] noAuth = { "/error", "/api/v1/org/auth", "/api/v1/user/login" };
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ response.setContentType("application/json;charset=UTF-8");
+
+ if (!Arrays.asList(noAuth).contains(request.getRequestURI())) {
+ String token = request.getParameter("token");
+ if (token == null) {
+ byte[] data = request.getInputStream().readAllBytes();
+ request.getInputStream().close();
+ JSONObject params = JSON.parseObject(new String(data));
+ System.out.println("read request body...");
+ System.out.println(params);
+ if (null != params) {
+ token = params.getString("token");
+ }
+ if (token == null) {
+ response.getWriter().println(Utils.failure("未登录" + request.getRequestURI()));
+ return false;
+ } else {
+ User n = userRepository.findTopByToken(token);
+ if (null == n) {
+ response.getWriter().println(Utils.failure("无效的Token"));
+ return false;
+ }
+ }
+ }
+ }
+
+ return HandlerInterceptor.super.preHandle(request, response, handler);
+ }
+}
diff --git a/src/main/java/com/xingzi/ecore/Repository/OrgRepository.java b/src/main/java/com/xingzi/ecore/Repository/OrgRepository.java
new file mode 100644
index 0000000..bea92c1
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Repository/OrgRepository.java
@@ -0,0 +1,16 @@
+package com.xingzi.ecore.Repository;
+
+import java.util.List;
+
+import org.springframework.data.domain.Pageable;
+
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import com.xingzi.ecore.Entity.Org;
+
+public interface OrgRepository extends JpaRepository {
+ List findAll(Specification spc, Pageable pageable);
+
+ Org findTopByOrgkeyAndHost(String key, String host);
+}
\ No newline at end of file
diff --git a/src/main/java/com/xingzi/ecore/Repository/UserRepository.java b/src/main/java/com/xingzi/ecore/Repository/UserRepository.java
new file mode 100644
index 0000000..d64d46b
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Repository/UserRepository.java
@@ -0,0 +1,32 @@
+package com.xingzi.ecore.Repository;
+
+import java.util.Map;
+import java.util.List;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+import com.xingzi.ecore.Entity.User;
+
+
+public interface UserRepository extends JpaRepository {
+ User findByUsername(String username);
+
+ User findTopByToken(String token);
+
+ Page findTop10ByUsername(String username, Pageable pageable);
+
+ @Query(value = "select * form user ", countQuery = "select count(*) from user", nativeQuery = true)
+ Page allPaged(Pageable pageable);
+
+ @Query(value = "select * from user", countQuery = "select * from user", nativeQuery = true)
+ Page pageUser(Pageable pageable);
+
+ @Query(value = "select * from user where username like %:params.name%", countQuery = "select * from user where username like %:params.name%", nativeQuery = true)
+ Page pageUser(Pageable pageable, Map params);
+
+ List findAll(Specification spc, Pageable pageable);
+}
\ No newline at end of file
diff --git a/src/main/java/com/xingzi/ecore/Util/Utils.java b/src/main/java/com/xingzi/ecore/Util/Utils.java
new file mode 100644
index 0000000..3773c78
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Util/Utils.java
@@ -0,0 +1,46 @@
+package com.xingzi.ecore.Util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.alibaba.fastjson.JSON;
+
+public class Utils {
+
+ public static String success() {
+ return "{\"success\":true,\"message\":\"ok\"}";
+ }
+
+ public static String success(String message) {
+ return String.format("{\"success\":true,\"message\":\"%s\"}", message);
+ }
+
+ static String success(String message, Object data) {
+ return String.format("{\"success\":true,\"message\":\"%s\",\"data\":%s}", message, JSON.toJSONString(data));
+ }
+
+ public static String success(String message, Object data, String key) {
+ return String.format("{\"success\":true,\"message\":\"%s\",\"%s\":%s}", message, key, JSON.toJSONString(data));
+ }
+
+ static String failure() {
+ return "{\"success\":false,\"message\":\"failed\"}";
+ }
+
+ public static String failure(String message) {
+ Map map = new HashMap<>();
+ map.put("success", false);
+ map.put("message", message);
+ return JSON.toJSONString(map);
+ }
+
+ static String failure(String message, Object data) {
+ return String.format("{\"success\":false,\"message\":\"%s\",\"data\":%s}", message,
+ JSON.toJSONString(data));
+ }
+
+ static String failure(String message, Object data, String key) {
+ return String.format("{\"success\":false,\"message\":\"%s\",\"$s\":%s}", message, key,
+ JSON.toJSONString(data));
+ }
+}
diff --git a/src/main/java/com/xingzi/ecore/Wrapper/RequestWrapper.java b/src/main/java/com/xingzi/ecore/Wrapper/RequestWrapper.java
new file mode 100644
index 0000000..429a462
--- /dev/null
+++ b/src/main/java/com/xingzi/ecore/Wrapper/RequestWrapper.java
@@ -0,0 +1,78 @@
+package com.xingzi.ecore.Wrapper;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+public class RequestWrapper extends HttpServletRequestWrapper {
+
+ private String body = "";
+
+ public RequestWrapper(HttpServletRequest request) throws IOException {
+ super(request);
+
+ String contentType = request.getContentType();
+ if (contentType != null && contentType.equals("application/json")) {
+ InputStream inputStream = null;
+ try {
+ inputStream = request.getInputStream();
+ if (inputStream.available() != 0) {
+ byte[] data = inputStream.readAllBytes();
+ body = new String(data);
+ inputStream.close();
+ }
+ } catch (IOException exception) {
+ System.out.println("io error: ");
+ System.err.println(exception);
+ }
+ }
+
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ InputStream bodyStream = new ByteArrayInputStream(body.getBytes());
+
+ return new ServletInputStream() {
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener listener) {
+
+ }
+
+ @Override
+ public int read() throws IOException {
+ return bodyStream.read();
+ }
+
+ };
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ public String getBody() {
+ return this.body;
+ }
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..0f0e860
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,16 @@
+# mysql
+spring.jpa.hibernate.ddl-auto=update
+spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/ecore?charactorEncoding=utf8mb4 &
+autoReconnect=true &
+serverTimeZone=Asia/Shanghai
+spring.datasource.username=liuniu
+spring.datasource.password=Lnkj2022
+# spring.datasource.username=xingzi
+# spring.datasource.password=root
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.jpa.show-sql=true
+spring.jpa.properties.hibernate.format_sql=true
+logging.level.org.hibernate.SQL=DEBUG
+logging.level.org.hibernate.type=TRACE
+logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
+server.port=8081
diff --git a/src/test/java/com/xingzi/ecore/EcoreApplicationTests.java b/src/test/java/com/xingzi/ecore/EcoreApplicationTests.java
new file mode 100644
index 0000000..9d8df2c
--- /dev/null
+++ b/src/test/java/com/xingzi/ecore/EcoreApplicationTests.java
@@ -0,0 +1,13 @@
+package com.xingzi.ecore;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class EcoreApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}