news 2026/7/19 4:13:27

Spring Boot+MyBatis图书管理系统开发实战:从零到部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot+MyBatis图书管理系统开发实战:从零到部署

在实际 Java Web 开发学习路径中,图书管理系统是一个经典且综合性强的练手项目。它涵盖了用户认证、数据增删改查、业务逻辑分层、数据库设计等核心技能点,非常适合用于巩固 Java 基础、理解 MVC 模式以及掌握 Spring Boot + MyBatis 等主流技术栈。本文将基于 IntelliJ IDEA 开发环境,从零开始构建一个功能完整的图书管理系统,重点讲解项目结构设计、数据库表关系、核心功能实现、以及如何排查部署中的常见问题,最终交付一个可运行、可扩展的毕业设计或课程设计级别的项目。

1. 项目核心需求与技术栈选型

一个完整的图书管理系统至少需要实现以下核心功能模块:

  • 用户管理:区分管理员与普通用户,实现登录、注册、权限控制。
  • 图书管理:图书信息的增、删、改、查,包括书名、作者、出版社、库存等字段。
  • 借阅管理:用户借书、还书流程,借阅记录查询,超期提醒或处罚逻辑。
  • 数据统计:简单的数据可视化,如图书借阅排行榜、库存预警等。

基于这些需求,技术栈选择如下:

  • 后端:Spring Boot 2.7.x(兼顾稳定性和新特性)、Spring MVC、MyBatis-Plus(简化 CRUD 操作)。
  • 数据库:MySQL 8.0(或 5.7),使用 InnoDB 存储引擎支持事务。
  • 前端:Thymeleaf 模板引擎(服务端渲染,适合初学者理解前后端交互)、Bootstrap 5(快速构建响应式界面)。
  • 开发工具:IntelliJ IDEA 2022+,Maven 3.6+,JDK 17(与标题中提示的目标发行版一致)。
  • 其他:Druid 数据源(监控 SQL 性能)、Lombok(简化 POJO 编写)。

注意:JDK 版本必须与项目配置一致。如果遇到 “源发行版 17 需要目标发行版 17” 警告,需检查 IDEA 中 Project Structure 的 Project 和 Modules 的 Language level 是否均为 17。

2. 数据库设计与表结构构建

数据库设计是项目的基石,合理的表结构能减少后期业务扩展的阻力。本系统至少需要以下四张核心表:

用户表 (user)

CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `username` varchar(50) NOT NULL UNIQUE COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '密码(加密存储)', `name` varchar(50) DEFAULT NULL COMMENT '真实姓名', `role` int(1) NOT NULL DEFAULT '0' COMMENT '角色:0-普通用户,1-管理员', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

图书表 (book)

CREATE TABLE `book` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `isbn` varchar(20) DEFAULT NULL COMMENT 'ISBN号', `name` varchar(100) NOT NULL COMMENT '图书名称', `author` varchar(50) DEFAULT NULL COMMENT '作者', `publisher` varchar(100) DEFAULT NULL COMMENT '出版社', `total_count` int(11) NOT NULL DEFAULT '0' COMMENT '总库存', `current_count` int(11) NOT NULL DEFAULT '0' COMMENT '当前可借库存', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '上架时间', PRIMARY KEY (`id`), KEY `idx_name` (`name`), KEY `idx_author` (`author`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图书表';

借阅记录表 (borrow_record)

CREATE TABLE `borrow_record` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` int(11) NOT NULL COMMENT '用户ID', `book_id` int(11) NOT NULL COMMENT '图书ID', `borrow_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '借书时间', `expected_return_time` datetime DEFAULT NULL COMMENT '预计归还时间', `actual_return_time` datetime DEFAULT NULL COMMENT '实际归还时间', `status` int(1) NOT NULL DEFAULT '0' COMMENT '状态:0-借阅中,1-已归还,2-超期未还', PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`), KEY `idx_book_id` (`book_id`), CONSTRAINT `fk_borrow_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`), CONSTRAINT `fk_borrow_book` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='借阅记录表';

关键设计要点

  1. 密码字段使用varchar(100)为加密后密文预留空间。
  2. 图书表分离total_countcurrent_count,避免每次借阅都需查询历史记录计算可用库存。
  3. 借阅记录表通过status字段管理生命周期,并设置外键约束保证数据一致性。
  4. 为常用查询字段(如图书名称、作者)建立索引提升查询效率。

3. Spring Boot 项目结构与核心配置

使用 IDEA 创建 Spring Boot 项目后,标准的多模块结构如下:

src/main/java/com/example/library/ ├── LibraryApplication.java # 启动类 ├── config/ │ ├── WebMvcConfig.java # MVC配置(拦截器、静态资源) │ └── MybatisPlusConfig.java # MyBatis-Plus 分页插件配置 ├── controller/ │ ├── LoginController.java # 登录/注册控制 │ ├── BookController.java # 图书管理 │ └── BorrowController.java # 借阅管理 ├── entity/ # 实体类(与数据库表对应) ├── mapper/ # MyBatis Mapper 接口 ├── service/ # 业务逻辑层 │ └── impl/ # 实现类 ├── util/ # 工具类(加密、日期处理等) └── resources/ ├── static/ # CSS/JS/图片 ├── templates/ # Thymeleaf 模板 ├── application.yml # 主配置文件 └── mapper/ # XML 映射文件

application.yml 关键配置

spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/library_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password type: com.alibaba.druid.pool.DruidDataSource thymeleaf: cache: false # 开发时关闭缓存,修改模板立即生效 mode: HTML encoding: UTF-8 server: port: 8080 mybatis-plus: configuration: map-underscore-to-camel-case: true # 自动转换表字段到实体类属性 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除字段 logic-delete-value: 1 logic-not-delete-value: 0

注意:数据库连接参数需根据本地环境调整。若使用 Druid 数据源,需在 pom.xml 中显式引入依赖,并在配置类中开启监控功能(生产环境需配置访问权限)。

4. 核心业务逻辑实现与代码详解

4.1 用户登录与会话管理

登录流程需处理密码加密验证和会话创建。使用 Spring Boot 内置的HttpSession实现简单会话管理:

LoginController 关键代码

@Controller public class LoginController { @Autowired private UserService userService; @PostMapping("/login") public String login(String username, String password, HttpSession session) { User user = userService.findByUsername(username); if (user != null && userService.checkPassword(password, user.getPassword())) { session.setAttribute("loginUser", user); if (user.getRole() == 1) { return "redirect:/admin/index"; // 管理员首页 } return "redirect:/user/index"; // 普通用户首页 } // 登录失败,返回错误信息 return "redirect:/login?error=1"; } @GetMapping("/logout") public String logout(HttpSession session) { session.invalidate(); return "redirect:/login"; } }

密码加密工具类(使用 Spring Security 的 BCrypt):

public class PasswordEncoderUtil { private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); public static String encode(String rawPassword) { return encoder.encode(rawPassword); } public static boolean matches(String rawPassword, String encodedPassword) { return encoder.matches(rawPassword, encodedPassword); } }

关键点:不要明文存储密码。注册时对密码加密后存库,登录时使用matches方法对比。

4.2 图书管理增删改查

利用 MyBatis-Plus 的强大功能,只需定义 Mapper 接口即可获得大部分 CRUD 能力:

BookController 列表查询与分页

@Controller @RequestMapping("/admin/book") public class BookController { @Autowired private BookService bookService; @GetMapping("/list") public String list(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, Model model) { Page<Book> page = new Page<>(pageNum, pageSize); Page<Book> bookPage = bookService.page(page); model.addAttribute("pageInfo", bookPage); return "admin/book_list"; } @PostMapping("/save") public String save(Book book) { // 新增时初始化库存 if (book.getId() == null) { book.setCurrentCount(book.getTotalCount()); } bookService.saveOrUpdate(book); return "redirect:/admin/book/list"; } @PostMapping("/delete") public String delete(Integer id) { // 删除前检查是否有未归还记录 if (borrowService.existsBorrowingRecord(id)) { // 返回错误提示 return "redirect:/admin/book/list?error=1"; } bookService.removeById(id); return "redirect:/admin/book/list"; } }

前端分页控件(Thymeleaf + Bootstrap)

<div th:if="${pageInfo.pages > 1}"> <nav> <ul class="pagination"> <li class="page-item" th:classappend="${pageInfo.current == 1} ? 'disabled'"> <a class="page-link" th:href="@{/admin/book/list(pageNum=1)}">首页</a> </li> <li th:each="pageNum : ${#numbers.sequence(1, pageInfo.pages)}" class="page-item" th:classappend="${pageNum == pageInfo.current} ? 'active'"> <a class="page-link" th:href="@{/admin/book/list(pageNum=${pageNum})}" th:text="${pageNum}"></a> </li> </ul> </nav> </div>

4.3 借阅业务中的事务控制

借书操作需同时更新借阅记录和图书库存,必须保证事务原子性:

BorrowService 借书方法

@Service public class BorrowService { @Autowired private BorrowRecordMapper borrowRecordMapper; @Autowired private BookMapper bookMapper; @Transactional(rollbackFor = Exception.class) // 声明式事务管理 public boolean borrowBook(Integer userId, Integer bookId) { // 1. 检查图书库存 Book book = bookMapper.selectById(bookId); if (book == null || book.getCurrentCount() <= 0) { return false; } // 2. 插入借阅记录 BorrowRecord record = new BorrowRecord(); record.setUserId(userId); record.setBookId(bookId); record.setBorrowTime(new Date()); record.setExpectedReturnTime(calculateReturnDate(30)); // 借期30天 record.setStatus(0); borrowRecordMapper.insert(record); // 3. 更新图书库存 book.setCurrentCount(book.getCurrentCount() - 1); bookMapper.updateById(book); return true; } private Date calculateReturnDate(int days) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, days); return calendar.getTime(); } }

关键点:@Transactional注解确保三步操作要么全部成功,要么全部回滚。避免出现记录插入成功但库存未减少的数据不一致情况。

5. 部署运行与常见问题排查

5.1 项目启动步骤

  1. 环境准备:确保本地已安装 JDK 17、MySQL 8.0+、Maven 3.6+,并配置好 IDEA 开发环境。
  2. 数据库初始化:执行提供的 SQL 脚本创建数据库和表结构。
  3. 配置修改:在application.yml中修改数据库连接参数。
  4. 依赖下载:在项目根目录执行mvn clean compile下载依赖。
  5. 启动项目:运行LibraryApplication主类,控制台输出Started Spring Boot即表示启动成功。
  6. 访问系统:打开浏览器访问http://localhost:8080,使用默认管理员账号(admin/123456)登录。

5.2 常见问题与解决方案

问题现象可能原因检查方式处理建议
启动时报端口占用8080 端口被其他进程占用执行netstat -ano | findstr 8080修改server.port或终止占用进程
数据库连接失败数据库服务未启动/密码错误/网络不通检查 MySQL 服务状态,用客户端工具测试连接确认服务启动,核对连接参数
页面模板解析错误Thymeleaf 模板语法错误或路径不对查看控制台异常栈,检查模板文件位置修正模板语法,确认文件在templates目录下
静态资源 404静态文件未放在正确目录或路径引用错误浏览器 F12 查看 Network 请求将 CSS/JS 放入static目录,使用相对路径引用
插入中文乱码数据库字符集不支持中文或连接参数未指定编码检查数据库、表、字段的字符集是否为utf8mb4确保连接 URL 包含useUnicode=true&characterEncoding=utf8

5.3 功能验证清单

部署完成后,按以下顺序验证系统功能是否正常:

  • [ ] 能够访问登录页面(http://localhost:8080/login)
  • [ ] 使用默认管理员账号成功登录并跳转到管理员首页
  • [ ] 在图书管理页面能够添加新图书(填写完整信息)
  • [ ] 添加后能在列表页看到新图书,库存显示正确
  • [ ] 能够编辑图书信息并保存成功
  • [ ] 能够删除无借阅记录的图书
  • [ ] 注册新用户并能够以该用户身份登录
  • [ ] 普通用户能够借阅有库存的图书
  • [ ] 借阅后图书可用库存减少,借阅记录生成
  • [ ] 归还图书后库存恢复,借阅记录状态更新

6. 生产环境部署建议与扩展方向

6.1 生产环境关键配置

学习环境与生产环境的主要差异在于安全性、性能和可观测性:

application-prod.yml 示例

spring: datasource: url: jdbc:mysql://生产数据库IP:3306/library_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: 专用数据库账号 password: 强密码 druid: initial-size: 5 max-active: 20 min-idle: 5 # 配置监控统计和防SQL注入 filters: stat,wall web-stat-filter: enabled: true stat-view-servlet: enabled: true login-username: admin login-password: 监控密码 thymeleaf: cache: true # 生产环境开启模板缓存 logging: level: com.example.library.mapper: DEBUG # 生产环境可改为 INFO 或 WARN file: name: logs/library.log pattern: file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n" server: port: 80 servlet: context-path: /library # 添加上下文路径,避免直接使用根路径

6.2 系统扩展方向

基础功能实现后,可以考虑以下扩展点提升项目完整度:

  1. 权限细化:使用 Spring Security 替代简单 Session 管理,实现基于角色的细粒度权限控制。
  2. Redis 缓存:将热点图书数据、用户会话缓存到 Redis,减轻数据库压力。
  3. 异步任务:使用@Async实现借阅超期提醒邮件发送等异步功能。
  4. API 接口:增加 RESTful API 层,支持移动端 App 调用。
  5. 数据可视化:集成 ECharts,展示借阅趋势、图书分类统计等图表。
  6. 全文检索:集成 Elasticsearch,实现图书名称、作者、简介的模糊搜索。
  7. 微服务化:将用户服务、图书服务、借阅服务拆分为独立微服务。

图书管理系统作为 Java Web 开发的经典案例,真正价值不在于功能有多复杂,而在于通过它掌握企业级应用的标准开发流程、数据设计原则和问题排查方法。建议在完成基础版本后,选择 1-2 个扩展方向深入实践,这将极大提升对分布式系统、性能优化等高级主题的理解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 4:12:53

开篇 | 自动化专业的编程成长路

这是我发布的第一篇博客。想来想去&#xff0c;开篇不如就从“我是谁、我要做什么”写起——既是给自己的成长立一个清晰的起点&#xff0c;也希望能给同样处在摸索阶段的工科同学一点参考。 ## 一、关于我 我是一名自动化专业的学生&#xff0c;即将升入大二。最初接触编程是从…

作者头像 李华
网站建设 2026/7/19 4:12:21

三星Galaxy A6s刷机全攻略:从准备到优化

1. 三星Galaxy A6s刷机前的准备工作作为一名长期从事Android设备维护的技术人员&#xff0c;我深知刷机前的准备工作往往决定了整个过程的成败。这次为家人尝试刷机的三星Galaxy A6s(SM-G6200)是2018年发布的机型&#xff0c;搭载高通骁龙660处理器&#xff0c;出厂系统为Andro…

作者头像 李华
网站建设 2026/7/19 4:11:19

影刀RPA 条件判断if-else的正确写法与嵌套技巧

影刀RPA 条件判断if-else的正确写法与嵌套技巧 作者&#xff1a;林焱 条件判断是流程控制的基础。几乎每个RPA流程都有条件分支&#xff1a;如果登录成功就继续采集、如果数据为空就跳过、如果价格超过阈值就告警。但很多新手写条件判断时逻辑混乱——嵌套太深看不懂、条件写反…

作者头像 李华
网站建设 2026/7/19 4:09:32

Python实现安全登录接口:从基础到实践

1. Python登录接口实现概述登录功能作为系统安全的第一道防线&#xff0c;是每个开发者必须掌握的基础技能。用Python实现一个健壮的登录接口&#xff0c;不仅能巩固文件操作、流程控制等基础知识&#xff0c;更能理解实际业务中的安全设计逻辑。这个看似简单的功能背后&#x…

作者头像 李华
网站建设 2026/7/19 4:08:32

【AI辅助编程三个月学习路线】

AI辅助编程实战&#xff1a;从入门到独立开发 学习目标&#xff1a; 在三个月内&#xff0c;从能够使用AI编程工具辅助编码&#xff0c;进阶到能够独立运用AI辅助完成完整项目的开发与部署&#xff0c;形成稳定高效的AI辅助编程工作流。学习内容&#xff1a; 第1个月&#xff1…

作者头像 李华
网站建设 2026/7/19 4:07:39

单片机中断的一些概念(AI回答)

硬件部分在硬件上&#xff0c;中断的本质是&#xff1a;一根物理导线&#xff08;或内部总线&#xff09;上的电平跳变&#xff08;信号&#xff09;&#xff0c;这根线直接连接到 CPU 核心的一个特殊输入引脚上。1. 信号源&#xff08;源头&#xff09;&#xff1a;一根“拉扯…

作者头像 李华