ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaWeb图书管理系统课程设计:Servlet+JSP+SQL Server源码解析

JavaWeb图书管理系统课程设计:Servlet+JSP+SQL Server源码解析 简介一套面向JavaWeb初学者的图书管理系统开发文档与源码资料包聚焦登录、查询、借还、管理四大子系统技术栈覆盖Servlet/JSP、HTML/CSS与SQL Server。文档内含完整项目源代码、文件目录结构截图以及书籍-书库存放关系、用户-书籍借阅关系E-R图同时提供需求分析、功能模块设计、关系模式转换、开发工具配置等说明帮助读者理清从概念模型、逻辑设计到物理表结构的完整过程。资源以单个docx文件封装压缩包大小12.82MB目前已有588人学习。读者可参照其中管理员增删改查、读者管理、图书借阅超期限制、用户借还流程等实现思路作为JavaWeb课程设计或毕业设计参考资料也可基于其数据库表结构设计和前后端交互方式快速搭建一套可运行的图书管理平台减少重复开发工作。1. 图书管理系统一套能跑通的 JavaWeb 课程设计源码包先说结论这套基于 JavaWeb 的图书管理系统是典型的 Servlet JSP SQL Server 技术栈课程设计功能上覆盖了登录、查询、借还、管理四个子系统数据库层设计了书籍、用户、书库、借阅四张核心表并且实现了「有超期未还书籍时禁止再次借书」这条业务规则。适合正在做 JavaWeb 课程设计、需要完整源码参考的在校学生也适合想快速搭一个图书管理 Demo 来梳理 Servlet JSP 请求流转的初学者。代码里用的是 Eclipse 项目结构数据库脚本和 E-R 图都随包附带还原成本很低。对我这种常年拆项目源码的人来说这套东西的价值不在代码多花哨而在「麻雀虽小、五脏俱全」——登录鉴权、CRUD、借还流程、外键约束全都有拿来做学习骨架刚刚好。2. 系统拆解四个子系统各自干了什么数据流怎么走2.1 登录子系统管理员与普通用户的双通道设计登录是整个系统的入口代码里区分了管理员和普通用户两条验证路径。管理员登录需要账户和密码登录后进入管理后台可以操作图书和读者信息的增删改查普通用户走的是注册 → 登录 → 借阅/归还的路径。这里有一个容易被忽略的细节管理员和用户是两张独立的表而不是用一张表加角色字段来区分。从数据库设计的角度看这种方式在课程设计里更常见因为它的 E-R 图表达更直观写 SQL 的时候也不需要加role条件判断。实际做登录功能时我一般会提醒自己检查两点密码在数据库里存的到底是明文还是密文——这套系统里是明文存储课程设计够用但放在简历上千万别说自己做了加密登录成功后是用 Session 还是 Cookie 维持状态——Servlet 场景下用HttpSession是标准做法登录成功把用户对象塞进 Session后续页面通过判断 Session 是否为空来控制访问权限。// LoginServlet.java 核心逻辑 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); String role request.getParameter(role); // admin 或 user if (admin.equals(role)) { Admin admin adminDao.findByUsernameAndPassword(username, password); if (admin ! null) { request.getSession().setAttribute(admin, admin); response.sendRedirect(admin_index.jsp); } else { request.setAttribute(msg, 管理员账号或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } } else { User user userDao.findByUsernameAndPassword(username, password); if (user ! null) { request.getSession().setAttribute(user, user); response.sendRedirect(user_index.jsp); } else { request.setAttribute(msg, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); } } }这段代码的关键在于role参数的引入——前端登录页面的表单里有一个角色下拉框后端根据角色值选择查询不同的表。新手容易踩的坑是只判断了账号密码对不对没判断角色导致管理员账号能从普通用户入口登录进去页面是用户端但权限却是管理员的数据就乱了。2.2 借还子系统超期未还禁止借书的业务规则是怎么落地的借书和还书是这个系统业务逻辑最重的地方。普通用户登录后可以看到所有书籍列表输入书号就能借书。但这里有一个硬性条件如果用户当前存在超出还书期限且未归还的书籍系统会拒绝再次借书。这个规则我在项目正文里看到的时候觉得很有意思它比多数课程设计里的借还逻辑多了一层「信用约束」实际编码时判断逻辑大概是这样// BorrowServlet.java 借书核心逻辑 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session request.getSession(); User user (User) session.getAttribute(user); String bookId request.getParameter(bookId); // 第一步判断用户是否有超期未还的书籍 ListBorrowRecord overdueRecords borrowDao.findOverdueByUsername(user.getUsername()); if (overdueRecords ! null overdueRecords.size() 0) { request.setAttribute(msg, 您有超期未还的书籍请先归还后再借书); request.getRequestDispatcher(user_borrow.jsp).forward(request, response); return; } // 第二步判断书籍库存是否足够 Book book bookDao.findById(bookId); if (book.getQuantity() 0) { request.setAttribute(msg, 该书库存不足); request.getRequestDispatcher(user_borrow.jsp).forward(request, response); return; } // 第三步插入借阅记录同时扣减库存 borrowDao.insert(user.getUsername(), bookId, new Date()); bookDao.decreaseQuantity(bookId); response.sendRedirect(user_borrow.jsp); }这里要注意findOverdueByUsername这条 SQL 的写法它本质上查的是「还书日期小于当前日期且归还状态为否」的记录。这套系统里的还书期限是按借书时间加固定天数算的课程设计里一般是加 30 天想改成 7 天就在 SQL 里把DATEADD(day, 30, borrow_date)改成DATEADD(day, 7, borrow_date)。还书逻辑相对简单找到借阅记录更新归还时间和归还状态再把书籍的库存量加回去。但这套系统有一个小细节值得注意它没有做「同一本书同一用户只能借一本」的约束也就是说用户拿着同一个书号可以反复借多次这在真实图书馆场景里是不合理的。如果你要把这套系统交到更严格的老师手里建议在数据库层加一个联合唯一索引。2.3 管理子系统图书和读者的增删改查要覆盖哪些细节管理员的权限面比普通用户大得多。管理员登录后能做四类操作读者管理、图书管理、读者查询、图书查询。这个「管理」和「查询」分开的设计是有讲究的——管理是增删改查询是只读。JSP 页面里要区分编辑模式和查看模式很多课程设计的翻车点就在这里把update和select写在一个页面里点完编辑又去查结果表单数据没带过来。图书管理这块的表单字段对应数据库里的书籍表书号、书名、作者、价格、出版社。注意这套系统里书籍没有「分类」字段如果你想在功能上做扩展这是最现成的切入点了。管理员添加图书时如果是新书号就插入记录如果是已有书号就增加库存数量这个逻辑需要在BookDao里做存在性判断。读者管理这块要处理的是用户表包括用户名、密码、性别、借书数量。有一个被很多人忽略的点删除用户时要考虑该用户当前是否有未归还的图书如果有就不能删。这个约束在原系统里没有做但不代表你可以不做——数据库表之间已经通过外键建立了借阅关系强行删除会报外键冲突错误。你可以在删除前查一下该用户是否有return_date IS NULL的借阅记录有就提示管理员先处理书籍归还。3. 数据库设计拆解E-R 图、关系模式与建表脚本的对应关系3.1 书籍与书库的一对多关系为什么要单独设计一张存放表这套系统的数据库设计是非常规矩的课堂范式它用 E-R 图表达了实体间关系再转换成关系模式最后落到建表 SQL。书籍和书库之间是存放关系一本书只能存放在一个书库里一个书库可以存多本书所以是一对多。但在关系模式那一节里存放关系被拆成了「存放书号书库号数量」这张表书号是外码同时也是主码。这个设计看起来和一对多矛盾实际上是在为数量这个属性做妥协——书库里同一本书可以有多本数量单独挂在存放关系上。对照建表 SQL 来看这个设计的合理性更清楚。书籍表存的是书号、书名、作者、价格、出版社这些静态信息书库表存的是书库号、书库地址存放表把书号和书库号关联起来同时记录数量。如果你用过 MySQL 做这个系统很多人会直接给书籍表加一个quantity字段不单独建存放表但那样就丢失了「书库」这个实体。课程设计的评分老师很看重 E-R 图和关系模式是否对应所以别省这张表。3.2 用户与书籍的多对多借阅关系借阅记录表是必经之路用户和书籍之间是借阅关系一个用户可以借多本书一本书也可以被多个用户借过所以是多对多。多对多关系在关系模式里必须拆成一张中间表这套系统里就是「借阅/归还用户名书号」用户名和书号都做外码联合组成主码。实际建表时这张表还需要加借书日期和还书日期两个字段否则没法判断超期。表结构我建议这样落CREATE TABLE borrow_record ( username VARCHAR(50) NOT NULL, book_id VARCHAR(20) NOT NULL, borrow_date DATETIME NOT NULL, return_date DATETIME, is_returned BIT DEFAULT 0, CONSTRAINT pk_borrow PRIMARY KEY (username, book_id, borrow_date), CONSTRAINT fk_borrow_user FOREIGN KEY (username) REFERENCES users(username), CONSTRAINT fk_borrow_book FOREIGN KEY (book_id) REFERENCES books(book_id) );用(username, book_id, borrow_date)做联合主码是因为同一个用户可能在不同时间借同一本书只用(username, book_id)做主键的话第二次借书会违反主键约束。is_returned字段方便查询超期记录不用去判断return_date IS NULL。如果你想把还书期限做进 SQL 里可以在查询时用DATEADD(day, 30, borrow_date) GETDATE() AND is_returned 0这个条件。3.3 关系模式转换的四个坑主外键、复合主码、命名一致、级联策略把 E-R 图转成关系模式再转成建表 SQL这个链路看着简单实际写起来有四个高频翻车点第一表名和字段名在 JSP、Servlet、DAO、数据库四个层面必须完全一致。这套系统里有username也有user_name的写法的话SQL 查询就会直接报错。第二复合主键代码里建表顺序要统一建议按「先建主表、再建中间表」的顺序执行建表脚本否则外键引用会失败。第三用户表和书籍表的主键类型要保持同一个风格——都用VARCHAR还是都用INT混用在新手项目里很常见。第四级联删除策略要想好删用户或删书时借阅记录怎么办。原系统没有做级联处理靠业务层判断来规避如果你在 SQL Server 里建表时直接写ON DELETE CASCADE那只要一删用户借阅记录就全部没了反而危险。4. 环境搭建与部署Eclipse Tomcat 7.0 SQL Server 2012 的复现过程4.1 开发环境版本怎么选JDK、Tomcat、数据库的兼容矩阵这套系统的开发工具是 Eclipse服务器是 Tomcat 7.0数据库是 SQL Server 2012运行环境是 Windows 10。我实际复现过类似配置的 JavaWeb 课程设计给你一组经过验证的版本搭配组件推荐版本说明JDKJDK 1.7 或 1.8Tomcat 7 支持到 JDK 8JDK 9 以上会出兼容性问题EclipseEclipse EE 版自带 JSP 编辑器不需要额外装插件Tomcat7.0.x项目原版环境Servlet 规范 3.0SQL Server2012 及以上后面版本也能跑改一下 JDBC 驱动即可如果你是学生且电脑里已经有新版 JDK比如 JDK 17我的建议是别硬上开个虚拟机或者装一个 JDK 8否则 Tomcat 7 可能连启动都起不来。Tomcat 10 之后 Jakarta EE 改名javax.servlet会变成jakarta.servlet这套系统的源码直接迁移会报错一堆包不存在所以版本别乱动。JDBC 驱动方面SQL Server 2012 对应的是sqljdbc4.jar或sqljdbc41.jar需要手动放到项目的WebContent/WEB-INF/lib目录下。这个 jar 包很容易被忽略但缺了它所有数据库操作都会报ClassNotFoundException。4.2 部署配置的三个关键点项目字符编码、数据库连接、Tomcat 启动部署这套系统时我建议你先不要急着把代码导入 Eclipse而是按照下面这个顺序来可以少踩很多坑。第一步是创建数据库并执行建表脚本。如果你拿到的源码包里没有.sql文件也没关系根据第 3 章的表结构手动建表再把初始数据插进去效果是一样的——E-R 图两张实体的属性就对应所有字段了。-- SQL Server 建库建表 CREATE DATABASE library_db; GO USE library_db; GO CREATE TABLE books ( book_id VARCHAR(20) PRIMARY KEY, book_name VARCHAR(100) NOT NULL, author VARCHAR(50), price DECIMAL(10, 2), publisher VARCHAR(50) ); CREATE TABLE users ( username VARCHAR(50) PRIMARY KEY, password VARCHAR(50) NOT NULL, gender VARCHAR(10), borrow_count INT DEFAULT 0 ); CREATE TABLE book_storage ( book_id VARCHAR(20) PRIMARY KEY, storage_id VARCHAR(20) NOT NULL, quantity INT DEFAULT 0 ); CREATE TABLE borrow_record ( username VARCHAR(50) NOT NULL, book_id VARCHAR(20) NOT NULL, borrow_date DATETIME NOT NULL, return_date DATETIME, is_returned BIT DEFAULT 0, PRIMARY KEY (username, book_id, borrow_date), FOREIGN KEY (username) REFERENCES users(username), FOREIGN KEY (book_id) REFERENCES books(book_id) );这张建表脚本里book_storage对应的就是关系模式里的存放关系。实际做的时候建议在users表里先插一个管理员账号比如usernameadmin、passwordadmin123这样登录页面直接输账号就能进后台不用每次先注册一个测试账号再改角色。第二步是修改数据库连接配置。这套系统通常把数据库连接写在工具类里比如DBUtil.java或者db.properties重点是确认四个值正确private static final String URL jdbc:sqlserver://localhost:1433;DatabaseNamelibrary_db; private static final String USER sa; private static final String PASSWORD your_password;注意 SQL Server 的 JDBC URL 格式和 MySQL 的区别很大DatabaseName区分大小写TCP/IP 协议要确认已经开启。很多新手在本地装完 SQL Server 后服务是默认启动了但「SQL Server Browser」没启动导致 1433 端口连不上——这个在 SQL Server 配置管理器里把 TCP/IP 启用即可。第三步才是导入 Eclipse 并配置 Tomcat。项目如果是.war包那最简单放进 Tomcat 的webapps目录启动 Tomcat 就能自动解压访问。如果给的是源码目录就需要在 Eclipse 里用「Import → Existing Projects into Workspace」导入然后右键项目选「Properties → Targeted Runtimes」勾选 Tomcat 7。部署完后访问路径一般是http://localhost:8080/项目名/login.jsp首页跳转在这个项目里走的是一个index.jsp转发。4.3 连接池换不换课程设计用 DriverManager 足够别折腾这套系统大概率用的是DriverManager.getConnection()直连方式。我知道很多人会想换成 C3P0 或者 Druid 连接池显得项目更专业但我的建议是别换——课程设计的评分点是功能完整度和数据库设计不是连接池。你换了连接池反而引入更多不确定因素比如连接池配置文件的放置路径、Tomcat 类加载顺序、依赖 jar 包冲突。如果老师问起来你能说清楚「生产环境会用连接池课程设计场景为了可读性选择直连」就足够了这是有充分理由的技术取舍不是能力不足。5. 避坑手册部署和运行中常见的五个翻车现场5.1 页面中文乱码JSP、Servlet、数据库三层各自要设置编码现象页面显示书名和作者时全是问号或者乱码。 原因JSP 页面、Servlet 接收参数、数据库表字段三个层面的字符编码没有统一。 解决JSP 页面顶部写好pageEncodingUTF-8Servlet 里在doPost方法第一行加request.setCharacterEncoding(UTF-8)SQL Server 建表的时候字符型的字段要确认数据库排序规则是支持中文的一般默认的Chinese_PRC_CI_AS就可以。如果改完全部还乱码大概率是 SQL Server 数据库本身排序规则不对你可以重建库并在建库时指定COLLATE Chinese_PRC_CI_AS。5.2 Tomcat 能启动但 404项目部署名与访问路径不一致现象Tomcat 启动日志显示正常但访问http://localhost:8080/admin_index.jsp报 404。 原因项目在 Eclipse 里的部署名和 Web 应用根路径不一致。比如项目名叫bookmanage部署到 Tomcat 后访问路径应该是http://localhost:8080/bookmanage/...如果少写了项目名或者项目名拼错了就会 404。 解决在 Eclipse 的 Servers 视图里双击 Tomcat 实例打开选项找到「Modules」看Path列填的是什么。通常把 Path 改成/bookmanage然后 JSP 页面里的跳转路径response.sendRedirect(admin_index.jsp)这类也要跟着加上项目名前缀否则会出现页面跳转后 404 的情况。更省事的做法是在页面里用${pageContext.request.contextPath}拼路径。5.3 SQL 连接失败能拼对 JDBC URL 的前三句话吗现象启动项目后第一次访问数据库相关页面就报com.microsoft.sqlserver.jdbc.SQLServerException: 通过端口 1433 连接到主机 localhost 失败。 原因SQL Server 默认不开启 TCP/IP 协议或者sa账号的密码不正确或者防火墙拦了端口。 解决打开「SQL Server 配置管理器」找到「SQL Server 网络配置」下的「MSSQLSERVER 的协议」把 TCP/IP 改成「已启用」然后重启 SQL Server 服务。这一步做完后再检查登录账号——如果用sa登录确认sa的密码就是DBUtil里写的那一个并且sa账号没有被「禁用」属性卡住。最后在命令行里测试telnet localhost 1433能通就说明端口开了问题不在防火墙。5.4 借书操作执行了但没反应事务没提交或页面表单字段名对不上现象点击借书按钮后没有报错数据也没有插入借阅记录表。 原因表单提交的字段名和 Servlet 里取参数的字段名对不上。比如前端表单里写的input namebookIdServlet 里用的是request.getParameter(book_id)那就取不到值。 解决先用浏览器开发者工具看 Network 面板找到提交的请求在 Payload 里确认表单字段名和实际提交值。再在 Servlet 里doPost第一行加System.out.println(request.getParameter(bookId))检查是否为空。这套系统里书号的字段名是关键因为有的页面写的bookId有的写的是book_no不一致就会静默失败。5.5 管理员删除用户报外键冲突没有处理借阅记录的中间状态现象管理员在读者管理里删除一个用户系统直接报外键约束错误。 原因用户表被借阅记录表外键引用。数据库里这条用户有未归还的借阅记录所以 SQL Server 拒绝删除。原系统的功能设计里没有对这个场景做处理我在第 2 章已经说过这个问题。 解决在删除前的逻辑里加一步判断查询borrow_record表是否存在is_returned 0的记录如果有前端提示「该用户有未归还图书请先通知其还书」不执行删除如果没有先删借阅记录再删用户或者用事务包住两步操作。6. 把课程设计改造成可展示的项目三个值得加的功能点如果这套系统只是交差那照着原样部署跑通就够了。但如果你想把它写进简历或者作为毕业设计的基础版本我建议你花点时间加三个功能——它们都不难改但能让系统从「课程设计」变成「像样的小项目」。第一个是密码加密存储。现在密码是明文存在数据库里的这放在简历上是减分项。改成 MD5 加盐或者 SHA-256 都可以后端在注册和登录时做哈希登录查询前先对输入哈希再比对。为了兼容老数据你可以写一个一次性转换工具启动项目时扫一遍用户表把明文密码批量转成密文。第二个是借阅记录的异步归还。原系统的还书逻辑是用户自己点击还书这不像真实图书馆。你可以加一个「超期未还自动标记」的定时任务用 Quartz 或者就是一个Scheduled注解如果你用了 Spring。没有用 Spring 的话写一个TimerTask放在 ServletContextListener 里启动也行。这个改动会在借阅列表页显示更丰富的状态比如说「超期天数」列。第三个是分页查询。现在图书列表是一次性加载所有数据书多了页面会卡。加一个分页十分简单先在BookDao里写getBooksByPage(page, pageSize)用 SQL Server 的OFFSET ... FETCH语法SELECT * FROM books ORDER BY book_id OFFSET ? ROWS FETCH NEXT ? ROWS ONLY;然后在 JSP 页面上加上「上一页、下一页」的按钮传入page参数。这套改完系统的查询性能和代码组织都会比原版好一个台阶。我自己的习惯是拿到任何一套课程设计源码先跑通、再拆开看表结构和业务逻辑、最后改两个点练手。这套系统我是从数据库设计和借还规则入手看的改完分页和密码加密后再回看原版的代码结构对这四张表之间怎么通过外键协作理解比只看一遍深得多。从那以后我做 JavaWeb 的课程设计项目时都强制自己走一遍「先读表结构 → 画出请求流转 → 改一个功能点」这套流程确实能少走很多弯路这套系统你也可以按这个顺序来摸索。希望帮到你。本文还有配套的精品资源点击获取
返回列表