资讯详情

学生信息管理系统课设实战:JSP+Servlet+MySQL完整拆解

📅 2026/10/15 12:48:05 | 华诺云谱 👁 阅读
学生信息管理系统课设实战:JSP+Servlet+MySQL完整拆解
简介基于Java Web的简单学生信息管理系统是一份面向Java Web初学者及课程设计场景的完整项目源码采用jspservletlayuijquery技术实现涵盖学生注册登记、教师登录管理、信息增删改查等核心功能部署于jdk7tomcat8mysqlIntelliJ IDEA环境非常适合作为实训作业、期末项目或课程设计参考。资源包共2个文件主体为zip压缩包内含项目工程文件及lib目录下所需jar包另附一个htm说明文档帮助读者快速了解部署流程与资源下载地址整体大小仅2.13MB轻量易用。已有6435人学习浏览。项目数据库文件通过百度网盘单独提供jar包已内置按readme指引即可导入IDEA运行代码注释清晰jspservlet分层结构简单直观可帮助读者理解请求响应机制、数据库连接及基础增删改查实现同时结合layui美化前端界面方便在此基础上扩展功能或调整业务逻辑。1. 简单学生信息管理系统课程设计里最常见的JSPServlet项目到底怎么落如果你的课程设计题目恰好是“简单学生信息管理系统”并且要求用JSPServlet来写那这套资源值得你在动手前完整过一遍。它的核心组合是JSP做页面、Servlet做请求控制、MySQL存数据整套代码不是教学片段而是能直接跑在Tomcat上的可运行项目。我拆完之后的感受是这个系统真正难的地方不在代码量而在数据库设计、请求流转和部署环境三块。适合刚做完JavaWeb基础、想拿一套完整代码换皮或逐段理解的人也适合答辩前想排查部署问题的人。读完后你至少能分清哪些是必须改的哪些属于加分项。2. 系统架构与数据库设计五张表的边界与三层的分工2.1 JSP/Servlet/JavaBean 三层职责边界一个“简单学生信息管理系统”如果控制不好分层容易写成每个JSP页面里直接用JDBC查库表面上省事实际上每一处都要改而且不好回答评委提问。常见做法是把系统拆成三层JSP只负责接收数据并渲染Servlet负责解析请求参数、调用业务方法、决定跳转JavaBean承担模型和数据访问。这里的模型不是只指实体类而是DAO和Service两类对象。课程设计阶段不要求引入Spring所以这一层靠手工维护。为什么还要选JSPServlet而不是Spring Boot因为很多课程设计的评分标准是“让学生说清楚HTTP请求从浏览器到数据库再到页面经过哪些环节”。用Servlet能直接面对HttpServletRequest和HttpServletResponse概念不经过框架包装答起题来更直观。Spring Boot当然更快但评委一旦追问“拦截器、过滤器、依赖注入”的原理基础不牢就会露馅。所以从课程设计角度JSPServlet不是过时而是一个更容易被验证的教学过程。请求流转也很简单浏览器访问某个URLweb.xml或WebServlet把URL映射到对应ServletServlet调用DAO操作数据库把结果封装成JavaBean列表通过request.setAttribute传给JSPJSP用JSTL或表达式语言循环渲染。这套链路理解透了后面看每一段代码都不会是黑匣子。2.2 数据库设计五张表的结构与约束这套资源库里数据库一共五张表分别是用户表、班级表、学生表、课程表和成绩表。表名建议都带 t_ 前缀避免与MySQL保留字冲突。用户表负责管理员登录班级与学生是父子关系学生与课程通过成绩表关联。这样的设计不是堆表而是让你在答辩时能解释清楚“为什么要分多张表”——一张学生表里塞班级名、课程名、成绩会导致大量冗余且删除学生时容易丢成绩。下面是一份可以放进MySQL直接执行的DDL建库用utf8mb4排序规则用utf8mb4_unicode_ci。注意外键约束我每一行都写了这样在批量删数据时会比无外键的项目安全一些如果课程设计模板不允许外键去掉FOREIGN KEY也能跑只是逻辑上的父删子留容易造成脏数据。CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE student_db; -- 管理员用户表密码保存MD5摘要 CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(30) NOT NULL UNIQUE, password CHAR(32) NOT NULL ) ENGINEInnoDB COMMENT管理员用户表; -- 班级表 CREATE TABLE t_class ( id INT PRIMARY KEY AUTO_INCREMENT, class_name VARCHAR(50) NOT NULL ) ENGINEInnoDB COMMENT班级表; -- 学生表学号唯一 CREATE TABLE t_student ( id INT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(20) NOT NULL UNIQUE, name VARCHAR(30) NOT NULL, gender CHAR(1) DEFAULT 男, birth_date DATE, phone VARCHAR(20), class_id INT NOT NULL, CONSTRAINT fk_student_class FOREIGN KEY (class_id) REFERENCES t_class(id) ) ENGINEInnoDB COMMENT学生表; -- 课程表 CREATE TABLE t_course ( id INT PRIMARY KEY AUTO_INCREMENT, course_name VARCHAR(50) NOT NULL, credit DECIMAL(3,1) DEFAULT 2.0 ) ENGINEInnoDB COMMENT课程表; -- 成绩表外键关联学生和课程 CREATE TABLE t_score ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, course_id INT NOT NULL, score DECIMAL(5,2), CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES t_student(id), CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES t_course(id) ) ENGINEInnoDB COMMENT成绩表;这里有几个参数可以按自己需求调student_no设为UNIQUE是为了防止同一学号重复插入这是删除和查重时的底线gender字段用CHAR(1)长度足够不用VARCHARscore用DECIMAL(5,2)最大999.99对课设足够ID全部用INT自增学生量不超过几十万都可以。如果你要扩展学生照片建议加一个VARCHAR保存相对路径不要让数据库存base64或二进制大文件否则页面加载很慢、备份也很痛苦。这是我处理课设时很常用的一个边界。2.3 数据库连接方式Druid连接池与db.properties参数连接池是这套资源里容易被忽略但必须搞懂的部分。很多课程设计模板还是用DriverManager每次请求现连数据库代码少但每次握手开销大页面上连续操作几次就变慢。这里改成Druid连接池配置集中在db.properties里改数据库密码不用动Java代码。下面四个参数最重要。# MySQL 8驱动类名 driverClassNamecom.mysql.cj.jdbc.Driver # 连接地址时区必须显式声明 urljdbc:mysql://127.0.0.1:3306/student_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai usernameroot password123456 # 连接池初始连接数和最大连接数 initialSize5 maxActive20 maxWait3000driverClassName是MySQL 8以上必须的驱动类名如果是MySQL 5.7很多老项目写的还是com.mysql.jdbc.Driver那就会报找不到类。URL里我加了serverTimezoneAsia/ShanghaiMySQL 8连接时不给时区直接报错。initialSize表示启动时创建的连接数maxActive是最大连接数课程设计场景20足够。这段配置变更是最常见的部署坑后面避坑章节会详细说。对应的JdbcUtils工具类要写好不然每个DAO都要重复加载配置文件。完整写法如下public class JdbcUtils { private static DataSource dataSource; static { try { // 从classpath读取配置文件 Properties props new Properties(); props.load(JdbcUtils.class.getClassLoader() .getResourceAsStream(db.properties)); // 交给Druid创建连接池 dataSource DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }注意ClassLoader.getResourceAsStream读取的是classpath根目录下的文件所以db.properties必须放在src目录或resources目录下而不是WEB-INF里。DruidDataSourceFactory.createDataSource会读到配置文件里的每个键键名不能改改了会静默使用默认值。等排查时发现连接数不对先回头看配置名是否写错。getConnection返回的是连接池里的连接使用后要close回收不是真的断开。3. 用户登录与权限控制从登录请求到Session校验3.1 登录流程与MD5加密存储这个系统的登录入口是login.jsp页面提交后由LoginServlet处理。流程上Servlet先读取username和password两个参数再做一次简单非空校验然后调用UserDao查询数据库中是否存在匹配记录。这里有一个必须做的细节密码不要明文存。课程设计中很多同学为了省事注册管理员直接insert明文答辩演示时打开数据库给评委看密码是123456不太好看。更合理的做法是在SQL脚本里预置一条MD5密文记录。MD5加密在工具类里封装一个静态方法即可。注意只做一次MD5加密不加盐足够应付课程设计生产环境还要加盐或改成BCrypt这里不展开。如果你准备答辩被问到为什么要加密答案就一句数据库泄露时明文密码会直接泄露MD5加密后至少不能直接还原。但也要知道MD5本身可以被彩虹表反查所以别把它吹成安全方案。真正要防守的是越权和注入而不是加密算法本身。public class Md5Util { public static String md5(String input) { try { // 计算MD5摘要 MessageDigest md MessageDigest.getInstance(MD5); byte[] result md.digest(input.getBytes(UTF-8)); StringBuilder sb new StringBuilder(); for (byte b : result) { // 每个字节转两位十六进制 sb.append(String.format(%02x, b)); } return sb.toString(); } catch (Exception e) { throw new RuntimeException(e); } } }这段代码关键点在MessageDigest.getInstance(MD5)拿到摘要对象digest返回16字节数组再用String.format(%02x)转成32位十六进制字符串。SQL脚本里预置用户数据时直接写Md5Util.md5(admin123)得到的值不要写原始密码。如果登录逻辑仍然查不到用户先检查一次密码加密是否正确最简单的方式是写一个临时main方法打印密文和数据库里的值比对。登录成功后我一般建议把用户对象存进Session而不是只存用户名。因为后续可能要显示当前操作者的信息或者扩展角色字段。Session里保存对象还有一个好处Filter判断时可以直接取对象的属性而不是只判断一个裸字符串。这个习惯能让后面的权限控制好扩展很多。3.2 用Filter统一做Session校验登录接口之外的所有页面都应该被保护否则用户在浏览器地址栏直接输入student_list.jsp就能跳过登录。课程设计里常见做法是在每个Servlet里都写一段“session是否为空”的判断代码重复且容易漏。更好的做法是用Filter统一拦截这也是答辩时的高频问题。资源里建议放一个AuthFilter把所有请求拦下来判断当前会话中是否有登录标记。下面是doFilter方法的核心逻辑public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; // 不主动创建Session防止无效会话占用内存 HttpSession session request.getSession(false); String uri request.getRequestURI(); String contextPath request.getContextPath(); // 放行登录页、登录接口和静态资源 if (uri.endsWith(/login.jsp) || uri.endsWith(/login) || uri.endsWith(.css) || uri.endsWith(.js) || uri.endsWith(.png)) { chain.doFilter(request, response); return; } // 已登录则放行否则重定向到登录页 if (session ! null session.getAttribute(loginUser) ! null) { chain.doFilter(request, response); } else { response.sendRedirect(contextPath /login.jsp); } }这里用request.getSession(false)而不是getSession()区别在于getSession(false)在没有会话时返回null不会主动创建Session。uri.endsWith判断是排除登录页、登录接口和静态资源如果你用的是web.xml配置拦截路径这里的排除逻辑就是防拦截的重中之重。把Filter放在web.xml里用/拦截或者用WebFilter(/)都可以但要确保filter-mapping在servlet-mapping之前声明这不是玄学是部署描述符的解析顺序。注意登录成功后要向session中设置一个属性比如session.setAttribute(loginUser, user)属性名要和Filter里的判断一致。否则明明登录成功了Filter还是把你弹回登录页这是很多同学踩过的坑。另外登录页本身不要做这个拦截否则会出现重定向死循环浏览器报“页面跳转次数过多”的错。3.3 退出与Session销毁退出功能的代码量很少但它能强化你对Session生命周期的理解。简单的退出Servlet里调用invalidate()方法把整个Session作废再重定向到登录页。很多人写成只removeAttribute(loginUser)那只会移除当前登录属性Session对象本身还在浏览器关闭前如果重新登录相关上下文可能残留。课程设计阶段用invalidate更彻底。WebServlet(/logout) public class LogoutServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 作废整个会话 request.getSession().invalidate(); response.sendRedirect(request.getContextPath() /login.jsp); } }退出建议用GET请求因为它是幂等操作不产生副作用直接放在页面导航链接里即可。而删除操作不同后面会讲到为什么不能把删除也做成GET。另外退出后你想防止浏览器后退看到缓存页面还需要在受保护页面设置no-cache响应头或者在Filter里设置response.setHeader(Cache-Control, no-store)。这个不算必须但答辩时主动提出来是加分项。4. 学生信息增删改查与分页Servlet路由与参数传递4.1 列表分页查询limit参数与PageBean列表页是整个系统体量最大的部分难点集中在分页和模糊查询。先看分页。数据库层用MySQL的limit可以很直接地控制每页记录数和偏移量Servlet里接收两个参数currentPage默认1pageSize默认5或10。要传给DAO两个整数DAO执行“select * from student where 条件 limit ?, ?”参数依次是偏移量和每页条数。这里要注意偏移量的计算是currentPage - 1* pageSize很多第一次写的同学直接把页码当成偏移量传进去第一页没问题第二页就少了一半数据。DAO层可以封装一个PageBean成员包括list、totalCount、totalPage、currentPage、pageSize。查询时先执行count统计再执行limit查询。两步之间如果有新增数据会出现总数和列表差一条课程设计不要求事务无所谓。下面是StudentDao里分页查询的写法public ListStudent findPage(int currentPage, int pageSize, String keyword) throws SQLException { // 分页查询offset由页码计算 String sql SELECT * FROM t_student st JOIN t_class cl ON st.class_id cl.id WHERE st.name LIKE ? OR st.student_no LIKE ? LIMIT ?, ?; int offset (currentPage - 1) * pageSize; try (Connection conn JdbcUtils.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); ps.setString(2, % keyword %); ps.setInt(3, offset); ps.setInt(4, pageSize); try (ResultSet rs ps.executeQuery()) { ListStudent list new ArrayList(); while (rs.next()) { Student stu new Student(); stu.setId(rs.getInt(id)); stu.setStudentNo(rs.getString(student_no)); list.add(stu); } return list; } } }这段代码用了join查询班级名一并展示。注意LIKE条件里的百分号是拼在参数里的而不是拼在SQL字符串里这是为了保持PreparedStatement的占位符完整。try-with-resources会自动关闭Connection、PreparedStatement、ResultSet省去finally里一堆判断。Connection从连接池拿回后close只是归还连接不会真的断开所以在这个方法内关闭没有任何问题。页面底部的页码栏需要计算总页数。totalPage (int) Math.ceil(totalCount * 1.0 / pageSize); 在JSP里可以用JSTL的c:if控制上一页、下一页的显示。这里最容易翻车的是JSTL标签没引入依赖页面直接报500。如果你不想引JSTL就用脚本片段但答辩观感稍差。资源里如果用了JSTL记得把jstl相关jar放进WEB-INF/lib。4.2 新增与修改表单中文乱码处理与SQL注入新增和修改放到一起讲因为它们的表单结构和后端处理基本一样。资源里的表单提交到StudentServletServlet通过一个隐藏字段id判断是新增还是修改id为空就是添加id不为空就是编辑。这样只需要一个doPost方法避免复制代码。doPost里第一行就应该是request.setCharacterEncoding(UTF-8)并且必须在调用getParameter之前。如果放在getParameter之后POST请求体已经按ISO-8859-1解析过了中文参数再转也容易丢字。同时response要设置ContentType为text/html;charsetUTF-8。JSP页面顶部的pageEncoding也要保持一致三层编码不统一中文在某个环节变成问号就是血泪经验。写入数据库的部分不要用字符串拼接而是用PreparedStatement。对比一下拼接写法是“INSERT INTO t_student VALUES ( id , name )”一旦name中包含单引号要么SQL报错要么被注入。PreparedStatement用setString绑定参数MySQL驱动会处理特殊字符。下面给出通用的插入方法片段String sql INSERT INTO t_student(student_no, name, gender, birth_date, phone, class_id) VALUES(?, ?, ?, ?, ?, ?); PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, studentNo); ps.setString(2, name); ps.setString(3, gender); // 日期从java.util.Date转成java.sql.Date ps.setDate(4, new java.sql.Date(birthDate.getTime())); ps.setString(5, phone); ps.setInt(6, classId); ps.executeUpdate();这里要注意日期参数页面传来的birthDate是String需要先用SimpleDateFormat解析成java.util.Date再转成java.sql.Date否则PreparedStatement没法直接setDate。如果直接setString到一个DATE字段MySQL在严格模式下会报日期格式错误。我第一次写的时候就把日期字符串直接塞进SQL后来发现不同MySQL版本有的不报错有的直接拒绝依赖数据库放宽校验不是好路子。修改操作和插入操作唯一区别是把VALUES改成SET然后条件加WHERE id?。dao每执行成功后Servlet要重定向到列表页而不是forward到列表页具体原因避坑章节会展开。4.3 删除操作POST提交与权限校验删除是危险操作不能用超链接直接访问deleteServlet?id1这种方式。原因是搜索引擎爬虫、浏览器预加载以及用户误触都可能触发GET请求一旦没有确认机制一行数据就没了。课程设计虽然不涉及线上环境但答辩老师会看你的请求设计GET删除很容易减分。正确做法是把删除按钮放在一个form表单里method设为POST提交到deleteServlet。页面上每个学生行都写一个form会比较啰嗦但安全。下面是在JSP中使用表单删除的示意form action${pageContext.request.contextPath}/student/delete methodpost input typehidden nameid value${stu.id} button typesubmit onclickreturn confirm(确认删除该学生吗)删除/button /form这个JSP片段里用了EL表达式动态拼接项目上下文路径避免部署在不同路径下时404。onclick返回false时表单不会提交。后端doPost里先判断Session中的loginUser是否为空为空就直接拒绝然后才执行删除。删除前还可以先查一遍学生是否存在避免删除一个已经被删过的记录时报SQL异常。给表设计外键后删除学生时如果成绩表有外键引用MySQL会阻止删除并在控制台报外键约束失败。这时要么先删成绩再删学生要么在DELETE语句发出前在Service层统一处理。我一般会在Service里先执行“DELETE FROM t_score WHERE student_id?”再执行“DELETE FROM t_student WHERE id?”两次操作包在一个事务里避免一个成功一个失败导致中间态。5. 常见问题排查部署、乱码、连接失败的五个典型坑5.1 页面中文乱码JSP、请求、响应三层不一致现象登录后学生名单页面所有中文都显示成问号或者添加“王小明”后列表里变成“????”。原因JSP文件本身没按UTF-8保存页面pageEncoding没设置Servlet读取POST参数时没指定字符集response输出时又用了默认编码。三处只要有一处不一致中文就可能丢。Tomcat 7及更早版本对URL参数默认用ISO-8859-1也是乱码来源之一。解决先把所有JSP页面头部的contentType改为“text/html; charsetUTF-8”pageEncoding也改成UTF-8。登录和管理端所有Servlet的doGet/doPost第一行加request.setCharacterEncoding(UTF-8)response也用setCharacterEncoding(UTF-8)。最后如果还在用Tomcat 7在server.xml的Connector节点增加URIEncodingUTF-8Tomcat 8.5以上默认就是UTF-8不用再加加了也没问题。按这个顺序排查乱码基本一轮解决。5.2 数据库连接失败驱动类、时区、密码校验规则都可能是元凶现象启动Tomcat后访问登录页正常登录一提交就报java.sql.SQLException或ClassNotFoundException控制台堆栈里有Communications link failure。原因最常见的是mysql-connector-java.jar没有放到WEB-INF/lib里或者放的是一个很老的5.x驱动去连MySQL 8。第二常见的是URL里没有serverTimezoneMySQL 8连接会拒绝。第三是MySQL用户的密码加密方式是caching_sha2_password老版本驱动无法完成认证。解决确认JDBC URL里的driverClassName是com.mysql.cj.jdbc.DriverURL里带serverTimezoneAsia/Shanghai。把数据库驱动jar放到WEB-INF/lib目录并重启Tomcat。如果还连不上在MySQL命令行执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;但要注意这个方案在MySQL 8里是兼容选项新版MySQL 9可能移除了所以更建议直接升级驱动jar。密码里尽量不要带、#这类字符因为properties文件解析URL时会把#当注释截断这是很多同学忽略的坑。5.3 404/405错误Servlet路径映射不一致现象表单提交后浏览器地址变成http://localhost:8080/student/delete页面返回404或者点击删除返回405 Method Not Allowed。原因WebServlet(/student/delete)里的路径和表单action写的路径不一致或者大小写不一致。405则说明Servlet类没有重写对应的doGet或doPost方法表单method是post但Servlet只写了doGet。解决先在浏览器直接访问Servlet路径如果能访问说明不是路由问题。资源里的代码默认用注解方式注解值必须以/开头表单action最好用“${pageContext.request.contextPath}/student/delete”动态加上项目名避免换部署环境后项目上下文名称变化导致404。如果要兼容课设模板里的web.xml配置注意web.xml里servlet-mapping的url-pattern是“/student/delete”不能写“student/delete”漏掉前导斜杠会直接部署报错。5.4 数据重复提交刷新页面把同一条学生信息插入两次现象新增一个学生后按F5刷新列表页浏览器提示“要重新发送表单吗”点是之后数据库中多了一条相同学号的学生。原因Servlet在插入成功后使用request.getRequestDispatcher(list.jsp).forward()把请求转发给列表页面此时浏览器的地址栏还是student/add刷新操作会重复提交上一次的POST请求。GET刷新不会出问题POST刷新就中招。解决使用Post/Redirect/Get模式插入成功后立刻response.sendRedirect(request.getContextPath() /student/list)让浏览器重新发起GET请求获取列表。这个重定向解决了重复提交但没解决兜底问题。更保险的做法是给student_no建唯一索引重复学号插入时数据库会直接报错。我自己的习惯是两层都做页面层靠重定向数据层靠唯一约束这两条一起才能保证不翻车。5.5 部署后看不到更新Tomcat没有清理旧class现象修改了Servlet代码重新发布后页面访问还是老功能甚至控制台没有任何报错。原因IDEA或Eclipse里增量部署时Tomcat的work目录没有完全清理旧的Servlet class还在被使用。有时浏览器缓存也会让你误以为没更新。另外一个隐蔽情况是项目里有多个同名的Servlet classclasspath顺序导致加载了旧包里的类。解决先把浏览器缓存强制刷新一次快捷键CtrlF5。如果无效停掉Tomcat在IDEA里执行Build - Rebuild Project再清理Tomcat的work目录。Eclipse则右键项目Clean Project然后重新Publish。如果项目是Maven结构先把target目录删掉再重新package。部署这类行为看起来像玄学本质是Tomcat加载类时优先读取work目录下的方法缓存清了缓存基本就好了。6. 最后补两点把项目改成Maven工程并写一份能答辩的README6.1 迁移到Mavenpom.xml依赖清单你拿到的资源如果是传统Eclipse工程lib下带着一堆jar用起来没问题但后续想换成Maven管理会比较费劲。如果决定迁移只要新建一个war类型工程把原来的src和webapp目录拷过去再写一个最小的pom.xml。下面这个依赖块覆盖了Servlet、JSTL、MySQL驱动和Druid连接池都是这套系统运行时需要的!-- Servlet和JSP依赖由容器提供编译期生效 -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.23/version /dependency注意servlet-api必须用provided scope表示编译时提供打包时由Tomcat容器提供不然部署后会遇到jar包冲突。如果项目已经用注解写了WebServlet全Java代码无需配置web.xml也能跑但Filter如果也想用注解需要对应Servlet 3.0以上的Tomcat版本建议直接在web.xml里配置兼容性更好。6.2 答辩前必须验证的三件事第一件事用一个干净的MySQL实例执行SQL脚本不要拿你开发时已经跑过的库去演示。干净库能暴露掉缺外键、字段名不一致等隐藏问题。第二件事把db.properties里的密码改成演示机器上MySQL的真实密码然后重启Tomcat登录、增删改查、退出完整走一遍。第三件事换一个浏览器打开项目确认没有依赖浏览器插件才能显示的内容。很多系统在本地开发机上没问题换到教室电脑上就“不认路”多半是因为localhost没改成127.0.0.1或者项目名错了。我自己的习惯是每次答辩前一天都强制自己删掉Tomcat的work目录和target目录然后从零启动一遍整个过程控制在十分钟内。这一遍看着简单能避免绝大多数现场翻车。希望这次拆解能帮到你让你在课程设计这条路上少走几段弯路。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