搭建后台框架
This commit is contained in:
parent
84cdc2a983
commit
142150c907
51
.gitignore
vendored
51
.gitignore
vendored
@ -1,26 +1,33 @@
|
|||||||
# ---> Java
|
HELP.md
|
||||||
# Compiled class file
|
target/
|
||||||
*.class
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
# Log file
|
### STS ###
|
||||||
*.log
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
# BlueJ files
|
### IntelliJ IDEA ###
|
||||||
*.ctxt
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
# Mobile Tools for Java (J2ME)
|
### NetBeans ###
|
||||||
.mtj.tmp/
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
# Package Files #
|
/dist/
|
||||||
*.jar
|
/nbdist/
|
||||||
*.war
|
/.nb-gradle/
|
||||||
*.nar
|
build/
|
||||||
*.ear
|
!**/src/main/**/build/
|
||||||
*.zip
|
!**/src/test/**/build/
|
||||||
*.tar.gz
|
|
||||||
*.rar
|
|
||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
|
||||||
hs_err_pid*
|
|
||||||
replay_pid*
|
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
119
pom.xml
Normal file
119
pom.xml
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
<?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>3.5.0</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>com.api</groupId>
|
||||||
|
<artifactId>java-master</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>demo</name>
|
||||||
|
<description>管理系统</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<druid.version>1.2.21</druid.version>
|
||||||
|
<mybatisplus.version>3.5.5</mybatisplus.version>
|
||||||
|
<mybatis.spring>3.0.3</mybatis.spring>
|
||||||
|
<sqlserver.version>4.0</sqlserver.version>
|
||||||
|
<oracle.version>11.2.0.3</oracle.version>
|
||||||
|
<dameng.version>8.1.2.141</dameng.version>
|
||||||
|
<hutool.version>5.8.29</hutool.version>
|
||||||
|
<jsoup.version>1.15.3</jsoup.version>
|
||||||
|
<knife4j.version>4.5.0</knife4j.version>
|
||||||
|
<lombok.version>1.18.24</lombok.version>
|
||||||
|
<javax.servlet.version>4.0.1</javax.servlet.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- mysql驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||||
|
<version>${druid.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>${mybatisplus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis-spring</artifactId>
|
||||||
|
<version>${mybatis.spring}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jsoup</groupId>
|
||||||
|
<artifactId>jsoup</artifactId>
|
||||||
|
<version>${jsoup.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
|
<version>${knife4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>public</id>
|
||||||
|
<name>aliyun nexus</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>public</id>
|
||||||
|
<name>aliyun nexus</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
12
src/main/java/io/Application.java
Normal file
12
src/main/java/io/Application.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package io;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
src/main/java/io/common/annotation/Login.java
Normal file
12
src/main/java/io/common/annotation/Login.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package io.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录效验
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface Login {
|
||||||
|
}
|
19
src/main/java/io/common/annotation/LoginUser.java
Normal file
19
src/main/java/io/common/annotation/LoginUser.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
package io.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户信息
|
||||||
|
*
|
||||||
|
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface LoginUser {
|
||||||
|
|
||||||
|
}
|
18
src/main/java/io/common/exception/ErrorCode.java
Normal file
18
src/main/java/io/common/exception/ErrorCode.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package io.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误编码,由5位数字组成,前2位为模块编码,后3位为业务编码
|
||||||
|
* <p>
|
||||||
|
* 如:10001(10代表系统模块,001代表业务代码)
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface ErrorCode {
|
||||||
|
int INTERNAL_SERVER_ERROR = 500;
|
||||||
|
int UNAUTHORIZED = 401;
|
||||||
|
int NOT_NULL = 500;
|
||||||
|
|
||||||
|
int ACCOUNT_PASSWORD_ERROR = 10004;
|
||||||
|
|
||||||
|
int IDENTIFIER_NOT_NULL = 10006;
|
||||||
|
|
||||||
|
}
|
43
src/main/java/io/common/exception/ExceptionUtils.java
Normal file
43
src/main/java/io/common/exception/ExceptionUtils.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package io.common.exception;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception工具类
|
||||||
|
*/
|
||||||
|
public class ExceptionUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取异常信息
|
||||||
|
* @param ex 异常
|
||||||
|
* @return 返回异常信息
|
||||||
|
*/
|
||||||
|
public static String getErrorStackTrace(Exception ex){
|
||||||
|
StringWriter sw = null;
|
||||||
|
PrintWriter pw = null;
|
||||||
|
try {
|
||||||
|
sw = new StringWriter();
|
||||||
|
pw = new PrintWriter(sw, true);
|
||||||
|
ex.printStackTrace(pw);
|
||||||
|
}finally {
|
||||||
|
try {
|
||||||
|
if(pw != null) {
|
||||||
|
pw.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if(sw != null) {
|
||||||
|
sw.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
}
|
46
src/main/java/io/common/exception/RenException.java
Normal file
46
src/main/java/io/common/exception/RenException.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package io.common.exception;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义异常
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RenException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
public RenException(int code, String... params) {
|
||||||
|
this.code = code;
|
||||||
|
this.msg = Arrays.toString(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
this.code = 500;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenException(String msg, Throwable e) {
|
||||||
|
super(msg, e);
|
||||||
|
this.code = 400;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
public void setCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
src/main/java/io/common/exception/RenExceptionHandler.java
Normal file
41
src/main/java/io/common/exception/RenExceptionHandler.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package io.common.exception;
|
||||||
|
|
||||||
|
import io.common.utils.Result;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理器
|
||||||
|
*/
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class RenExceptionHandler {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RenExceptionHandler.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理自定义异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(RenException.class)
|
||||||
|
public Result handleRenException(RenException ex){
|
||||||
|
Result result = new Result();
|
||||||
|
result.error(ex.getCode(), ex.getMsg());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(DuplicateKeyException.class)
|
||||||
|
public Result handleDuplicateKeyException(DuplicateKeyException ex){
|
||||||
|
Result result = new Result();
|
||||||
|
result.error("数据库中已存在该记录!");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public Result handleException(Exception ex){
|
||||||
|
logger.error(ex.getMessage(), ex);
|
||||||
|
|
||||||
|
return new Result().error(ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package io.common.interceptor;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import io.common.annotation.Login;
|
||||||
|
import io.common.exception.RenException;
|
||||||
|
import io.entity.TokenEntity;
|
||||||
|
import io.service.TokenService;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
/**
|
||||||
|
* 权限(Token)验证
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AuthorizationInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
public static final String USER_KEY = "userId";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
|
||||||
|
Login annotation;
|
||||||
|
if (handler instanceof HandlerMethod) {
|
||||||
|
annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (annotation == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//从header中获取token
|
||||||
|
String token = request.getHeader("Authorization");
|
||||||
|
//如果header中不存在token,则从参数中获取token
|
||||||
|
if (StrUtil.isBlank(token)) {
|
||||||
|
token = request.getParameter("Authorization");
|
||||||
|
}
|
||||||
|
//token为空
|
||||||
|
if (StrUtil.isBlank(token)) {
|
||||||
|
throw new RenException(401,"登录失效");
|
||||||
|
}
|
||||||
|
//查询token信息
|
||||||
|
TokenEntity tokenEntity = tokenService.getByToken(token);
|
||||||
|
if (tokenEntity == null || tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()) {
|
||||||
|
throw new RenException(401,"登录失效");
|
||||||
|
}
|
||||||
|
//设置userId到request里,后续根据userId,获取用户信息
|
||||||
|
request.setAttribute(USER_KEY, tokenEntity.getUserId());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package io.common.resolver;
|
||||||
|
|
||||||
|
import io.common.annotation.LoginUser;
|
||||||
|
import io.common.interceptor.AuthorizationInterceptor;
|
||||||
|
import io.entity.UserEntity;
|
||||||
|
import io.service.UserService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||||
|
import org.springframework.web.context.request.NativeWebRequest;
|
||||||
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
|
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 有@LoginUser注解的方法参数,注入当前登录用户
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsParameter(MethodParameter parameter) {
|
||||||
|
return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
|
||||||
|
NativeWebRequest request, WebDataBinderFactory factory){
|
||||||
|
//获取用户ID
|
||||||
|
Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
|
||||||
|
|
||||||
|
if (object == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取用户信息
|
||||||
|
UserEntity user = userService.getUserByUserId((Long) object);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
54
src/main/java/io/common/utils/DateUtils.java
Normal file
54
src/main/java/io/common/utils/DateUtils.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package io.common.utils;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期处理
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DateUtils {
|
||||||
|
/** 时间格式(yyyy-MM-dd) */
|
||||||
|
public final static String DATE_PATTERN = "yyyy-MM-dd";
|
||||||
|
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
|
||||||
|
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期格式化 日期格式为:yyyy-MM-dd
|
||||||
|
* @param date 日期
|
||||||
|
* @return 返回yyyy-MM-dd格式日期
|
||||||
|
*/
|
||||||
|
public static String format(Date date) {
|
||||||
|
return format(date, DATE_PATTERN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期格式化 日期格式为:yyyy-MM-dd
|
||||||
|
* @param date 日期
|
||||||
|
* @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
|
||||||
|
* @return 返回yyyy-MM-dd格式日期
|
||||||
|
*/
|
||||||
|
public static String format(Date date, String pattern) {
|
||||||
|
if (date != null) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat(pattern);
|
||||||
|
return df.format(date);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期解析
|
||||||
|
* @param date 日期
|
||||||
|
* @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
|
||||||
|
* @return 返回Date
|
||||||
|
*/
|
||||||
|
public static Date parse(String date, String pattern) {
|
||||||
|
try {
|
||||||
|
return new SimpleDateFormat(pattern).parse(date);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
75
src/main/java/io/common/utils/Result.java
Normal file
75
src/main/java/io/common/utils/Result.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package io.common.utils;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应数据
|
||||||
|
*
|
||||||
|
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
@Schema(title = "响应")
|
||||||
|
public class Result<T> implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 编码:0表示成功,其他值表示失败
|
||||||
|
*/
|
||||||
|
@Schema(title = "编码:0表示成功,其他值表示失败")
|
||||||
|
private int code = 0;
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
@Schema(title = "消息内容")
|
||||||
|
private String msg = "success";
|
||||||
|
/**
|
||||||
|
* 响应数据
|
||||||
|
*/
|
||||||
|
@Schema(title = "响应数据")
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
public Result<T> ok(T data) {
|
||||||
|
this.setData(data);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public boolean success(){
|
||||||
|
return code == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<T> error(int code, String msg) {
|
||||||
|
this.code = code;
|
||||||
|
this.msg = msg;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<T> error(String msg) {
|
||||||
|
this.code = 500;
|
||||||
|
this.msg = msg;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(T data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
}
|
92
src/main/java/io/common/validator/AssertUtils.java
Normal file
92
src/main/java/io/common/validator/AssertUtils.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package io.common.validator;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
|
||||||
|
import io.common.exception.ErrorCode;
|
||||||
|
import io.common.exception.RenException;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验工具类
|
||||||
|
*
|
||||||
|
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class AssertUtils {
|
||||||
|
|
||||||
|
public static void isBlank(String str, String... params) {
|
||||||
|
isBlank(str, ErrorCode.NOT_NULL, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isBlank(String str, Integer code, String... params) {
|
||||||
|
if(code == null){
|
||||||
|
throw new RenException(ErrorCode.NOT_NULL, "code");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(str)) {
|
||||||
|
throw new RenException(code, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isNull(Object object, String... params) {
|
||||||
|
isNull(object, ErrorCode.NOT_NULL, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isNull(Object object, Integer code, String... params) {
|
||||||
|
if(code == null){
|
||||||
|
throw new RenException(ErrorCode.NOT_NULL, "code");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object == null) {
|
||||||
|
throw new RenException(code, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isArrayEmpty(Object[] array, String... params) {
|
||||||
|
isArrayEmpty(array, ErrorCode.NOT_NULL, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isArrayEmpty(Object[] array, Integer code, String... params) {
|
||||||
|
if(code == null){
|
||||||
|
throw new RenException(ErrorCode.NOT_NULL, "code");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ArrayUtil.isEmpty(array)){
|
||||||
|
throw new RenException(code, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isListEmpty(List<?> list, String... params) {
|
||||||
|
isListEmpty(list, ErrorCode.NOT_NULL, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isListEmpty(List<?> list, Integer code, String... params) {
|
||||||
|
if(code == null){
|
||||||
|
throw new RenException(ErrorCode.NOT_NULL, "code");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(CollUtil.isEmpty(list)){
|
||||||
|
throw new RenException(code, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isMapEmpty(Map map, String... params) {
|
||||||
|
isMapEmpty(map, ErrorCode.NOT_NULL, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isMapEmpty(Map map, Integer code, String... params) {
|
||||||
|
if(code == null){
|
||||||
|
throw new RenException(ErrorCode.NOT_NULL, "code");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MapUtil.isEmpty(map)){
|
||||||
|
throw new RenException(code, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/main/java/io/config/MybatisPlusConfig.java
Normal file
21
src/main/java/io/config/MybatisPlusConfig.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package io.config;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.DbType;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class MybatisPlusConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新的分页插件配置方式
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||||
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||||
|
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||||
|
return interceptor;
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/io/config/ResourceConfig.java
Normal file
18
src/main/java/io/config/ResourceConfig.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package io.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ResourceConfig implements WebMvcConfigurer {
|
||||||
|
@Value("${spring.web.resources.static-locations}")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
|
registry.addResourceHandler("/upload/**")
|
||||||
|
.addResourceLocations(path);
|
||||||
|
}
|
||||||
|
}
|
77
src/main/java/io/config/WebMvcConfig.java
Normal file
77
src/main/java/io/config/WebMvcConfig.java
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package io.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import io.common.interceptor.AuthorizationInterceptor;
|
||||||
|
import io.common.resolver.LoginUserHandlerMethodArgumentResolver;
|
||||||
|
import io.common.utils.DateUtils;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||||
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MVC配置
|
||||||
|
*
|
||||||
|
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
|
@Resource
|
||||||
|
private AuthorizationInterceptor authorizationInterceptor;
|
||||||
|
@Resource
|
||||||
|
private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(authorizationInterceptor).addPathPatterns("/api/**");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||||
|
argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||||
|
converters.add(new ByteArrayHttpMessageConverter());
|
||||||
|
converters.add(new StringHttpMessageConverter());
|
||||||
|
converters.add(new ResourceHttpMessageConverter());
|
||||||
|
converters.add(new AllEncompassingFormHttpMessageConverter());
|
||||||
|
converters.add(new StringHttpMessageConverter());
|
||||||
|
converters.add(jackson2HttpMessageConverter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
|
||||||
|
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
//日期格式转换
|
||||||
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
mapper.setDateFormat(new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN));
|
||||||
|
mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||||
|
|
||||||
|
//Long类型转String类型
|
||||||
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
|
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||||
|
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
||||||
|
mapper.registerModule(simpleModule);
|
||||||
|
|
||||||
|
converter.setObjectMapper(mapper);
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
}
|
85
src/main/java/io/controller/UserController.java
Normal file
85
src/main/java/io/controller/UserController.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package io.controller;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import io.common.annotation.Login;
|
||||||
|
import io.common.annotation.LoginUser;
|
||||||
|
import io.common.utils.Result;
|
||||||
|
import io.entity.UserEntity;
|
||||||
|
import io.service.UserService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import java.util.Map;
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/users")
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
// UserController.java 添加登录方法
|
||||||
|
@PostMapping("/login")
|
||||||
|
public Result login(@Valid @RequestBody UserEntity dto) {
|
||||||
|
//用户登录
|
||||||
|
Map<String, Object> map = userService.login(dto);
|
||||||
|
return new Result().ok(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// UserController.java 添加注册方法
|
||||||
|
@PostMapping("/register")
|
||||||
|
public Result register(@Valid @RequestBody UserEntity dto) {
|
||||||
|
// 检查用户名是否已存在
|
||||||
|
if (userService.existsUsername(dto.getUsername())) {
|
||||||
|
return new Result().error("用户名已存在");
|
||||||
|
}
|
||||||
|
// 密码加密
|
||||||
|
String sha256Hex = DigestUtil.sha256Hex(dto.getPassword());
|
||||||
|
UserEntity user = new UserEntity();
|
||||||
|
user.setPassword(sha256Hex);
|
||||||
|
user.setUsername(dto.getUsername());
|
||||||
|
user.setRole("USER"); // 默认启用
|
||||||
|
userService.save(user);
|
||||||
|
return new Result().ok("注册成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
public Page<UserEntity> page(@RequestParam(defaultValue = "1") Integer current,
|
||||||
|
@RequestParam(defaultValue = "10") Integer size) {
|
||||||
|
Page<UserEntity> page = new Page<>(current, size);
|
||||||
|
return userService.page(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Login
|
||||||
|
@GetMapping
|
||||||
|
public Result list(@Parameter(hidden = true) @RequestAttribute("userId") Long userId) {
|
||||||
|
System.out.println(userId);
|
||||||
|
return new Result().ok(userService.list()) ; // 查询所有用户
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public boolean save(@RequestBody UserEntity user) {
|
||||||
|
return userService.save(user); // 新增用户
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public boolean update(@RequestBody UserEntity user) {
|
||||||
|
return userService.updateById(user); // 更新用户
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public boolean delete(@PathVariable Long id) {
|
||||||
|
return userService.removeById(id); // 删除用户
|
||||||
|
}
|
||||||
|
|
||||||
|
@Login
|
||||||
|
@GetMapping("userInfo")
|
||||||
|
@Operation(summary = "获取用户信息")
|
||||||
|
public Result<UserEntity> userInfo(@Parameter(hidden = true) @LoginUser UserEntity user) {
|
||||||
|
return new Result<UserEntity>().ok(user);
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/io/dao/BaseDao.java
Normal file
10
src/main/java/io/dao/BaseDao.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package io.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础Dao
|
||||||
|
*/
|
||||||
|
public interface BaseDao<T> extends BaseMapper<T> {
|
||||||
|
|
||||||
|
}
|
18
src/main/java/io/dao/TokenDao.java
Normal file
18
src/main/java/io/dao/TokenDao.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
package io.dao;
|
||||||
|
|
||||||
|
import io.entity.TokenEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户Token
|
||||||
|
*
|
||||||
|
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface TokenDao extends BaseDao<TokenEntity> {
|
||||||
|
TokenEntity getByToken(String token);
|
||||||
|
|
||||||
|
TokenEntity getByUserId(Long userId);
|
||||||
|
}
|
13
src/main/java/io/dao/UserDao.java
Normal file
13
src/main/java/io/dao/UserDao.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package io.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import io.entity.UserEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface UserDao extends BaseMapper<UserEntity> {
|
||||||
|
|
||||||
|
}
|
36
src/main/java/io/entity/TokenEntity.java
Normal file
36
src/main/java/io/entity/TokenEntity.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package io.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户Token
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("tb_token")
|
||||||
|
public class TokenEntity implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
/**
|
||||||
|
* 用户token
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
/**
|
||||||
|
* 过期时间
|
||||||
|
*/
|
||||||
|
private Date expireDate;
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
private Date updateDate;
|
||||||
|
|
||||||
|
}
|
25
src/main/java/io/entity/UserEntity.java
Normal file
25
src/main/java/io/entity/UserEntity.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package io.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.Date;
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("tb_user")
|
||||||
|
public class UserEntity {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String role;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private Date createDate;
|
||||||
|
private String nickName;
|
||||||
|
private String tag;
|
||||||
|
private String avatar; // 头像URL
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String confirmPassword;
|
||||||
|
}
|
29
src/main/java/io/service/TokenService.java
Normal file
29
src/main/java/io/service/TokenService.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package io.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import io.entity.TokenEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户Token
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface TokenService extends IService<TokenEntity> {
|
||||||
|
|
||||||
|
TokenEntity getByToken(String token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成token
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 返回token信息
|
||||||
|
*/
|
||||||
|
TokenEntity createToken(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置token过期
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
*/
|
||||||
|
void expireToken(Long userId);
|
||||||
|
|
||||||
|
}
|
20
src/main/java/io/service/UserService.java
Normal file
20
src/main/java/io/service/UserService.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package io.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import io.entity.UserEntity;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface UserService extends IService<UserEntity> {
|
||||||
|
|
||||||
|
//通过用户编号或者用户详情
|
||||||
|
UserEntity getUserByUserId(Long userId);
|
||||||
|
|
||||||
|
//判断用户是否存在
|
||||||
|
boolean existsUsername(String username);
|
||||||
|
|
||||||
|
//通过用户名获取用户信息
|
||||||
|
UserEntity getByUsername(String username);
|
||||||
|
|
||||||
|
Map<String, Object> login(UserEntity dto);
|
||||||
|
}
|
81
src/main/java/io/service/impl/TokenServiceImpl.java
Normal file
81
src/main/java/io/service/impl/TokenServiceImpl.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package io.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import io.dao.TokenDao;
|
||||||
|
import io.entity.TokenEntity;
|
||||||
|
import io.service.TokenService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TokenServiceImpl extends ServiceImpl<TokenDao, TokenEntity> implements TokenService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TokenDao tokenDao;
|
||||||
|
/**
|
||||||
|
* 12小时后过期
|
||||||
|
*/
|
||||||
|
private final static int EXPIRE = 3600 * 12;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TokenEntity getByToken(String token) {
|
||||||
|
return baseMapper.getByToken(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TokenEntity createToken(Long userId) {
|
||||||
|
//当前时间
|
||||||
|
Date now = new Date();
|
||||||
|
//过期时间
|
||||||
|
Date expireTime = new Date(now.getTime() + EXPIRE * 1000);
|
||||||
|
|
||||||
|
//用户token
|
||||||
|
String token;
|
||||||
|
|
||||||
|
//判断是否生成过token
|
||||||
|
TokenEntity tokenEntity = baseMapper.getByUserId(userId);
|
||||||
|
if(tokenEntity == null){
|
||||||
|
//生成一个token
|
||||||
|
token = generateToken();
|
||||||
|
|
||||||
|
tokenEntity = new TokenEntity();
|
||||||
|
tokenEntity.setUserId(userId);
|
||||||
|
tokenEntity.setToken(token);
|
||||||
|
tokenEntity.setUpdateDate(now);
|
||||||
|
tokenEntity.setExpireDate(expireTime);
|
||||||
|
//保存token
|
||||||
|
baseMapper.insert(tokenEntity);
|
||||||
|
}else{
|
||||||
|
//判断token是否过期
|
||||||
|
if(tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()){
|
||||||
|
//token过期,重新生成token
|
||||||
|
token = generateToken();
|
||||||
|
}else {
|
||||||
|
token = tokenEntity.getToken();
|
||||||
|
}
|
||||||
|
tokenEntity.setToken(token);
|
||||||
|
tokenEntity.setUpdateDate(now);
|
||||||
|
tokenEntity.setExpireDate(expireTime);
|
||||||
|
//更新token
|
||||||
|
this.updateById(tokenEntity);
|
||||||
|
}
|
||||||
|
return tokenEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expireToken(Long userId){
|
||||||
|
Date now = new Date();
|
||||||
|
LambdaUpdateWrapper<TokenEntity> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.eq(TokenEntity::getUserId, userId);
|
||||||
|
updateWrapper.set(TokenEntity::getExpireDate, now);
|
||||||
|
updateWrapper.set(TokenEntity::getUpdateDate, now);
|
||||||
|
tokenDao.update(updateWrapper);
|
||||||
|
}
|
||||||
|
private String generateToken(){
|
||||||
|
return UUID.randomUUID().toString().replace("-", "");
|
||||||
|
}
|
||||||
|
}
|
65
src/main/java/io/service/impl/UserServiceImpl.java
Normal file
65
src/main/java/io/service/impl/UserServiceImpl.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package io.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import io.common.exception.RenException;
|
||||||
|
import io.common.validator.AssertUtils;
|
||||||
|
import io.dao.UserDao;
|
||||||
|
import io.entity.TokenEntity;
|
||||||
|
import io.entity.UserEntity;
|
||||||
|
import io.service.TokenService;
|
||||||
|
import io.service.UserService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserEntity getUserByUserId(Long userId) {
|
||||||
|
return baseMapper.selectById(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsUsername(String username) {
|
||||||
|
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("username", username);
|
||||||
|
return baseMapper.selectCount(wrapper) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserEntity getByUsername(String username) {
|
||||||
|
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("username", username);
|
||||||
|
return baseMapper.selectOne(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> login(UserEntity dto) {
|
||||||
|
UserEntity user = getByUsername(dto.getUsername());
|
||||||
|
AssertUtils.isNull(user, "用户名不存在~");
|
||||||
|
|
||||||
|
//密码错误
|
||||||
|
if (!user.getPassword().equals(DigestUtil.sha256Hex(dto.getPassword()))) {
|
||||||
|
throw new RenException("密码输入错误~");
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取登录token
|
||||||
|
TokenEntity tokenEntity = tokenService.createToken(user.getId());
|
||||||
|
|
||||||
|
Map<String, Object> map = new HashMap<>(2);
|
||||||
|
map.put("token", tokenEntity.getToken());
|
||||||
|
map.put("expire", tokenEntity.getExpireDate().getTime() - System.currentTimeMillis());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
46
src/main/resources/application-dev.yml
Normal file
46
src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
spring:
|
||||||
|
web:
|
||||||
|
resources:
|
||||||
|
static-locations: "file:${upload.path}"
|
||||||
|
datasource:
|
||||||
|
druid:
|
||||||
|
#MySQL
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://localhost:3306/master?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||||
|
username: root
|
||||||
|
password: 123456
|
||||||
|
initial-size: 10
|
||||||
|
max-active: 100
|
||||||
|
min-idle: 10
|
||||||
|
max-wait: 6000
|
||||||
|
pool-prepared-statements: true
|
||||||
|
max-pool-prepared-statement-per-connection-size: 20
|
||||||
|
time-between-eviction-runs-millis: 60000
|
||||||
|
min-evictable-idle-time-millis: 300000
|
||||||
|
test-while-idle: true
|
||||||
|
test-on-borrow: false
|
||||||
|
test-on-return: false
|
||||||
|
stat-view-servlet:
|
||||||
|
enabled: true
|
||||||
|
url-pattern: /druid/*
|
||||||
|
mybatis-plus:
|
||||||
|
mapper-locations: classpath*:/mapper/**/*.xml
|
||||||
|
typeAliasesPackage: io.modules.*.entity,io.modules.*.entity
|
||||||
|
global-config:
|
||||||
|
db-config:
|
||||||
|
id-type: AUTO
|
||||||
|
banner: false
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
cache-enabled: false
|
||||||
|
call-setters-on-nulls: true
|
||||||
|
jdbc-type-for-null: 'null'
|
||||||
|
configuration-properties:
|
||||||
|
prefix:
|
||||||
|
blobType: BLOB
|
||||||
|
boolValue: TRUE
|
||||||
|
|
||||||
|
upload:
|
||||||
|
# path: ./upload
|
||||||
|
path: ${user.dir}${file.separator}upload${file.separator}
|
||||||
|
url: http://localhost:18081/
|
45
src/main/resources/application.yaml
Normal file
45
src/main/resources/application.yaml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Tomcat
|
||||||
|
server:
|
||||||
|
tomcat:
|
||||||
|
uri-encoding: UTF-8
|
||||||
|
threads:
|
||||||
|
max: 1000
|
||||||
|
min-spare: 30
|
||||||
|
port: 18080
|
||||||
|
servlet:
|
||||||
|
context-path: /
|
||||||
|
session:
|
||||||
|
cookie:
|
||||||
|
http-only: true
|
||||||
|
|
||||||
|
spring:
|
||||||
|
profiles:
|
||||||
|
active: dev
|
||||||
|
messages:
|
||||||
|
encoding: UTF-8
|
||||||
|
basename: i18n/messages
|
||||||
|
mvc:
|
||||||
|
pathmatch:
|
||||||
|
matching-strategy: ANT_PATH_MATCHER
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 100MB
|
||||||
|
max-request-size: 100MB
|
||||||
|
enabled: true
|
||||||
|
#mybatis
|
||||||
|
mybatis-plus:
|
||||||
|
mapper-locations: classpath*:/mapper/**/*.xml
|
||||||
|
typeAliasesPackage: io.modules.*.entity
|
||||||
|
global-config:
|
||||||
|
db-config:
|
||||||
|
id-type: AUTO
|
||||||
|
banner: false
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
cache-enabled: false
|
||||||
|
call-setters-on-nulls: true
|
||||||
|
jdbc-type-for-null: 'null'
|
||||||
|
configuration-properties:
|
||||||
|
prefix:
|
||||||
|
blobType: BLOB
|
||||||
|
boolValue: TRUE
|
Loading…
Reference in New Issue
Block a user