Solon + EasyQuery + ElementPlus 实现后台管理系统之 02-数据库设计与项目结构搭建
AI 摘要
前置工作
开发环境
项目开发使用的开发环境及相关版本为 IntelliJ IDEA、JDK 1.8、MySQL 8.0.42、Redis 7.2.6、Solon 3.7.2、EasyQuery 3.1.62、Redisx 1.7.0、HuTool 5.8.41、SaToken 1.44.0、Vue 3.5.25、ElementPlus 2.11.9。
数据库结构
根据通用后台管理系统的业务需求设计数据库结构,并初始化测试数据。本文提供的数据库结构及数据库脚本仅供参考,推荐根据实际需求自行扩展。
部门表(dept):
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | int | 部门 ID |
| name | varchar | 部门名称 |
| deleted | bigint | 删除状态,0 未删除 该字段用于逻辑删除 |
角色表(role):
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | int | 角色 ID |
| name | varchar | 角色名称 |
| perms | text | 授权的权限菜单列表 |
| remarks | varchar | 角色备注 |
| deleted | bigint | 删除状态,0 未删除 该字段用于逻辑删除 |
权限表(perms):
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | int | 权限 ID |
| parent_id | int | 父级权限 ID |
| name | varchar | 权限名称 |
| identifier | varchar | 权限标识 |
| path | int | 权限路由路径 |
| component | varchar | 权限路由组件 |
| type | int | 权限类型,0 目录/1 菜单/2 操作 |
| sort_id | int | 排序 ID |
| status | int | 权限状态,1 显示/0 隐藏 |
| deleted | bigint | 删除状态,0 未删除 该字段用于逻辑删除 |
用户表(users):
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | int | 用户 ID |
| dept_id | int | 关联部门 ID |
| role_id | int | 关联角色 ID |
| username | varchar | 账户账号 |
| password | varchar | 账户密码 |
| salts | varchar | 账户盐值 |
| realname | varchar | 真实姓名 |
| remarks | varchar | 用户备注 |
| status | int | 账户状态,1 正常/0 禁用 |
| deleted | bigint | 删除状态,0 未删除 该字段用于逻辑删除 |
操作日志表(actionlog):
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | int | 日志 ID |
| user_id | int | 关联用户 ID |
| ip | varchar | 操作 IP 信息 |
| address | varchar | 操作 IP 地址 |
| timestamp | bigint | 操作时间戳 |
| title | varchar | 日志标题 |
| request_url | varchar | 请求地址 |
| request_method | varchar | 请求方式 |
| request_params | text | 请求参数 |
| response_result | text | 响应结果 |
附数据库脚本:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for actionlog
-- ----------------------------
DROP TABLE IF EXISTS `actionlog`;
CREATE TABLE `actionlog` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '日志ID',
`user_id` int NOT NULL COMMENT '关联用户ID',
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作IP信息',
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作IP地址',
`timestamp` bigint NOT NULL COMMENT '操作时间戳',
`title` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '日志标题',
`request_url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求地址',
`request_method` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求方式',
`request_params` text COLLATE utf8mb4_general_ci COMMENT '请求参数',
`response_result` text COLLATE utf8mb4_general_ci COMMENT '响应结果',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='操作日志表';
-- ----------------------------
-- Records of actionlog
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for dept
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '部门ID',
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '部门名称',
`deleted` bigint NOT NULL DEFAULT '0' COMMENT '删除状态,0未删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='部门表';
-- ----------------------------
-- Records of dept
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for loginlog
-- ----------------------------
DROP TABLE IF EXISTS `loginlog`;
CREATE TABLE `loginlog` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '日志ID',
`user_id` int NOT NULL COMMENT '关联用户ID',
`ip` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录IP信息',
`address` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录IP地址',
`timestamp` bigint NOT NULL COMMENT '登录时间戳',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='登录日志表';
-- ----------------------------
-- Records of loginlog
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for perms
-- ----------------------------
DROP TABLE IF EXISTS `perms`;
CREATE TABLE `perms` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '权限ID',
`parent_id` int NOT NULL COMMENT '父级权限ID',
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '权限名称',
`identifier` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '权限标识',
`path` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '权限路由路径',
`component` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '权限路由组件',
`type` int NOT NULL COMMENT '权限类型,0目录/1菜单/2操作',
`sort_id` int NOT NULL DEFAULT '0' COMMENT '排序ID',
`status` int NOT NULL DEFAULT '1' COMMENT '权限状态,1显示/0隐藏',
`deleted` bigint NOT NULL DEFAULT '0' COMMENT '删除状态,0未删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='权限表';
-- ----------------------------
-- Records of perms
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色名称',
`perms` text COLLATE utf8mb4_general_ci COMMENT '授权的权限菜单列表',
`remarks` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '-' COMMENT '角色备注',
`deleted` bigint NOT NULL DEFAULT '0' COMMENT '删除状态,0未删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='角色表';
-- ----------------------------
-- Records of role
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`dept_id` int NOT NULL COMMENT '关联部门ID',
`role_id` int NOT NULL COMMENT '关联角色ID',
`username` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '账户账号',
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '账户密码',
`salts` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '账户盐值',
`realname` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '真实姓名',
`remarks` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户备注',
`status` int NOT NULL COMMENT '账户状态,1正常/0禁用',
`deleted` bigint NOT NULL DEFAULT '0' COMMENT '删除状态,0未删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表';
-- ----------------------------
-- Records of users
-- ----------------------------
BEGIN;
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;构建后端项目
Solon Web
在 IntelliJ IDEA 中创建 Solon 3.7.2 项目,移除多余的控制器、样式文件、视图文件。
修改 Maven 项目配置文件(pom.xml),保留依赖:
<!-- Solon Web -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-web</artifactId>
</dependency>
<!-- Solon Logback -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-logging-logback</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Solon Test -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-test</artifactId>
<scope>test</scope>
</dependency>修改 Solon 项目配置文件(classpath:/app.yml),保留配置:
server:
port: 8080 # 后端API端口号
solon:
logging:
appender:
console: # 控制台输出
level: INFO # 输出级别为INFO的日志
file: # 文件输出
level: INFO # 输出级别为INFO的日志MySQL
修改 Maven 项目配置文件(pom.xml),加入 HikariCP 数据源依赖、MySQL 驱动依赖:
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>修改 Solon 项目配置文件(classpath:/app.yml),配置数据源:
solon:
# ...
dataSources:
ds1!: # 数据源-ds1
class: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://127.0.0.1:3306/sadmin?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456..EasyQuery
EasyQuery 是一个国产开源 ORM 框架,是 Java 下最强的、最懂查询的 ORM。
EasyQuery 文档:https://www.easy-query.com/
参考文档:https://solon.noear.org/article/579
修改 Maven 项目配置文件(pom.xml),加入 EasyQuery 依赖:
<!-- EasyQuery -->
<dependency>
<groupId>com.easy-query</groupId>
<artifactId>sql-solon-plugin</artifactId>
<version>3.1.62</version>
</dependency>
<dependency>
<groupId>com.easy-query</groupId>
<artifactId>sql-processor</artifactId>
<version>3.1.62</version>
</dependency>修改 Solon 项目配置文件(classpath:/app.yml),配置 EasyQuery:
easy-query:
ds1: # 数据源-ds1
database: mysql # 数据库类型设置为mysql
print-sql: true # 打印SQL日志Redis
Redis 作为高性能的内存数据库,核心用于缓存提速、并发控制、数据暂存、异步通信等场景,尤其适合解决业务系统中高频查询、高并发操作、临时数据处理的痛点。
在 Solon 项目中操作 Redis,推荐使用 Redisx 客户端。
Redisx 是一个轻量级的 Redis Client,基于 Jedis 进行的友好封装。
Redisx 文档:https://gitee.com/noear/redisx
修改 Maven 项目配置文件(pom.xml),加入 Redisx 依赖:
<!-- Redisx -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>redisx</artifactId>
<version>1.7.0</version>
</dependency>修改 Solon 项目配置文件(classpath:/app.yml),配置 Redisx:
redis:
rd1: # 数据源-ds1
server: localhost:6379 # Redis服务地址
db: 1 # Redis数据库编号Redisx 中的操作客户端 RedisClient Bean 需要手动构建。
编写 Redisx 配置类(cn.duozai.sadmin.config.RedisxConfig):
/**
* Redisx 配置类
* @visduo
*/
@Configuration // 标记配置类
public class RedisxConfig {
/**
* 构建RedisClient Bean
* @visduo
*
* @Bean:构建一个Bean对象
* @Inject:将redis.rd1配置信息注入给RedisClient
*
* @param client 注入RedisClient
* @return RedisClient
*/
@Bean
public RedisClient redisClient(@Inject("${redis.rd1}") RedisClient client) {
return client;
}
}SaToken
SaToken 是一款开源、免费、轻量级的 Java 权限认证框架,让鉴权变得简单、优雅。
SaToken 文档:https://sa-token.cc/
参考文档:https://solon.noear.org/article/110
修改 Maven 项目配置文件(pom.xml),加入 SaToken 依赖、SaToken-Redisx 依赖:
<!-- SaToken-Solon -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-solon-plugin</artifactId>
<version>1.44.0</version>
</dependency>
<!-- SaToken-Redisx -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redisx</artifactId>
<version>1.44.0</version>
</dependency>修改 Solon 项目配置文件(classpath:/app.yml),配置 SaToken:
sa-token:
token-name: authtoken # Token名称
timeout: 2592000 # Token有效期
is-concurrent: false # 是否允许同一账号并发登录
token-style: uuid # Token风格
is-log: true # 打印日志编写 SaToken 配置类(cn.duozai.sadmin.config.SaTokenConfig):
/**
* SaToken配置类
* @visduo
*/
@Configuration
public class SaTokenConfig {
/**
* 构建SaTokenDao Bean
* @visduo
*
* @Inject:注入RedisClient
* 多种 Redis 接口适配可以复用一份配置
* 参考文档:https://solon.noear.org/article/592
*
* @param client 注入RedisClient
* @return SaTokenDao
*/
@Bean
public SaTokenDao saTokenDao(@Inject RedisClient client){
return new SaTokenDaoForRedisx(client);
}
}HuTool
Hutool 是一个功能丰富且易用的 Java 工具库,封装的工具涵盖了字符串、数字、集合、编码、日期、文件、IO、加密、数据库 JDBC、JSON、HTTP 客户端等一系列操作。
HuTool 文档:https://www.hutool.cn/
修改 Maven 项目配置文件(pom.xml),加入 HuTool 依赖:
<!-- HuTool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.41</version>
</dependency>ip2region
ip2region 是一个离线 IP 地址定位库和 IP 定位数据管理框架,同时支持 IPv4 和 IPv6,10 微秒级别的查询效率,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现。
ip2region 文档:https://gitee.com/lionsoul/ip2region
修改 Maven 项目配置文件(pom.xml),加入 ip2region 依赖:
<!-- ip2region -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>3.1.1</version>
</dependency>下载 ip2region_v4.xdb 数据库文件,放至 classpath:/db 目录下:
编写 ip2region 工具类(cn.duozai.sadmin.utils.ClientipUtil):
/**
* 客户端IP地址工具类
* @visduo
*/
public class ClientipUtil {
/**
* 日志记录器
*/
private static final Logger logger = LoggerFactory.getLogger(ClientipUtil.class);
/**
* ip2region数据库文件路径
*
* ResourceUtil.getResource().getPath():Solon内置工具类提供的方法,用于获取classpath下的文件的具体路径
*/
private static final String dbPath = ResourceUtil.getResource("db/ip2region_v4.xdb").getPath();
/**
* ip2region版本,设定为IPv4
*/
private static final Version version = Version.IPv4;
/**
* 解析IP地址
* @visduo
*
* @param ip IP信息
* @return IP地址
*/
public static String parse(String ip) {
// 0、特殊IP处理
if(ip.contains("localhost")) {
// localhost直接返回内网IP
return "内网IP";
} else if(!Validator.isIpv4(ip)) {
// 判断IPv4地址是否合法,不合法则结束
// 参考文档:https://plus.hutool.cn/apidocs/cn/hutool/core/lang/Validator.html
return "未知";
} else if(Ipv4Util.isInnerIP(ip)) {
// 其他格式的内网IP由ip2region处理结果比较乱,可以调用HuTool工具类判断是否为内网IP
// 参考文档:https://plus.hutool.cn/apidocs/cn/hutool/core/net/Ipv4Util.html
return "内网IP";
}
// 参考文档:参考文档:https://gitee.com/lionsoul/ip2region/tree/master/binding/java
// 1、文件验证
try {
Searcher.verifyFromFile(dbPath);
} catch (Exception e) {
// 适用性验证失败
// 当前查询客户端实现不适用于dbPath指定的xdb文件的查询.
// 应该停止启动服务,使用合适的xdb文件或者升级到适合dbPath的Searcher实现
logger.error("ip2region数据库文件验证失败:{}", e.getMessage());
return "未知";
}
// 2、从dbPath加载整个xdb到内存
LongByteArray cBuff;
try {
cBuff = Searcher.loadContentFromFile(dbPath);
} catch (Exception e) {
logger.error("ip2region数据库文件加载失败:{}", e.getMessage());
return "未知";
}
// 3、使用上述的cBuff创建一个完全基于内存的查询对象
Searcher searcher;
try {
searcher = Searcher.newWithBuffer(version, cBuff);
} catch (Exception e) {
logger.error("ip2region创建查询对象失败:{}", e.getMessage());
return "未知";
}
// 4、查询
try {
String searchResult = searcher.search(ip);
// 查询结果格式:中国|0|福建省|厦门市|电信
// 只需要提取省市县运营商,格式化字符串提取
String[] split = searchResult.split("\\|");
return split[2] + split[3] + split[4];
} catch (Exception e) {
logger.error("ip2region查询失败:{}", e.getMessage());
}
// 5、关闭资源:该searcher对象可以安全用于并发,等整个服务关闭的时候再关闭searcher
// searcher.close();
return "未知";
}
/**
* 测试方法
* @visduo
*
* @param args main args
*/
public static void main(String[] args) {
String ip1 = "192.168.3.1";
String ip2 = "localhost";
String ip3 = "27.154.86.48";
String ip4 = "211.99.98.197";
String ip5 = "112.5.16.1";
logger.debug("{}归属地为:{}", ip1, parse(ip1));
logger.debug("{}归属地为:{}", ip2, parse(ip2));
logger.debug("{}归属地为:{}", ip3, parse(ip3));
logger.debug("{}归属地为:{}", ip4, parse(ip4));
logger.debug("{}归属地为:{}", ip5, parse(ip5));
}
}测试结果:
MD5Salts
MD5Salts(MD5 加盐)是为增强 MD5 算法在密码存储场景中的安全性而设计的一种技术手段,核心是通过引入随机的盐值字符串,解决 MD5 因为相同输入对应相同哈希值而易受彩虹表攻击、暴力破解的问题。
盐值是一段随机生成的字符串,在密码 MD5 哈希时,将盐值与原始密码拼接后再进行 MD5 计算,即使两个用户密码相同,由于盐值不同,最终的哈希值也会完全不同,从而大幅提升破解难度。
编写 MD5 盐值加密工具类(cn.duozai.sadmin.utils.MD5SaltsUtil):
/**
* MD5盐值加密工具类
* @visduo
*/
public class MD5SaltsUtil {
/**
* 日志记录器
*/
private static final Logger logger = LoggerFactory.getLogger(MD5SaltsUtil.class);
/**
* 生成随机盐值
* @visduo
*
* @return 随机盐值
*/
public static String salts() {
// 调用HuTool工具类生成随机16位长度的字符串
// 参考文档:https://plus.hutool.cn/apidocs/cn/hutool/core/util/RandomUtil.html#randomString-int-
return RandomUtil.randomString(16);
}
/**
* MD5盐值加密
* @visduo
*
* @param password 明文密码
* @param salts 盐值
* @return 密文密码
*/
public static String md5(String password, String salts) {
// 密码和盐值进行MD5加密
// 参考文档:https://plus.hutool.cn/apidocs/cn/hutool/crypto/SecureUtil.html#md5--
// 在明文密码的基础上进行撒盐的规则可自定义
return SecureUtil.md5(salts + password + salts + salts);
}
/**
* 测试方法
* @visduo
*
* @param args main args
*/
public static void main(String[] args) {
// 明文密码
String password = "123456";
// 普通MD5加密密文密码
String md5Password = SecureUtil.md5(password);
// 加盐MD5加密密文密码
String md5SaltsPassword = md5(password, salts());
logger.debug("密码{}的普通MD5加密密文密码为:{}", password, md5Password);
logger.debug("密码{}的加盐MD5加密密文密码为:{}", password, md5SaltsPassword);
}
}测试结果:
ResponseResult
ResponseResult 是业务上自定义的统一响应结果类,核心作用是为了规范接口返回格式,统一前后端数据交互标准。后端所有的接口不再零散返回字符串、实体类等数据,而是统一包装成 ResponseResult 对象,让前端能以固定格式解析结果。
一个标准的 ResponseResult 通常包含 3 个核心字段:
| 名称 | 描述 |
|---|---|
| code | 响应状态,通常是 int/枚举类型 如 200/成功、-1/失败、500/系统异常、400/参数错误、401/未登录 |
| message | 响应信息,通常是 String 类型 如成功时返回操作成功,失败时返回具体错误提示 |
| data | 响应数据,通常是 Object/范型 一般返回业务数据,成功时返回具体数据(如列表数据),失败时返回 null |
编写统一响应结果类(cn.duozai.sadmin.utils.ResponseResult):
/**
* 统一响应结果类
* @visduo
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseResult {
/**
* 响应码
* 200成功/-1失败/500异常/401未登录/403无权限/404不存在/400参数错误
*/
public Integer code;
/**
* 响应信息
*/
public String message;
/**
* 响应数据
*/
public Object data;
/**
* 响应成功
* @visduo
*
* @param message 响应信息
* @param data 响应数据
* @return 响应结果实体
*/
public static ResponseResult success(String message, Object data) {
return new ResponseResult(200, message, data);
}
/**
* 响应失败
* @visduo
*
* @param message 响应信息
* @param data 响应数据
* @return 响应结果实体
*/
public static ResponseResult failure(String message, Object data) {
return new ResponseResult(-1, message, data);
}
/**
* 响应异常
* @visduo
*
* @param message 响应信息
* @param data 响应数据
* @return 响应结果实体
*/
public static ResponseResult error(String message, Object data) {
return new ResponseResult(500, message, data);
}
}Entity
使用 EasyQueryAssistant 插件生成数据库表实体类、代理类,并建立联表关系、配置逻辑删除属性:
用户表实体类(cn.duozai.sadmin.repository.UsersEntity):
/**
* 用户表 实体类。
*
* @author easy-query-plugin automatic generation
* @since 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@Table(value = "users")
@EntityProxy
public class UsersEntity implements ProxyEntityAvailable<UsersEntity, UsersEntityProxy> {
// ...
/**
* 删除状态,0未删除
*
* @LogicDelete:配置逻辑删除
* @LogicDeleteStrategyEnum.DELETE_LONG_TIMESTAMP:逻辑删除字段为Long型,值为当前时间戳
* 执行删除时,将删除时间戳保存到deleted中
*/
@LogicDelete(strategy = LogicDeleteStrategyEnum.DELETE_LONG_TIMESTAMP)
private Long deleted;
/**
* 关联部门表实体
*/
@Navigate(value = RelationTypeEnum.ManyToOne, selfProperty = {UsersEntity.Fields.deptId}, targetProperty = {DeptEntity.Fields.id})
private DeptEntity dept;
/**
* 关联角色表实体
*/
@Navigate(value = RelationTypeEnum.ManyToOne, selfProperty = {UsersEntity.Fields.roleId}, targetProperty = {RoleEntity.Fields.id})
private RoleEntity role;
}其余实体类操作、修改方式一致。
Git
Git 是目前最流行的分布式版本控制系统,核心价值是解决多人协作开发和代码变更追溯的痛点,现在几乎所有互联网公司、开源项目都用 Git 管理代码。
主流的 Git 代码托管平台:GitHub、Gitee、GitCode、Gitea(私有化)、Gitlab(私有化)等。
项目开发过程,选择使用 GitHub 进行代码托管。
GitHub 文档:https://github.com/
在 GitHub 上创建一个远程仓库:
仓库创建完成后,根据 GitHub 提示在创建本地仓库并与远程仓库建立关联,将后端项目推送至 Github:
构建前端项目
Vue 3
在终端中执行指令,创建 Vue 3 项目:
npm init vue@latest使用 IntelliJ IDEA 打开创建的 Vue 3 前端项目,并安装依赖项:
ElementPlus
ElementPlus 是一款基于 Vue 3,面向设计师和开发者的组件库。
ElementPlus 文档:https://element-plus.org/zh-CN/
在终端中执行指令,安装 ElementPlus:
npm install element-plus --save修改项目入口文件(main.js),完整引入 ElementPlus:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
// 完整引入ElementPlus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
// 安装ElementPlus
app.use(ElementPlus)
app.mount('#app')Axios
Axios 是一个基于 Promise 的 HTTP 库,可以发送 GET、POST、PUT、DELETE 等请求。
Axios 文档:http://www.axios-js.com/
在终端中执行指令,安装 Axios:
npm install axios编写 Axios 配置文件(plugins/axios.js):
"use strict";
import axios from "axios";
// Axios配置
let config = {
// 统一请求前缀
baseURL: "http://localhost:8080"
};
const _axios = axios.create(config);
// Axios请求拦截器
_axios.interceptors.request.use(
function(config) {
// Do something before request is sent
return config;
},
function(error) {
// Do something with request error
return Promise.reject(error);
}
);
// Axios响应拦截器
_axios.interceptors.response.use(
function(response) {
// Do something with response data
return response;
},
function(error) {
// Do something with response error
return Promise.reject(error);
}
);
const Plugin = {
install(app, options) {
app.axios = _axios;
window.axios = _axios;
}
}
export default Plugin;修改项目入口文件(main.js),引入 Axios:
// 引入Axios
import axios from '@/plugins/axios.js'
// 安装Axios
app.use(axios)QS
QS 是一款数据序列化工具,可以将 JSON 对象转为 URL 编码的表单格式字符串(key1=value1&key2=value2),Axios 常搭配 QS 使用,将默认传递的 JSON 参数转换成表单格式字符串。
QS 文档:https://www.npmjs.com/package/qs
在终端中执行指令,安装 QS:
npm install qsGit
在 GitHub 上创建一个远程仓库,用于存放前端项目。
前端项目与后端项目的仓库是分开的,需要分别创建,创建、初始化、推送方式一致。