2026-04-28 21:38:08 +08:00
2026-04-27 18:40:30 +08:00
2026-04-28 10:53:09 +08:00
2026-04-28 21:38:08 +08:00
2026-04-28 21:35:26 +08:00
2026-04-28 10:22:17 +08:00
2026-04-27 18:40:30 +08:00
2026-04-27 18:40:30 +08:00
2026-04-28 18:37:26 +08:00

MZH 图书馆管理系统

MZH Library Management 是一个基于 Java 11、Maven WAR、JSP、Servlet、JDBC DAO 和 MySQL 的 B/S 图书馆管理系统。项目以 Tomcat 部署为目标,采用传统 Java Web 分层结构,适合用于课程设计、Java Web 实训、图书馆业务原型验证,以及学习 Servlet -> Service -> DAO -> MySQL 的完整数据流。

当前仓库已经包含登录认证、角色权限、馆藏检索、图书管理、分类管理、读者档案、借阅流通、读者借阅历史、报表中心、管理员用户管理和系统日志查看等功能切片。

核心功能

  • 登录与会话管理:通过 /login 登录,认证成功后进入 /dashboard;会话中只保存安全的 AuthenticatedUser 快照、角色代码和权限代码集合。
  • 角色工作台:管理员、馆员、读者分别通过 /admin/home/librarian/home/reader/home 进入对应区域。
  • 馆藏检索:通过 /catalog 按图书编号、书名、作者和分类检索图书。
  • 图书管理:通过 /books 维护图书信息,支持新增、编辑、删除和库存状态管理。
  • 图书分类管理:通过 /book-categories 维护图书分类,并防止删除仍被图书引用的分类。
  • 读者管理:通过 /readers 维护读者档案、联系方式、状态和最大借阅数量。
  • 借阅流通:通过 /borrowing 完成借书、还书、续借、逾期筛选和库存联动更新。
  • 读者借阅历史:读者通过 /reader/loans 查看自己的借阅记录。
  • 报表中心:通过 /reports 查看馆藏汇总、借阅汇总、逾期列表和热门图书排行。
  • 用户管理:管理员通过 /admin/users 维护管理员、馆员和读者登录账户。
  • 系统日志:管理员通过 /admin/system-logs 查询关键操作、审计和异常日志。

技术栈

类别 当前配置
Java Java 11maven.compiler.release=11
构建工具 MavenWAR 项目
Web 技术 Servlet 4.0、JSP、JSTL
Servlet API javax.servlet:javax.servlet-api:4.0.1provided
JSP 标签库 javax.servlet:jstl:1.2
数据库 MySQLJDBC DAO 访问
MySQL 驱动 com.mysql:mysql-connector-j:8.0.33runtime
部署产物 target/library-management.war
Web 配置 src/main/webapp/WEB-INF/web.xmlweb-app 版本 4.0
编码 Maven 源码编码 UTF-8Web 请求通过 CharacterEncodingFilter 使用 UTF-8

建议使用兼容 Servlet 4.0 的 Tomcat 9.x 运行该 WAR。数据库脚本使用 InnoDB、utf8mb4 字符集和检查约束,建议使用 MySQL 8.x。

项目结构

.
├── pom.xml
├── README.md
├── src
│   ├── main
│   │   ├── java/com/mzh/library
│   │   │   ├── controller/        Servlet 控制器,负责路由、参数读取和 JSP 转发/重定向
│   │   │   ├── dao/               DAO 接口
│   │   │   ├── dao/impl/          JDBC DAO 实现
│   │   │   ├── entity/            JavaBean、枚举、查询条件和报表对象
│   │   │   ├── exception/         DAO 异常
│   │   │   ├── filter/            编码、登录认证、权限过滤器
│   │   │   ├── service/           Service 接口、权限策略和通用结果对象
│   │   │   ├── service/impl/      业务服务实现
│   │   │   └── util/              JDBC、密码哈希、Session 常量等工具
│   │   ├── resources
│   │   │   ├── db/schema.sql
│   │   │   └── db.properties.example
│   │   └── webapp
│   │       ├── WEB-INF/web.xml
│   │       ├── WEB-INF/jsp/       受保护的 JSP 页面和 JSP 片段
│   │       ├── static/css/app.css
│   │       ├── static/images/library-login.svg
│   │       └── index.jsp
│   └── test/java/com/mzh/library/service
│       └── *Check.java            服务层和权限策略自检类
└── target/                        Maven 构建输出,已被 .gitignore 忽略

