简介一套面向软件工程课程设计与大作业实战的基于JavaWeb药品存销信息管理系统源码包完整覆盖药品入库、出库、销售、库存预警等核心业务适合高校学生在毕业设计或课程项目中快速搭建可运行示例也便于教师作为教学案例参考。压缩包共623个文件整体约46.67MB包含108个Java源文件、202个编译后的class文件、36个JSP页面、65个XML配置、69个JAR依赖库并配有SQL数据库脚本、XLS/XLSX数据表格、JS/CSS前端样式及日志记录等辅助资源目录结构清晰既能直接导入开发工具运行也能按模块阅读学习。当前已有99人学习下载说明其在同类课设中具备一定参考价值。借助这套资料读者可系统掌握JavaWeb分层架构、数据库表关系设计、药品存销业务流程和前后端交互实现同时还能对照编译文件与源码定位问题适合需要短时间完成课程任务、准备答辩演示或复习SSH/SSM经典技术栈的学生。1. 软件工程大作业里的JavaWeb药品存销系统它到底解决什么问题如果你正在为软件工程课程设计选题发愁想找一个“业务有真实感、代码能写完、答辩有讲头”的项目那么“基于JavaWeb的药品存销信息管理系统”是一条很稳的路。这类系统的典型技术组合是 JSP Servlet JDBC MySQL Tomcat业务要覆盖药品的采购入库、销售出库、库存扣减和低库存/效期预警。它不是简单“增删改查”四件套入库单和销售单天然需要事务库存字段天然需要并发控制这正好用来展示数据库设计和代码分层能力。适合第一次独立完成JavaWeb项目、想从零跑通一个完整系统的软件工程与计算机专业学生。2. 技术选型与业务拆解为什么 JSPServletJDBC 对大作业最稳2.1 三种技术栈怎么选自写JDBC、SSM与Spring Boot的成本对比做这个题目第一件事不是写代码是把技术栈定死。标题只写了“基于JavaWeb”这里可以做的选择其实有三条路我把它们的成本和风险摊开看。技术方案技术组成上手成本大作业风险答辩优势自写 ServletJDBCJSP、Servlet、JDBC、MySQL、Tomcat低低代码量中等分层、事务、数据库设计都能自己讲SSMSpring SpringMVC MyBatis中等配置多版本坑多贴近企业开发套路Spring Boot ThymeleafSpring Boot、MyBatis中低可能超出课程大纲演示效果好但容易被追问框架原理我一般会建议大作业优先选第一行Servlet JSP JDBC 自己写。原因是软件工程课程设计最看重“你能解释每一行代码在干什么”自写JDBC时你对Connection、PreparedStatement、事务提交回滚的掌握程度是答辩时能当场说清的。SSM不是不好而是Spring版本、MyBatis版本、XML配置和Maven依赖一旦打架你会在配置上消耗大量时间最后数据库设计和业务逻辑反而没时间打磨。Spring Boot则适合已经自学过框架的同学如果你的课程大纲明确要求“可以用Spring Boot”那再考虑。2.2 角色与权限管理员和药房操作员分别能做什么药品存销系统的用户角色不需要做得很复杂两类角色就够展开业务了管理员和操作员。角色权限点管理员用户管理、药品信息维护、供应商管理、查看全部流水与报表操作员入库登记、销售开单、库存查询、处理库存预警权限落地很直接user表里放一个role字段登录时把用户对象放进session页面菜单根据角色判断是否显示再写一个过滤器拦截未登录请求。这一步如果能现场演示“操作员登录后看不到用户管理菜单”在答辩里是很实在的加分点。public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; HttpSession session request.getSession(false); Object loginUser session null ? null : session.getAttribute(loginUser); if (loginUser null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, res); }这段代码的逻辑是每次请求先看session里有没有loginUser没有就踢回登录页有就放行。要注意request.getSession(false)这个写法它不会主动创建session避免静态资源也去new一个空会话。过滤器在web.xml里配置url-pattern为/*但login.jsp和doLogin接口要单独排除否则登录功能自己会被拦住。2.3 把业务拆成三条主线入库、出库、库存预警整个系统的业务闭环可以拆成三条主线先想清楚它们再写表结构后面就不会改来改去。第一条线是采购入库操作员选择供应商在入库单里添加多个药品明细填写进货价和数量提交后同时完成两件事——生成入库主单和明细流水并把对应药品的库存数量加上去。第二条线是销售出库操作员开销售单选择药品和数量提交后生成销售主单、销售明细并把对应药品库存减掉。第三条线是预警系统查出stock_quantity已经小于等于low_limit的药品在列表里高亮展示医药类库存还可以加一个效期预警expiry_date距离当前日期不足90天的药品单独列出来。这三条线里入库和出库必须做成事务。为什么因为一次出库可能涉及多个药品如果第1个药品库存扣成功了、第2个药品扣失败那整个单据就处于“流水已生成但库存不对”的脏状态。事务就是用来保证这组操作要么全部成功、要么全部回滚。这是整个大作业最容易出彩的地方也是后面避坑章节会反复提到的地方。3. 数据库设计药品存销系统的表结构与建表SQL3.1 核心表关系药品、供应商、入库单、销售单怎么连数据库是这个系统的地基表设计得好不好直接决定代码好不好写。这个系统的核心实体有5个用户、药品、供应商、入库单、销售单。其中入库单和销售单是典型的主从表结构也就是“一张主表记录单据整体信息一张明细表记录每一条药品条目”。先理清关系一个供应商可以供应多种药品所以药品表里放supplier_id作为逻辑外键。一张入库单对应一个供应商但要装多种药品所以是stock_in主表对stock_in_item明细表一对多。销售单同理sale主表对sale_item明细表。药品和库存不单独建库存表直接把stock_quantity放在drug表里对于大作业来说足够如果你以后想做成正经进销存系统再拆库存表也不迟。3.2 建表SQL用户表、药品表、供应商表先建库、建用户表、药品表和供应商表。注意字符集用utf8mb4否则后面药品名称里出现生僻字时会变成问号。CREATE DATABASE IF NOT EXISTS drug_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE drug_db; CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(64) NOT NULL COMMENT 密码可存MD5, real_name VARCHAR(50) NOT NULL COMMENT 真实姓名, role VARCHAR(20) NOT NULL DEFAULT operator COMMENT admin/operator ) ENGINEInnoDB COMMENT用户表; CREATE TABLE supplier ( id INT PRIMARY KEY AUTO_INCREMENT, supplier_name VARCHAR(128) NOT NULL COMMENT 供应商名称, contact_person VARCHAR(50) DEFAULT NULL, phone VARCHAR(20) DEFAULT NULL, address VARCHAR(255) DEFAULT NULL ) ENGINEInnoDB COMMENT供应商表; CREATE TABLE drug ( id INT PRIMARY KEY AUTO_INCREMENT, approval_number VARCHAR(50) NOT NULL COMMENT 国药准字/批准文号, drug_name VARCHAR(128) NOT NULL COMMENT 药品名称, spec VARCHAR(50) DEFAULT NULL COMMENT 规格如0.25g*24粒, producer VARCHAR(128) DEFAULT NULL COMMENT 生产厂家, unit VARCHAR(10) NOT NULL DEFAULT 盒 COMMENT 计量单位, cost_price DECIMAL(10,2) NOT NULL COMMENT 进货价, sale_price DECIMAL(10,2) NOT NULL COMMENT 销售价, stock_quantity INT NOT NULL DEFAULT 0 COMMENT 当前库存, low_limit INT NOT NULL DEFAULT 10 COMMENT 低库存预警线, expiry_date DATE DEFAULT NULL COMMENT 药品效期, supplier_id INT DEFAULT NULL COMMENT 逻辑外键, status TINYINT NOT NULL DEFAULT 1 COMMENT 1上架 0下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_drug_name (drug_name), KEY idx_supplier (supplier_id) ) ENGINEInnoDB COMMENT药品表;几个字段要特别说明。approval_number对应药品的“国药准字”批号这是药品类系统区别于普通商品系统的关键点答辩时可以说“这是参考了药品经营质量管理规范里对批号管理的需求”。stock_quantity直接放在drug表里同时加上low_limit是为了让库存预警查询变得很简单。我要强调一下supplier_id这里我故意不建物理外键保留逻辑外键的关系。原因是课程设计阶段你经常要删测试数据物理外键一旦卡住删药品时还得先删供应商非常麻烦只要在代码里保证引用完整性逻辑外键完全够用。3.3 入出库主从表结构说明库存流水是这个系统的账本入出库都要留痕。主从表的做法是主表放单据级别的信息比如供应商、总金额、操作员、时间明细表放每一行药品的数量、价格、金额。这样设计的直接好处是统计“某一天入库总额”“某个供应商累计供货量”时只需要查主表而统计“某个药品卖了多少”时查明细表互不干扰。CREATE TABLE stock_in ( id INT PRIMARY KEY AUTO_INCREMENT, supplier_id INT NOT NULL, total_quantity INT NOT NULL COMMENT 入库总数量, total_amount DECIMAL(12,2) NOT NULL COMMENT 入库总金额, operator VARCHAR(50) NOT NULL COMMENT 操作人, stock_in_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, remark VARCHAR(255) DEFAULT NULL ) ENGINEInnoDB COMMENT入库单主表; CREATE TABLE stock_in_item ( id INT PRIMARY KEY AUTO_INCREMENT, stock_in_id INT NOT NULL COMMENT 所属入库单, drug_id INT NOT NULL, quantity INT NOT NULL, purchase_price DECIMAL(10,2) NOT NULL COMMENT 本次进货价, amount DECIMAL(10,2) NOT NULL COMMENT 明细金额 ) ENGINEInnoDB COMMENT入库单明细表; CREATE TABLE sale ( id INT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) DEFAULT NULL COMMENT 客户名, total_amount DECIMAL(12,2) NOT NULL, operator VARCHAR(50) NOT NULL, sale_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB COMMENT销售单主表; CREATE TABLE sale_item ( id INT PRIMARY KEY AUTO_INCREMENT, sale_id INT NOT NULL, drug_id INT NOT NULL, quantity INT NOT NULL, sale_price DECIMAL(10,2) NOT NULL COMMENT 本次销售价, amount DECIMAL(10,2) NOT NULL COMMENT 明细金额 ) ENGINEInnoDB COMMENT销售单明细表;这里有一个大作业里常见的纠结点明细表要不要存“当时的价格”我建议存而且必须存。因为药品价格会调整如果只关联drug_id三个月后查历史销售单单价全变成最新价格账就对不上了。把purchase_price、sale_price冗余到明细表里属于“用空间换正确性”的典型设计成本很低答辩时也能说出理由。3.4 索引、外键与初始数据索引方面不要给每张表都乱建。真正高频查询是按药品名称模糊查、按supplier_id查、按stock_in_id查明细、按sale_time查流水。所以我在drug_name、supplier_id、stock_in_id、sale_id这些列上建普通索引就够了。另外一个很实用的小技巧给stock_in_time和sale_time建索引会让“按月份汇总销售金额”这类统计查询快很多课程设计数据量小感觉不明显但这个习惯值得养成。初始数据尽量一次给够否则你自己演示时每开一个页面都要手敲测试数据。至少准备一个管理员账号admin/123456、一个操作员账号两条供应商记录五条药品记录其中一条库存低于预警线。初始数据用INSERT语句写进sql脚本里每执行一次就把系统恢复到可演示状态这对答辩前的环境准备非常有价值。4. 代码实现与IDEA运行配置从分层到跑通最小流程4.1 包结构与三层职责划分代码结构建议按软件工程课上常用的三层架构拆包不复杂但层次清楚也方便你画出架构图放进报告里。一般包结构是这样src ├── com.drug.entity // 实体类Drug, Supplier, Sale, SaleItem, User ├── com.drug.dao // 数据访问层DrugDao, StockDao, SaleDao ├── com.drug.service // 业务层StockService, SaleService ├── com.drug.servlet // Servlet控制器DrugServlet, SaleServlet ├── com.drug.filter // 登录过滤器 └── com.drug.util // DBUtil, DateUtil实体类对应三章里的每一张表字段名和表字段保持一致省去一堆setter映射的麻烦。dao层只做JDBC操作每个方法接收一个Connection参数这样上层才能把多个dao操作包进同一个事务。service层负责业务规则比如“销售出库时必须同时写主单、写明细、扣库存”。servlet层只负责接收请求、调用service、把结果放进request或session、转发JSP。这个分层的核心约束是servlet里不允许出现SQL字符串dao里不允许出现业务判断。写的时候守住这条线后面排错会容易很多。4.2 数据库连接工具类JDBC参数与Driver说明不管哪个dao都要先拿到数据库连接所以DBUtil是第一个写的类。用最基础的DriverManager就行暂时不用连接池因为课程设计并发量很小别给自己增加复杂度。public class DBUtil { private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/drug_db ?useUnicodetruecharacterEncodingutf8 useSSLfalseserverTimezoneAsia/Shanghai; private static final String USERNAME root; private static final String PASSWORD root; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(MySQL驱动加载失败); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USERNAME, PASSWORD); } }关键参数逐个说。DRIVER用com.mysql.cj.jdbc.Driver对应MySQL 8.x的驱动jar如果你用的是MySQL 5.7才改成com.mysql.jdbc.Driver这个区别是高频报错点。URL里的characterEncodingutf8决定中文能不能正常读写serverTimezoneAsia/Shanghai解决MySQL 8时区报错useSSLfalse只是关闭本地开发时的SSL告警。USERNAME和PASSWORD一定要改成你自己本机的。这里有个小建议把这个类里的连接参数集中放成常量以后换机器环境只需要改这一个文件不需要满项目找。4.3 入出库库存扣减带事务的核心代码整个项目最值得用心写的代码就是销售出库。很多人第一次写会分三步先查库存够不够够就插入销售单再UPDATE库存。这个写法看起来没问题但并发时会出大问题我们在避坑章节会讲。正确做法是把“校验库存”和“扣减库存”合并成一条UPDATE语句再配上事务。public boolean createSale(Sale sale, ListSaleItem items) { Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 开启事务 SaleDao saleDao new SaleDao(); int saleId saleDao.insertSale(conn, sale); SaleItemDao itemDao new SaleItemDao(); DrugDao drugDao new DrugDao(); for (SaleItem item : items) { item.setSaleId(saleId); itemDao.insertSaleItem(conn, item); int rows drugDao.deductStock(conn, item.getDrugId(), item.getQuantity()); if (rows 0) { throw new RuntimeException(库存不足或药品已下架); } } conn.commit(); return true; } catch (Exception e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } // 记录日志返回false return false; } finally { DBUtil.close(conn); } }这段代码的逻辑要讲清楚。先把自动提交关掉然后插入销售主单拿回主键saleId再循环插入每条明细每插一条明细就扣一次库存。扣库存如果返回0说明药品不存在或者余量不够这时抛异常触发回滚前面插进去的单据和明细全部撤销。finally里关闭连接时要注意如果此时事务没有提交close会自动回滚所以close方法的内部实现不能误提交。对应地DrugDao里的扣库存SQL长这样UPDATE drug SET stock_quantity stock_quantity - ? WHERE id ? AND stock_quantity ?这条SQL的神奇之处在于它在一次原子操作里同时完成了“判断库存充足”和“扣减库存”。数据库的行锁保证同一时间只有一个事务能改这条drug记录所以即使两个窗口同时卖最后一个库存也只有一个UPDATE成功另一个返回0并回滚。入库加库存不需要检查下限但也建议放在同一个事务里因为入库单主表和明细、药品库存三者要保持一致。4.4 用IDEA运行JavaWeb项目配置Tomcat、Artifact与jar包代码写完后真正卡住很多人的是把项目在IDEA里跑起来。这里我把常用配置顺序整理出来照着做就能避开大部分启动失败。第一步确认项目的依赖jar放对位置。mysql-connector的jar要放到WEB-INF/lib目录下或者通过Project Structure里的Libraries引入后再把它加进Artifact。第二步配置Tomcat。打开Run/Debug Configurations点左上角加号选择Tomcat Server → Local在Server页选好本机Tomcat目录。第三步最关键的Deployment页点加号选Artifact把项目以war exploded形式部署上去然后在Application context里填一个访问路径比如填/这样启动后直接用http://localhost:8080访问如果填/drug那就要通过http://localhost:8080/drug访问。第四步启动前到Project Structure确认Artifact的输出目录里WEB-INF/lib下面真的有mysql-connector-j-8.x.jar。提示war exploded是“解压war包”的意思IDEA开发时选这种模式改完JSP不需要重新打包就能生效比war模式省时间。启动后看到Tomcat日志出现“Server startup in xxx ms”就算成功了。如果访问页面404优先检查Deployment里有没有把Artifact加上去Application context和浏览器地址是否一致。注意每次改完Java代码最好重启Tomcat而不是依赖热部署JSP改完可以等资源重载但Java类和配置改动重启最保险。4.5 库存预警的SQL与JSP展示写法数据查出来之后预警页面不要搞复杂重点是把“哪些药该补货了”一眼看清。低库存预警查询直接用一条SQL在药品列表里把库存低于预警线的记录优先显示SELECT id, drug_name, spec, stock_quantity, low_limit FROM drug WHERE status 1 AND stock_quantity low_limit ORDER BY (stock_quantity - low_limit) ASC;如果要加效期预警再单独查一条过期药品SELECT id, drug_name, expiry_date, stock_quantity FROM drug WHERE status 1 AND expiry_date IS NOT NULL AND expiry_date DATE_ADD(CURDATE(), INTERVAL 90 DAY);JSP列表页展示时用简单的条件判断把预警行标红就行。比如用JSTL判一下当d.stockQuantity小于等于d.lowLimit时给tr加一个classdangerCSS里把danger的背景色设成浅红。如果你的项目没用JSTL用scriptlet写if判断也可以但页面里不要出现大段Java业务逻辑只做展示判断否则老师看到JSP里塞了SQL会很别扭。预警页面再配一个“一键查看全部低库存药品”的链接演示时特别好用。5. 避坑指南从404到库存超卖的5个常见问题5.1 启动后404Artifact没有部署到Tomcat现象IDEA启动Tomcat时日志显示启动成功但浏览器访问http://localhost:8080一直404。原因最常见的是Deployment配置里没有添加Artifact或者Application context填的路径和你访问地址不一致。IDEA默认不会把你指定的项目自动挂到Tomcat上所有东西都靠Artifact配置。解决打开Run/Debug Configurations找到Tomcat Server切到Deployment页点加号选择Artifact选“项目名:war exploded”然后再设Application context为/。我一般会顺手在Server页把“Open browser”勾上URL填http://localhost:8080/省得每次手动敲地址。改完直接重启Tomcat确定日志里出现“deploying web application”的说法就说明Artifact挂上了。5.2 数据库连接失败驱动类、URL与MySQL版本三连坑现象启动项目后登录页能打开但点登录时报错日志里出现Access denied for user或Communications link failure。原因这个报错分两类。Access denied说明用户名密码错或者root账号默认只能用命令行本机登录Communications link failure大多数情况是驱动版本和MySQL版本不匹配或者是URL里的serverTimezone没设置导致MySQL 8拒绝连接。解决先用命令行工具或IDEA自带的Database面板确认账号能连上排除密码错误。如果密码没问题检查驱动jar项目里放的是mysql-connector-j那Driver类要写成com.mysql.cj.jdbc.Driver。URL里把serverTimezoneAsia/Shanghai加上。这里有个排查技巧把DBUtil里的URL和账号临时打出来用一个小main方法直接调getConnection如果main方法里能连通、Tomcat里连不通问题多半出在jar包没有打进Artifact而不是代码本身。5.3 页面中文乱码三层编码设置缺一不可现象数据库里有正常中文但JSP页面显示一堆问号或者表单提交的中文到后台变成乱码存进了数据库。原因JavaWeb的中文乱码从来不是单一原因是请求、响应、数据库连接三层有一层没对齐。Tomcat默认请求编码不是UTF-8JSP默认响应编码也不是UTF-8MySQL连接默认字符集不是utf8mb4任何一层不对都乱。解决按三层分别处理。数据库连接URL加characterEncodingutf8JSP页面顶部写全contentType和pageEncodingServlet里在读取参数前先调request.setCharacterEncoding(UTF-8)响应端用response.setContentType(text/html;charsetUTF-8)。另外Tomcat的Server.xml里可以在Connector上加URIEncodingUTF-8这是很多老项目的做法。如果做完这些还有个别乱码直接在代码里用new String(value.getBytes(ISO-8859-1), UTF-8)做一次转换但这是最后手段正常情况不要依赖它。5.4 ClassNotFoundException: com.mysql.jdbc.Driverjar包没进Artifact现象IDEA项目里能看到mysql-connector的jar代码里import也没有报错但一启动Tomcat访问页面就抛ClassNotFoundException提示找不到驱动类。原因这个坑特别有迷惑性。IDEA编译时能找到jar是因为它在Libraries里但运行时Tomcat加载的是Artifact输出目录里的WEB-INF/lib如果jar没被放进这个目录Tomcat自然找不到。解决打开Project Structure左侧选Artifacts选中你的项目点开WEB-INF/lib看看右边Available Elements里的mysql-connector jar是否在里面。不在的话右键jar选择Put into /WEB-INF/lib。然后在Tomcat配置里把Application context对应的目录删掉重新部署一次保证把新的Artifact输出同步过去。判断是否成功最直接的办法是去IDEA的项目out目录下找到这个war解压文件夹看WEB-INF/lib里有没有那个jar。5.5 库存被减成负数事务和条件更新不能省现象数据库里某药品库存只剩1但两个操作员同时开销售单最终库存变成-1甚至出现两条销售明细都成功的情况。原因这是典型的并发超卖。常见写法是先SELECT出库存Java里判断大于0再UPDATE两个线程同时查都看到库存是1都通过了判断于是都执行了UPDATE库存被减两次。解决把“判断库存够不够”和“扣库存”合成一条UPDATE用WHERE里的stock_quantity ?做条件配合事务回滚。前面第4章写的deductStock就是标准做法。课程设计到这一步已经够答辩了如果你想进一步展示能力可以再说用乐观锁给drug表加一个version字段UPDATE时条件带version影响行数为0就提示“操作冲突请刷新重试”。但注意条件更新已经能解决超卖version属于加分项不是必做项。6. 验收演示与进阶方向把大作业从“能跑”做到“能讲”6.1 一版能站住脚的验收演示清单很多同学到答辩前才想起来调试结果现场录入一个药品后不知道下一步演示什么。我建议按下面的顺序预演每一步都有明确预期结果整套走下来大概10分钟既能覆盖业务闭环又能展示技术亮点。步骤操作预期结果1. 初始化数据库执行建表SQL导入初始数据admin能登录2. 登录系统管理员账号登录进入首页看到菜单3. 新增药品填写名称、批准文号、价格、预警线药品列表出现新记录4. 采购入库选供应商、选药品、填数量提交库存增加入库流水生成5. 销售出库开销售单选药品和数量库存减少销售流水生成6. 验证事务销售数量大于库存提交提示失败流水不残留7. 触发低库存预警把某药品库存调低列表高亮预警页能查到8. 切换角色换操作员登录看不到用户管理菜单演示时重点讲第6步故意让一次销售失败然后打开数据库给老师看销售主表和明细表里没有脏数据库存也没变化。这个动作比嘴上说“我用了事务”有说服力得多。6.2 进阶方向从JSPServlet到SSM/Spring Boot值得吗如果你的大作业还有余力可以考虑往三个方向升级但要分清楚哪些是刚需、哪些是炫耀。第一个方向是引入Maven管理依赖它能解决jar包到处放的问题对后面毕业设计也有帮助。第二个方向是把JDBC的DAO层换成MyBatis或Spring JDBC Template代码量会明显下降但你要保证能讲清楚原来JDBC的事务是怎么被框架接管的。第三个方向是给统计功能加Excel导出用POI把销售按日汇总导出成表格这在医药管理系统里很实用。我的态度是先把当前这套能跑稳再去动框架。我见过太多人答辩前一周决定把Servlet改成Spring Boot结果配置文件没跑通原来能演示的系统也崩了。这个系统的核心评分点永远是业务闭环、事务正确性和数据库设计技术栈只是载体。如果你选了升级记住保留一个不带框架的完整备份这算是给自己的后悔药。最后说个我自己的血泪教训读书时做大作业答辩前临时改了库存预警SQL当时偷懒没重启Tomcat现场点开页面还是旧数据我还以为是数据库没更新当着老师面反复执行脚本。后来我养成了一个习惯改代码先Clean再重启Tomcat改SQL先命令行跑通再贴进代码层演示前把数据库脚本完整执行一遍。这套习惯让我后来工作里少踩了很多坑希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?