简介这是一套基于JavaWeb的医院药品管理系统完整项目面向计算机相关专业正在做毕业设计的学生以及需要项目实战练习的Java学习者同时适用于课程设计或期末大作业。系统采用Java开发语言以MySQL作为后台数据库覆盖药品信息管理、库存维护等常用功能模块。压缩包共包含195个文件以Java源文件、JavaScript脚本、HTML页面、CSS样式等前后端代码为主并配有SQL数据库脚本、GIF演示图片和项目说明文档整体大小约869KB目录结构清晰便于导入IDE后直接运行。项目已获导师指导并通过所有代码经过严格调试确保下载即用、无需额外修改。目前已有652人学习下载适合需要快速获得完整毕设方案或学习JavaWeb开发流程的读者参考可直接作为毕业设计使用也可基于源码进行二次功能扩展。1. 拿到的医院药品管理系统先搞清楚这包东西值不值得解压先说实话这类 javaweb 的医院药品管理系统源码数据库在课程设计和毕业设计里出现频率极高也是我后台被问得最多的一类资源。这套东西本质是一个基于 Servlet JSP MySQL 的标准 JavaWeb 项目覆盖了药品信息管理、供应商管理、入库出库、库存预警和用户权限几个核心模块适合用来交 Java 课程设计、应付毕业设计答辩也适合刚学完 JavaWeb 想找个完整案例练手的人。这篇笔记我会按自己的拆包习惯来讲先看技术栈和模块边界再讲数据库脚本怎么用然后是 IDEA 里跑起来的完整配置流程最后把账号登录、增删改查这些必测点过一遍。中间会穿插我实际复现时踩过的坑——这套资源在 Tomcat 版本和 JDK 版本上非常敏感不是下下来就能跑的。读完你能知道这包源码的底细也能照着步骤把它在本地跑起来。2. 技术栈与模块边界为什么这个老组合到现在还是课设首选2.1 技术选型拆解JSP Servlet Javabean 的分层逻辑这套系统没有用 Spring 系框架核心是 JSP Servlet Javabean JDBC 的经典组合。很多刚学完 JavaWeb 的人拿到这种项目会疑惑现在企业里都是 SpringBoot为什么课设和毕设还在用这套老组合原因很简单课程设计考察的核心是「用 Java 语言操作数据库 理解 HTTP 请求处理链路」而不是框架熟练度。Servlet 负责接收请求和转发JSP 负责渲染页面Javabean 封装实体数据JDBC 负责和 MySQL 打交道。这个链路把 JavaWeb 最底层的逻辑跑了一遍比直接上 SpringBoot 更能让答辩老师看到你对基础知识的掌握程度。从这套资源的包结构也能看出来它通常按 com.xxx.entity、com.xxx.dao、com.xxx.service、com.xxx.servlet 这样的层级划分。entity 放药品、供应商、用户等实体类dao 层写 JDBC 的增删改查service 层处理业务逻辑比如入库时扣减库存、出库时校验库存量servlet 层接收前端请求并调用 service。这种分层虽然笨但边界清晰非常适合学习和二次改造。2.2 功能模块盘点药品、供应商、出入库和权限拿到手第一件事我会先把功能模块捋清楚。这套系统的模块一般包含下面这些模块核心功能涉及表用户登录账号密码校验、角色区分user / admin药品管理药品 CRUD、药品分类维护drug / category供应商管理供应商信息维护supplier入库管理采购入库、库存自动增加drug_in / drug_stock出库管理销售出库、库存扣减与校验drug_out / drug_stock库存预警低于安全库存时列表预警drug_stock系统管理用户密码修改、权限控制user这里要特别说一下权限控制。这套系统虽然简陋但一般会区分管理员和普通操作员两种角色。管理员能做药品的增删改和供应商维护操作员可能只能做出入库登记。这个设计在答辩里是加分项因为涉及会话管理和权限拦截面试官或答辩老师大概率会追问「你是怎么控制用户只能访问自己权限内的功能的」。提示源码里的 role 或 type 字段就是判断权限的开关你在 Servlet 里能看到if(role 1)这种硬编码判断这是一种最简单可行的权限方案但二次开发时建议改成过滤器统一拦截。2.3 数据库表设计这份 SQL 脚本里隐藏的依赖链数据库是这套资源的核心交付物之一通常是一个 .sql 文件或一个 db 文件夹。里面除了建库建表语句还会预置几条测试数据。我的习惯是先看表结构再捋表之间的外键关系。药品表一般是整张库的核心字段包括 drug_id、drug_name、category_id、specification、unit、purchase_price、sale_price、stock_quantity、safe_stock。其中 category_id 关联分类表stock_quantity 在入库、出库操作时会实时变动。供应商表通过 supplier_id 和入库记录关联属于典型的从表引用主表。这里有个常见坑这套老项目的 SQL 脚本很多是从 MySQL 5.x 时代导出的默认存储引擎是 MyISAM没有真正的外键约束只有逻辑上的关联关系。这意味着你在代码里删除一个分类时如果该分类下还有药品不会触发数据库级报错而是会在你的 service 层逻辑里漏掉校验导致药品表里出现孤立数据。这个后续在避坑章节我会单独展开。3. 数据库初始化与配置跑起来之前先让 MySQL 这边稳住3.1 建库建表与初始数据导入的完整操作拿到这份资源后数据库导入是第一关。一般源码包里会带一个 hospital_drug.sql 或类似命名的脚本你需要在本地 MySQL 里执行它。先在命令行登录 MySQL然后建库并导入mysql -u root -p # 输入密码后进入 MySQL 命令行执行以下命令 CREATE DATABASE IF NOT EXISTS hospital_drug DEFAULT CHARACTER SET utf8mb4; USE hospital_drug; SOURCE /your/path/hospital_drug.sql;SOURCE命令直接导入整个 SQL 文件如果文件里自带建库语句那你前面手动建的库会被覆盖。所以稳妥的做法是先用文本编辑器打开 SQL 文件看一眼开头——如果开头已经有CREATE DATABASE那就不需要手动建库直接执行SOURCE就行。导入完成后验证一下数据跑这几条命令USE hospital_drug; SHOW TABLES; SELECT COUNT(*) FROM drug; SELECT * FROM user;如果SHOW TABLES能列出所有表且 drug 表有数据、user 表里有预设的管理员账号说明脚本执行完整。常见情况是脚本中途报错比如Unknown collation或Duplicate column多半是 MySQL 版本差异或重复执行导致的。3.2 JDBC 连接参数与 MySQL 版本匹配驱动和 URL 是两回事数据库弄完接下来要看代码里的 JDBC 配置。打开项目的 jdbc.properties 或者 DBUtil 工具类核心就三行内容jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/hospital_drug?useUnicodetruecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456这里的第 1 行和第 2 行是最容易翻车的地方。如果你用的是 MySQL 5.x驱动类名com.mysql.jdbc.Driver没问题但如果你本机装的是 MySQL 8.x驱动类名必须改成com.mysql.cj.jdbc.Driver且 URL 里要带上时区参数jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/hospital_drug?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的密码提示改动驱动类名时记得把项目的 lib 目录或 Maven 依赖里的 mysql-connector-java 版本也换到位8.x 驱动对应 8.x 的 jar5.1.x 对应 5.x 的 jar版本对不上照样报ClassNotFoundException。这一步是新手重灾区。我见过太多人上来就改密码改完运行报Establishing SSL connection without servers identity verification或Unknown database最后发现是 URL 里库名拼错或者时区参数缺了。数据库的连接字符串是个细心活建议一行一行对着我的示例核对。3.3 数据库连接池为什么课设项目一般不用这套源码大概率不用连接池直接在 DAO 层DriverManager.getConnection()每次请求都新建连接用完再关。这在并发量极低的课设场景下完全够用但如果你想让它更接近企业级可以手动接一个 Druid 连接池。换成 Druid 只需在工具类里改成Properties props new Properties(); props.load(new FileInputStream(src/main/resources/druid.properties)); DataSource ds DruidDataSourceFactory.createDataSource(props); Connection conn ds.getConnection();druid.properties里配置driverClassName、url、username、password、initialSize5、maxActive20。这样做的好处是避免每次请求都新建连接插入效率会明显提升。不过如果你是交作业不建议改这一步——结构变了容易引入新问题答辩重点如果不在性能优化反而可能把自己绕进去。4. 在 IDEA 里完整跑起来配置路径与踩坑清单4.1 导入项目要选对导入方式别被 IDEA 的提示带偏用 IDEA 打开这份源码不要直接点 Open 然后选文件夹正确的做法是通过File - New - Project from Existing Sources导入然后在弹窗里选Import project from external model并选Eclipse或直接Create project from existing sources。注意这套老项目很多不带 Maven 或 Gradle 配置直接 Open 会让 IDEA 把它当成普通文件夹不识别源码根目录To Do 面板里一堆报错还不知道去哪修。导入完成后先检查 Project Structure 里的 SDK 和语言级别。点击File - Project Structure - Project把 SDK 选成你本机装的 JDK 1.8 或以上Language Level 选 8。然后在Modules里把src目录标记为 Sources把web或WebContent目录标记为 Web 资源目录。这套老项目通常是在 Eclipse 里开发的目录结构是srcWebContent。IDEA 导入后需要手动添加 Web Facet右键项目 -Add Framework Support- 勾选Web Application然后把 Web 资源目录从 IDEA 默认的web改为实际的WebContent。这一步不设对JSP 页面全部无法访问。4.2 配置 TomcatArtifact 与 Deployment 是运行的关键项目编译环境和 Web 目录都设置好之后就是配置 Tomcat 运行。先在Run/Debug Configurations里新增一个 Tomcat Server - Local然后在 Deployment 页签里添加 Artifact。这里最容易出问题的是 Artifact 类型。第一次添加时 IDEA 可能会弹出No artifacts marked as deployed的提示你需要点Fix或者手动在Project Structure - Artifacts里新增一个 Web Application Exploded 类型的 Artifact并指定对应的 WebContent 目录作为输出根目录。Tomcat 版本我建议用 Tomcat 8.5 或 Tomcat 9这两个版本兼容 JDK 8也是这套老代码比较稳定的运行环境。Tomcat 10 及以上把javax.servlet换成了jakarta.servlet这套老源码的引包全部是javax.servlet.*直接跑会报 NoClassDefFoundError所以千万别用新版本这不是配置问题而是兼容性问题。配置完 Server 后在 Application context 一栏填入/hospital_drug或者在浏览器里用http://localhost:8080/访问。建议填一个上下文路径这样 IDEA 自动打开的地址就是http://localhost:8080/hospital_drug/方便和数据库配置里的路径对上一对。4.3 配置步骤总览照这个顺序操作最稳妥我按自己的复现经验把整套启动流程压缩成下面几步照做基本能跑起来MySQL 中建库导入hospital_drug.sql确认 user 表有初始账号修改 JDBC 配置核对驱动类名、URL、用户名、密码四样全对IDEA 导入项目确认 src 为 Sources 根目录、JSP 目录被识别为 Web 资源目录添加 Web Application Exploded Artifact绑定 WEB-INF 的 web.xml配置 Tomcat 8.5/9Deployment 里添加刚建好的 Artifact修改 Application context 为/hospital_drug启动项目观察 IDEA Console 日志无异常再打开浏览器访问登录页启动成功后浏览器访问登录页能正常显示输入初始账号密码能跳转到主界面基本就确认这套源码是可运行的。如果你的首页静态资源垮了比如 CSS 和 JS 全部加载不出来那多半是 Artifact 配置里漏了WEB-INF/lib下面的 jar 包IDEA 没有把依赖打包进 Artifact。这个检查方法是在 Project Structure - Artifact 的 Output Layout 里确认所有 jar 都在如果没有就手动加。5. 避坑与常见问题这套源码最容易翻车的五个地方5.1 Artifact 是空的启动直接报 404现象Tomcat 正常启动日志也没报错但浏览器访问任何路径都是 404IDEA 里看 Artifact 是空的。原因项目在 Eclipse 里开发依赖的 jar 放在WebContent/WEB-INF/lib目录下。IDEA 导入时没有识别 Web 资源目录导致 Artifact 没有打包任何依赖。解决手动Add Framework Support勾选 Web Application然后到 Project Structure - Artifacts 里新建 Web Application Exploded把 Web 资源目录指定为WebContent。最后把WEB-INF/lib下的 jar 全部加入 Output Layout。这个问题我复现时至少遇到三次每次都是因为没有先检查 Output Layout建议启动前先看一眼这个列表至少要有十几个 mysql 和 servlet 相关 jar。5.2 数据库连接能 Ping 通但程序报Access denied for user现象Navicat 里用 root/123456 可以登录但程序运行时报 Access denied。原因MySQL 8.x 默认使用 caching_sha2_password 认证插件旧版 mysql-connector-java 5.x 驱动不支持这个插件。解决要么把驱动换成 8.x 并改驱动类名为com.mysql.cj.jdbc.Driver要么在 MySQL 里把 root 的认证方式改回 mysql_native_passwordALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456; FLUSH PRIVILEGES;两条路选一条走。我个人的建议是换驱动因为改认证方式到后面用 Navicat 也可能遇到其他兼容问题不如一步到位。5.3 页面中文全部乱码药品名称显示成问号现象页面数据全是???或乱码刚导入的测试数据中文显示异常。原因数据库连接 URL 里没有设置 characterEncoding或数据库本身默认字符集不是 utf8mb4。这套资源的 SQL 文件如果是 GBK 编码导出的导入 MySQL 时也会直接乱掉。解决先确认 SQL 文件本身的编码格式用记事本或 Sublime 打开看是否正常。然后在 jdbc.url 里加上characterEncodingutf8并确认数据库建表语句里有DEFAULT CHARSETutf8mb4。如果现有表不是 utf8mb4可以执行ALTER TABLE drug CONVERT TO CHARACTER SET utf8mb4;乱码问题对课设答辩影响很大因为老师打开页面第一眼看到的就是数据展示。检查顺序一定是先看数据库客户端里直接查询是否正常再看页面是否正常逐步缩小问题范围。5.4 Tomcat 启动报ClassNotFoundException: javax.servlet.ServletException现象Tomcat 一启动就报类找不到或者程序里 import 的 servlet 包全部标红。原因JDK 版本太新或者项目里引用了 servlet-api.jar 和 Tomcat 自带的冲突。JDK 9 模块化后javax.servlet不再自动出现在 classpath 里。解决确认 Project Structure 里 Project SDK 是 JDK 8然后检查WEB-INF/lib是否有 servlet-api.jar。如果有建议移除因为 Tomcat 自带了 servlet-api重复引用会导致版本冲突。同时把 Tomcat 的 library 添加到项目依赖中Project Structure - Modules - Dependencies - Add - Library - Tomcat。5.5 登录成功后跳转路径不对页面 404现象登录校验成功浏览器地址栏是/hospital_drug/login但是跳转后 404而直接在浏览器访问 index.jsp 是正常的。原因Servlet 里用了相对路径跳转比如request.getRequestDispatcher(index.jsp)而在 Servlet 的映射路径下相对路径解析的基准目录不是你期望的根目录。解决把所有跳转路径改成带上下文根的绝对路径常见写法是在 Servlet 里response.sendRedirect(request.getContextPath() /index.jsp);或者request.getRequestDispatcher(/index.jsp).forward(request, response);注意getRequestDispatcher里路径以斜杠开头就是相对于 Web 根目录不以斜杠开头就是相对于当前 Servlet 路径这个细节坑过很多人。建议拿到这套源码后全局搜一遍getRequestDispatcher(统一改成绝对路径能省掉一批跳转问题。6. 验证链路与二次开发入口从登录到改造成自己项目的正确姿势6.1 必测流程登录、增删改查、库存联动一条线走完项目跑起来后建议按完整业务链做一遍回归测试。先打开登录页输入初始管理员账号验证登录成功并进入主页面。然后创建一个新药品、再修改它的价格、删除一个库存为 0 的药品最后做一次入库操作看库存量是否自动增加再做一次出库操作看库存是否扣减。// 出库时检查库存是否充足避免负数库存这是这套项目里最常被忽略的校验 public boolean outStock(String drugId, int quantity) { String checkSql SELECT stock_quantity FROM drug_stock WHERE drug_id?; // 先查出当前库存 int stock getJdbcTemplate().queryForObject(checkSql, Integer.class, drugId); if (stock quantity) { return false; // 库存不足提示用户 } String updateSql UPDATE drug_stock SET stock_quantity stock_quantity - ? WHERE drug_id?; int rows jdbcTemplate.update(updateSql, quantity, drugId); return rows 0; }这段代码代表这套项目里最核心的一条业务逻辑出库前先查库存、再扣库存。很多课程设计在这个环节直接只做 UPDATE不做 SELECT 预检查结果库存能扣成负数答辩被老师问住。看一下你的源码里是不是也有同样问题如果确实验证了库存再更新这个项目的完成度是合格的。6.2 二次开发切入点给项目加上 Filter 权限控制如果你想让这个课设项目在答辩时显得更完整最值得做的小改造是加一个 Filter 做登录拦截。原来的代码里每个 Servlet 都写一遍if(session.getAttribute(user) null)太重复了抽成一个过滤器权限控制会清晰很多public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; HttpSession session request.getSession(); if (session.getAttribute(loginUser) null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(request, response); }然后在 web.xml 里配置 Filter 映射排除 login.jsp、登录 Servlet 和静态资源路径filter filter-nameLoginFilter/filter-name filter-classcom.hospital.filter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern*.jsp/url-pattern /filter-mapping这样所有 JSP 页面都必须登录后才能访问不需要登录的页面用dispatcher映射单独放行。这个改动大约 30 行代码但答辩时讲权限控制的思路就完全不一样了从「我在每个页面复制粘贴判断」变成「我用过滤器统一拦截」观感差距很大。6.3 换数据库表的技巧如果不想用预设的表结构有人会想把它改成别的管理系统比如换成仓库管理系统或图书管理系统。最快的方式是只改实体类字段和 JSP 页面标签保留整套 Servlet 流转骨架。具体做法是先在数据库里新建你的业务表再照着原表的 CRUD SQL 业务线逐层改改 entity 属性、改 dao 层 SQL 语句、改 service 传参逻辑。表面看起来改动很大但三层之间调用的结构完全不用动Servlet 的请求分发也不用动。这个项目是我拆过的课设资源里结构比较规矩的一类分层清楚、SQL 完整、权限有区分属于能直接跑、也能作为脚手架往上加东西的类型。我第一次拿到手时也踩了 Tomcat 版本和驱动不一致的坑前前后后折腾了一个小时才把环境对齐。从那以后我每接手这一类老 JavaWeb 项目都会强制先做三件事看 SQL 脚本开头的建库语句、确认驱动 jar 版本与 MySQL 版本对应、检查 Tomcat 是 9 还是 10。这三个点只要稳了项目基本就活了一半。希望这篇笔记能帮你少走一段弯路顺利把这套系统跑起来、交上去。本文还有配套的精品资源点击获取