first init

This commit is contained in:
liyupi 2022-06-29 23:31:32 +08:00
commit a63e4cbc55
29 changed files with 1779 additions and 0 deletions

33
.gitignore vendored Normal file
View File

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

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# SpringBoot 项目初始模板
> by [程序员鱼皮知识星球](https://yupi.icu)
Java SpringBoot 项目初始模板,整合了常用框架和示例代码,大家可以在此基础上快速开发自己的项目。
## 模板功能
- Spring Boot
- Spring MVC
- MySQL 驱动
- MyBatis
- MyBatis Plus
- Spring Session Redis 分布式登录
- Spring AOP
- Apache Commons Lang3 工具类
- Lombok 注解
- Swagger + Knife4j 接口文档
- Spring Boot 调试工具和项目处理器
- 全局请求响应拦截器(记录日志)
- 示例用户注册、登录、搜索功能
- 示例单元测试类
- 示例 SQL用户表

7
doc/db.md Normal file
View File

@ -0,0 +1,7 @@
# 数据库设计
> 建表语句见 `sql/ddl.sql` 文件
## 用户信息表

316
mvnw vendored Normal file
View File

@ -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 "$@"

188
mvnw.cmd vendored Normal file
View File

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

117
pom.xml Normal file
View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yupi</groupId>
<artifactId>springboot-init</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-init</name>
<description>springboot 初始项目</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- https://doc.xiaominfo.com/knife4j/documentation/get_start.html-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

24
sql/ddl.sql Normal file
View File

@ -0,0 +1,24 @@
# 第一次执行
create database my_db;
use my_db;
# 用户表
create table user
(
id bigint auto_increment comment 'id' primary key,
username varchar(256) null comment '用户昵称',
userAccount varchar(256) null comment '账号',
avatarUrl varchar(1024) null comment '用户头像',
gender tinyint null comment '性别',
userPassword varchar(512) not null comment '密码',
phone varchar(128) null comment '电话',
email varchar(512) null comment '邮箱',
userStatus int default 0 not null comment '状态 0 - 正常',
createTime datetime default CURRENT_TIMESTAMP comment '创建时间',
updateTime datetime default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
isDelete tinyint default 0 not null comment '是否删除',
userRole int default 0 not null comment '用户角色 0 - 普通用户 1 - 管理员'
) comment '用户';

View File

@ -0,0 +1,15 @@
package com.yupi.project;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.yupi.project.mapper")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

View File

@ -0,0 +1,54 @@
package com.yupi.project.aop;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 请求 AOP
*
* @author yupi
**/
@Aspect
@Component
@Slf4j
public class RequestInterceptor {
/**
* 请求响应日志
*/
@Around("execution(* com.yupi.project.controller.*.*(..))")
public Object logInterceptor(ProceedingJoinPoint point) throws Throwable {
// count time
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// get request path
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
// traceId
String requestId = UUID.randomUUID().toString();
String url = httpServletRequest.getRequestURI();
// get request params
Object[] args = point.getArgs();
String reqParam = "[" + StringUtils.join(args, ", ") + "]";
log.info("request startid: {}, path: {}, ip: {}, params: {}", requestId, url,
httpServletRequest.getRemoteHost(), reqParam);
// get response
Object result = point.proceed();
stopWatch.stop();
long totalTimeMillis = stopWatch.getTotalTimeMillis();
log.info("request end, id: {}, cost: {}ms", requestId, totalTimeMillis);
return result;
}
}

View File

@ -0,0 +1,42 @@
package com.yupi.project.common;
import lombok.Data;
import java.io.Serializable;
/**
* 通用返回类
*
* @param <T>
* @author yupi
*/
@Data
public class BaseResponse<T> implements Serializable {
private int code;
private T data;
private String message;
private String description;
public BaseResponse(int code, T data, String message, String description) {
this.code = code;
this.data = data;
this.message = message;
this.description = description;
}
public BaseResponse(int code, T data, String message) {
this(code, data, message, "");
}
public BaseResponse(int code, T data) {
this(code, data, "", "");
}
public BaseResponse(ErrorCode errorCode) {
this(errorCode.getCode(), null, errorCode.getMessage(), errorCode.getDescription());
}
}

View File

@ -0,0 +1,49 @@
package com.yupi.project.common;
/**
* 错误码
*
* @author yupi
*/
public enum ErrorCode {
SUCCESS(0, "ok", ""),
PARAMS_ERROR(40000, "请求参数错误", ""),
NULL_ERROR(40001, "请求数据为空", ""),
NOT_LOGIN(40100, "未登录", ""),
NO_AUTH(40101, "无权限", ""),
SYSTEM_ERROR(50000, "系统内部异常", ""),
SAVE_ERROR(50010, "新增失败", ""),
UPDATE_ERROR(50020, "更新失败", ""),
DELETE_ERROR(50030, "删除失败", "");
private final int code;
/**
* 状态码信息
*/
private final String message;
/**
* 状态码描述详情
*/
private final String description;
ErrorCode(int code, String message, String description) {
this.code = code;
this.message = message;
this.description = description;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public String getDescription() {
return description;
}
}

View File

@ -0,0 +1,62 @@
package com.yupi.project.common;
/**
* 返回工具类
*
* @author yupi
*/
public class ResultUtils {
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> success(T data) {
return new BaseResponse<>(0, data, "ok");
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode) {
return new BaseResponse<>(errorCode);
}
/**
* 失败
*
* @param code
* @param message
* @param description
* @return
*/
public static BaseResponse error(int code, String message, String description) {
return new BaseResponse(code, null, message, description);
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode, String message, String description) {
return new BaseResponse(errorCode.getCode(), null, message, description);
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode, String description) {
return new BaseResponse(errorCode.getCode(), errorCode.getMessage(), description);
}
}

View File

@ -0,0 +1,41 @@
package com.yupi.project.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Knife4j 接口文档配置
*
* https://doc.xiaominfo.com/knife4j/documentation/get_start.html
*
* @author yupi
*/
@Configuration
@EnableSwagger2
public class Knife4jConfiguration {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("springboot-init")
.description("springboot-init")
.termsOfServiceUrl("https://github.com/liyupi")
.contact(new Contact("yupi", "https://github.com/liyupi", "592789970@qq.com"))
.version("1.0")
.build())
.groupName("2.X版本")
.select()
// 这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.yupi.project.controller"))
.paths(PathSelectors.any())
.build();
}
}

