Spring Boot图书管理系统详细分析文档
1. 项目概述
本文档对基于Spring Boot实现的图书管理系统进行详细分析。该项目是一个典型的Web应用程序,采用了Spring Boot框架,结合MyBatis作为ORM工具,实现了图书信息的管理功能,包括图书的添加、查询、修改和删除等操作,以及用户登录验证功能。
1.1 项目地址
1.2 技术栈
- 后端框架:Spring Boot
- ORM框架:MyBatis
- 数据库:MySQL
- 前端技术:原生的框架
1.3 系统架构
该系统采用经典的Spring Boot MVC分层架构,主要包括以下几层:
- 控制器层(Controller):处理HTTP请求,接收前端数据并返回响应
- 服务层(Service):实现业务逻辑
- 数据访问层(Mapper):通过MyBatis实现与数据库的交互
- 数据模型层(Model):定义数据实体类
- 数据库层(Database):存储系统数据

2. 项目结构分析
2.1 目录结构
项目采用标准的Maven项目结构,主要代码位于src/main/java/org/example/jd20250417springbookdemo
目录下,按功能模块划分为多个包:
Mermaid
src/main/java/org/example/jd20250417springbookdemo/
├── contant/ # 常量定义
├── controller/ # 控制器类
│ ├── BookInfoController.java
│ └── UserInfoController.java
├── enums/ # 枚举类
│ └── BookStatusEnum.java
├── mapper/ # MyBatis映射接口
│ ├── BookInfoMapper.java
│ └── UserInfoMapper.java
├── model/ # 数据模型类
│ ├── BookInfo.java
│ ├── PageRequest.java
│ ├── ResponseResult.java
│ ├── Result.java
│ └── UserInfo.java
├── service/ # 服务类
│ ├── BookInfoService.java
│ └── UserInfoService.java
└── Jd20250417SpringbookDemoApplication.java # 应用程序入口类
2.2 数据流程
系统的数据流程如下图所示,展示了从Web浏览器发起请求到数据库操作的完整流程:

3. 核心组件详细分析
3.1 数据模型层(Model)
数据模型层定义了系统中使用的各种数据实体类,是系统的基础。
3.1.1 BookInfo.java
BookInfo
类是图书信息的实体类,定义了图书的基本属性。
java
public class BookInfo {
private Integer bookId; // 图书ID
private String bookName; // 图书名称
private String author; // 作者
private Integer count; // 数量
private Double price; // 价格
private String publish; // 出版社
private Integer status; // 状态(0-删除 1-正常 2-不可借阅)
private String statusCN; // 状态中文描述
// getter和setter方法
// ...
}
主要属性说明:
bookId
:图书的唯一标识符bookName
:图书名称author
:图书作者count
:图书数量price
:图书价格publish
:出版社status
:图书状态,使用整数表示不同状态statusCN
:图书状态的中文描述
3.1.2 UserInfo.java
UserInfo
类是用户信息的实体类,定义了用户的基本属性。
java
public class UserInfo {
private Integer userId; // 用户ID
private String userName; // 用户名
private String password; // 密码
// getter和setter方法
// ...
}
主要属性说明:
userId
:用户的唯一标识符userName
:用户名password
:用户密码
3.1.3 PageRequest.java
PageRequest
类用于实现分页查询,定义了分页相关的属性。
java
public class PageRequest {
private Integer currentPage; // 当前页码
private Integer pageSize; // 每页显示数量
// getter和setter方法
// ...
}
主要属性说明:
currentPage
:当前页码pageSize
:每页显示的记录数量
3.1.4 ResponseResult.java 和 Result.java
这两个类用于统一处理API响应结果,提供了标准化的响应格式。
ResponseResult.java
:
java
public class ResponseResult<T> {
private Integer count; // 总记录数
private List<T> records; // 数据记录列表
private PageRequest pageRequest; // 分页请求信息
// 构造方法和工具方法
// ...
}
Result.java
:
java
public class Result {
private Boolean success; // 是否成功
private String code; // 状态码
private String message; // 消息
private Object data; // 数据
// 静态工厂方法
public static Result success(Object data) {
// 创建成功响应
}
public static Result fail(String message) {
// 创建失败响应
}
// getter和setter方法
// ...
}
3.2 数据访问层(Mapper)
数据访问层通过MyBatis框架实现与数据库的交互,定义了SQL操作接口。
3.2.1 BookInfoMapper.java
BookInfoMapper
接口定义了对图书信息表的各种操作。
java
@Mapper
public interface BookInfoMapper {
// 添加图书
@Insert("INSERT INTO `book_info`(`book_name`, `author`, `count`, `price`, `publish`, `status`) " +
"VALUES (#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status})")
void addBook(BookInfo bookInfo);
// 分页查询图书
@Select("<script>" +
"SELECT * FROM `book_info` " +
"WHERE `status` != 0 " +
"LIMIT #{currentPage}, #{pageSize}" +
"</script>")
List<BookInfo> selectBooksByPage(PageRequest pageRequest);
// 统计图书数量
@Select("SELECT COUNT(*) FROM `book_info` WHERE `status` != 0")
Integer count();
// 根据ID查询图书
@Select("SELECT * FROM `book_info` WHERE `book_id` = #{bookId}")
BookInfo queryBookById(Integer bookId);
// 更新图书信息
@Update("<script>" +
"UPDATE `book_info` " +
"SET `book_name` = #{bookName}, " +
"`author` = #{author}, " +
"`count` = #{count}, " +
"`price` = #{price}, " +
"`publish` = #{publish}, " +
"`status` = #{status} " +
"WHERE `book_id` = #{bookId}" +
"</script>")
void updateBook(BookInfo bookInfo);
// 批量删除图书(逻辑删除)
@Update("<script>" +
"UPDATE `book_info` SET `status` = 0 " +
"WHERE `book_id` IN " +
"<foreach collection='array' item='id' open='(' separator=',' close=')'>" +
"#{id}" +
"</foreach>" +
"</script>")
void batchDelete(Integer[] bookIds);
}
主要方法说明:
addBook
:添加新图书selectBooksByPage
:分页查询图书列表count
:统计图书总数queryBookById
:根据ID查询图书详情updateBook
:更新图书信息batchDelete
:批量删除图书(逻辑删除,将状态设为0)
3.2.2 UserInfoMapper.java
UserInfoMapper
接口定义了对用户信息表的操作。
java
@Mapper
public interface UserInfoMapper {
// 根据用户名查询用户信息
@Select("SELECT * FROM `user_info` WHERE user_name = #{username}")
UserInfo queryUserInfoByName(String username);
}
主要方法说明:
queryUserInfoByName
:根据用户名查询用户信息,用于用户登录验证
3.3 服务层(Service)
服务层实现业务逻辑,调用数据访问层完成数据操作。
3.3.1 BookInfoService.java
BookInfoService
类实现了图书管理的业务逻辑。
java
@Service
public class BookInfoService {
@Autowired
private BookInfoMapper bookInfoMapper;
// 添加图书
public void addBook(BookInfo bookInfo) {
bookInfoMapper.addBook(bookInfo);
}
// 分页查询图书列表
public ResponseResult<BookInfo> getListByPage(PageRequest pageRequest) {
// 1. 获取总记录数
Integer count = bookInfoMapper.count();
// 2. 获取当前页面的数据
List<BookInfo> bookInfos = bookInfoMapper.selectBooksByPage(pageRequest);
// 对结果进行二次处理 --> 处理状态码
// 0-删除 1-正常 2-不可借阅
for (BookInfo bookInfo : bookInfos) {
// 前端展示时就能直接展示中文状态
bookInfo.setStatusCN(BookStatusEnum.getStatusByCode(bookInfo.getStatus()).getDesc());
}
// 返回分页结果对象
return new ResponseResult<>(count, bookInfos, pageRequest);
}
// 根据ID查询图书
public BookInfo queryBookById(Integer bookId) {
return bookInfoMapper.queryBookById(bookId);
}
// 更新图书信息
public void updateBook(BookInfo bookInfo) {
bookInfoMapper.updateBook(bookInfo);
}
// 批量删除图书
public void batchDelete(Integer[] bookIds) {
bookInfoMapper.batchDelete(bookIds);
}
}
主要方法说明:
addBook
:添加新图书getListByPage
:分页查询图书列表,并处理状态码转换为中文描述queryBookById
:根据ID查询图书详情updateBook
:更新图书信息batchDelete
:批量删除图书
3.3.2 UserInfoService.java
UserInfoService
类实现了用户相关的业务逻辑。
java
@Service
public class UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
// 根据用户名查询用户信息
public UserInfo queryUserNameByName(String username) {
return userInfoMapper.queryUserInfoByName(username);
}
}
主要方法说明:
queryUserNameByName
:根据用户名查询用户信息,用于用户登录验证
3.4 控制器层(Controller)
控制器层处理HTTP请求,调用服务层完成业务操作。
3.4.1 BookInfoController.java
BookInfoController
类处理图书相关的HTTP请求。
java
@Slf4j
@RequestMapping("/book")
@RestController
public class BookInfoController {
@Autowired
private BookInfoService bookInfoService;
// 添加图书
@PostMapping(value = "/addBook", produces = "application/json")
public Result addBook(@RequestBody BookInfo bookInfo) {
log.info("添加图书,request: {}", bookInfo);
// 参数校验
if (!StringUtils.hasLength(bookInfo.getBookName()) ||
!StringUtils.hasLength(bookInfo.getAuthor()) ||
bookInfo.getCount() == null ||
bookInfo.getPrice() == null ||
!StringUtils.hasLength(bookInfo.getPublish()) ||
bookInfo.getStatus() == null) {
log.warn("添加图书,参数不合法, request: {}", bookInfo);
// 检查各个参数并提供具体错误信息
if (!StringUtils.hasLength(bookInfo.getBookName())) {
return Result.fail("书名不能为空");
}
if (!StringUtils.hasLength(bookInfo.getAuthor())) {
return Result.fail("作者不能为空");
}
if (bookInfo.getCount() == null) {
return Result.fail("数量不能为空");
}
if (bookInfo.getPrice() == null) {
return Result.fail("价格不能为空");
}
if (!StringUtils.hasLength(bookInfo.getPublish())) {
return Result.fail("出版社不能为空");
}
if (bookInfo.getStatus() == null) {
return Result.fail("状态不能为空");
}
}
// 调用服务层添加图书
bookInfoService.addBook(bookInfo);
return Result.success(true);
}
// 分页查询图书列表
@GetMapping("/list")
public ResponseResult<BookInfo> getBookList(PageRequest pageRequest) {
return bookInfoService.getListByPage(pageRequest);
}
// 根据ID查询图书
@GetMapping("/query/{id}")
public Result queryBook(@PathVariable("id") Integer id) {
BookInfo bookInfo = bookInfoService.queryBookById(id);
return Result.success(bookInfo);
}
// 更新图书信息
@PutMapping("/update")
public Result updateBook(@RequestBody BookInfo bookInfo) {
// 参数校验
if (bookInfo.getBookId() == null) {
return Result.fail("图书ID不能为空");
}
// 调用服务层更新图书
bookInfoService.updateBook(bookInfo);
return Result.success(true);
}
// 批量删除图书
@DeleteMapping("/delete")
public Result deleteBooks(Integer[] ids) {
if (ids == null || ids.length == 0) {
return Result.fail("请选择要删除的图书");
}
// 调用服务层批量删除图书
bookInfoService.batchDelete(ids);
return Result.success(true);
}
}
主要方法说明:
addBook
:处理添加图书的POST请求,包含参数校验getBookList
:处理分页查询图书列表的GET请求queryBook
:处理根据ID查询图书的GET请求updateBook
:处理更新图书信息的PUT请求deleteBooks
:处理批量删除图书的DELETE请求
3.4.2 UserInfoController.java
UserInfoController
类处理用户相关的HTTP请求。
java
@Slf4j
@RequestMapping("/user")
@RestController
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
// 用户登录
@RequestMapping("/login")
public Result login(String username, String password, HttpSession session) {
// 验证步骤
// 1. 参数是否规范
// 2. 检验用户名和密码是否正确
// 3. 设置session
// 4. 返回结果
log.info("username: " + username);
if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
return Result.fail("用户名或密码不能为空");
}
// 客户端输入的参数和数据库中的参数进行比较
UserInfo userInfo = userInfoService.queryUserNameByName(username);
// 1. 先确认用户是否存在 2. 再确认密码是否正确
if (userInfo == null) {
return Result.fail("用户名不存在");
}
if (password.equals(userInfo.getPassword())) {
// 清空密码
userInfo.setPassword("");
session.setAttribute(Constants.SESSION_USER_KEY, userInfo);
return Result.success(true);
}
return Result.fail("密码错误");
}
}
主要方法说明:
login
:处理用户登录请求,验证用户名和密码,成功后将用户信息存入Session
3.5 枚举类(Enums)
3.5.1 BookStatusEnum.java
BookStatusEnum
枚举定义了图书的不同状态。
java
public enum BookStatusEnum {
DELETE(0, "删除"),
NORMAL(1, "正常"),
CANNOT_BORROW(2, "不可借阅");
private final Integer code;
private final String desc;
BookStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
// 根据状态码获取对应的枚举值
public static BookStatusEnum getStatusByCode(Integer code) {
for (BookStatusEnum status : BookStatusEnum.values()) {
if (status.getCode().equals(code)) {
return status;
}
}
return null;
}
// getter方法
// ...
}
状态说明:
DELETE(0, "删除")
:图书已删除NORMAL(1, "正常")
:图书状态正常,可借阅CANNOT_BORROW(2, "不可借阅")
:图书不可借阅
3.6 常量类(Constants)
3.6.1 Constants.java
Constants
类定义了系统中使用的常量。
java
public class Constants {
// Session中存储用户信息的键
public static final String SESSION_USER_KEY = "userInfo";
}
4. 数据库设计
根据代码分析,系统使用了两个主要的数据库表:
4.1 book_info表
存储图书信息的表,包含以下字段:
字段名 | 类型 | 说明 |
---|---|---|
book_id | INT | 主键,图书ID |
book_name | VARCHAR | 图书名称 |
author | VARCHAR | 作者 |
count | INT | 数量 |
price | DOUBLE | 价格 |
publish | VARCHAR | 出版社 |
status | INT | 状态(0-删除 1-正常 2-不可借阅) |
4.2 user_info表
存储用户信息的表,包含以下字段:
字段名 | 类型 | 说明 |
---|---|---|
user_id | INT | 主键,用户ID |
user_name | VARCHAR | 用户名 |
password | VARCHAR | 密码 |
5. 系统功能分析
5.1 用户功能
- 用户登录:验证用户名和密码,成功后将用户信息存入Session
5.2 图书管理功能
- 添加图书:添加新的图书信息
- 查询图书:分页查询图书列表
- 图书详情:根据ID查询图书详细信息
- 更新图书:修改图书信息
- 删除图书:批量删除图书(逻辑删除)
6. 系统特点与优势
6.1 架构清晰
系统采用经典的Spring Boot MVC分层架构,各层职责明确,代码结构清晰,便于维护和扩展。
6.2 代码规范
代码风格统一,命名规范,注释详细,便于理解和维护。
6.3 数据校验
系统对输入数据进行了严格的校验,提高了系统的健壮性和安全性。
6.4 统一响应格式
系统使用Result
和ResponseResult
类统一处理API响应,提供了标准化的响应格式,便于前端处理。
6.5 分页查询
系统实现了分页查询功能,提高了查询效率和用户体验。
7. 可改进之处
7.1 安全性
- 密码存储:当前密码以明文方式存储,建议使用加密算法(如BCrypt)对密码进行加密
- 权限控制:可以引入Spring Security实现更完善的权限控制
7.2 功能扩展
- 图书借阅功能:增加图书借阅、归还等功能
- 用户管理:增加用户注册、修改密码等功能
- 图书分类:增加图书分类功能,便于图书管理和查询
7.3 性能优化
- 缓存:引入Redis等缓存技术,提高查询效率
- 索引:优化数据库索引,提高查询性能
8. 总结
该Spring Boot图书管理系统是一个典型的Web应用程序,采用了Spring Boot框架和MyBatis ORM工具,实现了图书的基本管理功能和用户登录功能。系统架构清晰,代码规范,具有良好的可维护性和扩展性。通过对该系统的分析,可以深入理解Spring Boot应用的开发模式和最佳实践。