
简介基于JSP的CIMS课程设计源码面向正在学习Java动态网页技术或需要完成课程设计的学生与开发者通过实际项目理解模型-视图-控制器分层结构、JSP与Servlet协作方式以及数据库访问流程。资源包共212个文件大小约15.2MB以大量的XML配置文件、JAR依赖库、JAVA源文件、JSP页面为核心并配有CSS样式、JavaScript脚本、PNG图片、SQL初始化脚本与属性文件目录分级明了便于按功能检索学习。通过源码可熟悉JSP开发环境的搭建、调试及部署流程快速掌握常见业务模块的编写套路。当前已有103人浏览学习适合作为课堂实训、课程设计或毕业设计的辅助参考资料。源码中可看到分页Beans、控制器类、业务服务类等典型实现覆盖分页查询、用户管理、客户资料维护等常见场景同时提供数据库建表脚本和运行配置能够帮助快速搭建演示环境也为后续二次开发提供了清晰的基础。1. 课程设计交个静态网页不算完CIMS用JSP做出来才有分期末课程设计题目是“基于Java Server Pages技术的CIMS课程设计”很多同学第一反应是套个Bootstrap模板把页面做得好看点数据库都不连。但CIMS计算机集成制造系统课程设计的评分点恰恰在“系统”两个字上——能不能登录、能不能对生产计划做增删改查、物料库存能不能动态更新。这篇笔记从选型、数据库设计到核心模块代码把JSP版本的CIMS完整拆开给出一套能直接复现的落地路径。适合正在做Java Web课程设计的学生也适合想快速回顾JSP Servlet MySQL这套老技术栈的开发者。2. 选型先想明白为什么是JSP Servlet MySQL而不是Spring Boot2.1 CIMS系统在课程设计里到底要做什么CIMS全称Computer Integrated Manufacturing System计算机集成制造系统。听着很大但在本科课程设计层面老师要的通常不是真的去对接车间设备而是把制造企业的核心业务数据流用Web系统串起来。常见的功能划分是基础数据管理用户、角色、权限、生产计划管理计划制定、修改、下发、物料需求管理根据BOM计算物料需求、维护库存、订单管理客户订单录入、状态跟踪、设备管理设备台账、状态记录。如果你拿到手的题目说明比较含糊先做一件事把题目里的功能词圈出来按“必须有”和“加分项”分两类。登录和用户管理几乎必有生产计划或物料管理至少有一样剩下的看时间定。生产计划这块是CIMS区别于普通进销存系统的关键点。普通课设做订单、做商品都能过但CIMS要求你体现出“制造”的概念——订单下来之后怎么排产、怎么关联物料、怎么跟踪状态。哪怕只是数据库层面把订单表和生产计划表通过外键关联起来业务逻辑上就已经站得住脚了。我见过不少同学把CIMS直接做成一个电商后台卖货下单库存一套全齐但就是没有“计划”和“制造”的影子答辩时老师一问就露馅。2.2 JSP Servlet JavaBean三层架构是怎么分工的标题把Java Server Pages写在最前面说明评分标准是围绕JSP技术展开的。常见做法是采用JSP Model 2架构也就是MVC的变体JSP负责视图层View放HTML、CSS、JavaScript通过EL表达式和JSTL标签动态渲染数据Servlet负责控制器Controller接收请求、调用业务逻辑、决定跳转到哪个页面JavaBean / DAO负责模型层Model封装数据、操作数据库。请求流转路径一般是浏览器请求 - web.xml里配置的Servlet映射 - Servlet调用DAO查询数据库 - 结果setAttribute放进request - forward到JSP页面 - JSP用JSTL遍历输出 - 浏览器渲染。JSP页面本身在服务器端会被编译成Servlet所以JSP能做的一切Servlet都能做但反过来Servlet里拼接HTML字符串是反人类的。Model 2架构的核心约定是JSP页面里不写Java业务逻辑只保留page指令和taglib指令数据通过request或session作用域传到页面用${}表达式取出来。这样做的直接好处是代码分层清楚评分老师翻代码时看到JSP里干干净净、Servlet里没有out.println( )这种代码印象分会高不少。初学者最容易忽略的是JSP页面的生命周期。JSP文件第一次被访问时Tomcat会把它翻译成java文件再编译成class本质上JSP就是一个特殊的Servlet。这意味着你JSP里写的Scriptlet片段% %最后会被拼进Servlet的_jspService方法里。理解了这一点你就能理解为什么JSP里可以用request、response、session、application这些内置对象——它们就是_jspService方法的局部变量或Servlet的成员变量。答辩时被问“JSP和Servlet什么关系”把这段讲清楚比背定义有用得多。2.3 和Spring Boot、MyBatis方案的取舍这几年java课程设计案例源码里Spring Boot MyBatis占了多数但JSP课程设计用纯JDBC甚至DBUtils反而更稳。原因有三第一评分标准通常明确写了“用JSP Servlet JavaBean实现”用了框架不算错但答辩时老师会追问框架原理答不上来就减分第二纯JDBC的代码量不大一张表的增删改查也就几十行调试起来比套MyBatis更容易定位问题第三很多学校的实验环境还是Eclipse Tomcat 8.5 JDK 8这套组合跑JSP项目几乎零额外配置。我一般会建议如果你的课程设计说明里出现了“JSP”字样就老老实实用JSP Servlet JDBC如果说明里写的是“Web系统”那才考虑Spring Boot。选型本身不影响工作量影响的是答辩时的解释成本。还有一个时间成本问题课程设计一般三周第一周定方案和建表第二周写代码第三周测试和写报告每天实际能投入的时间可能只有两三个小时。JSP Servlet这套技术栈第三周开始写代码完全来得及Spring Boot光把起步依赖和配置类搞清楚一个周末可能就没了。如果你非要在这类JSP项目里用MyBatis也不是不可以。把mybatis-config.xml放在src目录下在Servlet里通过SqlSessionFactoryBuilder加载然后调用Mapper接口。但注意jar包要全部放到WEB-INF/lib下不要用Maven的中央仓库依赖管理因为课程设计提交的是整个工程目录老师要能直接import进Eclipse。不过说实话MyBatis的xml映射文件对新手来说比JDBC难调试尤其是一对多关联查询写不好就全表扫描课设阶段没必要给自己加这个负担。3. 数据库和工程骨架五张表加三层包结构先把地基打牢3.1 CIMS核心表设计从订单到物料怎么关联CIMS课程设计的数据库设计评分老师重点看三件事表结构是否合理、主外键是否规范、是否满足第三范式适度冗余。给出一套可以直接用的五表方案表名关键字段说明t_userid, username, password, role用户表role区分admin/operatort_orderid, order_no, customer_name, product_name, quantity, status, create_time订单表status记录待生产/生产中/已完成t_materialid, material_code, material_name, stock_quantity, safety_stock物料表safety_stock是安全库存预警线t_planid, plan_no, order_id, material_id, start_date, end_date, status生产计划表外键关联订单和物料t_deviceid, device_code, device_name, status设备表status记录运行/停机/维修这套表的关系是订单产生生产计划生产计划关联物料设备作为独立台账。为什么要外键关联因为答辩时老师大概率会问“订单删除后生产计划怎么办”如果你建了外键并设置了ON DELETE CASCADE就能答上来如果没建外键就要在代码里手动维护工作量更大还容易漏。建表SQL不要直接在Navicat里点鼠标建把DDL语句写进init.sql文件放到项目根目录既是交付物的一部分也方便老师复现。CREATE DATABASE cims DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE cims; CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20) NOT NULL UNIQUE, password VARCHAR(32) NOT NULL, role VARCHAR(10) DEFAULT operator ); -- 演示用户admin / 123456MD5后存入 INSERT INTO t_user (username, password, role) VALUES (admin, e10adc3949ba59abbe56e057f20f883e, admin);这里有个参数坑数据库字符集一定要在CREATE DATABASE时指定不要在表里单独指定。如果库是utf8mb4、表是utf8JSP页面里用UTF-8提交中文数据时偶尔会报“Incorrect string value”错误。统一utf8mb4能省掉这个麻烦。3.2 环境搭建Eclipse Tomcat 8.5 MySQL 5.7的一次性配置常见的课程设计环境组合是JDK 8 Eclipse IDE for Enterprise Java and Web Developers Tomcat 8.5 MySQL 5.7。如果你学校机房的版本不一样只要JDK不低于8、Tomcat不低于8用下面这套配置都能跑。Eclipse里新建项目File - New - Dynamic Web ProjectProject name填CIMSTarget runtime选Tomcat 8.5Configuration选Default Configuration for Apache Tomcat勾选Generate web.xml deployment descriptor。Dynamic Web Project和普通Java项目的区别在于多了WebContent目录JSP文件放这里class文件编译到WEB-INF/classes。生成web.xml很关键没有它Servlet映射就无处配置。项目结构约定成这样CIMS/ ├── src/ │ ├── com/cims/bean/ -- 实体类 │ ├── com/cims/dao/ -- 数据库访问 │ ├── com/cims/servlet/ -- 控制器 │ └── com/cims/util/ -- 工具类DBUtil、MD5Util ├── WebContent/ │ ├── index.jsp -- 登录页 │ ├── admin/ -- 管理端页面 │ ├── operator/ -- 操作员页面 │ ├── WEB-INF/ │ │ ├── web.xml │ │ └── lib/ -- mysql-connector-java-5.1.49.jar, jstl-1.2.jar │ └── css/ └── init.sql包结构的命名直接体现了分层思想答辩时老师看目录就能判断你是不是真的理解了三层架构。有些同学的代码全部塞在default package里临时文件东一个西一个这类工程就算功能全对印象分也高不了。3.3 DBUtil工具类数据库连接的唯一入口数据库连接不能每个DAO类里都写一遍DriverManager.getConnection那样代码重复率太高而且连接管理不统一必然出资源泄漏。建议所有DAO共用同一个DBUtil类package com.cims.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/cims?useUnicodetruecharacterEncodingUTF-8useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(com.mysql.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt ! null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }URL里的参数每个都有用useUnicodetrue配合characterEncodingUTF-8保证中文不乱码useSSLfalse避免MySQL 5.7连本地时报SSL警告刷屏serverTimezoneAsia/Shanghai是因为MySQL 8.0默认时区跟JVM不一致读写DATETIME会差8小时。如果你的MySQL是5.7serverTimezone不写也能跑但写了更保险。PASSWORD里的123456是本地开发库的密码提交前记得改成老师的统一配置不然换机器跑不起来这也是交付时最容易翻车的点。4. 核心模块实现登录、生产计划、物料清单三段可复制的JSP代码4.1 登录与权限控制Session Filter挡住未登录请求登录是每个Web课程设计都要有的。JSP课设里最常见的登录实现是表单提交到LoginServletServlet里查数据库比对用户名密码对了就session.setAttribute(user, user)错了就返回登录页并提示。登录页面index.jsp% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8% !DOCTYPE html html head meta charsetUTF-8 titleCIMS登录/title /head body h2计算机集成制造系统/h2 form actionlogin methodpost input typetext nameusername placeholder用户名 requiredbr input typepassword namepassword placeholder密码 requiredbr button typesubmit登录/button /form % String msg (String) request.getAttribute(msg); if (msg ! null) out.println(p stylecolor:red msg /p); % /body /html页面顶部的page指令里contentType和pageEncoding都设为UTF-8这是中文不乱码的第一道防线。form的action写成“login”而不是“loginServlet”因为web.xml里Servlet映射的url-pattern就是/login。注意这段脚本片段用了Scriptlet输出错误提示这是JSP里少数几个可以接受的使用场景——纯展示逻辑不涉及业务计算。LoginServlet.javapackage com.cims.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.cims.bean.User; import com.cims.dao.UserDao; public class LoginServlet extends HttpServlet { private static final long serialVersionUID 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password MD5Util.md5(request.getParameter(password)); UserDao dao new UserDao(); User user dao.findByUsernameAndPassword(username, password); if (user ! null) { HttpSession session request.getSession(); session.setAttribute(user, user); session.setMaxInactiveInterval(30 * 60); response.sendRedirect(plan/list); } else { request.setAttribute(msg, 用户名或密码错误); request.getRequestDispatcher(index.jsp).forward(request, response); } } }密码没有明文比对而是先用MD5Util.md5()做哈希再查库。课程设计里这个强度够用。Session超时设为30分钟防止答辩演示时系统挂着不动后Session过期所有页面突然跳登录页的尴尬。用Filter统一做权限校验比每个Servlet开头写if (session.getAttribute(user) null)要优雅。新建AuthFilter.javapackage com.cims.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class AuthFilter implements Filter { 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); String path request.getRequestURI(); if (path.endsWith(index.jsp) || path.contains(/login) || session ! null session.getAttribute(user) ! null) { chain.doFilter(req, res); } else { response.sendRedirect(request.getContextPath() /index.jsp); } } }Filter的白名单思路是登录页和登录接口放行其余请求必须有Session里的user属性否则重定向回登录页。注意request.getSession(false)里的false参数——如果传true没有Session时会新建一个空SessionFilter判断就会失效。web.xml里注册Servlet和Filter?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 servlet servlet-nameLoginServlet/servlet-name servlet-classcom.cims.servlet.LoginServlet/servlet-class /servlet servlet-mapping servlet-nameLoginServlet/servlet-name url-pattern/login/url-pattern /servlet-mapping filter filter-nameAuthFilter/filter-name filter-classcom.cims.filter.AuthFilter/filter-class /filter filter-mapping filter-nameAuthFilter/filter-name url-pattern/*/url-pattern /filter-mapping welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list /web-app4.2 生产计划管理DAO模式下的增删改查生产计划是CIMS的核心业务模块。从数据流来看订单进来后计划员创建生产计划、指定物料、设置起止日期然后下发到车间。在代码层面就是一张表的CRUD但DAO怎么设计是评分老师翻代码时重点看的。PlanDao.java里的查询方法package com.cims.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.cims.bean.Plan; import com.cims.util.DBUtil; public class PlanDao { public ListPlan findAll() { ListPlan list new ArrayListPlan(); String sql SELECT p.*, o.order_no, m.material_name FROM t_plan p LEFT JOIN t_order o ON p.order_id o.id LEFT JOIN t_material m ON p.material_id m.id ORDER BY p.start_date DESC; Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DBUtil.getConnection(); ps conn.prepareStatement(sql); rs ps.executeQuery(); while (rs.next()) { Plan plan new Plan(); plan.setId(rs.getInt(id)); plan.setPlanNo(rs.getString(plan_no)); plan.setStatus(rs.getString(status)); plan.setStartDate(rs.getDate(start_date)); plan.setEndDate(rs.getDate(end_date)); plan.setOrderNo(rs.getString(order_no)); plan.setMaterialName(rs.getString(material_name)); list.add(plan); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, rs); } return list; } }这里的JOIN是答题亮点单表查询在课程设计里不会扣分但能JOIN出订单号和物料名称至少说明你理解了表间关系。LEFT JOIN保证即使某条计划没有关联订单比如草稿状态也能查出来这在状态流转里很常见。对应的添加计划操作注意用PreparedStatement而不是Statement既能防SQL注入又是标准写法public boolean addPlan(Plan plan) { String sql INSERT INTO t_plan (plan_no, order_id, material_id, start_date, end_date, status) VALUES (?, ?, ?, ?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, plan.getPlanNo()); ps.setInt(2, plan.getOrderId()); ps.setInt(3, plan.getMaterialId()); ps.setDate(4, new java.sql.Date(plan.getStartDate().getTime())); ps.setDate(5, new java.sql.Date(plan.getEndDate().getTime())); ps.setString(6, plan.getStatus()); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } }Java 7的try-with-resources写法在这里正好用上省掉了finally里手动关闭连接的代码。但注意它要求Plan里的startDate是java.util.DatesetDate时转成java.sql.Date不然类型对不上会编译报错。控制层PlanAddServlet里接收表单参数、参数校验、调用DAO、跳转四步走protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String planNo request.getParameter(planNo); int orderId Integer.parseInt(request.getParameter(orderId)); int materialId Integer.parseInt(request.getParameter(materialId)); String startDate request.getParameter(startDate); String endDate request.getParameter(endDate); Plan plan new Plan(); plan.setPlanNo(planNo); plan.setOrderId(orderId); plan.setMaterialId(materialId); // SimpleDateFormat解析yyyy-MM-dd格式解析失败抛ParseException try { SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd); plan.setStartDate(sdf.parse(startDate)); plan.setEndDate(sdf.parse(endDate)); } catch (ParseException e) { request.setAttribute(msg, 日期格式不正确); request.getRequestDispatcher(plan/add.jsp).forward(request, response); return; } plan.setStatus(草稿); PlanDao dao new PlanDao(); if (dao.addPlan(plan)) { response.sendRedirect(plan/list); } else { request.setAttribute(msg, 添加失败); request.getRequestDispatcher(plan/add.jsp).forward(request, response); } }这里有个习惯值得养成日期字符串解析一定要try-catch用户输入“2025-13-45”这种非法日期时如果不拦截SimpleDateFormat抛出的ParseException会让整个请求500。课程设计答辩现场最怕的就是这种一眼就能看出来的低级错误崩掉。4.3 物料清单显示JSTL和EL表达式替代ScriptletJSP页面上最忌讳满屏的% for %和% if %。用JSTL的c:forEach遍历物料列表代码干净而且评分老师喜欢看到你用标准标签库。material/list.jsp% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8% % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % !DOCTYPE html html head meta charsetUTF-8 title物料清单/title link relstylesheet href${pageContext.request.contextPath}/css/common.css /head body h2物料库存/h2 table border1 tr th物料编码/th th物料名称/th th当前库存/th th安全库存/th th状态/th /tr c:forEach items${materialList} varm tr td${m.materialCode}/td td${m.materialName}/td td${m.stockQuantity}/td td${m.safetyStock}/td td c:choose c:when test${m.stockQuantity m.safetyStock}充足/c:when c:otherwisespan stylecolor:red不足/span/c:otherwise /c:choose /td /tr /c:forEach /table a href${pageContext.request.contextPath}/plan/list返回生产计划/a /body /htmlc:forEach遍历的是Servlet里setAttribute放进request作用域的materialList。c:choose/c:when/c:otherwise组合做库存是否低于安全线的判断比在JSP里写% if (m.getStockQuantity() m.getSafetyStock()) %干净得多。这里的关键点是${m.stockQuantity}实际上调用的是Material这个JavaBean的getStockQuantity()方法所以实体类属性名必须和getter方法对应否则页面上输出空白。这是新手最容易踩的坑——数据库中列名是stock_quantityJava属性写成stockQuantityJSP里写${m.stock_quantity}是大写的错。4.4 报表统计JDBC聚合查询撑起一张汇总表CIMS里通常要有一张统计报表最简单的就是按订单状态分组统计数量。这个功能不需要任何前端图表库一张HTML表格就够protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ListMapString, Object stats new ArrayListMapString, Object(); String sql SELECT status, COUNT(*) AS cnt FROM t_order GROUP BY status; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { MapString, Object row new HashMapString, Object(); row.put(status, rs.getString(status)); row.put(cnt, rs.getInt(cnt)); stats.add(row); } } catch (SQLException e) { e.printStackTrace(); } request.setAttribute(stats, stats); request.getRequestDispatcher(report/order_stat.jsp).forward(request, response); }用Map承载查询结果省掉新建一个统计VO类的步骤。课程设计的数据量不大这个做法完全够用但如果你想让代码更规范可以新建OrderStatBean把status和cnt封装成两个属性效果一样。JSP页面里展示时同样用c:forEach遍历stats内部用${s.status}和${s.cnt}取数。需要合计行的话可以在DAO里再查一次COUNT(*)也可以在Java代码里累加列表里的cnt第二种方式少一次数据库查询。5. 避坑JSP课程设计最常见的5个翻车现场5.1 页面全乱码数据库、页面、请求三层编码不一致现象表单提交中文数据后数据库里存的是问号或者页面显示乱码。原因三层编码不统一。数据库是latin1JSP页面是GBKServlet没有调用request.setCharacterEncoding任何一个环节掉链子中文就废了。解决全部统一为UTF-8。数据库建库时指定utf8mb4JSP页面page指令里contentType和pageEncoding都写UTF-8Servlet的doPost开头写request.setCharacterEncoding(UTF-8);。如果用了Tomcat 8以上connector的URIEncoding默认就是UTF-8不用额外配置。这个坑最容易在答辩前夜出现而且一旦数据已经用错误编码写进库清洗数据比改代码还麻烦所以一定在一开始就统一编码。5.2 部署后404web.xml里的url-pattern没带斜杠现象Eclipse里跑得好好的部署到Tomcat的webapps目录后访问/login报404。原因web.xml里写的 login 少了开头的斜杠Tomcat部署时解析不到映射。解决url-pattern必须写成/login这种以/开头的形式。另外检查项目是否被打成了war包WebContent目录下的文件是否都在war包根目录而不是多了一层文件夹。还有一种情况是Eclipse的Server配置里没勾选“Use Tomcat installation”而用了workspace metadata目录部署路径对不上建议在Server双击后把Server Locations改成Use Tomcat installation指定到Tomcat安装目录的webapps下。5.3 JDBC驱动加载ClassNotFoundException现象控制台报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因mysql-connector-java.jar没有放到WEB-INF/lib下。很多人把jar放在桌面然后用Build Path引入Eclipse运行时能找到但Tomcat部署时只看WEB-INF/lib。解决把jar文件复制到WebContent/WEB-INF/lib目录下然后右键项目Refresh再右键项目 - Build Path - Configure Build Path - Add JARs选中它。课程设计最常见的操作就是手动复制jar到lib目录这完全没问题但记得做完后重新Publish到Tomcat。如果你的Tomcat启动时在控制台也报这个错先检查jar是否真的在WEB-INF/lib下不要在Project Explorer里看着像在就完了实际文件可能没拷进去。5.4 数据库连接耗尽没有关闭连接页面越来越慢现象系统用个把小时后点任何页面都转圈控制台刷Too many connections。原因DAO里每次查询都new一个Connection用完没关。MySQL默认max_connections是151连接泄漏几次就炸了。解决每个DAO方法的finally块里调用DBUtil.close()关闭连接。如果你用了try-with-resources连接会在语句块结束时自动关闭。排查时可以用MySQL命令行执行SHOW PROCESSLIST;看看有没有大量Sleep状态的连接有就说明有连接没关。这个坑在课设验收时特别尴尬——平时页面少没人发现老师一上来多点几个页面就卡死了。想彻底解决的话可以用apache的commons-dbcp2连接池替代裸连接但那又要加jar包和配置课设阶段把连接关好就够了。5.5 页面显示的还是旧数据浏览器缓存和编译缓存现象改了JSP文件刷新浏览器看到的还是老样子。原因浏览器缓存了页面或者Eclipse没有重新编译JSP又或者Tomcat没重启。解决开发阶段在浏览器按CtrlF5强制刷新Eclipse里Project - Clean清一次编译缓存Tomcat里右键项目 - Clean把work目录下的编译产物清掉。JSP修改后不需要重启Tomcat但如果改了web.xml、Servlet或Filter一定要重启Tomcat才能生效。这个坑的迷惑性在于有时候你改对了代码但Tomcat跑的class还是旧的Java的编译缓存机制会让你怀疑人生。6. 让答辩加分的验证路径测试用例与运行日志课程设计答辩老师一般会现场让你演示几个功能然后随机抽查代码。你提前准备好一条演示链路比现场手足无措强一百倍。推荐的演示顺序是登录admin/123456- 进入生产计划列表 - 新增一条计划选订单、选物料、填日期- 返回列表确认数据出现 - 点进物料清单看库存变化 - 打开订单统计看数字变化。这条链路覆盖了登录、CRUD、关联查询、聚合统计几乎把系统的所有亮点都过了一遍。测试数据要预先准备不要现场造。比如订单表里准备三条不同状态的订单待生产、生产中、已完成物料表里准备一条库存低于安全线的记录这样页面上的红色“不足”提示就会出现老师看到系统有判断逻辑会加分。运行日志方面在Eclipse的Console里保留Tomcat启动日志和应用的System.out输出。答辩时如果被问到“系统运行正常吗”直接切到Console展示启动过程无异常比口头保证更有说服力。另外一个实用技巧在系统的导航栏把登录用户名显示出来答辩时可以演示Session的作用。点一个功能后用浏览器开发者工具看一下Cookie里的JSESSIONID然后告诉老师“JSP引擎靠这个维持会话”这个细节能让老师认为你真的理解了原理。最后说一个我自己的习惯课程设计提交前把MySQL的导出SQL和项目的init.sql对比一遍确保老师导入数据库后系统能一次跑通。很多项目在自己的机器上能跑换一台机器就死九成是数据库初始化脚本和代码默认配置对不上。立一个检查清单数据库名、用户名、密码、端口四处配置一致再交付。希望这些内容能帮你把JSP版本的CIMS系统做扎实答辩顺利。本文还有配套的精品资源点击获取