ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Java Web在线考试系统实战:基于SSM框架的完整项目部署与代码解析

Java Web在线考试系统实战:基于SSM框架的完整项目部署与代码解析 简介一套基于Java Web的在线考试系统完整项目面向正在学习Java Web开发的在校生、毕业设计选题者及需要快速搭建考试模块的开发者。项目基于IDEA MySQL JDK Tomcat环境构建内置管理员、教师、学生三类账号覆盖题库管理、在线答题、成绩统计等核心考试业务可直接导入运行并二次开发。资源共566个文件压缩包仅3.2MB以Java源码、class编译文件、HTML页面及XML/JS/CSS等前端资源为主另有SQL数据库脚本与项目配置文件结构完整便于对照学习分层架构与前后端交互逻辑。已有902人学习下载。对于想要完整走通“登录→组卷→考试→评分”流程的读者这套项目可节省大量从零搭建的时间尤其适合课程设计、期末项目或Java Web入门进阶的实战参考。1. 一个Java Web在线考试系统给我一个能演示的完整闭环就行接手过课程设计的朋友都有同感要么代码残缺要么数据库对不上要么一启动就报500。这套基于Java Web的在线考试系统源码包是我拆过为数不多「导入-建库-启动-登录」四步走完就能演示的完整项目。从压缩包里的文件结构看StudentEntityExample、TeacherEntityExample、FenshuEntityExample、CourseController这些类名非常眼熟——典型SSM分层风格的代码体系学生、老师、管理员三种角色各有独立登录入口测试账号直接写在说明里管理端、考试端、评分端串在一个MySQL数据库里。对需要交课程设计、或者想从增删改查进阶到完整业务流的Java初学者来说这套三个角色、四种实体的系统够用了。下面从架构开始拆。2. 先看清骨架项目分层、数据库表与角色权限边界2.1 从Controller到Mapper这是一套教科书式的分层Web应用从项目文件里的CourseController.class以及各种EntityExample类能判断这套在线考试系统的技术栈是传统的Servlet JSP MyBatis跑在Tomcat容器上具体开发环境是IDEA MySQL JDK Tomcat的组合。这类项目没有Spring Boot那种自动配置的魔法一切依赖都需要在配置文件和Tomcat容器里显式声明——这反而是好事你能亲手摸到一次请求从浏览器到数据库再返回的完整链路。展开讲这套系统每个人的职责边界很清晰。Controller层接收前端JSP页面传来的请求参数调用Service层完成业务判断Service层再操作MyBatis的Mapper接口。Mapper接口对应的XML文件里写SQL负责和MySQL实际交互。JSP页面放在webapp目录下通过URL访问。项目里最显眼的类是各种EntityExample。我第一次拆这个项目的时候也被$GeneratedCriteria这种文件搞懵过。实际上这是MyBatis Generator自动生成的代码专门用来构造动态SQL查询条件的。以学生实体为例它常见的用法是这样// 通过Example对象构造动态查询条件这是MyBatis Generator的核心用法之一 StudentEntityExample example new StudentEntityExample(); StudentEntityExample.Criteria criteria example.createCriteria(); // 精确匹配用户名必须等于zkd criteria.andUsernameEqualTo(zkd); // 可以追加另一个条件性别为男 criteria.andGenderEqualTo(男); // 把条件传给MapperselectByExample会自动拼接WHERE子句 ListStudentEntity studentList studentMapper.selectByExample(example); if (studentList ! null studentList.size() 0) { // 查到一个学生说明账号存在且性别匹配 StudentEntity student studentList.get(0); }逻辑说明createCriteria()创建一个查询条件容器上面加的各种andXxxEqualTo方法最终会生成一条SQL的WHERE部分。selectByExample是MyBatis Generator自动生成的查询方法它接收一个Example对象内部通过反射解析Criteria里的条件拼接SQL语句。参数说明andUsernameEqualTo(zkd)里的zkd就是摘要里提到的学生测试账号selectByExample返回的是ListStudentEntity哪怕只查一条也是List。实际业务里通常还会list.get(0)所以需要在取第一条之前判断非空。这套Example Criteria模式在项目里大量贯穿弄懂了它读这类旧版SSM项目的代码会顺很多。2.2 数据库设计五张核心表如何粘合完整考试业务从Entity类名反推这个项目的数据库设计能清晰看到在线考试系统的数据骨架——六张核心表表名核心字段对应实体类在业务里的作用studentid, username, password, genderStudentEntity存学生账号与基础信息teacherid, username, password, nameTeacherEntity存老师账号老师负责出题和打分index_tableid, course_name, teacher_idIndexTableEntity课程索引表考试以课程为维度组织fenshuid, student_id, course_id, scoreFenshuEntity成绩表学生某门课程的考试分数落库pingjiaxinxiid, student_id, course_id, contentPingjiaxinxiEntity评价信息表老师给学生写评语courseid, course_name, course_typeCourseController对应表课程本身的基础配置这个设计里的一个关键点成绩表和评价表都通过student_id和course_id两个外键把「谁考了哪门课得了多少分」关联起来。比如考试提交后要做的是插入fenshu表而不是去更新student表——这是典型的「主体表 明细表」结构符合数据库三范式的实践。数据库的导入方式在摘要里提到直接执行项目自带的SQL文件即可常见做法是用Navicat或IDEA自带的Database面板执行整个.sql文件一条命令就能搞定mysql -u root -p exam_system exam_system.sql注意这里exam_system是目标库名执行前需要先CREATE DATABASE exam_system DEFAULT CHARACTER SET utf8;防止导入时因为库不存在而报错。2.3 三种角色的权限边界管理员往哪走、学生往哪走、老师往哪走这套系统的登录逻辑是按角色分发入口的。摘要给出的三组账号——管理员daima、学生zkd、老师dzk——分别在数据库中存储于各自的实体表里Controller层收到登录请求后会先判断前端传来的role参数再根据角色到不同的表里查账号管理员登录成功后跳转后台管理页核心操作是维护课程信息、管理学生和老师账号。学生登录后进入考试页能看已选课程、参加考试、查询自己的成绩。老师登录后进入命题与评分页负责给班级出题、录入分数、给学生写评价信息。需要留意的是这类系统的权限往往只做前端跳转区分后端接口没有特别强的拦截器校验。也就是说任何角色登录后拿到的session里只是放了当前用户对象如果直接绕过URL访问其他角色的页面是很可能直接打开的。这是课设级项目的普遍情况不是个例。3. 把环境配好IDEA导入、MySQL初始化与Tomcat部署全流程3.1 环境版本选择JDK 8 MySQL 5.7 Tomcat 8.5 是稳定组合这个项目是传统Web应用不依赖Spring Boot环境版本的选择直接影响能不能一次跑起来。我建议的版本组合是JDK 1.8、MySQL 5.7、Tomcat 8.5、IDEA 2020及以上版本。为什么这样选JDK 8是这套代码的语法下限项目里用的集合泛型、字符串拼接、switch语法全是Java 8兼容写法MySQL 5.7的JDBC驱动只有一条连接串不需要处理8.0版本引入的时区和SSL报错Tomcat 8.5对应Servlet 3.1规范JSP和EL表达式的行为最稳定。如果你手里只有MySQL 8.0需要在数据库连接URL里追加?serverTimezoneAsia/ShanghaiuseSSLfalse两个参数否则启动时大概率报SQLException: The server time zone value。这里还有一个环境细节Tomcat的版本直接决定JSP编译的Java版本。Tomcat 9以上默认跑在Java 11上项目里如果用了javax.servlet的旧包会冲突。所以不要图新踏踏实实用Tomcat 8.5.32以上版本。3.2 数据库导入与连接参数修改打开Navicat或IDEA数据库面板新建一个exam_system数据库字符集选utf8排序规则选utf8_general_ci然后直接运行项目根目录下的SQL文件。导入完成后再检查三张账号表是否被成功填充核心表里应该各有一条对得上测试账号的记录——管理员表里有daima学生表里有zkd老师表里有dzk。接下来最关键的一步修改数据库连接配置。传统SSM项目的数据库连接信息一般在jdbc.properties或者db.properties文件里如果在src/main/resources目录下找不到就到src目录全局搜jdbc:mysql。常见内容长这样# 数据库连接配置文件改对用户名密码项目就跑通了一半 jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/exam_system?useUnicodetruecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456逻辑说明jdbc.url里的localhost:3306指本机MySQL端口exam_system是目标库名useUnicodetruecharacterEncodingutf8这条参数强制使用UTF-8传输数据如果省略考试题目和评价里的中文容易变问号。参数说明jdbc.username和jdbc.password要填你自己本机MySQL的账号密码很多项目跑不起来就是因为只改了库名没改密码。如果MySQL是8.0版本jdbc.driver需要改成com.mysql.cj.jdbc.DriverURL末尾追加serverTimezoneAsia/Shanghai这两处缺一处都会报连接异常。3.3 IDEA配置从导入到启动的完整操作序列IDEA配置这块网上说法散我把一个最稳的操作序列写出来第一步IDEA打开项目根目录。如果是普通Web工程IDEA会提示识别的项目类型选择Web应用如果项目里有pom.xmlIDEA会自动按Maven项目导入。这套项目更可能是非Maven的普通Web工程依赖jar包放在WEB-INF/lib目录下。第二步配置Project Structure。打开File - Project Structure确认Project SDK选1.8Libraries里能看到WEB-INF/lib下的jar包已被识别——如果只有部分基础设施依赖点加号手动添加lib目录。第三步配置Artifact。在Project Structure里找到Artifacts点加号选择Web Application: Exploded把项目Web模块关联上去。这一步漏掉的话Tomcat运行时页面会全部404。第四步配置Tomcat。打开Run - Edit Configurations点加号选Tomcat Server - LocalApplication server选择你本机Tomcat 8.5的安装目录Deployment选项卡里点加号选择ArtifactApplication context填/exam注意前后不要多余字符。第五步启动前做一次双击检查——Tomcat的VM参数里查-Dfile.encodingUTF-8JSP页面第一行确保是% page languagejava contentTypetext/html; charsetUTF-8 %。这两项是中文乱码的根治手段。全部就绪后在IDEA里点绿色三角形启动控制台出现Server startup in日志就表示Tomcat起来了。3.4 跑通第一个完整业务流程Tomcat启动成功后在浏览器输入摘要里写的地址http://localhost:8080应该能看到系统登录页。按顺序验证三个账号用zkd / 123登录学生端进个人主页查看是否有可参加考试课程。用dzk / 123登录老师端确认能进入命题管理或评分管理页面。用daima / 123登录管理员端检查课程管理、账号列表、成绩总览三个模块。这一步的正确姿势是三层验证而不是只截一张登录页图——很多朋友项目「跑通」了但只登录学生端就没往下看等到演示时发现老师端URL直接404血泪教训。登录成功一次只能说明Session正常工作三个角色全部跑通才算这套系统真正在你机器上立住了。4. 核心代码怎么读登录校验、考试流程与成绩落库的完整链路4.1 登录逻辑三层判断与Session的角色分流这套系统的登录Controller是标准的请求拦截模式。前端JSP页面的登录表单提交用户名、密码、角色三个字段到后端后端根据角色走三条不同的Service分支。伪代码逻辑如下// 登录校验先按角色分流查询再用Session标记登录态 RequestMapping(/doLogin) public String doLogin( String username, String password, String role, HttpSession session) { // 第一层判断角色参数决定查哪张表 if (admin.equals(role)) { AdminEntity admin adminService.login(username, password); if (admin ! null) { session.setAttribute(admin, admin); return redirect:/admin/index; // 管理员主页 } } else if (teacher.equals(role)) { TeacherEntity teacher teacherService.login(username, password); if (teacher ! null) { session.setAttribute(teacher, teacher); return redirect:/teacher/index; // 老师主页 } } else if (student.equals(role)) { StudentEntity student studentService.login(username, password); if (student ! null) { session.setAttribute(student, student); return redirect:/student/index; // 学生主页 } } // 第二层统一失败处理回到登录页并携带错误信息 return redirect:/login?error用户名或密码错误; }逻辑说明这是「按角色分流 会话保持」的实现。核心在于把不同的用户对象放进Session后续所有页面通过session.getAttribute(teacher)判断当前登录人。如果值为空就直接拦截跳回登录页。参数说明role字段对应登录表单里radio按钮的value值管理员、老师、学生三种角色的登录是同一套前端模板还是三套模板取决于复用的程度redirect:/login是重定向——浏览器地址栏会变为登录页这样刷新不会重复提交表单这是处理登录失败时必要的控制。4.2 考试模块题目加载、答案提交与计时处理学生登录后进入考试模块核心流程是选择课程 - 加载题目列表 - 提交答案 - 系统判分 - 写入fenshu表。这套业务放在Controller里实现代码量不大但每个细节都很关键题目加载的逻辑常见写法// 考试模块按课程加载题目并处理提交 RequestMapping(/exam/start) public String startExam( RequestParam(courseId) int courseId, HttpSession session, Model model) { // 从Session里拿当前登录学生 StudentEntity student (StudentEntity) session.getAttribute(student); if (student null) { return redirect:/login; // 未登录直接拦截 } // 按课程查询题目列表 ListQuestionEntity questionList questionService.selectByCourseId(courseId); model.addAttribute(questionList, questionList); model.addAttribute(courseId, courseId); // 把考试开始时间存入Session用于提交时校验 session.setAttribute(examStartTime, System.currentTimeMillis()); return examIndex; // 渲染答题页 }逻辑说明这里的题目表在数据库里叫question但项目本身的Entity里有IndexTable和Course两个与课程相关的实体说明课程体系是通过courseId把课程索引、题目、成绩串起来的。startExam只负责加载题目和记录开始时间真正的判分逻辑在提交接口里。提交判分的处理相比之下会复杂一些。提交接口需要遍历答题表单里每一道题的选项和数据库里的标准答案比对用计数器统计正确个数最后计算总成绩。计算完成后再组装一个FenshuEntity对象——设置student_id、course_id、score三个核心字段调用fenshuMapper.insert()落库。这就是成绩写入数据表的时机这套逻辑属于「前端收集答案、后端逐题判分」的经典实现方式和教师手动录分的FenshuController是两条不同的业务线。4.3 成绩与评价展示三个角色各自看到什么考试成绩落库之后三个角色看到的数据并不相同。学生端查询的是自己的成绩列表这是典型的学生视角展示逻辑// 学生查询成绩列表只能看到自己的分数 RequestMapping(/student/score) public String scoreList(HttpSession session, Model model) { StudentEntity student (StudentEntity) session.getAttribute(student); // 关键条件只查当前学生的成绩记录 FenshuEntityExample example new FenshuEntityExample(); FenshuEntityExample.Criteria criteria example.createCriteria(); criteria.andStudentIdEqualTo(student.getId()); // 按时间倒序排列 example.setOrderByClause(exam_time desc); ListFenshuEntity scoreList fenshuMapper.selectByExample(example); model.addAttribute(scoreList, scoreList); return studentScore; }逻辑说明andStudentIdEqualTo(student.getId())是成绩查询的权限屏障StudentId取自session里登录对象的Id这样学生永远只能看到自己的成绩这是整个系统中最核心的权限过滤条件。参数说明setOrderByClause(exam_time desc)是MyBatis自动生成的排序接口直接拼接SQL的ORDER BY子句——desc是倒序让最近一次考试成绩显示在最上面这样学生在成绩列表页第一眼看到的永远是当前最新的考试结果。老师端看到的数据范围则不一样老师登录后进入FenshuController对应的页面能看到课程下所有学生的成绩列表并且能给对应学生的pingjiaxinxi表插入一条评价记录。评价表和成绩表用studentId和courseId两个字段一起作为关联条件保证一条成绩对应一条评价的粒度对齐。5. 避坑指南我跑这个项目时踩过的五个典型坑5.1 数据库连接失败Access denied for user rootlocalhost现象Tomcat启动没有任何异常浏览器输入地址后页面直接报500控制台提示Access denied for user rootlocalhost (using password: YES)。原因jdbc.properties里的jdbc.username或jdbc.password和你本机MySQL不一致。很多人拿到源码后只改了jdbc.url里的库名账号密码还是提供者本机的。解决优先检查properties配置文件里的用户名密码确认能直接用命令行登录MySQLmysql -u root -p能登录成功说明MySQL侧没问题剩下的就是在配置文件里把信息对准。5.2 MySQL 8.0时区报错Server time zone value现象用MySQL 8.0建库导入SQL后启动控制台报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized后面还有SSL connection error。原因MySQL 8.0的JDBC驱动对时区要求更严项目里默认的com.mysql.jdbc.Driver在8.0驱动里要求显式指定时区。解决两步走。第一步把jdbc.driver改成com.mysql.cj.jdbc.Driver第二步在jdbc.url末尾加上?serverTimezoneAsia/ShanghaiuseSSLfalse。改完重启Tomcat即可。5.3 Tomcat端口被占用Port 8080 already in use现象启动Tomcat直接弹窗报Port 8080 required by Tomcat v8.5 Server at localhost is already in useIDEA控制台无法启动容器。原因系统里已经有另一个Java进程占了8080端口常见的是装了别的Tomcat、IDEA残留进程、其他开发服务器。解决Windows系统在命令行执行netstat -ano | findstr 8080找到PID再taskkill /PID 对应PID /F杀掉或者直接改IDEA里Tomcat配置的端口为8081、8082不过改端口会同时影响浏览器访问地址摘要定义的8080会失效我的习惯是保留8080杀掉占用进程。5.4 页面中文乱码考试题目全是问号现象登录页面正常但进入考试页面后题目和选项里的中文全部显示为???英文和数字正常。原因三层编码不统一。数据库连接串里没设置characterEncodingutf8JSP页面没声明charsetUTF-8或MySQL建库时字符集选成了latin1。解决检查按顺序排查——库的字符集改成utf8全库统一、jdbc.url里追加useUnicodetruecharacterEncodingutf8、JSP页面头部确保有contentTypetext/html; charsetUTF-8。三处一起改齐重启Tomcat后问题消失。5.5 静态资源404登录页能打开但CSS和JS全部失效现象登录页面是纯HTML文字样式全丢控制台一堆Failed to load resource: 404指向CSS和JS文件。原因Artifact配置错了站点根路径导致浏览器请求的CSS路径指向了不存在的位置。IDEA里Artifact名字通常带着_war_explodedApplication context如果不是/静态资源的绝对路径全部会偏。解决把Tomcat Deployment里的Application context改成/exam然后在login.jsp里用EL表达式${pageContext.request.contextPath}拼接资源路径比如${pageContext.request.contextPath}/css/style.css而不是写死/css/style.css。这样项目放到任意上下文路径下都能正确加载静态资源。6. 让它更好用两个值得动手改的小优化6.1 把密码从明文存储改成MD5加密这套系统的三个账号密码全是123这样的明文安全上其实没有任何防护能力。要做的是在数据库里把密码列改成MD5摘要值登录校验时用DigestUtils.md5Hex(input)对比。常见做法是在Service层登录逻辑处加一个工具类调用// 登录时对输入密码做MD5再比对避免明文密码直接进数据库 String md5Password DigestUtils.md5Hex(password).toUpperCase(); AdminEntity admin adminMapper.selectByUsernameAndPassword(username, md5Password);改完重启Tomcat后原来数据库里的明文密码全部失效需要先用MD5生成新摘要再UPDATE回数据库。这样处理不算最强的安全方案但至少不再是裸奔状态写在课程设计的文档里也是加分项。6.2 做一次完整的交叉验证三个账号三种入口全跑一遍拿到这个项目后我的习惯是做一次「全角色流程穿越」验证而不仅仅是登录成功就收工。完整流程是学生zkd先参加一门课程的考试、提交答案、查成绩老师dzk登录后看是否能看到该学生的分数记录并给出评价管理员daima登录后在成绩总览页确认数据条目数量和分数明细对得上。这个三方交叉验证的意义在于一旦某一环断掉出问题的模块第一时间就能定位——是成绩表没写入、还是课程索引没关联、或是Controller跳转逻辑有误。每次拆这种带源码的Java Web项目我都会强制走一遍「建库 → 导数据 → 改配置 → 启动 → 三方角色全跑一遍」的流程。密码加密这个改动也是第一步就做哪怕只是把明文换成MD5也算给这份源码又一个值得展示的亮点。这套传统Java Web在线考试系统的架构逻辑无论用于课设演示还是学习参考都是够格的希望帮到你。本文还有配套的精品资源点击获取
返回列表