本地数据库配置文件 src/main/resources/db.properties 也已被 .gitignore 忽略。不要提交真实数据库地址、账号或密码。

分层设计

项目遵循以下边界:

JSP/CSS 页面 -> Servlet 控制器 -> Service 业务层 -> DAO 数据访问层 -> MySQL
  • JSP 只负责展示、表单和用户交互,不直接访问数据库,不编写业务流程。
  • Servlet 负责读取请求参数、做基础格式校验、调用 Service,并决定转发 JSP 或重定向。
  • Service 负责权限检查、业务规则、事务边界和跨 DAO 工作流,例如借书、还书、续借和库存更新。
  • DAO 负责 SQL、JDBC 资源访问和 MySQL CRUD,不返回 HTML 或 Servlet 对象。
  • 过滤器统一处理 UTF-8 编码、登录拦截和基于权限的访问控制。

数据库初始化

数据库脚本位于:

src/main/resources/db/schema.sql

脚本会创建并使用数据库 mzh_library,包含以下核心表:

  • roles:角色定义。
  • permissions:权限定义。
  • role_permissions:角色与权限的关联。
  • users:登录账户,密码字段保存 PBKDF2 哈希。
  • system_logs:系统操作、审计和异常日志。
  • readers:读者档案、联系方式、状态和借阅上限。
  • book_categories:图书分类。
  • books:图书基础信息、分类、总册数、可借册数和状态。
  • borrow_records:借阅、归还、续借和逾期判断所需记录。

初始化示例:

mysql -u root -p < src/main/resources/db/schema.sql

脚本内包含本地验证用的演示角色、权限、用户、读者、分类和图书数据。演示账户只用于本地脚手架验证;在非本地数据库中使用前应更换或删除这些数据。

本地/demo 初始登录账号如下。这些是应用登录账号,不是 MySQL 数据库账号:

角色 用户名 初始密码
管理员 admin admin123
馆员 librarian librarian123
读者 reader reader123

这些明文密码只用于新部署本地环境的首次验证。非本地或生产环境上线前,必须通过系统用户管理功能改密,或删除/替换这些演示账号。

schema.sql 使用 INSERT IGNORE INTO users 写入演示账号。如果目标数据库里已经存在同名 adminlibrarianreader 行,重新执行脚本不会覆盖现有密码哈希。需要重置本地演示账号时,优先在系统用户管理功能中修改密码;如果无法登录,可在确认这是本地/demo 数据库后执行以下 SQL:

UPDATE users
SET password_hash = 'pbkdf2_sha256$60000$Ren1B30RDysysnApRiFVaQ==$1XwzMHaALqC7dKffwjbQkilBedfAuiMOXbR/xTMr5+Y=',
    active = 1
WHERE username = 'admin';

UPDATE users
SET password_hash = 'pbkdf2_sha256$60000$PV/DJwZlMRm8vy0lKMAM4g==$+Aijfop3YoPp6HTePN5r4wG8N3qgxJE+yZHkTfzfbaw=',
    active = 1
WHERE username = 'librarian';

UPDATE users
SET password_hash = 'pbkdf2_sha256$60000$wBzxTIT4ep79hgEzYDV9aQ==$w3oO5iSKRSfG4++b4558yiTHy6Tz9BB2+wuV9UOAKhs=',
    active = 1
WHERE username = 'reader';

本地配置

复制配置模板:

cp src/main/resources/db.properties.example src/main/resources/db.properties

模板内容使用以下键:

db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mzh_library?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
db.username=library_user
db.password=change_me

按本机 MySQL 环境调整 db.urldb.usernamedb.password。实际配置文件不应提交到版本库。

如果你希望单独创建应用数据库用户,可以在 MySQL 中按需授权,例如:

CREATE USER 'library_user'@'localhost' IDENTIFIED BY '<your-local-password>';
GRANT ALL PRIVILEGES ON mzh_library.* TO 'library_user'@'localhost';
FLUSH PRIVILEGES;

请将示例中的占位密码替换为本地安全密码,不要把真实密码写入 README、提交记录或共享截图。

构建与部署

在项目根目录执行:

mvn clean package

如果当前 shell 找不到 mvn,本工作区规范记录的 Maven 路径为:

/home/sjy/.sdkman/candidates/maven/current/bin/mvn clean package

构建成功后会生成:

target/library-management.war

部署到 Tomcat 的常见方式:

  1. 确认 MySQL 已启动,mzh_library 已初始化。
  2. 确认 src/main/resources/db.properties 已写入本地数据库连接信息。
  3. 执行 Maven 打包。
  4. target/library-management.war 放入 Tomcat 的 webapps/ 目录,或通过 Tomcat Manager 上传。
  5. 启动或重启 Tomcat。
  6. 默认情况下,WAR 文件名会形成访问上下文 /library-management,实际路径以 Tomcat 配置为准。

示例访问地址:

http://localhost:8080/library-management/login

主要路由

以下路由来自 src/main/webapp/WEB-INF/web.xml、welcome-file 配置和对应 Servlet

路由 处理者 用途
/welcome-file: index.jsp index.jsp 欢迎入口,页面会重定向到 /login
/login LoginServlet 登录页和登录提交
/logout LogoutServlet 退出登录
/dashboard DashboardServlet 登录后的总览页
/admin/home RoleAreaServlet 管理员区域首页
/librarian/home RoleAreaServlet 馆员工作台
/reader/home RoleAreaServlet 读者中心
/catalog BookCatalogServlet 馆藏检索
/books/books/new/books/edit/books/update/books/delete BookManagementServlet 图书管理
/book-categories/book-categories/new/book-categories/edit/book-categories/update/book-categories/delete BookManagementServlet 图书分类管理
/readers/readers/new/readers/edit/readers/update/readers/delete ReaderManagementServlet 读者档案管理
/borrowing/borrowing/new/borrowing/create/borrowing/return/borrowing/renew BorrowingManagementServlet 借阅、归还、续借
/reader/loans ReaderLoanHistoryServlet 当前读者借阅历史
/reports ReportServlet 报表中心
/admin/users/admin/users/new/admin/users/edit/admin/users/update/admin/users/deactivate UserManagementServlet 管理员用户管理
/admin/system-logs SystemLogServlet 系统日志查询
/unauthorized UnauthorizedServlet 无权限提示

静态资源路径 /static/ 不要求登录。除 //login/unauthorized/favicon.ico 和静态资源外,其他页面会经过 AuthenticationFilterAuthorizationFilter

角色与权限

系统当前包含三类角色。运行时权限由 PermissionPolicy 根据 Role 枚举授予;schema.sql 同时保留 rolespermissionsrole_permissions 表和本地种子数据,但当前登录流程不会从 role_permissions 动态加载权限。

角色代码 显示名称 权限概览
administrator 管理员 运行时策略授予全部 Permission 枚举权限;具体入口仍受路由规则约束
librarian 馆员 可管理图书、读者、借阅流通,查看报表和馆藏
reader 读者 可查看馆藏,并访问读者自己的借阅历史

权限代码包括:

  • manage_users
  • manage_books
  • manage_readers
  • manage_borrowing
  • view_reports
  • view_system_logs
  • view_catalog
  • borrow_books

访问控制重点:

  • /admin/system-logs 需要 view_system_logs
  • /admin/** 用户管理入口需要 manage_users
  • /books/**/book-categories/** 需要 manage_books
  • /readers/** 需要 manage_readers
  • /borrowing/** 需要 manage_borrowing
  • /reports 需要 view_reports
  • /catalog 需要 view_catalog
  • /reader/loans 需要 borrow_books,并且必须是 reader 角色。

当前代码中的读者自助入口是 /reader/loans 借阅历史查看;借书、还书和续借操作由管理员或馆员通过 /borrowing 工作台处理。

业务规则摘要

  • 图书以 book_identifier 作为面向用户的唯一编号。
  • 图书分类名称唯一,已被图书引用的分类不能直接删除。
  • 图书状态使用 availableunavailablearchived
  • 读者以 reader_identifier 作为面向用户的唯一编号。
  • 读者状态使用 activesuspendedinactive,最大借阅数量范围为 1 到 50。
  • 借阅记录状态使用 activereturned;逾期不是单独状态,而是由未归还且 due_at 早于当前时间的记录推导。
  • 借书会在同一事务中创建借阅记录并减少图书可借册数。
  • 还书会在同一事务中标记归还并恢复可借册数。
  • 续借会延长应还时间并增加续借次数,当前 MVP 对单笔借阅限制一次续借。
  • 用户管理变更会写入系统日志,审计信息不应记录密码、明文凭据或密码哈希。

开发约定

  • 保持 Servlet -> Service -> DAO -> MySQL 的层次边界。
  • JSP 页面只渲染 Servlet 设置的 request/session 属性,避免 JSP scriptlet、SQL、JDBC 或业务流程。
  • 受保护操作必须经过服务层权限校验,不能只依赖页面按钮是否显示。
  • 新增数据库访问时使用参数化 SQL 或 PreparedStatement 风格,避免拼接用户输入。
  • 多表一致性操作放在服务层事务边界中,DAO 只处理具体 SQL。
  • 用户可见的页面文案、表单标签、按钮、空状态和服务反馈消息使用简体中文。
  • URL、请求参数名、Java 标识符、数据库枚举值和权限代码保持现有代码形式。
  • 本地私密配置只放在 src/main/resources/db.properties,不要提交真实凭据。

测试与检查

当前仓库在 src/test/java/com/mzh/library/service/ 下包含多个自检类:

  • AuthServiceCheck
  • BookServiceCheck
  • BorrowingServiceCheck
  • PermissionPolicyCheck
  • ReaderServiceCheck
  • ReportServiceCheck
  • SystemLogServiceCheck
  • UserAccountServiceCheck

这些自检类使用 public static void main 和内部断言。当前 pom.xml 没有引入 JUnit/TestNG,也没有配置 Surefire 执行 *Check,因此 mvn test 会编译测试源码,但不会自动运行这些自检类。

常用编译和打包检查命令:

mvn test
mvn clean package

如需手动运行自检类,可在 mvn test 编译完成后执行:

for check in AuthServiceCheck BookServiceCheck BorrowingServiceCheck PermissionPolicyCheck ReaderServiceCheck ReportServiceCheck SystemLogServiceCheck UserAccountServiceCheck; do
  java -cp target/classes:target/test-classes "com.mzh.library.service.${check}"
done

如果 Maven 不在 PATH 中,可使用:

/home/sjy/.sdkman/candidates/maven/current/bin/mvn test
/home/sjy/.sdkman/candidates/maven/current/bin/mvn clean package

文档或页面调整后的人工自查建议:

  • README 中的路径、路由和依赖版本是否与 pom.xmlweb.xmlschema.sql 一致。
  • 是否意外写入真实数据库账号、密码、连接串或生产部署信息。
  • JSP 中是否出现 SQL、JDBC、密码字段展示或业务逻辑 scriptlet。
  • 管理入口是否仍与 AuthorizationFilter 的权限规则一致。

常见问题

访问页面时跳回登录页

//login/unauthorized/favicon.ico/static/ 外,系统默认要求登录。请确认已经登录,并检查 Tomcat 会话是否过期。当前登录会话超时时间为 30 分钟。

登录或数据库操作提示服务不可用

优先检查:

  • MySQL 是否启动。
  • mzh_library 是否已经通过 schema.sql 初始化。
  • src/main/resources/db.properties 是否存在。
  • db.urldb.usernamedb.password 是否与本地 MySQL 一致。
  • MySQL Connector/J 依赖是否已被 Maven 正确下载。

打包后访问路径不是 /library-management

Maven 当前将 WAR 产物命名为 library-management.war。Tomcat 通常会用 WAR 文件名作为上下文路径,但如果你在 Tomcat 中手动配置了 Context,最终访问路径以 Tomcat 配置为准。

可以把 db.properties 提交吗?

不可以。src/main/resources/db.properties 是本地私密配置,已经被 .gitignore 忽略。只应提交 src/main/resources/db.properties.example

重新执行 schema.sql 后演示账号密码为什么没变?

schema.sql 使用 INSERT IGNORE INTO users 写入本地/demo 账号。已有同名用户时,MySQL 会跳过插入,不会覆盖现有密码哈希。需要重置时,请参考“数据库初始化”里的本地/demo 账号说明;不要在非本地数据库中直接恢复这些演示密码。

维护提示

pom.xmlweb.xml、数据库表结构、角色权限、主要 JSP 路径或测试入口变化时,应同步更新本 README,避免部署步骤和功能说明与实际代码脱节。

S
Description
No description provided
Readme 1.7 MiB
Languages
Java 66.3%
Python 29.9%
CSS 3.5%
JavaScript 0.3%