build(config): add docker support and project documentation

- Integrate Docker Spring Boot application plugin for containerization
- Bump project version to 0.1
- Include MIT license and project README
- Ignore IDE configuration files in version control
This commit is contained in:
2026-05-24 01:51:41 +08:00
parent 57683ad64c
commit aa745f8d81
6 changed files with 367 additions and 1 deletions
+1
View File
@@ -45,3 +45,4 @@ out/
**/application-dev.properties **/application-dev.properties
**/.env **/.env
/log/ /log/
.idea/
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 msksbr
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+264
View File
@@ -0,0 +1,264 @@
# 图书管理系统
<p align="center">
<img src="https://img.shields.io/badge/version-0.1-blue" alt="version">
<img src="https://img.shields.io/badge/Kotlin-2.2.21-purple?logo=kotlin" alt="Kotlin">
<img src="https://img.shields.io/badge/Spring_Boot-4.0.6-green?logo=springboot" alt="Spring Boot">
<img src="https://img.shields.io/badge/MySQL-8.0-orange?logo=mysql" alt="MySQL">
<img src="https://img.shields.io/badge/Java-21-red" alt="Java 21">
<img src="https://img.shields.io/badge/license-MIT-brightgreen" alt="license">
</p>
一个基于 **Spring Boot + Kotlin + MyBatis-Plus** 的后端图书管理系统,提供图书管理、用户认证、借阅归还等核心功能。项目注重安全性、可审计性,等保三级审计日志开箱即用。
## 功能
- **认证与授权** — JWT 无状态登录,Argon2 密码哈希,基于 AOP 的角色权限校验(admin / user),防用户枚举攻击
- **图书管理** — 搜索(书名 / 作者)、查看详情、新增 / 修改 / 删除 / 调整库存(管理员),书名 + 作者判重
- **借阅管理** — 借书 / 还书(自动扣减 / 恢复库存)、个人借阅记录、管理员可查看全部借阅及手动操作
- **审计日志** — 等保三级(GB/T 22239-2019 8.1.4.3),结构化审计日志,含用户标识、来源 IP、操作参数、结果摘要,支持持久化到文件
- **统一响应** — 所有接口返回 `ApiResult<T>` 统一格式,业务码自动映射 HTTP 状态码
- **OpenAPI 文档** — SpringDoc 自动生成,支持在线调试
## 技术栈
| 类别 | 技术 | 版本 | 说明 |
|------|------|------|------|
| 语言 | Kotlin | 2.2.21 | JVM 目标 |
| 框架 | Spring Boot | 4.0.6 | |
| ORM | MyBatis-Plus | 3.5.15 | 零 XML 配置,BaseMapper 通用 CRUD |
| 数据库 | MySQL | 8.0 | InnoDButf8mb4 |
| 认证 | jjwt (JSON Web Token) | 0.13.0 | HMAC-SHA256 签名 |
| 密码 | Argon2 (Spring Security Crypto) | 5.3+ | 抗 GPU/ASIC 暴力破解 |
| 协程 | kotlinx-coroutines | 1.10.2 | 并发查询用户 + 图书信息 |
| 文档 | SpringDoc OpenAPI | 3.0.3 | Swagger UI |
| AOP | AspectJ Weaver | — | 日志 / 审计 / 权限三切面 |
| 日志 | Logback + kotlin-logging | 7.0.0 | Janino 条件表达式,按天滚动 |
## 快速开始
### 1. 准备数据库
MySQL 8.0 中新建一个数据库(如 `bookmgr`),然后运行建表脚本:
```bash
mysql -u root -p bookmgr < bookmgr.schema.sql
```
脚本只建表,不插数据。默认用户由应用首次启动时自动创建。
### 2. 配置环境变量
生产环境通过环境变量注入配置:
```bash
export DB_DRIVER=com.mysql.cj.jdbc.Driver
export DB_TYPE=mysql
export DB_URL=localhost
export DB_PORT=3306
export DB_NAME=bookmgr
export DB_USER=root
export DB_PASSWORD=your-password
export JWT_SECRET=your-secret-at-least-32-chars
export JWT_EXPIRATION_TIME=86400000 # 可选,默认 24 小时,单位毫秒
export LOG_PATH=/var/log/bookmgr # 可选,不设置则不写日志文件
export LOG_EXPORT_AUDIT=true # 可选,审计日志持久化,默认开启
export LOG_EXPORT_RUNTIME=false # 可选,运行日志持久化,默认关闭
export LOG_LEVEL=INFO # 可选,包级别日志级别,默认 INFO
```
| 变量 | 必填 | 说明 |
|------|------|------|
| `DB_DRIVER` | 是 | 驱动类名 |
| `DB_TYPE` | 是 | 数据库类型(mysql |
| `DB_URL` | 是 | 数据库地址 |
| `DB_PORT` | 是 | 数据库端口 |
| `DB_NAME` | 是 | 数据库名 |
| `DB_USER` | 是 | 数据库用户 |
| `DB_PASSWORD` | 是 | 数据库密码 |
| `JWT_SECRET` | **强烈建议** | 不设置则每次启动随机生成,已签发 token 全部失效 |
| `JWT_EXPIRATION_TIME` | 否 | token 有效期(毫秒),默认 86400000(24 小时) |
### 3. 运行
```bash
./gradlew bootRun
```
### 4. 默认用户
应用首次启动时自动创建以下用户(幂等,已存在则跳过):
| 用户名 | 密码 | 角色 |
|--------|------|------|
| `admin` | `admin` | 管理员 |
| `user01` | `user01` | 普通用户 |
| `user02` | `user02` | 普通用户 |
> **注意**:预置用户当前硬编码在 `InitUserRunner` 中。未来计划分三步演进:硬编码 → 配置文件 → 前端初始化向导。生产部署后请第一时间修改密码。
## 开发指南
### IDEA 运行配置
1. 复制 `src/main/resources/application.yaml``application-dev.yaml`,修改数据库连接等本地配置
2. IDEA → Run Configuration → Active profiles 填写 `dev`
![](readme.Assets/IdeaRunConfig.png)
3. 启动即可
示例 `application-dev.yaml`
```yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/bookmgr
username: root
password: your-password
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl
logging:
level:
com.msksbr.bookmgr: DEBUG
export:
path: ./log
runtime-enabled: true
jwt:
expiration: 86400000
springdoc:
swagger-ui:
enabled: true
api-docs:
enabled: true
```
### Swagger 文档
开发环境启动后访问:`http://localhost:8080/swagger-ui/index.html`
> 生产环境默认关闭,防止 API 文档暴露。
### API 概览
```
公开接口:
POST /api/auth/login — 登录
POST /api/auth/logout — 登出
GET /api/books/search — 搜索图书
GET /api/books/getone — 图书详情
GET /api/books/getall — 所有图书
普通用户(需 JWT + user 角色):
GET /api/borrows/getall — 我的借阅
GET /api/borrows/search — 搜索我的借阅
GET /api/borrows/getone — 借阅详情
POST /api/borrows/borrowbook — 借书
POST /api/borrows/returnbook — 还书
管理员(需 JWT + admin 角色):
POST /api/admin/books/add — 新增图书
POST /api/admin/books/update — 修改图书
POST /api/admin/books/delete — 删除图书
POST /api/admin/books/update-stock — 调整库存
GET /api/admin/borrows/search — 搜索借阅
GET /api/admin/borrows/getone — 借阅详情
GET /api/admin/borrows/getall — 全部借阅
POST /api/admin/borrows/borrowbook — 手动借书
POST /api/admin/borrows/returnbook — 手动还书
```
请求示例:
```bash
# 登录获取 token
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
# 搜索图书
curl "http://localhost:8080/api/books/search?query=西游记"
# 借书
curl -X POST "http://localhost:8080/api/borrows/borrowbook?bookId=1" \
-H "Authorization: Bearer <token>"
```
### 项目结构
```
src/main/kotlin/com/msksbr/bookmgr/
├── controller/ # 控制器 — 接口入口
├── service/ # 服务接口
│ └── impl/ # 服务实现 — 业务逻辑
├── mapper/ # MyBatis-Plus 映射器 — 数据访问
├── entity/ # 实体 — 表映射
├── dto/ # 请求体 DTO
├── vo/ # 响应 VO
│ └── borrow/ # 借阅相关 VO
├── config/ # 配置 — JWT / 密码 / AOP 切面 / 异常处理 / OpenAPI
├── annotation/ # 自定义注解 — @RequireRole
├── runner/ # 启动任务 — InitUserRunner
├── script/ # 扩展 — log / audit Logger 快捷获取
└── template/ # ApiResult<T> 统一响应模板
```
## 部署
### Java 直接运行
```bash
./gradlew bootJar
java -jar build/libs/bookMgr-0.1.jar
```
> `bootJar` 会自动排除 `application-dev.yaml`。
### Docker
Dockerfile 待补充。镜像后续发布至私有 Gitea 仓库:
[git.msksbr.com/msksbr/bookMgr](https://git.msksbr.com/msksbr/bookMgr)
### Docker Compose
Compose 文件待补充。注意生产环境应执行 `bookmgr.schema.sql`(仅建表,不含种子数据),用户由应用初始化。
## 审计日志
满足等保三级要求的结构化审计日志,默认输出到控制台。配置 `LOG_PATH` 后自动持久化到文件:
```
$LOG_PATH/
├── audit/
│ ├── audit.log # 当天审计日志
│ └── audit.2026-05-23.0.gz # 历史归档(滚动策略:按天 + 100MB,保留 365 天,上限 20GB
└── runtime/
├── runtime.log # 当天运行日志(需 LOG_EXPORT_RUNTIME=true
└── runtime.2026-05-23.0.gz
```
审计日志记录字段:事件类型(CTRL / SVC)、用户名、用户 ID、角色、来源 IP、User-Agent、HTTP 方法 + 路径、操作参数(敏感字段自动掩码)、返回状态码、操作对象 ID、耗时。
## 安全特性
- 密码使用 **Argon2** 哈希存储,即使数据库泄露也无法还原
- 登录失败时对齐响应时间(dummy hash),防止基于延时的用户枚举
- 敏感参数(password / token / secret / authorization)在审计日志中自动掩码为 `***`
- JWT 密钥支持环境变量注入,不配置则每次启动随机生成
- 全局异常捕获,不向客户端泄露堆栈信息
- 生产环境默认关闭 Swagger 文档
## 声明
本项目基于 **MIT** 协议开源。本软件无任何销售渠道,不收取费用。请遵守开源协议合法使用。
## 作者
- 个人主页:[msksbr.com](https://msksbr.com/)
- 项目仓库:[git.msksbr.com/msksbr/bookMgr](https://git.msksbr.com/msksbr/bookMgr)
+59
View File
@@ -0,0 +1,59 @@
/*
Navicat Premium Dump SQL
Source Server : root@localhost
Source Server Type : MySQL
Source Server Version : 80045 (8.0.45)
Source Host : 127.0.0.1:3306
Source Schema : bookmgr
Target Server Type : MySQL
Target Server Version : 80045 (8.0.45)
File Encoding : 65001
Date: 24/05/2026 01:05:44
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for book
-- ----------------------------
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`author` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`stock` int DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Table structure for borrow_record
-- ----------------------------
DROP TABLE IF EXISTS `borrow_record`;
CREATE TABLE `borrow_record` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint DEFAULT NULL,
`book_id` bigint DEFAULT NULL,
`borrow_time` datetime DEFAULT NULL,
`return_time` datetime DEFAULT NULL,
`status` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`role` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT 'USER',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SET FOREIGN_KEY_CHECKS = 1;
+22 -1
View File
@@ -3,10 +3,11 @@ plugins {
kotlin("plugin.spring") version "2.2.21" kotlin("plugin.spring") version "2.2.21"
id("org.springframework.boot") version "4.0.6" id("org.springframework.boot") version "4.0.6"
id("io.spring.dependency-management") version "1.1.7" id("io.spring.dependency-management") version "1.1.7"
id("com.bmuschko.docker-spring-boot-application") version "10.0.0"
} }
group = "com.msksbr" group = "com.msksbr"
version = "0.0.1-SNAPSHOT" version = "0.1"
description = "bookMgr" description = "bookMgr"
java { java {
@@ -58,3 +59,23 @@ tasks.bootJar {
exclude("application-dev.yaml") exclude("application-dev.yaml")
} }
val giteaRegistry = System.getenv("GITEA_REGISTRY") ?: "gitea.example.com"
val giteaUser = System.getenv("GITEA_USERNAME") ?: ""
val giteaToken = System.getenv("GITEA_TOKEN") ?: ""
docker {
springBootApplication {
baseImage.set("bellsoft/liberica-runtime-container:jre-21-slim-musl")
ports.set(listOf(8080))
images.set(setOf(
"$giteaRegistry/$giteaUser/bookMgr:${project.version}",
"$giteaRegistry/$giteaUser/bookMgr:latest"
))
jvmArgs.set(listOf("-Xmx512m", "-Dfile.encoding=UTF-8"))
}
registryCredentials {
url.set("https://$giteaRegistry")
username.set(giteaUser)
password.set(giteaToken)
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB