目录
1.创建SpringBoot空项目
1.1新建项目
1.2 选择项目类型
- 选择项目为Maven项目
- 选择JDK版本为1.8
1.3 选择项目版本及名称
- 项目名:ySir
- 项目路径:com.yanze
- 项目版本:1.0-SNAPSHOT
1.4 完成创建
2.导入POM依赖、编写配置文件
2.1 导入POM依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yanze</groupId>
<artifactId>ySir</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<artifactId>spring-boot-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.2.2.RELEASE</version>
</parent>
<!-- 版本依赖 -->
<properties>
<fastJson.version>1.2.78</fastJson.version>
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<druid.version>1.1.10</druid.version>
<hutool.version>5.6.5</hutool.version>
<jwt.version>3.10.3</jwt.version>
</properties>
<dependencies>
<!-- Web容器 begin =================================== -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Web容器 end -->
<!-- 测试 Test begin =================================== -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<!--依赖项目仅仅参与测试相关的工作。包括测试代码的编译和执行,不会被打包-->
<scope>test</scope>
</dependency>
<!-- 测试 Test end -->
<!-- 阿里 FastJson begin =================================== -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastJson.version}</version>
</dependency>
<!-- 阿里 FastJson -->
<!-- MyBatisPlus begin =================================== -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- MySQL begin =================================== -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- MySQL end -->
<!-- 阿里数据库连接池 Druid begin =================================== -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 阿里数据库连接池Druid end -->
<!-- jwt begin =================================== -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- jwt end -->
<!-- ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ -->
<!-- ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 通用包 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ -->
<!-- ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ -->
<!-- Lombok begin =================================== -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!--减少不必要的依赖传递-->
<optional>true</optional>
</dependency>
<!-- Lombok end -->
<!-- StringUtils工具类 begin =================================== -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- StringUtils工具类 end -->
<!-- HuTool工具类 begin =================================== -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- HuTool工具类 end -->
</dependencies>
<build>
<plugins>
<!-- 打包插件 =================================== -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2 编写配置文件
- 文件所在位置:resources/application.yml
# 项目相关配置
ysir:
# 名称
name: ySir
# 版本
version: 0.0.1
# 作者
author: yanze
# 版权年份
copyrightYear: Copyright © 2023 yanze
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 80
servlet:
# 应用的访问路径
context-path: /
# 应用的名称
application-display-name: ySir
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# tomcat最大线程数,默认为200
max-threads: 800
# Tomcat启动初始化的线程数,默认值25
min-spare-threads: 30
# Spring配置
spring:
application:
name: ySir
# 配置不同环境
profiles:
active: dev
main:
# 配置当遇到同名的bean时,是否覆盖
allow-bean-definition-overriding: true
# SpringSecurity
security:
user:
name: yanze # 用户名
password: yanze # 密码
# MyBatisPlus配置
mybatis-plus:
# 配置mapper扫描,扫描mapper.xml映射文件
mapper-locations: classpath:mybatis/mapper/*Mapper.xml
# 配置别名目录
type-aliases-package: com.yanze.YSIR.model.PO
# 以下配置均有默认值,可以不设置
global-config:
# 主键类型(0:数据库自增,1:用户输入ID,2:全局唯一ID(数字类型唯一ID),3全局唯一ID(UUID))
id-type: 0
# 字段策略(0:忽略判断,1:非NULL判断,2非空判断)
field-strategy: 2
# 驼峰下划线转换
db-column-underline: true
# 刷新mapper
refresh-mapper: false
configuration:
# 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的
map-underscore-to-camel-case: true
# 配置日志
logging:
file:
# 生成到当前项目根目录下的log文件中
name: log/ySir.log
# 最大历史天数
max-history: 70
# 最大文件大小
max-size: 22MB
pattern:
# 输出日志中日期的格式
dateformat: yyyy-MM-dd HH:mm:ss.SSS
level:
# 输出指定包下的日志
com.yanze.YSIR.common.security: debug
com.yanze.YSIR.mapper: debug
2.3 编写配置文件(开发环境)
- 文件所在位置:resources/application-dev.yml
- 更换数据库名称、用户名、密码。
####################
# 开发环境配置
spring:
# 配置数据源
datasource:
url: jdbc:mysql://localhost:3306/ysir?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
# 配置连接池 Druid
type: com.alibaba.druid.pool.DruidDataSource
# ===================== ↓↓↓↓↓↓ 使用druid数据源 ↓↓↓↓↓↓ =====================
druid:
# 最小空闲数
min-idle: 10
# 最大活跃数
max-active: 20
# 最大等待时长,单位毫秒
max-wait: 60000
# 创建连接池的时候,初始化连接数量
initial-size: 3
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
timeBetweenEvictionRunsMillis: 60000
# 检查连接有效性的时候,用什么SQL检查,相当于心跳
validationQuery: SELECT 1
# 当连接为空闲状态的时候,是否检查有效性
testWhileIdle: true
# 当连接被外界获取的时候,是否检查有效性
testOnBorrow: false
# 当连接返回的时候,是否检查有效性
testOnReturn: false
# 是否开启预编译缓存,预编译的是SQL。打开PSCache,并且指定每个连接上PSCache的大小。
poolPreparedStatements: true
# 预编译缓存容量
maxPoolPreparedStatementPerConnectionSize: 20
# 自定义属性
2.4 编写banner文件
- 文件所在位置:resources/banner.txt
- 更换文字图案地址:点这里!!!
.----------------. .----------------. .----------------. .----------------.
| .--------------. | .--------------. | .--------------. | .--------------. |
| | ____ ____ | | | _______ | | | _____ | | | _______ | |
| | |_ _||_ _| | | | / ___ | | | | |_ _| | | | |_ __ \ | |
| | \ \ / / | | | | (__ \_| | | | | | | | | | |__) | | |
| | \ \/ / | | | '.___`-. | | | | | | | | | __ / | |
| | _| |_ | | | |`\____) | | | | _| |_ | | | _| | \ \_ | |
| | |______| | | | |_______.' | | | |_____| | | | |____| |___| | |
| | | | | | | | | | | | |
| '--------------' | '--------------' | '--------------' | '--------------' |
'----------------' '----------------' '----------------' '----------------'
${AnsiColor.BRIGHT_GREEN}Application Info:
${AnsiColor.BRIGHT_YELLOW} 项目名称:${ysir.name}
${AnsiColor.BRIGHT_RED} 项目版本:${ysir.version}
${AnsiColor.BRIGHT_CYAN} 项目作者:${ysir.author}
${AnsiColor.BRIGHT_MAGENTA} 项目版权:${ysir.copyrightYear}
${AnsiColor.BRIGHT_GREEN}Spring Boot Version: ${spring-boot.version}
${AnsiColor.BRIGHT_GREEN}Spring Application Name: ${spring.application.name}
3.编写启动类、完善目录结构
3.1 编写启动类
- 类所在包:com.yanze.ySir.YSIRApplication.java
package com.yanze.YSIR;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* YSIR启动类
*
* @author YanZeSir
* @date 2023/1/15 23:08
*/
@Slf4j
@SpringBootApplication
public class YSIRApplication {
public static void main(String[] args) {
SpringApplication.run(YSIRApplication.class, args);
log.info("\n" +
" __ _______ _____ _____ \n" +
" \\ \\ / / ____|_ _| __ \\ \n" +
" \\ \\_/ | (___ | | | |__) |\n" +
" \\ / \\___ \\ | | | _ / \n" +
" | | ____) |_| |_| | \\ \\ \n" +
" |_| |_____/|_____|_| \\_\\\n" +
" \n" +
" \n" +
"\n\tySir 启动成功....\n" +
"\t严先生系统 启动成功....\n");
log.info("");
}
}
3.2 完善目录结构
- log:日志目录。存放日志文件,一般会在配置文件中配置好,自动生成。
- sql:sql目录。存放SQL文件,建表语句及测试数据等。
- src/main/java/
- com/yanze/YSIR/:项目包路径。
- common:公共包。存放公共类。
- Result:统一返回格式包。存放返回的统一响应格式。
- security:安全权限包。存放跟权限相关的内容。
- config:配置包。存放配置类。命名规则:XxxxConfig.java
- constant:常量包。存放常量类。命名规则:XxxxConstants.java
- controller:控制层。存放控制器类。命名规则:XxxxController.java
-
exception:异常包。存放异常类。命名规则:XxxxException.java
-
mapper:数据持久层。存放访问数据库的接口。通常也命名为dao。命名规则:XxxxMapper.java、XxxxDao.java
-
model:模型层。存放实体类。通常也命名为entity、pojo。
-
PO:数据库传输对象。封装数据库表的字段。命名规则:表名PO.java
-
DTO:数据传输对象。封装多个实体类之间的关系。命名规则:XxxxDTO.java
-
VO:视图包装对象。封装客户端请求的数据。命名规则:XxxxVo.java
-
-
service:业务层。存放业务类。命名规则:XxxxService.java
-
impl:业务层实现类。存放业务接口实现类。命名规则:XxxxServiceImpl.java
-
-
util:工具包。存放工具类。命名规则:XxxxUtils.java
- common:公共包。存放公共类。
- com/yanze/YSIR/:项目包路径。
-
src/main/resources/
-
mybatis:MyBatis配置文件。
-
mapper:存放Mapper映射文件。命名规则:XxxxMapper.xml、XxxxDao.xml
-
-
-
src/test/java/:测试目录。
注意:包的舍去根据自己项目来决定,以上的目录结构是本人根据MVC三层划分并结合自己的使用风格规划的。
4.完善统一返回格式包
- 包所在路径:com.yanze.YSIR.common.Result
4.1 编写统一返回格式对象
- Result.java
package com.yanze.YSIR.common.Result;
import java.io.Serializable;
/**
* 统一返回格式对象
*
* @author YanZeSir
* @date 2023/1/18 10:39
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
private Integer code;
private String msg;
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer 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;
}
}
4.2 编写统一返回格式枚举对象
- ResultEnum.java
package com.yanze.YSIR.common.Result;
/**
* 统一返回格式枚举对象
*
* @author YanZeSir
* @date 2023/1/18 10:41
*/
public enum ResultEnum {
//操作成功
OK(2000, "操作成功!"),
//操作失败
NO_OK(1000, "操作失败!"),
//请求成功
SUCCESS(2002, "请求成功!"),
//请求失败
FAIL(1001, "请求失败!"),
//响应成功
RESPONSE_SUCCESS(2222, "响应成功!"),
//响应失败
RESPONSE_FAILED(1111, "响应失败!"),
//权限不足
NO_PERMISSION(3333, "权限不足!"),
//客户端错误
CLIENT_ERROR(4000, "客户端错误!"),
//服务器错误
SERVER_ERROR(5000, "服务器错误!"),
//未知错误
UNKNOWN_ERROR(-1, "未知错误!");
private Integer code;
private String msg;
ResultEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
4.3 编写统一返回格式响应方法
- ResultData.java
package com.yanze.YSIR.common.Result;
/**
* 统一返回格式响应方法
*
* @author YanZeSir
* @date 2023/1/18 10:42
*/
public class ResultData {
// ↓↓↓↓↓↓↓↓↓↓ 请求成功方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 操作成功【增删改】
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> ok() {
return common(ResultEnum.OK.getCode(), ResultEnum.OK.getMsg(), null);
}
/**
* 操作成功,自定义响应信息【增删改】
*
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> ok(String msg) {
return common(ResultEnum.OK.getCode(), msg, null);
}
/**
* 操作成功,携带响应对象【增删改】
*
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> ok(T data) {
return common(ResultEnum.OK.getCode(), ResultEnum.OK.getMsg(), data);
}
/**
* 操作成功,自定义响应信息和响应对象【增删改】
*
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> ok(String msg, T data) {
return common(ResultEnum.OK.getCode(), msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 请求成功方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 操作失败【增删改】
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> noOk() {
return common(ResultEnum.NO_OK.getCode(), ResultEnum.NO_OK.getMsg(), null);
}
/**
* 操作失败,自定义响应信息【增删改】
*
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> noOk(String msg) {
return common(ResultEnum.NO_OK.getCode(), msg, null);
}
/**
* 操作失败,携带响应对象【增删改】
*
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> noOk(T data) {
return common(ResultEnum.NO_OK.getCode(), ResultEnum.NO_OK.getMsg(), data);
}
/**
* 操作失败,自定义响应信息和响应对象【增删改】
*
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> noOk(String msg, T data) {
return common(ResultEnum.NO_OK.getCode(), msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 请求成功方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 请求成功【查询】
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> success() {
return common(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), null);
}
/**
* 请求成功,自定义响应信息【查询】
*
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> success(String msg) {
return common(ResultEnum.SUCCESS.getCode(), msg, null);
}
/**
* 请求成功,携带响应对象【查询】
*
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> success(T data) {
return common(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), data);
}
/**
* 请求成功,自定义响应信息和响应对象【查询】
*
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> success(String msg, T data) {
return common(ResultEnum.SUCCESS.getCode(), msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 请求失败方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 请求失败
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> fail() {
return common(ResultEnum.FAIL.getCode(), ResultEnum.FAIL.getMsg(), null);
}
/**
* 请求失败,自定义响应信息
*
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> fail(String msg) {
return common(ResultEnum.FAIL.getCode(), msg, null);
}
/**
* 请求失败,携带响应对象
*
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> fail(T data) {
return common(ResultEnum.FAIL.getCode(), ResultEnum.FAIL.getMsg(), data);
}
/**
* 请求失败,自定义响应信息和响应对象
*
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> fail(String msg, T data) {
return common(ResultEnum.FAIL.getCode(), msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 响应成功方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 响应成功
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> respSuccess() {
return common(ResultEnum.RESPONSE_SUCCESS.getCode(), ResultEnum.RESPONSE_SUCCESS.getMsg(), null);
}
/**
* 响应成功,自定义响应信息
*
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> respSuccess(String msg) {
return common(ResultEnum.RESPONSE_SUCCESS.getCode(), msg, null);
}
/**
* 响应成功,携带响应对象
*
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> respSuccess(T data) {
return common(ResultEnum.RESPONSE_SUCCESS.getCode(), ResultEnum.RESPONSE_SUCCESS.getMsg(), data);
}
/**
* 响应成功,自定义响应信息和响应对象
*
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> respSuccess(String msg, T data) {
return common(ResultEnum.RESPONSE_SUCCESS.getCode(), msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 响应失败方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 响应失败
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> respFailed() {
return common(ResultEnum.RESPONSE_FAILED.getCode(), ResultEnum.RESPONSE_FAILED.getMsg(), null);
}
/**
* 响应失败,自定义响应信息
*
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> respFailed(String msg) {
return common(ResultEnum.RESPONSE_FAILED.getCode(), msg, null);
}
/**
* 响应失败,携带响应对象
*
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> respFailed(T data) {
return common(ResultEnum.RESPONSE_FAILED.getCode(), ResultEnum.RESPONSE_FAILED.getMsg(), data);
}
/**
* 响应失败,自定义响应信息和响应对象
*
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> respFailed(String msg, T data) {
return common(ResultEnum.RESPONSE_FAILED.getCode(), msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 权限不足方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 权限不足
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> noPermission() {
return common(ResultEnum.NO_PERMISSION.getCode(), ResultEnum.NO_PERMISSION.getMsg(), null);
}
// ↓↓↓↓↓↓↓↓↓↓ 客户端错误方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 客户端错误
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> clientError() {
return common(ResultEnum.CLIENT_ERROR.getCode(), ResultEnum.CLIENT_ERROR.getMsg(), null);
}
// ↓↓↓↓↓↓↓↓↓↓ 服务器错误方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 服务器错误
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> serverError() {
return common(ResultEnum.SERVER_ERROR.getCode(), ResultEnum.SERVER_ERROR.getMsg(), null);
}
/**
* 服务器错误
*
* @param msg 响应信息
* @param <T> T
* @return Result<T>
*/
public static <T> Result<T> serverError(String msg) {
return common(ResultEnum.SERVER_ERROR.getCode(), msg, null);
}
// ↓↓↓↓↓↓↓↓↓↓ 未知错误方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 未知错误
*
* @param <T> T
* @return Result
*/
public static <T> Result<T> unKnowError() {
return common(ResultEnum.UNKNOWN_ERROR.getCode(), ResultEnum.UNKNOWN_ERROR.getMsg(), null);
}
/**
* 未知错误
*
* @param msg 响应信息
* @param <T> T
* @return Result<T>
*/
public static <T> Result<T> unKnowError(String msg) {
return common(ResultEnum.UNKNOWN_ERROR.getCode(), msg, null);
}
// ↓↓↓↓↓↓↓↓↓↓ 公共响应方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 自定义响应格式
*
* @param code 响应码
* @param msg 响应信息
* @param <T> T
* @return Result
*/
public static <T> Result<T> customResp(Integer code, String msg) {
return common(code, msg, null);
}
/**
* 自定义响应格式
*
* @param code 响应码
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
public static <T> Result<T> customResp(Integer code, String msg, T data) {
return common(code, msg, data);
}
// ↓↓↓↓↓↓↓↓↓↓ 公共响应方法 ↓↓↓↓↓↓↓↓↓↓
/**
* 公共响应方法
*
* @param code 响应码
* @param msg 响应信息
* @param data 响应对象
* @param <T> T
* @return Result
*/
private static <T> Result<T> common(Integer code, String msg, T data) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
}
5.完善常量包、完善工具包
- 包所在路径:com.yanze.YSIR.constant
- 包所在路径:com.yanze.YSIR.util
5.1 编写基础常量类
- BaseConstants.java
package com.yanze.YSIR.constant;
/**
* 基础常量
*
* @author YanZeSir
* @date 2023/1/18 10:58
*/
public class BaseConstants {
/**
* 前端统一传入的字符串参数
*/
public static String JSON_STR = "jsonStr";
/**
* Token过期时间
*/
public static final Long TOKEN_EXPIRE_TIME = 5 * 60 * 1000L;
/**
* PC端Token
*/
public static String PC_USER_TOKEN = "token";
/**
* PC端Token,大写Token
*/
public static String PC_USER_TOKEN_ = "TOKEN";
/**
* APP端Token
*/
public static String APP_USER_TOKEN;
/**
* WX端Token
*/
public static String WX_USER_TOKEN;
}
5.2 编写字符串常量类
- StringConstants.java
package com.yanze.YSIR.constant;
/**
* 字符串常量
*
* @author YanZeSir
* @date 2023/1/18 10:59
*/
public class StringConstants {
public static String RETURN_LOGIN_SUCCESS = "登录成功!";
public static String RETURN_LOGIN_FAILED = "登录失败!";
public static String RETURN_OPERATION_SUCCESS = "操作成功!";
public static String RETURN_OPERATION_FAILED = "操作失败!";
public static String RETURN_REQUEST_SUCCESS = "请求成功!";
public static String RETURN_REQUEST_FAILED = "请求失败!";
public static String RETURN_RESPONSE_SUCCESS = "响应成功!";
public static String RETURN_RESPONSE_FAILED = "响应失败!";
public static String EXCEPTION_CUSTOM = "自定义业务异常!";
public static String EXCEPTION_PARAM_ERROR = "参数错误!【缺少变量jsonStr或jsonStr没有值】";
public static String EXCEPTION_NO_LOGIN = "用户未登录!";
public static String EXCEPTION_NO_LOGIN_TOKEN = "用户未登录!【Token不存在】";
public static String EXCEPTION_NO_LOGIN_SESSION = "用户未登录!【Session不存在】";
public static String EXCEPTION_URL_NO_EXITS = "URL不存在!";
public static String LOGIN_CHECK_START = "==========登录校验 START==========";
public static String LOGIN_CHECK_END = "===========登录校验 END===========";
public static String LOGIN_CHECK_START_TIME = "校验开始时间:";
public static String LOGIN_CHECK_END_TIME = "校验结束时间:";
public static String LOGIN_CHECK_URL = ">>>>>>>>>> 校验URL";
public static String LOGIN_CHECK_IS_NO = ">>>>>>>>>> 无需校验";
public static String LOGIN_CHECK_PARAM = ">>>>>>>>>> 参数错误";
public static String LOGIN_CHECK_SUCCESS = ">>>>>>>>>> 校验成功!";
public static String LOGIN_CHECK_FAILED = ">>>>>>>>>> 校验失败!用户未登录!";
public static String LOGIN_CHECK_TOKEN_FAILED = ">>>>>>>>>> 校验失败!Token验证错误!";
}
5.3 编写JSON工具类
- JsonUtils.java
package com.yanze.YSIR.util;
import com.alibaba.fastjson.JSONObject;
/**
* Json工具类
*
* @author YanZeSir
* @date 2023/1/18 10:59
*/
public class JsonUtils {
/**
* 把String转换成JSON对象
* @param jsonObj jsonObj
* @return JSONObject
*/
public static JSONObject strToJson(String jsonObj) {
return JSONObject.parseObject(jsonObj);
}
}
5.4 编写Url工具类
- StringUtils.java
package com.yanze.YSIR.util;
/**
* Url工具类
*
* @author YanZeSir
* @date 2023/1/18 11:00
*/
public class UrlUtils {
/**
* 获取请求地址
* @param request request
* @return String
*/
public static String getUrl(HttpServletRequest request) {
return request.getServletPath();
}
}
6.完善配置包、异常包
- 包所在路径:com.yanze.YSIR.config
- 包所在路径:com.yanze.YSIR.exception
6.1 编写MyBatisPlus配置类
- MyBatisPlusConfig.java
package com.yanze.YSIR.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;
/**
* MyBatisPlus配置类
*
* @author YanZeSir
* @date 2023/1/18 16:24
*/
@Configuration
public class MyBatisPlusConfig {
/**
* 分页插件配置(配置方式根据MyBatisPlus版本有所不同)
*
* @return MybatisPlusInterceptor
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
6.2 编写自定义业务异常类
- CustomBusinessException.java
package com.yanze.YSIR.exception;
/**
* 自定义业务异常
*
* @author YanZeSir
* @date 2023/1/18 16:28
*/
public class CustomBusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final String message;
public CustomBusinessException(String message) {
this.message = message;
}
public CustomBusinessException(String message, Throwable e) {
super(message, e);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
6.3 编写未登录异常类
- NoLoginException.java
package com.yanze.YSIR.exception;
/**
* 未登录异常
*
* @author YanZeSir
* @date 2023/1/18 16:29
*/
public class NoLoginException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final String message;
public NoLoginException(String message) {
this.message = message;
}
public NoLoginException(String message, Throwable e) {
super(message, e);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
6.4 编写参数错误异常类
- ParamErrorException.java
package com.yanze.YSIR.exception;
/**
* 参数错误异常
*
* @author YanZeSir
* @date 2023/1/18 16:30
*/
public class ParamErrorException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final String message;
public ParamErrorException(String message) {
this.message = message;
}
public ParamErrorException(String message, Throwable e) {
super(message, e);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
6.5 编写Token错误异常
- TokenErrorException.java
package com.yanze.YSIR.exception;
/**
* Token错误异常
*
* @author YanZeSir
* @date 2023/1/18 19:45
*/
public class TokenErrorException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final String message;
public TokenErrorException(String message) {
this.message = message;
}
public TokenErrorException(String message, Throwable e) {
super(message, e);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
6.6 编写自定义全局异常处理器类
- CustomGlobalExceptionHandler.java
package com.yanze.YSIR.exception;
import com.yanze.YSIR.common.Result.Result;
import com.yanze.YSIR.common.Result.ResultData;
import com.yanze.YSIR.common.Result.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.util.NestedServletException;
/**
* 自定义全局异常处理器
*
* @author YanZeSir
* @date 2023/1/18 16:31
*/
@Slf4j
@RestControllerAdvice
public class CustomGlobalExceptionHandler {
/**
* 自定义业务异常
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler(CustomBusinessException.class)
public Result<String> customException(CustomBusinessException e) {
log.error("自定义异常信息:{}", e.getMessage());
return ResultData.customResp(ResultEnum.SERVER_ERROR.getCode(), ResultEnum.SERVER_ERROR.getMsg(), e.getMessage());
}
/**
* Http请求消息序列化异常
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler({HttpMessageNotReadableException.class})
public Result<String> httpNotReadableException(HttpMessageNotReadableException e) {
log.error("Http请求消息序列化异常:{}", e.getMessage());
log.error("HttpMessageNotReadableException:传入类型错误或没有传参错误!");
return ResultData.customResp(ResultEnum.SERVER_ERROR.getCode(), "Http请求消息序列化异常", e.getMessage());
}
/**
* 用户未登录异常
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler({NoLoginException.class})
public Result<String> noLoginException(NoLoginException e) {
log.error("用户未登录异常:{}", e.getMessage());
return ResultData.customResp(ResultEnum.SERVER_ERROR.getCode(), "用户未登录!");
}
/**
* Token验证错误异常
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler({TokenErrorException.class})
public Result<String> tokenErrorException(TokenErrorException e) {
log.error("Token验证错误异常:{}", e.getMessage());
return ResultData.customResp(ResultEnum.SERVER_ERROR.getCode(), "Token验证错误!");
}
/**
* 参数错误异常
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler({ParamErrorException.class})
public Result<String> paramErrorException(ParamErrorException e) {
log.error("参数错误异常:{}", e.getMessage());
return ResultData.customResp(ResultEnum.SERVER_ERROR.getCode(), e.getMessage());
}
/**
* 堆栈溢出错误
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler({NestedServletException.class, StackOverflowError.class})
public Result<String> stackOverflowException(Exception e) {
log.error("堆栈溢出错误:{}", e.getMessage());
return ResultData.serverError("堆栈溢出错误!");
}
/**
* 全局异常
*
* @param e e
* @return Result<String>
*/
@ExceptionHandler({Exception.class})
public Result<String> overallException(Exception e) {
log.error("全局异常信息:{}", e.getMessage());
System.out.println(e.getClass());
return ResultData.unKnowError("全局异常!");
}
}
7.完善安全权限包
- 包所在路径:com.yanze.YSIR.common.security
7.1 编写JwtToken类
- JwtToken.java
package com.yanze.YSIR.common.security;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.yanze.YSIR.constant.BaseConstants;
import com.yanze.YSIR.constant.StringConstants;
import com.yanze.YSIR.exception.NoLoginException;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
* JwtToken生成类
*
* @author YanZeSir
* @date 2023/1/18 16:38
*/
@Slf4j
public class JwtToken {
/**
* 生成Token
*
* @param userId 用户ID(唯一标识)
* @param username 用户名(唯一标识)
* @param password 密码
* @param request request
* @return String
*/
public static String getJwtToken(String userId, String username, String password, HttpServletRequest request) {
return getJwtToken(userId, username, password, 0L, request);
}
/**
* 生成Token
*
* @param userId 用户ID(唯一标识)
* @param username 用户名(唯一标识)
* @param password 密码
* @param expireTime 过期时间
* @param request request
* @return String
*/
public static String getJwtToken(String userId, String username, String password, Long expireTime, HttpServletRequest request) {
//过期时间
Date date;
if (expireTime == null || expireTime == 0) {
//默认过期时间5分钟
date = new Date(System.currentTimeMillis() + BaseConstants.TOKEN_EXPIRE_TIME);
} else {
date = new Date(System.currentTimeMillis() + expireTime);
}
//创建Token
String token = JWT.create()
//签收者
.withAudience(userId, username)
//主题
.withSubject("token")
//过期时间
.withExpiresAt(date)
//token密匙
.sign(Algorithm.HMAC256(password));
//将Token存到Session中
HttpSession session = request.getSession();
session.setAttribute("token", token);
return token;
}
/**
* 判断Token是否存在并且是否正确(和Session中是否一致)
*
* @param token token
* @return boolean
*/
public static boolean judgeTokenIsExitsAndCorrect(String token, HttpServletRequest request) {
//从Session中获取Token
HttpSession session = request.getSession();
String tokenSession = (String) session.getAttribute("token");
if (tokenSession == null) {
log.error("Session不存在");
throw new NoLoginException(StringConstants.EXCEPTION_NO_LOGIN_SESSION);
}
//判断传进来的token和Session中的token是否相等,并返回结果
return tokenSession.equals(token);
}
}
7.2 编写登录校验注解
- LoginCheck.java
package com.yanze.YSIR.common.security;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义 - 登录校验注解
*
* @author YanZeSir
* @date 2023/1/18 22:52
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface LoginCheck {
/**
* 方法描述
*
* @return String
*/
String description() default "";
/**
* 是否必须校验Token
*
* @return boolean
*/
boolean isToken() default true;
/**
* 是否必须包含参数
* @return boolean
*/
boolean isParam() default true;
/**
* 方法请求类型
*
* @return String
*/
String method() default "POST";
}
7.3 编写登录校验拦截器
- LoginCheckInterceptor.java
package com.yanze.YSIR.common.security;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.yanze.YSIR.constant.BaseConstants;
import com.yanze.YSIR.constant.StringConstants;
import com.yanze.YSIR.exception.NoLoginException;
import com.yanze.YSIR.exception.ParamErrorException;
import com.yanze.YSIR.exception.TokenErrorException;
import com.yanze.YSIR.util.JsonUtils;
import com.yanze.YSIR.util.UrlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
/**
* 登录校验拦截器
*
* @author YanZeSir
* @date 2023/1/18 22:56
*/
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println();
log.debug("进入拦截器....");
return this.hasLogin(request, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.debug("退出拦截器....");
}
/**
* 登录校验
*
* @param request request
* @param handler handler
* @return boolean
*/
private boolean hasLogin(HttpServletRequest request, Object handler) {
if (handler instanceof HandlerMethod) {
log.info(StringConstants.LOGIN_CHECK_START);
HandlerMethod handlerMethod = (HandlerMethod) handler;
//获取当前请求的URL
String servletPath = UrlUtils.getUrl(request);
//获取方法上的【登录校验】注解
LoginCheck loginCheckAnnotation = handlerMethod.getMethod().getAnnotation(LoginCheck.class);
//方法没有【登录校验】注解,直接放行
if (loginCheckAnnotation == null) {
log.info(StringConstants.LOGIN_CHECK_IS_NO + "【" + servletPath + "】");
log.info(StringConstants.LOGIN_CHECK_END);
return true;
}
// TODO 这里可以对注解中第四个参数进行校验,传入的是请求方法,默认是POST
//方法有【登录校验】注解,并且不要校验Token,直接放行
if (!loginCheckAnnotation.isToken()) {
log.info(StringConstants.LOGIN_CHECK_IS_NO + "【" + servletPath + "】");
log.info(StringConstants.LOGIN_CHECK_END);
return true;
}
//方法有【登录校验】注解,并且不必须包含参数,直接放行
if (!loginCheckAnnotation.isParam()) {
log.info(StringConstants.LOGIN_CHECK_IS_NO + "【" + servletPath + "】");
log.info(StringConstants.LOGIN_CHECK_END);
return true;
}
log.info(StringConstants.LOGIN_CHECK_START_TIME + LocalDateTime.now());
log.info(StringConstants.LOGIN_CHECK_URL + "【" + servletPath + "】");
//获取传进来的参数jsonStr
String jsonStr = request.getParameter(BaseConstants.JSON_STR);
if (StrUtil.isBlank(jsonStr)) {
log.info(StringConstants.LOGIN_CHECK_PARAM);
log.info(StringConstants.LOGIN_CHECK_END_TIME + LocalDateTime.now());
log.info(StringConstants.LOGIN_CHECK_END);
throw new ParamErrorException(StringConstants.EXCEPTION_PARAM_ERROR);
}
//字符串转换成JSONObject对象
JSONObject jsonObject = JsonUtils.strToJson(jsonStr);
//获取JSONObject对象中的Token键
String token = (String) jsonObject.get(BaseConstants.PC_USER_TOKEN);
//判断是否有Token,没有说明未登录
if (StrUtil.isBlank(token) && StrUtil.isBlank(token = (String) jsonObject.get(BaseConstants.PC_USER_TOKEN_))) {
log.info(StringConstants.LOGIN_CHECK_FAILED);
log.info(StringConstants.LOGIN_CHECK_END_TIME + LocalDateTime.now());
log.info(StringConstants.LOGIN_CHECK_END);
throw new NoLoginException(StringConstants.EXCEPTION_NO_LOGIN_TOKEN);
}
//有token,并对比Token和Session中的Token是否一致,不一致
if (!JwtToken.judgeTokenIsExitsAndCorrect(token, request)) {
log.info(StringConstants.LOGIN_CHECK_TOKEN_FAILED);
log.info(StringConstants.LOGIN_CHECK_END_TIME + LocalDateTime.now());
log.info(StringConstants.LOGIN_CHECK_END);
throw new TokenErrorException(StringConstants.LOGIN_CHECK_TOKEN_FAILED);
}
log.info(StringConstants.LOGIN_CHECK_SUCCESS + token);
log.info(StringConstants.LOGIN_CHECK_END_TIME + LocalDateTime.now());
log.info(StringConstants.LOGIN_CHECK_END);
return true;
} else {
log.error(StringConstants.EXCEPTION_URL_NO_EXITS);
throw new CustomBusinessException(StringConstants.EXCEPTION_URL_NO_EXITS);
//return false;
}
}
}
7.4 编写登录校验拦截器配置
- LoginCheckInterceptorConfig.java
package com.yanze.YSIR.common.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 登录校验拦截器配置
*
* @author YanZeSir
* @date 2023/1/18 22:55
*/
@Configuration
public class LoginCheckInterceptorConfig implements WebMvcConfigurer {
@Bean
public LoginCheckInterceptor loginCheckInterceptor() {
return new LoginCheckInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor()).addPathPatterns("/**");
}
}
8.完善PO包、VO包
- 包所在路径:com.yanze.YSIR.model.PO
- 包所在路径:com.yanze.YSIR.model.VO
8.1 编写基础PO类
- BasePO.java
package com.yanze.YSIR.model.PO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 据库映射 - 公共基础字段
*
* @author YanZeSir
* @date 2023/1/18 23:35
*/
@Data
public class BasePO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 创建时间
*/
@TableField("create_time")
private Date createTime;
/**
* 更新时间
*/
@TableField("update_time")
private Date updateTime;
/**
* 备注
*/
@TableField("remarks")
private String remarks;
}
8.2 编写用户PO类
- UserPO.java
package com.yanze.YSIR.model.PO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 数据库映射 - 用户对象
*
* @author YanZeSir
* @date 2023/1/18 23:36
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("user")
public class UserPO extends BasePO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户表主键(使用UUID)
*/
@TableField("user_id")
private String userId;
/**
* 用户名
*/
@TableField("username")
private String username;
/**
* 密码
*/
@TableField("password")
private String password;
}
8.3 编写用户VO类
- UserVo.java
package com.yanze.YSIR.model.VO;
import com.yanze.YSIR.model.PO.UserPO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 视图映射 - 用户对象
*
* @author YanZeSir
* @date 2023/1/18 23:37
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class UserVO extends UserPO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
public String userId;
/**
* 用户名
*/
public String username;
/**
* 用户密码
*/
public String password;
/**
* 用户Token
*/
public String token;
}
9.完善数据持久层、完善映射文件
- 包所在路径:com.yanze.YSIR.mapper
9.1 编写用户类对应Mapper接口
- UserMapper.java
package com.yanze.YSIR.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yanze.YSIR.model.PO.UserPO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* User对应Mapper接口
* @author YanZeSir
* @date 2023/1/18 23:41
*/
@Mapper
public interface UserMapper extends BaseMapper<UserPO> {
/**
* 查询所有用户信息
*
* @return List<UserPO>
*/
List<UserPO> selectAllUser();
}
9.2 编写用户类对应Mapper接口映射文件
- UserMapper.xml
<!--查询所有用户信息-->
<select id="selectAllUser" resultType="com.yanze.YSIR.model.PO.UserPO">
select *
from ysir_asfs.asfs_user
</select>
10.完善业务层、完善业务层实现类
10.1 编写用户类对应业务层接口
- UserService.java
package com.yanze.YSIR.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yanze.YSIR.model.PO.UserPO;
import com.yanze.YSIR.model.VO.UserVO;
import java.util.List;
/**
* User对应业务层接口
*
* @author YanZeSir
* @date 2023/1/18 23:48
*/
public interface UserService extends IService<UserPO> {
/**
* 获取所有用户对象信息
*
* @return List<UserVO>
*/
List<UserVO> getAllUser();
}
10.2 编写用户类对应业务层接口实现类
- UserServiceImpl.java
package com.yanze.YSIR.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yanze.YSIR.mapper.UserMapper;
import com.yanze.YSIR.model.PO.UserPO;
import com.yanze.YSIR.model.VO.UserVO;
import com.yanze.YSIR.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* User对应业务层接口实现类
*
* @author YanZeSir
* @date 2023/1/18 23:49
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements UserService {
@Resource
private UserMapper userMapper;
/**
* 获取所有用户对象信息
*
* @return List<UserVO>
*/
@Override
public List<UserVO> getAllUser() {
List<UserPO> userPoList = userMapper.selectAllUser();
List<UserVO> userVoList = new ArrayList<>();
for (UserPO userPo : userPoList) {
UserVO userVo = new UserVO();
//对象的拷贝,拷贝属性相同的对象
BeanUtils.copyProperties(userPo, userVo);
userVoList.add(userVo);
}
return userVoList;
}
}
11.完善控制器层
11.1 编写用户类对应控制器类
- UserController.java
package com.yanze.YSIR.controller;
import com.yanze.YSIR.common.Result.Result;
import com.yanze.YSIR.common.Result.ResultData;
import com.yanze.YSIR.common.security.LoginCheck;
import com.yanze.YSIR.model.VO.UserVO;
import com.yanze.YSIR.service.UserService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* User对应控制器层
*
* @author YanZeSir
* @date 2023/1/18 23:51
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
/**
* 获取所有用户
*
* @return Result<Object>
*/
@PostMapping("/userList")
//@LoginCheck
public Result<Object> getAllUser(String jsonStr) {
List<UserVO> userVOList = userService.getAllUser();
return ResultData.success(userVOList);
}
}
12.项目启动测试
- 启动YSIRApplication.java启动类
- 打开Postman,选择POST请求
- 输入地址,http://localhost/user/userList
- 在Headers中定义,key=Content-Type,value=application/json
- 点击Send有响应即表示搭建完成。
写在最后
本项目模板为自己在开发项目中总结出来的。
本文中,很多功能并没有测试:例如,登录校验等。
本文只需要对着步骤一步一步进行,即可100%完整的创建出来。
如有其他疑问,可以留言或者私信我!!!
项目文件链接:SpringBoot项目模板,用于前后端分离项目