View File

@ -0,0 +1,23 @@
package com.yupi.project.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.yupi.project.mapper")
public class MybatisPlusConfig {
/**
* 新的分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@ -0,0 +1,27 @@
package com.yupi.project.constant;
/**
* 用户常量
*
* @author yupi
*/
public interface UserConstant {
/**
* 用户登录态键
*/
String USER_LOGIN_STATE = "userLoginState";
// ------- 权限 --------
/**
* 默认权限
*/
int DEFAULT_ROLE = 0;
/**
* 管理员权限
*/
int ADMIN_ROLE = 1;
}

View File

@ -0,0 +1,104 @@
package com.yupi.project.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yupi.project.common.BaseResponse;
import com.yupi.project.common.ErrorCode;
import com.yupi.project.common.ResultUtils;
import com.yupi.project.exception.BusinessException;
import com.yupi.project.model.entity.User;
import com.yupi.project.model.request.UserLoginRequest;
import com.yupi.project.model.request.UserRegisterRequest;
import com.yupi.project.service.UserService;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
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.RestController;
/**
* 用户接口
*
* @author yupi
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@PostMapping("/register")
public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
if (userRegisterRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
String userAccount = userRegisterRequest.getUserAccount();
String userPassword = userRegisterRequest.getUserPassword();
String checkPassword = userRegisterRequest.getCheckPassword();
if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
return null;
}
long result = userService.userRegister(userAccount, userPassword, checkPassword);
return ResultUtils.success(result);
}
@PostMapping("/login")
public BaseResponse<User> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
if (userLoginRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
String userAccount = userLoginRequest.getUserAccount();
String userPassword = userLoginRequest.getUserPassword();
if (StringUtils.isAnyBlank(userAccount, userPassword)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User user = userService.userLogin(userAccount, userPassword, request);
return ResultUtils.success(user);
}
@PostMapping("/logout")
public BaseResponse<Integer> userLogout(HttpServletRequest request) {
if (request == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
int result = userService.userLogout(request);
return ResultUtils.success(result);
}
@GetMapping("/current")
public BaseResponse<User> getCurrentUser(HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
long userId = loginUser.getId();
User user = userService.getById(userId);
User safetyUser = userService.getSafetyUser(user);
return ResultUtils.success(safetyUser);
}
@GetMapping("/search")
public BaseResponse<List<User>> searchUser(String username, HttpServletRequest request) {
userService.assertAdmin(request);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(username)) {
queryWrapper.like("username", username);
}
List<User> userList = userService.list(queryWrapper);
List<User> list = userList.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList());
return ResultUtils.success(list);
}
@PostMapping("/delete")
public BaseResponse<Boolean> deleteUser(@RequestBody long id, HttpServletRequest request) {
userService.assertAdmin(request);
if (id <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
boolean b = userService.removeById(id);
return ResultUtils.success(b);
}
}

View File

@ -0,0 +1,41 @@
package com.yupi.project.exception;
import com.yupi.project.common.ErrorCode;
/**
* 自定义异常类
*
* @author yupi
*/
public class BusinessException extends RuntimeException {
private final int code;
private final String description;
public BusinessException(String message, int code, String description) {
super(message);
this.code = code;
this.description = description;
}
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
this.description = errorCode.getDescription();
}
public BusinessException(ErrorCode errorCode, String description) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}

View File

@ -0,0 +1,30 @@
package com.yupi.project.exception;
import com.yupi.project.common.BaseResponse;
import com.yupi.project.common.ErrorCode;
import com.yupi.project.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*
* @author yupi
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public BaseResponse businessExceptionHandler(BusinessException e) {
log.error("businessException: " + e.getMessage(), e);
return ResultUtils.error(e.getCode(), e.getMessage(), e.getDescription());
}
@ExceptionHandler(RuntimeException.class)
public BaseResponse runtimeExceptionHandler(RuntimeException e) {
log.error("runtimeException", e);
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage(), "");
}
}

View File

@ -0,0 +1,15 @@
package com.yupi.project.mapper;
import com.yupi.project.model.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* UserMapper
*/
public interface UserMapper extends BaseMapper<User> {
}

View File

@ -0,0 +1,90 @@
package com.yupi.project.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* 用户
*
* @TableName user
*/
@TableName(value = "user")
@Data
public class User implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 用户昵称
*/
private String username;
/**
* 账号
*/
private String userAccount;
/**
* 用户头像
*/
private String avatarUrl;
/**
* 性别
*/
private Integer gender;
/**
* 密码
*/
private String userPassword;
/**
* 电话
*/
private String phone;
/**
* 邮箱
*/
private String email;
/**
* 状态 0 - 正常
*/
private Integer userStatus;
/**
* 创建时间
*/
private Date createTime;
/**
*
*/
private Date updateTime;
/**
* 是否删除
*/
@TableLogic
private Integer isDelete;
/**
* 用户角色 0 - 普通用户 1 - 管理员
*/
private Integer userRole;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,20 @@
package com.yupi.project.model.request;
import lombok.Data;
import java.io.Serializable;
/**
* 用户登录请求体
*
* @author yupi
*/
@Data
public class UserLoginRequest implements Serializable {
private static final long serialVersionUID = 3191241716373120793L;
private String userAccount;
private String userPassword;
}

View File

@ -0,0 +1,21 @@
package com.yupi.project.model.request;
import java.io.Serializable;
import lombok.Data;
/**
* 用户注册请求体
*
* @author yupi
*/
@Data
public class UserRegisterRequest implements Serializable {
private static final long serialVersionUID = 3191241716373120793L;
private String userAccount;
private String userPassword;
private String checkPassword;
}

View File

@ -0,0 +1,81 @@
package com.yupi.project.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yupi.project.model.entity.User;
import javax.servlet.http.HttpServletRequest;
/**
* 用户服务
*
* @author yupi
*/
public interface UserService extends IService<User> {
/**
* 用户注册
*
* @param userAccount 用户账户
* @param userPassword 用户密码
* @param checkPassword 校验密码
* @return 新用户 id
*/
long userRegister(String userAccount, String userPassword, String checkPassword);
/**
* 用户登录
*
* @param userAccount 用户账户
* @param userPassword 用户密码
* @param request
* @return 脱敏后的用户信息
*/
User userLogin(String userAccount, String userPassword, HttpServletRequest request);
/**
* 用户脱敏
*
* @param originUser
* @return
*/
User getSafetyUser(User originUser);
/**
* 用户注销
*
* @param request
* @return
*/
int userLogout(HttpServletRequest request);
/**
* 是否为管理员
*
* @param request
* @return
*/
boolean isAdmin(HttpServletRequest request);
/**
* 是否为管理员
*
* @param user
* @return
*/
boolean isAdmin(User user);
/**
* 断言是管理员
*
* @param request
*/
void assertAdmin(HttpServletRequest request);
/**
* 获取登录用户查缓存
*
* @param request
* @return
* @throws com.yupi.project.exception.BusinessException 未登录则抛异常
*/
User getLoginUser(HttpServletRequest request);
}

View File

@ -0,0 +1,189 @@
package com.yupi.project.service.impl;
import static com.yupi.project.constant.UserConstant.USER_LOGIN_STATE;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.project.common.ErrorCode;
import com.yupi.project.constant.UserConstant;
import com.yupi.project.exception.BusinessException;
import com.yupi.project.mapper.UserMapper;
import com.yupi.project.model.entity.User;
import com.yupi.project.service.UserService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
/**
* 用户服务实现类
*
* @author yupi
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
implements UserService {
@Resource
private UserMapper userMapper;
/**
* 盐值混淆密码
*/
private static final String SALT = "yupi";
@Override
public long userRegister(String userAccount, String userPassword, String checkPassword) {
// 1. 校验
if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
}
if (userAccount.length() < 4) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");
}
if (userPassword.length() < 8 || checkPassword.length() < 8) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
}
// 账户不能包含特殊字符
String validPattern = "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
if (matcher.find()) {
return -1;
}
// 密码和校验密码相同
if (!userPassword.equals(checkPassword)) {
return -1;
}
// 账户不能重复
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("userAccount", userAccount);
long count = userMapper.selectCount(queryWrapper);
if (count > 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
}
// 2. 加密
String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
// 3. 插入数据
User user = new User();
user.setUserAccount(userAccount);
user.setUserPassword(encryptPassword);
boolean saveResult = this.save(user);
if (!saveResult) {
return -1;
}
return user.getId();
}
@Override
public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {
// 1. 校验
if (StringUtils.isAnyBlank(userAccount, userPassword)) {
return null;
}
if (userAccount.length() < 4) {
return null;
}
if (userPassword.length() < 8) {
return null;
}
// 账户不能包含特殊字符
String validPattern = "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
if (matcher.find()) {
return null;
}
// 2. 加密
String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
// 查询用户是否存在
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("userAccount", userAccount);
queryWrapper.eq("userPassword", encryptPassword);
User user = userMapper.selectOne(queryWrapper);
// 用户不存在
if (user == null) {
log.info("user login failed, userAccount cannot match userPassword");
return null;
}
// 3. 用户脱敏
User safetyUser = getSafetyUser(user);
// 4. 记录用户的登录态
request.getSession().setAttribute(USER_LOGIN_STATE, safetyUser);
return safetyUser;
}
/**
* 用户脱敏
*
* @param originUser
* @return
*/
@Override
public User getSafetyUser(User originUser) {
if (originUser == null) {
return null;
}
User safetyUser = new User();
safetyUser.setId(originUser.getId());
safetyUser.setUsername(originUser.getUsername());
safetyUser.setUserAccount(originUser.getUserAccount());
safetyUser.setAvatarUrl(originUser.getAvatarUrl());
safetyUser.setGender(originUser.getGender());
safetyUser.setPhone(originUser.getPhone());
safetyUser.setEmail(originUser.getEmail());
safetyUser.setUserRole(originUser.getUserRole());
safetyUser.setUserStatus(originUser.getUserStatus());
safetyUser.setCreateTime(originUser.getCreateTime());
return safetyUser;
}
/**
* 用户注销
*
* @param request
*/
@Override
public int userLogout(HttpServletRequest request) {
// 移除登录态
request.getSession().removeAttribute(USER_LOGIN_STATE);
return 1;
}
@Override
public boolean isAdmin(HttpServletRequest request) {
Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
User user = (User) userObj;
return user != null && user.getUserRole() == UserConstant.ADMIN_ROLE;
}
@Override
public boolean isAdmin(User user) {
return user != null && user.getUserRole() == UserConstant.ADMIN_ROLE;
}
@Override
public void assertAdmin(HttpServletRequest request) {
if (!isAdmin(request)) {
throw new BusinessException(ErrorCode.NO_AUTH);
}
}
@Override
public User getLoginUser(HttpServletRequest request) {
Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
User loginUser = (User) userObj;
if (loginUser == null) {
throw new BusinessException(ErrorCode.NOT_LOGIN);
}
return loginUser;
}
}

