简介这是一套基于Java Web技术栈开发的轻量级学生信息管理系统适用于高校Java Web课程设计或初学者项目实践帮助学习者掌握JSP、Servlet、MySQL数据库交互及前后端基础协同开发流程。资源包共2个文件主程序为ZIP压缩包2.13MB含完整可运行项目源码含LayuijQuery前端界面、数据库SQL脚本及lib依赖库另附HTML格式README说明文档清晰指引环境配置JDK7Tomcat8MySQL与部署步骤。已有6433人学习下载项目结构规范包含用户注册、教师管理、增删改查等核心功能模块代码注释充分适合作为教学范例或二次开发起点同时提供百度网盘版数据库与JAR包资源便于快速复现运行环境。1. 这不是“过时”的课设代码而是一套能跑通、能改、能交、能答辩的 Java Web 学生信息管理系统JSP Servlet MySQL你手头那份被导师打回来三次的“简单学生信息管理系统”课设是不是还在用 Tomcat 9 启动时报ClassNotFoundException: com.mysql.cj.jdbc.Driver是不是刚写完一个增删改查就卡在 JSP 页面里取不到 request.getAttribute()是不是打包成 WAR 丢进 Tomcat webapps 目录后浏览器只显示 404连登录页都刷不出来别急——这不是你学得差而是这套基于 JSP Servlet 的传统 Java Web 架构早被现代框架“边缘化”但恰恰因为它的结构清晰、依赖透明、无黑匣子、每一步都可调试反而成了课程设计最稳妥的落地选择。它不追求高并发、不搞微服务、不卷 Spring Boot 自动装配就老老实实走 MVC 分层Servlet 控制流程、JSP 渲染视图、MySQL 存数据、DAO 封装操作。适合大三刚学完 JDBC 和 HTML 的同学3 天能搭起骨架5 天能填满功能答辩时老师问“Servlet 生命周期怎么触发的”你能指着web.xml里的load-on-startup1/load-on-startup说清楚问“为什么不用 EL 表达式直接取 session 值”你能现场改一行 JSP 验证。这不是怀旧是用最小认知负荷拿下课程设计硬性交付指标。2. 从零建项目IDEA 新建 JSP 项目 配置 Tomcat 连接 MySQL 的完整链路2.1 创建标准 Dynamic Web Project非 Maven并校验目录结构很多同学一上来就选 “Maven Web App”结果发现webapp/WEB-INF/web.xml被自动删掉、JSP 编译路径错乱、甚至 IDEA 报红“Cannot resolve symbol ‘javax.servlet’”。这是典型环境错配。必须用原生 Dynamic Web ProjectFile → New → Project → 选择Java Enterprise→ 勾选Web Application→ 取消勾选Create project from archetype→ Next → 输入项目名如StudentMgmtSystem→ Finish。创建后检查关键目录是否存在src/放 Java 类Servlet、DAO、Beanwebapp/根目录放index.jsp、login.jsp、list.jsp等页面webapp/WEB-INF/必须存在放web.xml、lib/放 jar 包、classes/编译输出webapp/WEB-INF/lib/手动新建后续放mysql-connector-java-8.0.33.jar、servlet-api.jarTomcat 自带无需下载提示若webapp/WEB-INF/classes不存在右键src→Build Path → Configure Build Path → Source → Add Folder → 选中webapp/WEB-INF/classes否则编译的.class文件不会自动输出到正确位置导致 404。2.2 配置 Tomcat Server 并设置 Deployment 路径别信网上“一键配置”教程——它们常漏掉最关键的 Artifact 设置。File → Settings → Build, Execution, Deployment → Application Servers → → Tomcat Server → 选本地解压路径如D:\apache-tomcat-9.0.87Run → Edit Configurations → → Tomcat Server → Local → Deployment → → Artifact → 选StudentMgmtSystem:war exploded注意是exploded不是 war在 Artifact 设置页确认Application context填/student不是/避免和 Tomcat 默认首页冲突点击 OK 后启动按钮旁会显示http://localhost:8080/student—— 这就是你项目的根 URL验证是否生效在webapp/index.jsp写h1Test OK/h1启动 Tomcat访问http://localhost:8080/student看到标题即成功。若报 404请回头检查 Deployment 中的 Artifact 是否选对、Application context 是否有前导/、webapp是否被误设为源码根目录。2.3 MySQL 连接配置驱动版本、URL 参数、连接池取舍课程设计不需 HikariCP 或 Druid但必须避开 MySQL 8 的经典坑。下载mysql-connector-java-8.0.33.jar不能用 5.x 版本否则com.mysql.cj.jdbc.Driver找不到放入webapp/WEB-INF/lib/右键 →Add as Library在src/com/example/dao/DBUtil.java中写连接逻辑public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/student_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 123456; // 请按自己 MySQL 密码修改 static { try { Class.forName(com.mysql.cj.jdbc.Driver); // 必须显式加载JDK9 后 Class.forName 不再自动触发初始化 } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL Driver not found, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }参数说明useSSLfalse是本地开发必需否则报 SSL handshake 错误serverTimezoneAsia/Shanghai解决时区转换异常插入时间字段变 00:00allowPublicKeyRetrievaltrue应对 MySQL 8.0.28 默认禁用公钥检索。这些不是“可选参数”是不加就必翻车的硬性开关。3. 核心功能实现Servlet 控制流 JSP 视图渲染 DAO 数据封装的三层闭环3.1 Student 实体类与 DAO 接口定义含字段命名一致性实体类不是随便写的 POJO它直接决定 JSP 表单 name 属性、Servlet request.getParameter() 键名、SQL INSERT 字段顺序。必须严格对齐// src/com/example/bean/Student.java public class Student { private String id; // 对应数据库 student.id VARCHAR(10) private String name; // 对应 student.name VARCHAR(20) private String gender; // 对应 student.gender CHAR(1)存 M/F private int age; // 对应 student.age TINYINT private String major; // 对应 student.major VARCHAR(30) // 必须有无参构造JSP jsp:useBean 依赖 public Student() {} // getter/setter 全部生成IDEA AltInsert → Generate → Getter and Setter // 注意age 是 int不是 Integer避免 null 转换异常 }DAO 接口定义操作契约不写实现// src/com/example/dao/StudentDAO.java public interface StudentDAO { ListStudent findAll() throws SQLException; Student findById(String id) throws SQLException; boolean add(Student student) throws SQLException; boolean update(Student student) throws SQLException; boolean delete(String id) throws SQLException; }3.2 BaseServlet 抽象基类解决 URL 映射爆炸问题每个功能写一个 ServletLoginServlet、ListServlet、AddServlet…会导致web.xml膨胀、重复代码多。用反射统一调度// src/com/example/servlet/BaseServlet.java public abstract class BaseServlet extends HttpServlet { Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method req.getParameter(method); // URL 传 methodadd 或 methoddelete if (method null || method.isEmpty()) { method index; // 默认方法 } try { Method actionMethod this.getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class); actionMethod.setAccessible(true); actionMethod.invoke(this, req, resp); } catch (Exception e) { throw new ServletException(e); } } }然后让具体 Servlet 继承它// src/com/example/servlet/StudentServlet.java public class StudentServlet extends BaseServlet { private StudentDAO dao new StudentDAOImpl(); public void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ListStudent students dao.findAll(); req.setAttribute(students, students); req.getRequestDispatcher(/list.jsp).forward(req, resp); } public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Student s new Student(); s.setId(req.getParameter(id)); s.setName(req.getParameter(name)); s.setGender(req.getParameter(gender)); s.setAge(Integer.parseInt(req.getParameter(age))); s.setMajor(req.getParameter(major)); dao.add(s); resp.sendRedirect(req.getContextPath() /student?methodlist); } }关键点req.getParameter(age)返回 String必须Integer.parseInt()否则 DAO 层 insert 会因类型不匹配报错resp.sendRedirect()用重定向避免表单重复提交req.getContextPath()动态获取应用上下文如/student比硬写/student/list.jsp更健壮。3.3 JSP 页面EL 表达式 JSTL 标签 表单 name 与 Bean 字段严格对应list.jsp是展示核心必须用 JSTL 避免 scriptlet% %污染% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html headtitle学生列表/title/head body h2学生信息列表/h2 a hrefadd.jsp添加学生/a table border1 trth学号/thth姓名/thth性别/thth年龄/thth专业/thth操作/th/tr c:forEach items${students} vars tr td${s.id}/td td${s.name}/td td${s.gender M ? 男 : 女}/td td${s.age}/td td${s.major}/td td a hrefstudent?methodeditid${s.id}编辑/a | a hrefstudent?methoddeleteid${s.id} onclickreturn confirm(确定删除 ${s.name})删除/a /td /tr /c:forEach /table /body /html注意c:forEach的items${students}中students必须与 Servlet 中req.setAttribute(students, students)的 key 完全一致${s.gender M ? 男 : 女}是 JSP EL 内置三元运算比c:if更简洁删除链接的onclickreturn confirm(...)是前端防误点刚需不加会被老师当场指出“缺少用户确认”。4. 避坑指南那些让课设卡在最后一公里的 5 个真实血泪问题4.1 现象启动 Tomcat 后访问http://localhost:8080/student显示 404但index.jsp明明存在原因IDEA 默认将webapp目录设为 “Resources Root”导致其不被识别为 Web Resourcesindex.jsp不参与部署。解决右键webapp→Mark Directory as → Resources Root取消勾选再右键 →Mark Directory as → Web Resource Root。重启 Tomcat 即可。4.2 现象登录成功后跳转list.jsp页面空白控制台无报错students列表没渲染出来原因req.setAttribute(students, students)之后用了req.getRequestDispatcher(/list.jsp).forward(req, resp)但list.jsp中${students}取不到值常见于web.xml中welcome-file-list未配置或index.jsp里未做登录态校验。解决检查list.jsp开头是否有% page importjava.util.* %虽非必需但部分低版本 Tomcat 需显式导入更关键的是在list.jsp顶部加调试语句% request.getAttribute(students) null ? null : not null %若输出 null则证明 forward 未传递属性——此时检查StudentServlet.list()方法是否真的执行加System.out.println(list called)再确认web.xml中StudentServlet的url-pattern/student/url-pattern是否与 JSP 中hrefstudent?methodlist的路径完全匹配少斜杠或多斜杠都会失败。4.3 现象新增学生时MySQL 报错Data truncation: Data too long for column id at row 1原因数据库student.id字段定义为VARCHAR(10)但前端表单传入了超长字符串如复制粘贴带空格的学号或未做长度校验。解决在add.jsp表单中加 HTML5 属性input typetext nameid maxlength10 required在 Servlet 的add()方法开头加校验String id req.getParameter(id); if (id null || id.trim().length() 10) { req.setAttribute(msg, 学号长度不能超过10位); req.getRequestDispatcher(/add.jsp).forward(req, resp); return; }4.4 现象中文姓名、专业名存入 MySQL 后变成???乱码原因三个环节任一缺失① MySQL 服务端字符集非 utf8mb4② 数据库/表创建时未指定CHARSETutf8mb4③ JDBC URL 未加characterEncodingutf8。解决MySQL 命令行执行SHOW VARIABLES LIKE character_set%;确保character_set_server utf8mb4创建数据库时用CREATE DATABASE student_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;修改 JDBC URLjdbc:mysql://localhost:3306/student_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltruecharacterEncodingutf8在web.xml中配置过滤器强制请求编码filter filter-nameCharacterEncodingFilter/filter-name filter-classorg.apache.catalina.filters.SetCharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameCharacterEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping4.5 现象打包 WAR 部署到独立 Tomcat 后所有 Servlet 404但 IDEA 内置 Tomcat 正常原因IDEA 的 exploded 模式会自动把src下 class 编译到webapp/WEB-INF/classes而 WAR 包需要WEB-INF/classes下有编译后的.class文件但默认打包可能遗漏。解决File → Project Structure → Artifacts → 选中StudentMgmtSystem:war exploded→ 右侧 Output Layout → 确认Available Elements中studentmgmtsystem_main即src已拖入WEB-INF/classes/目录下Build → Build Artifacts → Build将生成的StudentMgmtSystem.war位于out/artifacts/复制到独立 Tomcat 的webapps/目录启动 Tomcat观察logs/catalina.out确认无ClassNotFoundException且日志出现INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive字样。5. 课设答辩加分项3 个让老师眼前一亮的轻量级增强技巧5.1 用 Filter 实现登录拦截不写 Shiro5 行代码搞定老师最爱问“怎么保证未登录不能访问 list.jsp”——别答“前端隐藏链接”要展示服务端校验。写一个LoginFilter// src/com/example/filter/LoginFilter.java public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); // 放行登录页、静态资源、登录动作 if (uri.contains(/login.jsp) || uri.contains(/login) || uri.contains(/css/) || uri.contains(/js/)) { chain.doFilter(req, resp); return; } // 检查 session 中是否有 user HttpSession session request.getSession(false); if (session null || session.getAttribute(user) null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, resp); } }在web.xml中注册filter filter-nameLoginFilter/filter-name filter-classcom.example.filter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern/*/url-pattern /filter-mapping效果直接访问http://localhost:8080/student/list.jsp会自动跳回login.jsp登录成功后session.setAttribute(user, username)后续所有请求自动放行。答辩时演示“删掉 session 后刷新页面自动跳转”老师会点头。5.2 用 JavaScript AJAX 实现无刷新删除不引 jQuery原生 fetch传统hrefstudent?methoddeleteidxxx是整页刷新显得粗糙。在list.jsp底部加script function deleteStudent(id, name) { if (!confirm(确定删除 name )) return; fetch(${pageContext.request.contextPath}/student?methoddeleteid id, { method: POST }) .then(response response.text()) .then(data { alert(删除成功); location.reload(); // 简单粗暴也可用 DOM 操作移除行 }) .catch(err alert(删除失败 err)); } /script对应 Servlet 的delete()方法改为支持 POSTpublic void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String id req.getParameter(id); dao.delete(id); // 返回纯文本避免 forward 冲突 resp.setContentType(text/plain;charsetUTF-8); resp.getWriter().write(success); }价值展示你懂前后端分离雏形且代码量极少。老师若问“为什么用 POST”答“DELETE 是幂等操作但浏览器 a 标签只能发 GET所以用 POST 模拟符合 RESTful 设计思想”。5.3 用 Log4j2 记录关键操作日志替代 System.out.println答辩时被问“系统操作有留痕吗”掏出日志文件比口头说强十倍。下载log4j-api-2.20.0.jar和log4j-core-2.20.0.jar放入WEB-INF/lib/在src/下新建log4j2.xml?xml version1.0 encodingUTF-8? Configuration statusWARN Appenders File nameFileAppender fileNamelogs/student.log PatternLayout pattern%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n/ /File /Appenders Loggers Root levelinfo AppenderRef refFileAppender/ /Root /Loggers /Configuration在StudentServlet.add()开头加private static final Logger logger LogManager.getLogger(StudentServlet.class); // ... logger.info(新增学生{}姓名{}专业{}, s.getId(), s.getName(), s.getMajor());效果运行后logs/student.log自动生成内容如14:22:03.123 [http-nio-8080-exec-1] INFO c.e.s.StudentServlet - 新增学生2023001姓名张三专业计算机科学与技术。答辩时打开文件老师立刻感知工程规范性。从那以后我每次交课设都会在web.xml里加filter、在list.jsp里加fetch、在logs/下建日志目录——不是为了炫技而是让每一个功能点都有可验证、可演示、可解释的落脚点。课程设计不是堆代码是用有限技术讲清楚一个闭环逻辑。希望帮到你。本文还有配套的精品资源点击获取