在实际 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 2022Maven 3.6JDK 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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT借阅记录表;关键设计要点密码字段使用varchar(100)为加密后密文预留空间。图书表分离total_count和current_count避免每次借阅都需查询历史记录计算可用库存。借阅记录表通过status字段管理生命周期并设置外键约束保证数据一致性。为常用查询字段如图书名称、作者建立索引提升查询效率。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?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/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?error1; } GetMapping(/logout) public String logout(HttpSession session) { session.invalidate(); return redirect:/login; } }密码加密工具类使用 Spring Security 的 BCryptpublic 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) { PageBook page new Page(pageNum, pageSize); PageBook 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?error1; } bookService.removeById(id); return redirect:/admin/book/list; } }前端分页控件Thymeleaf Bootstrapdiv th:if${pageInfo.pages 1} nav ul classpagination li classpage-item th:classappend${pageInfo.current 1} ? disabled a classpage-link th:href{/admin/book/list(pageNum1)}首页/a /li li th:eachpageNum : ${#numbers.sequence(1, pageInfo.pages)} classpage-item th:classappend${pageNum pageInfo.current} ? active a classpage-link th:href{/admin/book/list(pageNum${pageNum})} th:text${pageNum}/a /li /ul /nav /div4.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 项目启动步骤环境准备确保本地已安装 JDK 17、MySQL 8.0、Maven 3.6并配置好 IDEA 开发环境。数据库初始化执行提供的 SQL 脚本创建数据库和表结构。配置修改在application.yml中修改数据库连接参数。依赖下载在项目根目录执行mvn clean compile下载依赖。启动项目运行LibraryApplication主类控制台输出Started Spring Boot即表示启动成功。访问系统打开浏览器访问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 包含useUnicodetruecharacterEncodingutf85.3 功能验证清单部署完成后按以下顺序验证系统功能是否正常[ ] 能够访问登录页面http://localhost:8080/login[ ] 使用默认管理员账号成功登录并跳转到管理员首页[ ] 在图书管理页面能够添加新图书填写完整信息[ ] 添加后能在列表页看到新图书库存显示正确[ ] 能够编辑图书信息并保存成功[ ] 能够删除无借阅记录的图书[ ] 注册新用户并能够以该用户身份登录[ ] 普通用户能够借阅有库存的图书[ ] 借阅后图书可用库存减少借阅记录生成[ ] 归还图书后库存恢复借阅记录状态更新6. 生产环境部署建议与扩展方向6.1 生产环境关键配置学习环境与生产环境的主要差异在于安全性、性能和可观测性application-prod.yml 示例spring: datasource: url: jdbc:mysql://生产数据库IP:3306/library_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/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 系统扩展方向基础功能实现后可以考虑以下扩展点提升项目完整度权限细化使用 Spring Security 替代简单 Session 管理实现基于角色的细粒度权限控制。Redis 缓存将热点图书数据、用户会话缓存到 Redis减轻数据库压力。异步任务使用Async实现借阅超期提醒邮件发送等异步功能。API 接口增加 RESTful API 层支持移动端 App 调用。数据可视化集成 ECharts展示借阅趋势、图书分类统计等图表。全文检索集成 Elasticsearch实现图书名称、作者、简介的模糊搜索。微服务化将用户服务、图书服务、借阅服务拆分为独立微服务。图书管理系统作为 Java Web 开发的经典案例真正价值不在于功能有多复杂而在于通过它掌握企业级应用的标准开发流程、数据设计原则和问题排查方法。建议在完成基础版本后选择 1-2 个扩展方向深入实践这将极大提升对分布式系统、性能优化等高级主题的理解。