View File

@ -0,0 +1,6 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db
username: root
password: 123456

View File

@ -0,0 +1,34 @@
spring:
application:
name: springboot-init
# DataSource Config
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db
username: root
password: 123456
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
# session 失效时间(分钟)
session:
timeout: 86400
store-type: redis
# redis 配置
redis:
port: 6379
host: localhost
database: 0
server:
port: 7529
servlet:
context-path: /api
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: isDelete # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

View File

@ -0,0 +1 @@
我的项目 by 程序员鱼皮 https://github.com/liyupi

View File

@ -0,0 +1,30 @@
<?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.yupi.project.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.yupi.project.model.entity.User">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="userAccount" column="userAccount" jdbcType="VARCHAR"/>
<result property="avatarUrl" column="avatarUrl" jdbcType="VARCHAR"/>
<result property="gender" column="gender" jdbcType="TINYINT"/>
<result property="userPassword" column="userPassword" jdbcType="VARCHAR"/>
<result property="phone" column="phone" jdbcType="VARCHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="userStatus" column="userStatus" jdbcType="INTEGER"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
<result property="userRole" column="userRole" jdbcType="INTEGER"/>
</resultMap>
<sql id="Base_Column_List">
id,username,userAccount,
avatarUrl,gender,userPassword,
phone,email,userStatus,
createTime,updateTime,isDelete,
userRole
</sql>
</mapper>

View File

@ -0,0 +1,96 @@
package com.yupi.project.service;
import com.yupi.project.model.entity.User;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
/**
* 用户服务测试
*
* @author yupi
*/
@SpringBootTest
class UserServiceTest {
@Resource
private UserService userService;
@Test
void testAddUser() {
User user = new User();
user.setUsername("dogYupi");
user.setUserAccount("123");
user.setAvatarUrl("");
user.setGender(0);
user.setUserPassword("xxx");
user.setPhone("123");
user.setEmail("456");
boolean result = userService.save(user);
System.out.println(user.getId());
Assertions.assertTrue(result);
}
@Test
void testUpdateUser() {
User user = new User();
user.setId(1);
user.setUsername("dogYupi");
user.setUserAccount("123");
user.setAvatarUrl("");
user.setGender(0);
user.setUserPassword("xxx");
user.setPhone("123");
user.setEmail("456");
boolean result = userService.updateById(user);
Assertions.assertTrue(result);
}
@Test
void testDeleteUser() {
boolean result = userService.removeById(1L);
Assertions.assertTrue(result);
}
@Test
void testGetUser() {
User user = userService.getById(1L);
Assertions.assertNotNull(user);
}
@Test
void userRegister() {
String userAccount = "yupi";
String userPassword = "";
String checkPassword = "123456";
try {
long result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
userAccount = "yu";
result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
userAccount = "yupi";
userPassword = "123456";
result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
userAccount = "yu pi";
userPassword = "12345678";
result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
checkPassword = "123456789";
result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
userAccount = "dogYupi";
checkPassword = "12345678";
result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
userAccount = "yupi";
result = userService.userRegister(userAccount, userPassword, checkPassword);
Assertions.assertEquals(-1, result);
} catch (Exception e) {
}
}
}