资讯详情

资讯详情

JavaWeb学生信息管理系统实战:Servlet+JSP+JDBC完整搭建指南

简介本资源是一套高分通过的JavaWeb期末大作业项目——学生信息管理系统面向计算机及相关专业本科生专为课程设计、期末综合实践及Web开发入门实战打造。项目包含完整可运行源码、配套数据库脚本与详细课程设计报告已获98分实绩验证覆盖用户登录、学生增删改查、数据导出等核心功能模块适合夯实Servlet、JSP、MySQL及MVC分层开发能力。压缩包共77个文件含20个Java源文件、20个编译后Class文件、3个JSP页面、3个CSS与3个JS前端资源、9张系统界面截图JPG、1份SQL建表脚本及1份Word格式设计报告整体4.03MB结构清晰便于快速部署与代码研读。目前已有727人学习下载提供即开即用的完整工程环境、典型业务流程图与系统处理逻辑说明助力初学者理解JavaWeb项目全链路开发规范与常见问题解决路径。1. 这不是又一个“增删改查”Demo用 JavaWeb 做出能过答辩、能跑通、能讲清楚的学生信息管理系统你手头这份“javaweb期末作业-学生信息管理系统源码报告”大概率正躺在压缩包里解压后是src/、WebContent/、lib/和一份 Word 报告。但别急着交——很多同学照着网上抄的代码一运行就报404连登录页都打不开改了数据库配置Tomcat 启动成功却提示ClassNotFoundException: com.mysql.cj.jdbc.Driver写完 Servlet 编译没问题但表单提交后数据死活不进 MySQL报告里写着“采用 MVC 模式”可翻遍代码根本找不到 Controller 层在哪……这不是代码不行是整个工程结构、依赖链、部署路径和调试逻辑没对齐。本篇不讲抽象概念只拆解真实课堂场景下能跑通、能截图、能答辩、能讲清技术选型理由的最小可行方案用原生 Servlet JSP JDBC不引入 Spring Boot 或 MyBatis搭建一个带登录验证、学生 CRUD、分页查询、密码加密BCrypt、错误统一跳转的真实 JavaWeb 系统。适合大二大三正在赶课设、对 Tomcat 部署流程模糊、被web.xml和context.xml绕晕、想靠一份干净可复现的源码稳过期末的同学。2. 从零搭起骨架用 IDEA 创建标准 JavaWeb 工程并配通 Tomcat2.1 创建符合 Servlet 4.0 规范的动态 Web 项目非 Maven很多同学直接新建 “Maven Project”选maven-archetype-webapp结果发现pom.xml里一堆插件冲突web.xml版本错乱IDEA 提示 “Servlet version mismatch”。这不是你的错是模板太老。真实课堂环境最稳妥的做法是手动创建标准 Dynamic Web Project# 在 IDEA 中操作路径 File → New → Project → 选择 Java Enterprise → 勾选 Web Application → 取消勾选 Create project from archetype → Next → 输入项目名如 student-mgr→ Next → 设置 Target runtime 为已配置好的 Tomcat 9.x必须 9.0因需支持 Servlet 4.0→ Next → 勾选 Generate web.xml descriptor → Finish提示web.xml是 JavaWeb 的“宪法”它定义了 Servlet 映射、过滤器顺序、上下文参数。课堂作业中不写web.xml 主动放弃答辩时解释“为什么用 Filter 做登录拦截”的机会。务必保留并手动编辑。创建后项目结构应为student-mgr/ ├── src/ # Java 源码Servlet、DAO、Bean ├── WebContent/ # Web 资源根目录等价于传统 WAR 的 webapp/ │ ├── WEB-INF/ │ │ ├── web.xml # 核心配置文件必须存在 │ │ └── lib/ # 手动放入 jar 包mysql-connector-java-8.0.33.jar、bcrypt-3.1.0.jar │ ├── index.jsp │ ├── login.jsp │ └── list.jsp └── out/ # IDEA 编译输出目录对应 Tomcat 的 work/Catalina/...2.2 Tomcat 9 配置三要素JDK 版本、编码、Context PathIDEA 默认用 JDK 17 启动 Tomcat但 Tomcat 9 官方仅支持到 JDK 11 Apache Tomcat 9 Requirements 。若强行用 JDK 17启动时会报java.lang.UnsupportedClassVersionError。血泪经验统一用 JDK 11。在 IDEA 中配置File → Project Structure → Project → SDK 选11 (11.0.x)File → Project Structure → Modules → Sources → Language level 选11Run → Edit Configurations → Tomcat Server → Configuration → JRE 选11接着解决两个高频翻车点① 中文乱码问题GET/POST 全覆盖在web.xml最顶部web-app标签下插入字符编码过滤器!-- 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 init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameCharacterEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping② Context Path 必须为/或/student不能留空在 Run → Edit Configurations → Deployment → Application context 中填/student不要/student/末尾斜杠会导致重定向 302 失败。这样访问地址才是http://localhost:8080/student/login.jsp而非http://localhost:8080/student//login.jsp。2.3 数据库连接池用 DBCP2 替代手写 DriverManager避免连接泄漏课堂作业常犯的错误每次 Servlet 请求都new Connection()用完不close()导致 MySQL 连接数爆满第二个人登录就卡死。必须用连接池。DBCP2 是 Apache 官方维护、轻量、无依赖、兼容 Java 11 的首选。下载commons-dbcp2-2.9.0.jar和commons-pool2-2.11.1.jar放入WebContent/WEB-INF/lib/。在WEB-INF/web.xml中配置初始化监听器listener listener-classcom.student.util.DBInitListener/listener-class /listener新建src/com/student/util/DBInitListener.javapackage com.student.util; import org.apache.commons.dbcp2.BasicDataSource; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; WebListener public class DBInitListener implements ServletContextListener { private static BasicDataSource dataSource; Override public void contextInitialized(ServletContextEvent sce) { dataSource new BasicDataSource(); dataSource.setUrl(jdbc:mysql://localhost:3306/student_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue); dataSource.setUsername(root); dataSource.setPassword(123456); // 实际请改为你本地 MySQL 密码 dataSource.setInitialSize(5); dataSource.setMaxTotal(20); dataSource.setMaxWaitMillis(3000); dataSource.setTestOnBorrow(true); dataSource.setValidationQuery(SELECT 1); // 将数据源存入 ServletContext全局可取 sce.getServletContext().setAttribute(dataSource, dataSource); } Override public void contextDestroyed(ServletContextEvent sce) { if (dataSource ! null) { try { dataSource.close(); } catch (Exception e) { e.printStackTrace(); } } } public static BasicDataSource getDataSource() { return dataSource; } }参数说明useSSLfalseMySQL 8.0 默认强制 SSL本地开发关掉省事生产环境必须开serverTimezoneAsia/Shanghai避免java.sql.SQLException: The server time zone value XXX is unrecognizedallowPublicKeyRetrievaltrue解决Public Key Retrieval is not allowed错误MySQL 8.0.21 新增限制setTestOnBorrowtruevalidationQuerySELECT 1每次从池取连接前执行校验防失效连接3. 核心业务落地学生登录与 CRUD 的 Servlet-JSP 分层实现3.1 登录模块用 BCrypt 加密密码 Filter 拦截未登录请求明文存密码是答辩时老师第一句就会问的致命漏洞。必须用bcrypt非 MD5/SHA-1不可逆且带盐。下载bcrypt-3.1.0.jar放入lib/。登录 Servlet (LoginServlet.java)package com.student.servlet; import com.student.dao.UserDao; import com.student.entity.User; import com.student.util.DBInitListener; import org.mindrot.jbcrypt.BCrypt; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; WebServlet(/login) public class LoginServlet extends HttpServlet { private UserDao userDao new UserDao(); Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password req.getParameter(password); User user userDao.findByUsername(username); if (user ! null BCrypt.checkpw(password, user.getPassword())) { // 密码正确存入 session HttpSession session req.getSession(); session.setAttribute(user, user); resp.sendRedirect(req.getContextPath() /list); } else { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(/login.jsp).forward(req, resp); } } }关键点说明BCrypt.checkpw()是验证方法BCrypt.hashpw()才是加密用于注册时req.getSession()不加参数默认true即自动创建新 session若只想获取已有 session用req.getSession(false)resp.sendRedirect()是客户端重定向URL 变req.getRequestDispatcher().forward()是服务器端转发URL 不变登录失败走后者保持在 login.jsp登录拦截 Filter (LoginFilter.java)package com.student.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; WebFilter(filterName LoginFilter, urlPatterns {/list, /add, /edit, /delete}) public class LoginFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; HttpSession session req.getSession(false); if (session null || session.getAttribute(user) null) { // 未登录重定向到登录页并携带原始请求路径便于登录后跳回 String originalUrl req.getRequestURI(); if (req.getQueryString() ! null) { originalUrl ? req.getQueryString(); } resp.sendRedirect(req.getContextPath() /login.jsp?redirect originalUrl); return; } chain.doFilter(request, response); } }为什么用 Filter 而不用在每个 Servlet 里判断因为这是横切关注点Cross-Cutting Concern——所有需要权限的 URL 都要检查硬编码会重复 5 次以上违反 DRY 原则。Filter 是 JavaWeb 原生解决方案比 Spring AOP 更轻量、更易向老师解释。3.2 学生列表页JSP JSTL 分页封装避免 scriptlet课堂作业常见反模式JSP 里写% while(rs.next()) { %混杂 Java 逻辑与 HTML。答辩时老师会问“如果换数据库这段代码要不要改”——答“要”就暴露了紧耦合。正确做法用 JSTL EL 表达式 自定义分页工具类。引入 JSTL下载jstl-1.2.jar放入lib/在list.jsp顶部声明% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt %StudentListServlet.java查询逻辑含分页package com.student.servlet; import com.student.dao.StudentDao; import com.student.entity.PageBean; import com.student.entity.Student; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; WebServlet(/list) public class StudentListServlet extends HttpServlet { private StudentDao studentDao new StudentDao(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取当前页码默认第1页 String pageNumStr req.getParameter(pageNum); int pageNum 1; if (pageNumStr ! null !pageNumStr.trim().isEmpty()) { pageNum Integer.parseInt(pageNumStr); } // 每页显示条数 int pageSize 5; PageBeanStudent pageBean studentDao.findPage(pageNum, pageSize); req.setAttribute(pageBean, pageBean); req.getRequestDispatcher(/list.jsp).forward(req, resp); } }PageBean.java通用分页模型package com.student.entity; import java.util.List; public class PageBeanT { private ListT list; // 当前页数据 private int pageNum; // 当前页码 private int pageSize; // 每页条数 private int total; // 总记录数 private int totalPage; // 总页数 public PageBean(ListT list, int pageNum, int pageSize, int total) { this.list list; this.pageNum pageNum; this.pageSize pageSize; this.total total; this.totalPage (int) Math.ceil((double) total / pageSize); } // getter/setter 省略IDEA 自动生成 }list.jsp中使用 JSTL 渲染c:forEach items${pageBean.list} varstu tr td${stu.id}/td td${stu.name}/td td${stu.gender}/td tdfmt:formatDate value${stu.birthday} patternyyyy-MM-dd//td td${stu.major}/td td a href${pageContext.request.contextPath}/edit?id${stu.id}编辑/a | a href${pageContext.request.contextPath}/delete?id${stu.id} onclickreturn confirm(确定删除 ${stu.name})删除/a /td /tr /c:forEach分页 URL 构造技巧a href?pageNum${pageBean.pageNum - 1}上一页/aa href?pageNum${pageBean.pageNum 1}下一页/a注意?pageNum会覆盖原有参数若需保留搜索条件如按专业筛选应拼接完整 URL课堂作业可简化处理。4. 避坑指南这 4 个错误让 80% 的同学卡在部署前4.1 现象启动 Tomcat 后访问http://localhost:8080/student/login.jsp报 404原因login.jsp不在WebContent/目录下而在src/或其他错误路径IDEA 未将WebContent/设为 Web Resource Directory右键 → Mark Directory as → Resources Rootweb.xml中welcome-file-list未配置login.jsp且未通过 Servlet 映射访问。解决确认login.jsp物理路径为student-mgr/WebContent/login.jsp在web.xml中添加欢迎页welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list若仍 404打开 Tomcat 日志logs/catalina.out搜索deploy关键字确认应用是否成功部署。4.2 现象登录时控制台报java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver原因mysql-connector-java-8.0.33.jar未放入WebContent/WEB-INF/lib/放错位置如src/或out/无效Jar 包版本与 MySQL 服务端不匹配MySQL 5.7 用mysql-connector-java-5.1.49.jarMySQL 8.0 必须用8.0.xweb.xml中未配置resource-refDBCP2 不需要此为旧式 JNDI 配置课堂作业禁用。解决删除lib/下所有 mysql jar只留一个mysql-connector-java-8.0.33.jar在DBInitListener.java的setUrl()中确认协议为jdbc:mysql://非jdbc:mysql:thin:重启 Tomcat必须重启热部署不加载新 jar。4.3 现象添加学生后页面空白数据库无数据无任何报错原因StudentAddServlet.java中doPost()方法内未调用studentDao.add(student)add.jsp表单methodget但 Servlet 只写了doPost()request.setCharacterEncoding(UTF-8)未设置中文字段存入数据库为???虽不报错但数据损坏。解决在StudentAddServlet.java的doPost()开头强制设置编码req.setCharacterEncoding(UTF-8);检查表单form action/student/add methodpost使用浏览器开发者工具F12→ Network → 查看 Form Data 是否有值确认前端传参正确。4.4 现象登录成功后点击“学生列表”报 404但直接输入 URLhttp://localhost:8080/student/list可访问原因login.jsp中跳转链接写死为a href/list缺少 Context Pathweb.xml中url-pattern写成/list/*但 Servlet 映射为/list导致 Filter 拦截失败。解决所有链接必须用 EL 表达式a href${pageContext.request.contextPath}/list学生列表/aFilter 的WebFilter(urlPatterns {/list, /add, ...})必须与 Servlet 的WebServlet(/list)完全一致不能多/也不能少。5. 报告撰写核心用三张图讲清技术选型、数据流与安全设计5.1 技术选型对比表为什么不用 Spring Boot为什么用 DBCP2课堂报告不能只写“采用了 MVC 模式”要体现思考过程。用表格呈现决策依据对比项本方案ServletJSPJDBCSpring Boot 方案课堂适用性分析学习成本零额外框架直面 HTTP 协议、Servlet 生命周期需理解 IOC/AOP/自动配置入门门槛高✅ 本方案更利于理解底层机制部署复杂度Tomcat 单容器war 包一键部署需嵌入 Tomcat 或打 jar 包端口/配置易冲突✅ 符合高校机房统一环境要求数据库连接DBCP2 连接池手动管理 DataSourceHikariCP Spring JDBC Template✅ DBCP2 依赖少jar 包体积 500KB无反射黑盒安全实践BCrypt 密码加密 Filter 权限控制Spring Security 配置繁杂✅ BCrypt 是 OWASP 推荐算法Filter 是 JavaEE 标准方案答辩话术“老师我们选择原生 JavaWeb 是为了精准匹配课程教学目标——掌握 Servlet 生命周期、HTTP 请求响应模型、JDBC 连接管理这些核心能力。Spring Boot 虽好但它把太多细节封装掉了反而不利于建立知识树。”5.2 数据流转图从浏览器到数据库的 7 步闭环附关键代码行号画一张横向流程图可用 PPT 或 draw.io标注每一步的触发者与关键代码[浏览器] ↓ GET /student/login.jsp [login.jsp] → 渲染登录表单 ↓ POST /student/login (表单提交) [LoginServlet.java:22] → req.getParameter(username) ↓ 调用 UserDao.findByUsername() [UserDao.java:35] → PreparedStatement.executeQuery(SELECT * FROM user WHERE username?) ↓ 返回 User 对象 [LoginServlet.java:28] → BCrypt.checkpw() 验证密码 ↓ 成功则 req.getSession().setAttribute(user, user) [LoginFilter.java:25] → 检查 session 中 user 是否存在 ↓ 存在则放行至 StudentListServlet [StudentListServlet.java:32] → studentDao.findPage() 查询分页数据 ↓ setAttribute(pageBean, pageBean) [list.jsp] → JSTL c:forEach 渲染表格价值点这张图让老师一眼看清你是否真正理解请求生命周期而非只会复制粘贴。5.3 安全加固清单3 项实操级防护非口号很多报告写“系统安全性高”却无具体措施。以下 3 条必须写进报告并在代码中体现密码存储安全使用BCrypt.hashpw(password, BCrypt.gensalt(12))生成带盐哈希盐值随哈希一起存入数据库password字段长度需设为VARCHAR(255)。SQL 注入防护所有 DAO 方法均使用PreparedStatement杜绝字符串拼接 SQL如WHERE name name 。XSS 防护JSP 中输出用户数据时用 JSTLc:out value${stu.name}/替代${stu.name}自动转义,,等字符。实测效果在姓名字段输入scriptalert(1)/script页面显示纯文本不执行 JS。6. 答辩前最后一遍检查5 个必做动作与我的血泪习惯6.1 本地 Clean Rebuild清除所有编译残留IDEA 的Build → Clean and Rebuild Project不等于真正干净。必须手动删除三个目录out/IDEA 编译输出target/若误建了 Maven 项目Tomcat/work/Catalina/localhost/student/Tomcat 的 JSP 编译缓存常驻内存导致修改 JSP 不生效我的习惯写一个clean.batWindows或clean.shmacOS/Linux放在项目根目录# clean.sh rm -rf out/ target/ rm -rf ~/apache-tomcat-9.0.83/work/Catalina/localhost/student/ echo Clean done. Now restart Tomcat.每次答辩前双击运行比点菜单快 10 秒且不会漏删。6.2 数据库初始化脚本一行命令还原测试数据别再手动在 Navicat 里一条条 INSERT。在项目根目录放init.sqlCREATE DATABASE IF NOT EXISTS student_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE student_db; CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL ); INSERT INTO user VALUES (1, admin, $2a$12$ZqHbQvYxWzRtUoIjKlMnOpQrStUvWxYzAbCdEfGhIjKlMnOpQrStU); -- bcrypt(123456) CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, gender ENUM(男,女) DEFAULT 男, birthday DATE, major VARCHAR(100), create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); INSERT INTO student VALUES (1,张三,男,2002-05-10,计算机科学与技术,2024-03-01), (2,李四,女,2001-11-22,软件工程,2024-03-02);答辩演示技巧提前在 MySQL 中执行DROP DATABASE student_db;然后当着老师面运行source /path/to/init.sql展示“从零构建”的可控性。6.3 报告中的源码截图规范只截关键 3 行带行号与注释老师不会看你 200 行的StudentDao.java。报告中只放 3 类截图架构图用 draw.io 画的 MVC 分层图Controller/Serlvet、View/JSP、Model/EntityDAO安全代码BCrypt.hashpw()调用行 注释“密码加密符合 OWASP 密码策略”异常处理try-catch(SQLException e)中e.printStackTrace()→ 改为log.error(DB error, e)用java.util.logging即可无需 log4j我的血泪教训曾因报告里贴了整页web.xml被老师问“这个load-on-startup值 1 和 2 有什么区别”当场卡壳。现在只贴load-on-startup所在行并手写注释“值越小优先级越高此处设为 1 确保 DB 初始化监听器最先加载”。6.4 答辩演示 checklist打印出来逐项打钩项目检查方式是否完成✅ Tomcat 启动后localhost:8080/student跳转到login.jsp浏览器直接访问☐✅ 输入 admin/123456 登录成功URL 变为/student/list手动输入☐✅ 点击“添加学生”填完提交后列表页立即出现新学生新增一条数据☐✅ 修改学生姓名保存后列表页显示新名字编辑功能☐✅ 删除学生后刷新列表页该学生消失删除功能☐✅ 在姓名栏输入scriptalert(1)/script页面显示原文本不弹窗XSS 防护☐✅ 关闭浏览器再打开localhost:8080/student/list自动跳回登录页Session 失效验证☐6.5 我的终极习惯答辩前夜用手机拍下所有关键界面不是为了存档是为了强迫自己用第三人视角审视系统。打开手机相机对准屏幕拍下登录页URL 栏可见:8080/student/login.jsp列表页显示至少 2 条学生数据分页控件可见添加页表单完整提交按钮可点击浏览器开发者工具 Console 标签页确保无红色报错Navicat 中student表数据证明数据真实落库看着这 5 张照片你会突然意识到“哦原来我的系统真的跑起来了不是幻觉。” 这种确定感比背 10 遍原理都管用。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →