Money - 基于 Spring Boot 2.7、Spring Security、MyBatis-Plus 的后台快速开发框架
- 主流技术栈:基于 Spring Boot 2.7、Spring Security、MyBatis-Plus 等主流技术构建,代码规范,风格干净。
- 组件化设计:采用组件化思想,功能模块按需引入,开箱即用。
- 前后端分离:面向 API 接口开发,前端配套代码:Qk-MONEY UI。
依赖 | 版本 |
---|---|
JDK | 1.8+ |
Maven | 3.8.1 |
Spring Boot | 2.7.18 |
MyBatis-Plus | 3.5.7 |
JJWT | 0.11.5 |
Hutool | 5.8.34 |
Jackson | 2.13.5 |
Spring Doc | 1.8.0 |
Qiniu | 7.13.1 |
XXL-JOB | 2.3.1 |
- 主 POM:根目录下的
pom.xml
,声明模块版本。 - 清单 POM:
qk-money-parent
包下的pom.xml
,声明第三方依赖版本。
功能模块 | 描述 |
---|---|
通用 Web 功能 | 全局响应处理、全局异常处理、日志链路追踪。 |
权限认证 | 基于 JWT 和 RBAC 模型的认证授权解决方案。 |
多租户 | 基于表字段的多租户支持。 |
对象存储 OSS | 支持本地存储和七牛云存储。 |
缓存模块 | 支持 Hutool Cache、Redis(集成 Spring Cache)。 |
邮件发送 | 提供邮件发送功能。 |
定时任务 | 集成 XXL-JOB,支持分布式定时任务。 |
国际化 | 支持多语言、多时区。 |
接口文档 | 集成 OpenAPI 3,自动生成接口文档。 |
代码生成器 | 提供 CRUD 代码生成功能。 |
日志管理 | 使用 Logback 实现日志本地化。 |
模块 | 描述 |
---|---|
qk-money-parent 📜 |
👉 父模块:BOM(依赖版本清单) 统一管理第三方依赖版本。 |
qk-money-app |
👉 应用模块:主要开发的模块 |
money-app-api |
应用 API 模块:常量枚举、异常、Entity、DTO、VO 等。 |
money-app-biz |
应用业务模块:Controller、Service、Mapper 等,启动类所在。 |
money-app-system |
系统管理模块:预设的权限管理系统,可单独拆卸。 |
qk-money-common |
👉 通用模块:各种方便易用的功能包 |
money-common-web 📜 |
通用 Web 模块:全局响应处理、异常处理、日志链路追踪等。 |
money-common-mybatis 📃 |
MyBatis 模块:分页插件、审计字段填充、代码生成器。 |
money-common-cache |
缓存模块:本地缓存和 Redis 缓存。 |
money-common-mail 📃 |
邮件模块:邮件发送功能。 |
money-common-schedule 📃 |
定时任务模块:集成 XXL-JOB。 |
money-common-oss 📃 |
OSS 模块:本地存储和七牛云存储。 |
money-common-swagger 📃 |
接口文档模块:集成 Swagger(OpenAPI 3)。 |
qk-money-security 📃 |
👉 安全模块:基于 Spring Security 的认证授权功能。 |
qk-money-tenant 📃 |
👉 多租户模块:基于 MyBatis-Plus 的多租户支持。 |
xxl-job-admin |
👉 XXL-JOB 调度中心:分布式任务调度。 |
点击📃查看对应模块使用文档,📜开发前建议先看。
-
克隆项目
git clone https://github.com/ycf1998/qk-money
-
创建 & 初始化数据库
-
修改数据库连接信息
编辑
application-dev.yml
文件,配置数据库连接信息: -
启动项目
运行
QkMoneyApplication
启动项目。
-
建表
CREATE TABLE `qk-money`.`demo` ( `id` bigint UNSIGNED NOT NULL, `name` varchar(255) NOT NULL COMMENT '名称', `create_by` varchar(32) NOT NULL, `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_by` varchar(32) NOT NULL, `update_time` datetime NOT NULL, `tenant_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
- 基础字段:
id
、create_by
、create_time
、update_by
、update_time
。(搭配继承BaseEntity
) - 可选字段:
tenant_id
(租户 ID)。
- 基础字段:
-
运行代码生成器
运行
money-common-mybatis
模块下的MybatisPlusGenerator
: -
调整并补充业务代码
根据生成的代码结构,调整并补充业务逻辑:
功能模块 | 截图 |
---|---|
用户管理 | ![]() |
角色管理 | ![]() |
权限管理 | ![]() |
字典管理 | ![]() |
租户管理 | ![]() |
个人信息管理 | ![]() |
money:
web:
# 全局响应处理器
response-handler: true
# 全局异常处理器
exception-handler: true
# 全局请求日志切面
web-log-aspect:
enabled: true
mode: ignore_get_result
# 多语言
i18n:
enabled: true
support:
- en
# 多时区
timezone:
enabled: true
default-time-zone: GMT+08:00
# 多租户
tenant:
# 开关
enabled: false
# 请求头
header: Y-tenant
# 默认租户id
default-tenant-id: "0"
# 忽略的表
ignore-table:
- sys_tenant
- sys_dict
- sys_dict_detail
# 缓存
cache:
# 本地缓存
local:
# 提供者 hutool(默认)、caffeine
provider: hutool
# hutool-cache参数
hutool:
# 失效策略:LRU(默认)、LFU、FIFO、TIMED、WEAK
strategy: LRU
# 容量
capacity: 102400
# 过期时间:ms,0代表永不过期
ttl: 86400000
# redis 缓存
redis:
# 开关,默认关闭
enabled: false
# 过期时间:ms,主要用于@Cacheable相关注解的过期时间
ttl: 86400000
# 安全
security:
# token配置
token:
# token请求头名称
header: Authorization
# 令牌类型:完整token:"{tokenType} {accessToken}"
token-type: Bearer
# 密钥
secret: money
# access token过期时间 ms,默认8小时
ttl: 28800000
# refresh token过期时间 ms,默认30天
refresh-ttl: 2592000000
# 策略:jwt(自动过期,默认)、redis
strategy: jwt
# 缓存键名
cache-key: "security:token:"
# 忽略的url
ignore:
get:
- /tenants/byCode
- /auth/refreshToken
post:
- /auth/login
- /auth/logout
pattern:
- /error/**
- /actuator/**
- /swagger**/**
- /webjars/**
- /v3/**
- /assets/**
- /demo/**
# 邮件服务
mail:
host: smtp.shahow.top # 邮箱服务器
username: qk-money@money.shahow.top # 账号
password: Vv123456#
properties:
mail:
smtp:
auth: true
starttls: # 使用SSL安全协议,必须配置如下
enable: true
required: true
port: 465 # 端口
protocol: smtps # 协议
default-encoding: utf-8
fromAlias: 麦尼 # 发件人别名
# ================================= 本地
# 目标空间
local.bucket = F:/qk-money/
# 资源处理器
local.resource-handler = /assets/**
# ================================= 七牛云
# 访问密钥
qiniu.access-key =
# 秘密密钥
qiniu.secret-key =
# 是否使用https
qiniu.use-https = false
# 访问域名
qiniu.domain = r3xou9o36.hn-bkt.clouddn.com
# 目标空间
qiniu.bucket = qk-money
# 区域
qiniu.region = huanan
# 令牌过期时间
qiniu.token-expire = 3600
# 上传策略 https://developer.qiniu.com/kodo/1206/put-policy
qiniu.policy.returnBody = {\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"fname\":\"$(x:fname)\",\"age\":\"$(x:age)\"}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 引入Spring上下文配置属性 -->
<springProperty scope="context" name="app_name" source="spring.application.name" defaultValue="app"/>
<!-- 设置变量 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="FILE_LOG_PATTERN" value="%X{requestId}|%X{userId}> %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{36} : %msg%n"/>
<property name="ACCESS_LOG_PATTERN" value="%X{requestId}|%X{userId}> %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] : %msg%n"/>
<property name="LOG_PATH" value="log"/>
<!-- 控制台日志输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 访问日志 -->
<appender name="ACCESS_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/access.log</fileNamePattern>
<maxHistory>7</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${ACCESS_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- INFO级别及以上日志 -->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/service.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/service.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>9GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- ERROR级别日志 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/error.log</file>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/error.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>9GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 异步日志 -->
<appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="FILE_INFO" />
</appender>
<!-- 特定日志记录器配置 -->
<logger name="com.money.web.log.DefaultWebLogAspect" level="info" additivity="false">
<appender-ref ref="ACCESS_LOG" />
</logger>
<!-- 根日志记录器配置 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="ASYNC_FILE_INFO" />
<appender-ref ref="FILE_ERROR" />
</root>
</configuration>