简介:面向JavaWeb学习者与开发者,这份完整源码包演示了基于Servlet/JSP+MySQL的学生信息管理系统,覆盖学生、班级、教师、课程等核心模块的增删改查场景,适合用于课程设计、毕业设计或理解MVC分层架构的实战参考。资源共40个文件,主要包含11个Java源码、11个class编译文件、4个JSP页面、3个jar依赖包、XML配置及SQL初始化脚本,压缩包仅1.26MB,便于下载与本地部署。已有5103人学习,具有一定参考热度。通过Eclipse导入即可查看DAO、Service、Servlet、JSP各层协作方式,结合SQL脚本快速建表并运行,可深入体会数据层与业务层分离的编码规范,对掌握JavaWeb请求处理流程和数据库操作有直接帮助。
1. 这个javaweb学生管理系统源码包,先别急着删
你是不是也下过这样一个压缩包:文件名写着“javaweb学生管理系统(含源码).zip”,解压开一堆sql和jsp,不知道从哪个文件开始双击。这个标题背后是一个很标准的JavaWeb课程设计案例:JSP+Servlet+MySQL,跑起来能看到登录、学生信息增删改查、成绩录入完整流程。它能帮你解决的问题很直接:把别人能跑的源码变成自己能讲的系统,省下从零搭项目的时间,避开“做完却跑不起来”的尴尬。适合有一点Java语法基础,但对Tomcat部署、数据库连接、web.xml还一窍不通的初学者。手里有这样一个zip,照着下面流程跑通,它就是你的第一份完整项目。
2. 导入与运行:把mysql数据库和IDEA里的Tomcat先串起来
要理解这类源码包,先记住它不是一个双击就能打开的软件。JavaWeb学生管理系统跑起来的条件是:MySQL负责存学生和成绩,Tomcat负责运行Servlet和JSP,IDEA负责编译和部署。三者的关系很像“数据库是仓库,Tomcat是柜台,IDEA是打包员”,包装不对柜台就摆不上货。下面这个流程是几乎所有javaweb项目完整案例mysql写法通用的,包含源码包导入、建库、配置Tomcat、连接串修改。
2.1 解压后先查这几样:sql文件、src目录、web目录、readme
拿到zip后先不要双击index.jsp,也不要急着在IDEA里打开,而是先在文件管理器里把压缩包解压到一个没有中文和空格的路径,比如D:\workspace\student。接着按下面四样东西找:
- sql或db目录下的.sql文件,这是建库脚本;
- src目录,按包名放entity、dao、service、servlet;
- web或WebRoot目录,里面有jsp页面、WEB-INF/web.xml和lib目录;
- readme.txt或说明.doc,通常会写数据库名、tomcat端口、初始账号密码。
我一般会先打开readme再打开sql文件。为什么先看readme?因为很多同学在自己电脑上把MySQL密码改成了自己的生日,导出项目时忘了改源码里的connection,导致别人拿到zip后第一步就被卡住。readme里如果写了“数据库密码123456”,就用123456,没写就去db.properties里翻,翻不到再用“root/空密码”试一遍。有些readme还会明确要求使用JDK8和Tomcat8.5,因为JDK9之后Tomcat8.5带javax.servlet的编译方式会变,老项目经常在导入阶段就报错。
找齐后再动手会省很多时间。我见过有人解压后直接点WEB-INF里的web.xml,浏览器显示XML一堆,以为项目坏了,其实是没找到入口。确认好再进入下一步,这类源码包的正确打开方式永远是先过一遍文件清单,而不是先激动地点JSP。
2.2 导入sql文件:用命令行或Navicat建库,字符集选utf8
学生管理系统第一步通常是建库,因为所有源码里的SQL都建立在student这个库名上。常见做法是打开Navicat或命令行执行脚本。命令行版本最不容易出错:
mysql -uroot -p123456 -e "CREATE DATABASE student DEFAULT CHARSET utf8 COLLATE utf8_general_ci;" mysql -uroot -p123456 student < sql/student.sql第一行命令里,-u是用户名,root就是MySQL超级管理员;-p是密码,这里直接跟在-p后面写123456;如果密码为空,写成-p后不接内容。之后通过-e执行一条建库SQL,DEFAULT CHARSET utf8指定了库的默认字符集是utf8,COLLATE是排序规则,选utf8_general_ci足够学生项目用。第二行的<符号是重定向,意思是把sql/student.sql文件里的所有SQL逐条执行到前面的student库里。
如果sql文件里本身就带了CREATE DATABASE student和USE student,那第一行可以去掉,直接执行第二行即可。但这里有个坑:很多老sql文件导出时没有指定字符集,表结构里写的是latin1,导入后中文全是乱码。所以导入前先用文本编辑器打开sql文件,搜索有没有SET NAMES utf8或default charset=utf8;没有的话,最好在sql文件最顶部手动加一行SET NAMES utf8;再保存重新导入。判断导入成功与否,可以在mysql里执行show tables;看到user、student、score之类的名字就说明基础表建好了。
2.3 在IDEA里配置tomcat:artifact和deployment是重点
把项目导入IDEA后,许多新手按Shift+F10直接运行main方法,发现控制台没有任何Tomcat输出。这是因为JavaWeb项目没有main入口,它需要被Tomcat容器加载。用IDEA运行javaweb项目配置过的同学都知道,关键在Run/Debug Configurations里新增一个Tomcat Server的Local配置。
具体走一遍:打开菜单Run -> Edit Configurations,点+号,找到Tomcat Server -> Local。然后在Server页签里选择本地Tomcat安装目录,建议用解压版Tomcat8.5或9.0,不要用安装版,因为安装版会占用系统服务,IDEA里还要处理权限问题。选好后再切到Deployment页签,点+号选择Artifact,把项目打包出的war exploded加进去,Exploded就是解压目录,这样改了jsp后刷新浏览器就能看到变化,不用每次重新打包。Application context建议填/student,这个值决定访问路径前缀。
很多同学在这一步卡住是因为IDEA没有识别Web模块:Project Structure -> Modules -> 选中当前模块,点+加Web,把Web Resource Directory指到项目里的web或src/main/webapp目录。如果不是Maven项目,还要在Artifacts里把Available Elements里的WEB-INF、jsp页面都拖到Output Root下。这一套做完,IDEA才会生成正确的artifact,Tomcat启动后才不会直接404。配置好后,点绿色运行按钮,看到控制台出现“Deployment is in progress”和“Artifact is deployed successfully”字样,才算真正起来。
2.4 数据库连接配置:db.properties或JDBC URL里别写错编码
Tomcat能跑起来只代表JSP页面能显示,要登录成功还需要让Java代码连上MySQL。源码包里连接数据库的信息一般放在src/db.properties,或者写在DBUtil.java类的字符串常量里。最常见的连接配置就是下面这种:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=123456说明一下各参数含义:localhost是MySQL所在主机,3306是默认端口,student是刚才建的库名;useUnicode=true和characterEncoding=utf8告诉驱动用utf8处理字符,这对学生管理系统里的中文姓名和课程名尤其重要;useSSL=false是关闭SSL加密握手,MySQL5.7的驱动不写可能出现一堆ssl警告。如果本地MySQL是8.0以上,驱动类名要改成com.mysql.cj.jdbc.Driver,而且url里最好补充serverTimezone=Asia/Shanghai,否则查询时间会有8小时错位。
改完连接串之后,一定要重新编译再重启Tomcat。很多人在properties文件里改了半天,控制台里还是旧错误,就是因为IDEA没有重新打包artifact,Tomcat加载的还是之前那套class。这个连接配置可以说是整个源码包里最需要细心的地方,因为字段一旦拼错,比如把student写成students,登录页会一直停在“系统异常”。
注意:如果源码包不是Maven结构,mysql驱动jar必须放在WEB-INF/lib下,否则Tomcat启动时根本找不到Driver类。
3. 读懂分层代码:jsp→servlet→service→dao的调用链
跑通一次后,源码包对你来说从“黑匣子”变成了“零件库”。JavaWeb学生管理系统最典型的源码结构是分层:JSP负责显示,Servlet负责接请求,Service负责业务,DAO负责SQL。这种分层的直接好处是,你想改前端不用碰SQL,想改数据库不用动页面,毕业设计答辩时老师问“你这个项目怎么设计的”,你就能把这条链讲清楚。下面按调用顺序从登录页面讲起,正好对应学生在系统里的第一次操作。
3.1 从login.jsp开始:form表单的action决定了去哪个Servlet
打开项目里的login.jsp,先看中间有没有一个form标签。几乎所有学生管理系统的登录页都是这样设计的:
<form action="loginServlet" method="post"> <input name="username" placeholder="用户名" /> <input type="password" name="password" placeholder="密码" /> <button type="submit">登 录</button> </form>这里action不是文件名,而是web.xml里登记的Servlet映射名。如果在WEB-INF/web.xml里找到类似 /loginServlet ,说明浏览器在以Post方式请求这个地址。method选post而不是get,除了URL好看,还有一层原因:get会把username和password放到URL查询串里,任何一个访问记录都留了密码明文。input里的name属性要和Servlet里request.getParameter("username")的名字完全一致,改错一个,后台拿到的就是null,一登录就报空指针。
老一些的源码包会在form里写action="loginServlet?action=login",这种带问号参数的写法也不是不行,只是Servlet里要多写一个if分支去判断action。建议你阅读代码时先搜索web.xml里的servlet-mapping,把每个URL和对应类列出来,再回来看JSP就清楚多了。把这条线摸清后,你会明白登录页只是个壳,真正决定页面跳转的是服务器端Java类。
3.2 Servlet里只做参数组装和跳转,业务逻辑丢给Service
分层规范的源码包,Servlet里的代码不会太多。下面是学生系统里登录Servlet最常见的骨架:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); UserService service = new UserService(); User user = service.login(username, password); if (user != null) { req.getSession().setAttribute("user", user); resp.sendRedirect("listStudentServlet"); } else { req.setAttribute("msg", "用户名或密码错误"); req.getRequestDispatcher("login.jsp").forward(req, resp); } }这段代码做了三件事。第一步从请求里取参数;第二步创建UserService并调用login方法;第三步根据返回值决定重定向还是转发。注意login方法返回null表示查不到这个人,返回User对象表示登录成功。成功时把user塞进session,这样后续页面可以通过session判断“当前有没有人登录”;失败时setAttribute设置msg,并在login.jsp里用${msg}显示出来。
为什么不直接在Servlet里写查询?因为一个系统里有登录、列表、新增、删除、修改五个接口,如果每个Servlet都直接拼SQL,你会发现改一个字段要同时改五个文件,少改一个SQL页面就报错。Service层的价值是把登录校验、批量删除这种业务规则集中起来,让Servlet保持薄,让DAO保持专一。答辩时可以说“这是分层解耦”,比单纯背概念有说服力。
3.3 Service和DAO:预编译PreparedStatement是底线
继续往下走,UserService.login内部会调用UserDAO的某个方法。学生管理系统的DAO层代码风格差别很大,有直接用Statement的,也有用PreparedStatement的。我强烈建议你拿到源码后,搜索一下“Statement.executeQuery”和“PreparedStatement”,如果你手上的源码全是statement字符串拼接,最好自己改成下面这种:
public User findByUsernameAndPassword(String username, String password) { String sql = "SELECT * FROM user WHERE username = ? AND password = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); ResultSet rs = ps.executeQuery(); if (rs.next()) { User u = new User(); u.setId(rs.getInt("id")); u.setUsername(rs.getString("username")); return u; } } catch (SQLException e) { e.printStackTrace(); } return null; }这段代码的关键是问号占位符。PreparedStatement不会直接把参数拼进SQL字符串,而是先在数据库里预编译,再把参数用setString传进去,这样即使输入包含SQL关键字,也无法改变原有语句结构。相比之下,如果写成"SELECT * FROM user WHERE username='" + username + "'",输入一个' or '1'='1就会把条件变成永真,直接绕过密码。这是课程设计答辩时最容易被问到的安全问题。
还要注意try-with-resources写法。Connection和PreparedStatement都实现了AutoCloseable,放在try括号里,方法结束后会自动关闭,不用再写finally。这种写法在JDK7以后都能用。有些项目DBUtil.getConnection()会返回null,原因是前面的db.properties没配对,此时程序会直接进catch,在控制台打印SQLException,不会像前端那样友好提示。
3.4 JSP列表页:用EL表达式和JSTL替换掉Java脚本
学生管理系统里最重要的页面是学生列表页,源码包在这一页的写法和版本关系很大。老项目多用JSP脚本片段,比如:
<% List<Student> list = (List<Student>) request.getAttribute("list"); if (list != null) { for (Student s : list) { %> <tr><td><%=s.getName()%></td></tr> <% } } %>这段代码在Tomcat7时代可以运行,但到了Jakarta命名空间的Tomcat10,javax.servlet包被改成jakarta.servlet,整个页面经常编译报错。更推荐的写法是JSTL循环:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:forEach items="${list}" var="s"> <tr><td>${s.studentId}</td><td>${s.name}</td></tr> </c:forEach>这里${list}对应Servlet里的request.setAttribute("list", list),items是循环的数据源,var是每次循环的变量名。${s.name}的写法不是直接访问字段,而是调用Student类的getName()方法。如果列表没有数据,c:forEach会自然跳过,不会像脚本片段那样在页面上留下一大片空白。
使用JSTL之前,要保证WEB-INF/lib下放了jstl和standard两个jar包,并且在JSP头部写上taglib指令。很多源码包已经带了这个依赖,但如果是从旧博客下载的,可能缺jar,运行时会出现Caused by: java.lang.ClassNotFoundException: org.apache.taglibs.standard.tag.common.core.ForEachSupport。解决办法就是去maven仓库下载JSTL1.2的jar放进lib目录。做到这一步,你对源码包的阅读就算真正入门了。
4. 改造成自己的java课程设计:加字段、加功能、换前端
跑通和读懂之后,下一步就是把这个源码包变成“你自己的”java课程设计案例源码。很多同学以为改个文件名、换个背景图就叫改造,其实老师打开数据库表结构和Java类一眼就看得出是不是原包。真正有效的改造是从数据结构下手,让系统的字段、逻辑、页面都留有你的痕迹。下面四个改造点是我比较推荐的,既能展示工作量,又不至于重写整个项目。
4.1 给student表加字段,从数据库到JSP全链路同步
以“给学生表加一个家庭住址字段”为例。先看student表现在的结构,打开MySQL命令行或Navicat执行:
ALTER TABLE student ADD COLUMN address VARCHAR(100) DEFAULT '' COMMENT '家庭住址';这条命令会给student表增加一个address字段,允许为空,默认空字符串。执行后只完成了数据库端的改动,假如你现在启动项目,新增学生的页面里根本没有address输入框,后台接收参数时也取不到address,程序不会报错,只是字段一直为空。完整改造分四步:
- 改实体类Student.java,增加private String address,并补getter/setter;
- 改addStudentServlet的doPost,增加String address = request.getParameter("address");;
- 改DAO里的insert语句,把address列和?占位符加进去;
- 改addStudent.jsp表单,增加。
这四步的顺序不能乱。很多教程只让加数据库字段,结果代码一跑,实体类里没有这个属性,导致JSP里${s.address}永远显示空。反过来只改实体类不改SQL,插入学生时SQL会报column count doesn't match value count。要记住一条规律:字段从数据库到Java实体,再到Servlet参数、DAO绑定、JSP输入框,是一条必须闭环的链条,缺一环就是局部修改,不叫新功能。
4.2 把物理删除改成逻辑删除:一个status字段解决
原系统里的删除多半是DELETE FROM student WHERE id=?,这种做法在演示系统里没问题,但老师一旦问“你如何保留误删数据”就答不上来。把删除改成软删除是很有性价比的改造,先加状态字段:
ALTER TABLE student ADD COLUMN status TINYINT NOT NULL DEFAULT 1 COMMENT '1正常 0删除';然后把删除Servlet里的SQL从DELETE换成UPDATE:
String sql = "UPDATE student SET status = 0 WHERE id = ?";这里有一个容易被忽略的地方:查询列表的SQL也要跟着改。原来select * from student现在必须变成select * from student where status = 1,否则软删除的“已删除”学生仍然出现在列表里,逻辑自相矛盾。分页的总条数、按班级筛选等查询都要逐个检查,凡是原来查student表的地方都要带上status条件。
这个改造会让DAO层的方法签名也要多考虑一个状态参数。比如findAll方法从无条件变成findAllWithStatus(int status),Service调用时传入1。做完之后,你可以在答辩时主动说“删除是逻辑删除,后台留了status字段”,这一句话就能显示你懂数据安全,比通篇说“我用了MVC”强得多。
4.3 换皮:把JSP里的静态资源改成相对路径或本地文件
学生管理系统最常被吐槽的是页面风格老气。很多源码包默认用表格布局和自带CSS,你至少把登录页和列表页换一版。最简单的方式是引入Bootstrap,并且用EL表达式获取项目根路径,避免绝对路径在部署名变化后失效:
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css"> <script src="${pageContext.request.contextPath}/js/jquery.min.js"></script>其中${pageContext.request.contextPath}在运行时会被解析成/student,拼接后变成/student/css/bootstrap.min.css。如果你直接写href="/css/bootstrap.min.css",那么换部署名、换端口后样式全部丢失。把CSS和JS下载到webapp的css/js目录后,JSP头部替换这段引用即可。
换肤的时候注意排版兼容性。一些老JSP用frame框架集,改成Bootstrap时要把多个frame页面合并到一个主页面。如果项目用了很多嵌入式Java脚本,比如<% for %>循环放在表格行内,也要先替换成3.4讲过的JSTL再改样式,否则新CSS对老结构无能为力。换完页面后,务必清一下浏览器缓存再检查,不然你改了代码却看到旧的样式,很容易误判“没改成功”。
4.4 备份你的改动:git init或者打完zip再放一份
做改造之前第一件事不是写代码,而是备份一份原始源码包。常见的后悔药是在解压目录下先复制一份整个文件夹,命名为“student_original”,再开始改动。如果你愿意用Git,在项目根目录初始化版本库,成本更低:
git init git add . git commit -m "initial import"这三条命令的作用分别是:把当前文件夹初始化成一个Git仓库;把当前所有文件加入暂存区;提交一个叫initial import的初始版本。之后每完成一个小功能,就再执行git add .和git commit -m "xxx",这样每次改动都能记录下来。改坏了直接git checkout -- .回退到上一个提交,或者git log查看历史。这个习惯在我带课程设计时反复强调过,因为学生管理系统源码包里文件多,手一抖删了web.xml,如果没有版本控制,只能重解压再来一遍,浪费的时间足够你多写一个模块。
5. 避坑:javaweb学生管理系统运行时的6个翻车现场
源码包在别人电脑上能跑,在你电脑上跑不起来,十有八九是环境问题而不是代码问题。下面六条是我从不同学生项目里收集到的最高频踩坑记录,每条按现象、原因、解决的顺序写,你可以直接对照排查。
5.1 现象:Tomcat启动后访问项目404
404有两种常见情况:一种是日志显示“Artifact is deployed successfully”,但浏览器还是404;另一种是Tomcat启动正常,但访问http://localhost:8080/直接显示404。前者的原因多半是IDEA的Deployment里没有加artifact,或者Application context填错了;后者原因多半是Tomcat的webapps下没有项目目录。解决起来也简单:回到Run/Debug Configurations,确认Deployment页签下有artifact,并且Application context写的是/student,然后在地址栏访问http://localhost:8080/student/login.jsp。如果还是404,到Tomcat安装目录的webapps下看有没有student文件夹,没有说明部署没有生效,清理缓存重新部署。还有一个容易被忽略的点:浏览器地址栏里还存着之前的端口,比如以前用8081,现在改回8080,按F5刷新不出来时,要看一下地址栏端口是不是旧的。
5.2 现象:登录成功但列表页全是问号
中文乱码是JavaWeb学生管理系统最常见的问题,尤其是从旧版MySQL导出的库。根源有三个:数据库表是latin1编码;页面JSP没指定UTF-8;JDBC连接串没带characterEncoding=utf8。解决分三步。第一步,把student库和所有表改成utf8mb4,执行ALTER DATABASE student CHARACTER SET utf8mb4;以及ALTER TABLE student CONVERT TO CHARACTER SET utf8mb4;。第二步,检查JDBC url,确保带了useUnicode=true&characterEncoding=utf8。第三步,在每个JSP顶部加<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>。改完重启Tomcat,不要只刷新浏览器,因为Tomcat里缓存了旧页面。这里还有一个细节:如果数据已经是乱码,改编码后依然乱码,需要把旧数据删掉重新导入,因为编码转换不会修复已损坏的字节。如果JSP里写死charset=gb2312,也要一起改成utf8,否则浏览器发送中文表单还是会乱。
5.3 现象:启动时抛出ClassNotFoundException: com.mysql.jdbc.Driver
这个报错直接告诉你MySQL驱动不在运行时类路径里。很多初学者把mysql-connector-java的jar下载到了桌面,以为导入IDEA的Libraries就够了,但Tomcat在部署时不一定加载这个Libraries。解决方法是把jar复制到项目的WEB-INF/lib目录下。这里说清楚:WEB-INF/lib里的jar会被Tomcat自动加载,这也是传统Web项目的标准做法。复制后,IDEA需要右键jar选择Add as Library,再重新打包部署。如果你用的是Maven项目,那么检查pom.xml的依赖才对,但标题里这类zip源码包大多数不是Maven结构,直接放jar最省事。确定是否加进来的办法,是看Project Structure里的Artifacts输出目录,发布时WEB-INF/lib会出现在Output Root下列出的jar清单里。
5.4 现象:Tomcat启动失败,Address already in use
Tomcat默认端口是8080,如果你之前启动过另一个Tomcat实例,或者IDEA没关掉上一个调试进程,端口就会被占用。最直接的排查命令是Windows下执行netstat -ano | findstr 8080,看到LISTENING对应的PID后,在任务管理器结束该进程。如果是你自己开了两个Tomcat,也可以把当前Tomcat的server.xml中的8080改成8081,改的时候要注意三处:Server port、Connector port、如果配置了AJP也要改。改完端口,浏览器里的访问地址也要同步改为http://localhost:8081/student/。如果你在源码里看到JDBC url里有端口,那个是MySQL端口,和Tomcat端口无关,不需要动。有时候不是端口被占,而是Tomcat正在关闭还没完全释放,重启IDEA能解决。
5.5 现象:上传的头像/文件刷新后丢失
部分学生管理系统源码带上传功能,上传时会先保存到某个磁盘路径,比如D:\upload\xxx.jpg,然后页面用img标签引用这个绝对路径。本机演示没问题,一旦换一台电脑访问,立即图片失败。原因是Web项目的图片必须由Tomcat作为静态资源访问,浏览器不能直接读取服务器文件系统的任意路径。解决方法是把上传目录放到项目部署目录下,并且保存时通过ServletContext拿真实路径:
String uploadPath = getServletContext().getRealPath("/upload");这行代码会根据项目部署位置生成一个服务器绝对路径,文件保存后浏览器就能通过/upload/xxx.jpg访问。注意getRealPath在Tomcat解压部署和war包部署下行为不同,war包部署时write操作只对解压目录有效。课程设计阶段用getRealPath足够交差,但你要能说出这个局限。另外,如果老项目把上传图片直接存到数据库BLOB字段,列表页也会变慢,改成存路径是更规范的方案。
5.6 现象:直接访问listStudent.jsp显示空指针
学生管理系统的列表页顶部通常会判断当前登录用户,比如<%if(session.getAttribute("user")==null) return;%>,如果写的是直接调用user.getName(),没有先判空,那么绕过登录直接访问该JSP时,session里没有user,就会在页面上报NullPointerException。解决思路是加全局过滤器,而不是在每个页面加判断。最后一章会贴一个最小Filter,这里先说一下配置路径:新建LoginFilter类,实现javax.servlet.Filter接口,在web.xml的filter-mapping里拦截/*,在doFilter中只放行login.jsp和静态资源,其余请求必须验证session。这样从根上挡住未登录访问,而不是等JSP抛异常再补救。配置过滤器后要记得,登录成功后必须把user放进session,否则登录成功也会被过滤器踢回登录页。
6. 答辩前干三件事:登录拦截、输入校验、把技术点讲清楚
6.1 用Filter把未登录用户挡在列表页外面
第5.6提到空指针,这里给出最小Filter解法:
public class LoginFilter implements Filter { 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.endsWith(".css") || uri.endsWith(".js") || uri.endsWith(".png") || uri.endsWith(".jpg")) { chain.doFilter(request, response); } else if (request.getSession().getAttribute("user") != null) { chain.doFilter(request, response); } else { response.sendRedirect(request.getContextPath() + "/login.jsp"); } } }这个Filter只做一件事:判断当前请求是不是登录页或静态资源,是就放行;不是就检查session里有没有user,有就继续走,没有就重定向到登录页。然后在web.xml中配置filter和filter-mapping,url-pattern写/*,就能覆盖所有页面。注意登录请求本身也要放行,否则你还没登录就被拦回去了。静态资源通过后缀判断放行,因为Bootstrap的css/js如果被拦,页面样式就全丢了。
6.2 按最小用例清单验证登录和增删改查
答辩前不要只看控制台不报错就完事,至少按表格里的用例点一遍:
| 功能 | 操作 | 预期结果 |
|---|---|---|
| 登录 | 输入错误密码 | 页面提示用户名或密码错误 |
| 登录 | 输入正确账号 | 跳转到学生列表页,session写入user |
| 新增 | 不填姓名直接提交 | 后端或前端校验给出提示 |
| 删除 | 点击删除一个学生 | 记录消失,数据库status变为0 |
| 修改 | 改电话后保存 | 列表页显示新电话 |
| 注入 | 用户名输入' or '1'='1 | 登录失败,而不是查出所有用户 |
为什么要按这个顺序?因为登录是所有功能的前置条件,然后才是增删改查,最后才是安全项。如果前面任何一步失败,后面的验证都没有意义。表格里没有分页和模糊查询,不代表不用测,而是至少把主流程跑通一遍,再补边界用例。
6.3 给每个功能准备一句“为什么”
老师防抄袭常问的是“这个地方为什么这么写”。删除学生时,回答“我用的是逻辑删除,保留了status字段”,比“点了就能删”强很多。登录查询用PreparedStatement,可以解释为“防止SQL注入”。表单提交用post,可以解释为“避免密码出现在URL里”。每一句不需要长,但必须说到点上。我自己的血泪经验是:交项目前最喜欢改样式,结果登录拦截没配置,老师演示时直接从地址栏输出了listStudent.jsp,页面暴露了整个学生表,场面十分尴尬。后来每次拿到这类javaweb学生管理系统源码包,我都先加过滤器、再跑功能验证,最后才改前端。希望帮到你。
本文还有配套的精品资源,点击获取