基于Servlet、JSP技术的学生在线考试系统

基于Servlet、JSP技术的学生在线考试系统

我们一路前行,不是为了能改变世界,而是为了不让世界改变我们!

一、引言

随着网络技术的发展,教育和学习的方式也在不断地改变。在线考试系统是一种利用网络技术实现的无纸化考试系统,可以大大提高考试效率,降低考试成本,同时也可以提高考试的公正性和公平性。本文将对在线考试系统的需求进行分析,以期为在线考试系统的设计和实现提供参考。

二、相关技术

本系统使用MVC架构模式,持久化层使用JDBC技术,前端页面主要使用JSP、AJAX、JavaScript等技术实现,为了界面更加美观,使用了lay-ui前端框架的一些组件如页面布局、按钮、表格等。控制层使用Servlet技术。

三、系统需求分析

整个系统主要面向两类用户设计:学生和教师。
其中教师的主要功能模块包括:题库管理模块,主要负责对题库进行增删改查等操作,确保题库中题目能得到实时更新,方便教师进行查阅;试卷生成与发布模块,该模块主要用于帮助教师快速创建试卷,教师可以的从题库中选择需要的题目,并将其添加到指定试卷中,此外还提供了一键发布功能,系统会显示还未发布的试卷,教师可以一键发布试卷,发布试卷后,系统将通过选课记录自动匹配需要参加考试的考生,考生也可以看到待考试信息,实现了教师端和学生端的同步。学生成绩管理模块,该模块主要用于协助教师完成学生成绩的录入。考虑到目前大多数高校采用过程化考核方式对学生进行成绩认定,该模块还实现了供教师修改平时成绩在总评成绩的占比。此外,如果考试类型是期末考试,学生考试完毕后,该模块支持自动提交学生的期末成绩,只需要教师录入平时成绩即可自动计算学生的总评成绩,减轻了教师的工作量。
对于学生而言,学生的主要模块包括查看考试信息模块,该模块负责向学生展示考试信息,包括考试科目、时间、考试时长等。考试模块,考试模块主要负责向学生展示试卷中的试题并存储学生的作答记录,收到学生作答记录后,该模块还会负责计算学生的考试成绩,提交给相应教师供教师进行学生成绩分析。查看成绩模块,当考试结束,且教师将学生成绩录入完毕后,学生即可查看自己的成绩信息。

四、开发运行环境

(1)开发终端:LAPTOP-V3D33N24(64位)
(2)开发工具:IntelliJ IDEA 2022.1.2,Navicat Premium 16
(3)JDK版本:1.8
(4)数据库: 8.0.26 MySQL Community Server - GPL
(5)服务器:apache-Tomcat 8.0.50
(6)操作系统:Windows10

五、核心模块的实现

1. 登录模块与题库管理模块

//***************View: QuestionManageTable.jsp
<table class="layui-table" lay-even>
        <tr>
            <th>编号</th><th>学科</th><th>命题人</th><th>类型</th><th>题目</th>
            <th>A</th><th>B</th><th>C</th><th>D</th><th>E</th><th>答案</th> <th>操作</th>
        </tr>
        <c:forEach items="${questions}" var="question">
            <tr><td>${question.questionNumber}</td>//...
                 <td>${question.correctAnswer}</td>
                 <td><div class="layui-btn-group">
                        <button type="button"  data-type="editbut"><a                            href="${pageContext.request.contextPath}/teacher.editQuestion?qid=${question.questionNumber}"></a></i>
                     </div></td></tr>
        </c:forEach>
    </table>
var qid = $(this).find('a').attr('href');//筛选用户点击动态绑定的url
$.ajax({//发送ajax请求到后端
    type: 'get',//get post 请求类型
    url: qid.toString(),//通讯地址
    dataType: "text",//服务器传回来的数据text json
    success: function (res) {
        if (res == "success") {
            alert("删除成功!")
       window.location.href='${pageContext.request.contextPath}/teacher.questionManage'
        } else {
            alert("删除失败!")
        }}})
//***************Controller:TeacherServlet
case "/teacher.questionManage": {
    String qType = request.getParameter("type");
    String qSubject = request.getParameter("subject");
    ArrayList<Question> questions = questionService.queryQuestion(qType, qSubject);
    session.setAttribute("questions", questions);
    response.sendRedirect("/exam/tView/QuestionManageTable.jsp");//重定向
}
break;
//***************pojo:Question
public class Question {
    private Integer questionNumber;
    private String subject;
    private String type;
    private String author;
    private String question;
    private String optionA;
    private String optionB;
    private String optionC;
    private String optionD;
    private String optionE;
    private String correctAnswer;
}
//***************DAO:QuestionDaoImpl
public class QuestionDaoImpl implements QuestionDao {
    @Override
    public int addQuestion(Question q) {
        int i = 0;
        try {
            i = JDBCUtils.updateDate("insert into 题库(考察科目, 题目类型, 命题人, 题目, A, B, C, D, E, 正确答案)" +"values(?,?,?,?,?,?,?,?,?,?)", q.getSubject(), q.getType(), q.getAuthor(),
 q.getQuestion(), q.getOptionA(), q.getOptionB(), q.getOptionC(), q.getOptionD(), q.getOptionE(), q.getCorrectAnswer());
	return i; }
    public int updateQuestion(Question q, Integer id)//...

关键代码实现说明:为题库增删改按钮绑定事件,当点击按钮时会发送请求调用后端Controller中的相关方法,Controller间接调用调用DAO中的方法,将数据同步到数据库中。对题库的增删改查功能均已实现。

实际界面
登录界面
登录界面
题库管理界面
题库管理界面

2. 试卷生成与发布模块

//***************View: QuestionManageTable.jsp
<tr>
    <th>编号</th><th>试卷名称</th><th>考试科目</th><th>课号</th><th>组卷老师</th> <th>组卷时间</th>
    <th>开考时间</th><th>考试时长</th><th>满分</th><th>试卷类型</th> <th>试卷状态</th><th>操作</th>
</tr>
<c:forEach items="${paperInfos}" var="paper">
    <tr>
        <td>${paper.paperId}</td>
        //...此处代码省略
        <td>${paper.paperState}</td>
<td><a href="${pageContext.request.contextPath}/teacher.editPaper?paperId=${paper.paperId}"></a></i
</td>
</c:forEach>
//***************Controller:TeacherServlet
case "/teacher.delPaper": {//以删除试卷为例
    String paperId = request.getParameter("paperId");
    int i = paperService.deletePaperByPid(Integer.valueOf(paperId));
    if (i == 1) {
        response.getWriter().write("success");
    } else {
        response.getWriter().write("false");
    }
}
//***************pojo:
public class PaperInfo {
    private Integer paperId;
    private String paperName;
    private String examSubject;
    private String cno;
    private String tName;
    private Date paperFormationDate;
    private Timestamp examStartTime;
    private Time examContinue;
    private Integer examFullCredit;
    private String paperState;}
//***************DAO:QuestionDaoImpl
 public int deletePaperByPid(Integer pid) {
        return  JDBCUtils.updateDate("delete from 试卷 where 试卷编号 = ?",pid);
    }
}

关键代码实现说明:为试卷增删改按钮绑定事件,当点击按钮时会发送请求调用后端Controller中的相关方法,Controller间接调用调用DAO中的方法,将数据同步到数据库中。点击查看试卷后,会跳转到添加题库的页面,在该页面可以管理试卷上的试题,包括增删改查等功能。点击发布试卷后,选课学生即可看到试卷信息,并参与考试。上图示按钮的功能均已实现。

实际界面
试卷管理界面
试卷管理界面
试卷题目管理界面
试卷题目管理界面

3. 学生成绩管理模块

//***************View: GradeManageTable.jsp
<tr>
    <th>学年</th><th>学期</th><th>学号</th><th>姓名</th><th>课号</th><th>课名</th><th>班级</th>
    <th>考试成绩</th><th>总评成绩</th> <th>GPA</th><th>平时成绩</th><th>操作</th>
</tr>
<c:forEach items="${choiceCourseInfos}" var="choiceCourseInfo">
    <tr>
        <td>${choiceCourseInfo.academicYear}</td>
	//...此处代码省略
        <td><input type="text" placeholder="请输入" class="layui-input" value="${choiceCourseInfo.regularScore}"
                   cid="${choiceCourseInfo.courseId}" studentId="${choiceCourseInfo.studentId}"></td>
        <td>
            <button type="button" class="layui-btn" data-type="putInDataBase">录入</button>
        </td>
    </tr>
</c:forEach>
$("button[data-type='putInDataBase']").on("click", function () {
    var input = $(this).parent().parent().find("input");//jquery获取父级的父级元素下的input
    var url = "${pageContext.request.contextPath}/teacher.updatePsGrade?studentId=" +
        $(input).attr("studentId") + "&courseId=" + $(input).attr("cid") + "&psGrade=" + $(input).val();
    $.ajax({
        type: 'get',
        url: url,
        dataType: "text",
        success: function (res) {
            if (res == "success") {
                alert("录入成功!")
            } else {
                alert(("录入失败!"))
                window.location.href = "${pageContext.request.contextPath}/teacher.gradeManage"//重定向
            }
        },
        error:function (){
            alert("录入失败,平时成绩不能为NULL!")
        }
    })
})
//***************Controller:TeacherServlet
case "/teacher.updatePsGrade":{
    String studentId = request.getParameter("studentId");
    String courseId = request.getParameter("courseId");
    Integer psGrade = null;
    if(request.getParameter("psGrade")!=null) {
        psGrade = Integer.valueOf(request.getParameter("psGrade"));
    }
    int i = gradeManageService.updatePsGrade(studentId, courseId, psGrade);
    if(i>=1){
        response.getWriter().write("success");
    }else {
        response.getWriter().write("false");}}
//***************DAO:ChoiceCourseDaoImpl
@Override//查询所有学生成绩信息
public List<ChoiceCourse> getChoiceCourseByFilter(String academicYear, String semester, String classNo, String studentId, String courseId, String sName) {
    return choiceCourseDao.getChoiceCourseByFilter(academicYear,semester,classNo,studentId,courseId,sName);}
@Override//更新学生成绩信息
public int gradeManageService (String studentId, String courseId, Integer psGrade) {
    return choiceCourseDao.updatePsGrade(studentId,courseId,psGrade);
}

关键代码实现说明:教师可以修改平时成绩占总成绩的比例,底层通过调用ChoiceCourseManageService的updatePsRate方法修改,如果考试类型是期末考试,学生考试完毕后,自动将考试成绩插入考试成绩字段。教师录入平时成绩即可自动计算学生的总评成绩,底层使用数据库的触发器实现。录入平时成绩时,教师只需要输入成绩并点击录入即可调用gradeManageService方法,向数据库中添加学生成绩信息。同时系统为教师提供了多条件查询、模糊查询等功能,方便教师的使用。上述所有功能均已实现。

实际界面
修改平时成绩界面
修改平时成绩界面
学生成绩录入界面
学生成绩录入界面

4. 考试模块的实现

//***************View: Paper.jsp
<div class="container">
    <div class="question-container">
        <h1>${paperName}</h1>
        <div class="timer">
            <!-- 倒计时 -->
            考试倒计时 <span id="countdown"></span>
        </div>
        <form id="qfrom">
            <%--设置qid变量--%>
            <c:forEach items="${questions}" var="question">
                    <c:if test="${question.type=='单选题'}"> <!-- 单选题 -->
                    <div class="question" id="question${question.qIdInPaper}">
                        <h2>第${question.qIdInPaper}:</h2>
                        <p>${question.question}</p>
                        <input type="radio" name="q${question.qIdInPaper}"
                               value="A">A ${question.optionA}<br>
                        <input type="radio" name="q${question.qIdInPaper}"
                               value="B">B ${question.optionB}<br>
                        <input type="radio" name="q${question.qIdInPaper}"
                               value="C">C ${question.optionC}<br>
                        <input type="radio" name="q${question.qIdInPaper}"
                               value="D">D ${question.optionD}<br>
                    </div>
                </c:if>
                <c:if test="${question.type=='多选题'}">     //...            <%--多选题--%>
                <c:if test="${question.type=='判断题'}">     //...           <!-- 判断题 -->
	</c:forEach>
        </form>
              <c:forEach items="${questions}" var="question">
                <button onclick="goToQuestion(${question.qIdInPaper})">Q${question.qIdInPaper}</button>
            </c:forEach>
        </div>
</div>
<div class="container">
    <div class="submit-btn-container">
        <button class="submit-btn" onclick="prevQuestion()" id="left">上一题</button>
        <button class="submit-btn" onclick="nextQuestion()" id="right">下一题</button>
        <button class="submit-btn" onclick="submitExam()">交卷</button>
    </div>
</div>
//***************Controller:StudentServlet
        switch (servletPath) {
                case "/student.openThePaper": {
                               List<PaperQuestion> questions = getAllQuestionInPaperService.getAllPaperQuestionByPid(Integer.valueOf(pid));
                request.setAttribute("questions", questions);
                request.setAttribute("paperName", paperName);
                request.setAttribute("examEndTime", examEndTime);
                request.getRequestDispatcher("/sView/Paper.jsp").forward(request,response);
            }
//***************pojo:PaperQuestion
public class PaperQuestion {
    private Integer qIdInPaper;//试题在试卷上的编号
    private Integer paperId;//试卷编号
    private String type;//题目类型
    private Integer qIdInRepository;//试题在试卷上的编号
    private Integer qGrade;//题目分值
    private String subject;//科目
    private String author;//命题人
    private String question;//题目
    private String optionA;  //...  A-E选项
    //正确答案
    private String correctAnswer;
    private Map<String,String> beforeFlushOptionAnswerMap;//
//***************DAO:PaperContextDaoImpl
public List<PaperContext> showPaperContextByPid(Integer paperNumber,String type) {
    ArrayList<PaperContext> paperQuestions = new ArrayList<>();//存储试卷中的所有题目信息的集合
    String sql = "select * from 试卷题目视图 where 试卷编号=? ";
    if(type!=""&&type!=null){ sql = sql + " and 题目类型='"+ type +"'";  }
    sql +=" order by 题目类型 asc";
    Connection conn = null;
    PreparedStatement pre = null;
    ResultSet rs = null;
    	//...代码省略
            paperQuestion.setCorrectAnswer(rs.getString("正确答案"));
            paperQuestions.add(paperQuestion);
        }//...释放资源 return paperQuestions
}

关键代码实现说明:在PaperQuestion实体类中调用Collections工具类的shuffle()方法,随机刷新选项顺序。问题类中存储添加Map集合(key:选项信息,value:选项)beforeFlushOptionAnswerMap数据结构,存储刷新选项顺序前(即数据库中的选项顺序)的选项信息。学生答题后,将所选选项内容与上述Map集合做映射,映射为数据库中存储的选项。实现了不同学生的题目顺序一致而选项顺序不一致的效果。

实际界面
考试信息展示界面
考试信息展示界面
学生进入考试界面
学生进入考试界面
学生查看成绩界面
学生查看成绩界面

个人小结

虽然已经2024年了,servlet、jsp技术几乎不再被使用了,但迫于应试教育,不得不学一些过时的技术,希望路过的各位朋友分清主次,不要在这上面花费太多时间,这是我的第一篇博文,希望能给各位朋友提供帮助!
学生在线考试系统项目是对本学期所学内容的综合,它综合了servlet、jsp、html、css、js相关技术,同时项目中为了更好的与用用户交互,还用到了AJAX技术,使用传统的java script对DOM元素的筛选颇为繁琐,所以还用到了一些JQuery框架提供的一些功能函数。在开始着手做界面时,原本打算自己进行前端界面的设计,但由于成品非常难看,调节CSS样式时又非常耗时,效率极低,所以使用了layui框架提供的一些组件,如按钮、表格等,把主要精力放在后端的程序实现上。在后端程序设计上,由于之前已经做了Java SE相同题目的课程设计,所以对系统的结构有了一个初步的认识。在实现过程中,使用了MVC的架构模式,由于之前的一些课程设计代码量不大,没有意识到架构模式的重要性,但这次由于代码量较大,业务逻辑也较多,所以我深刻体会到采用架构模式的优点,例如,系统的结构更加清晰,维护起来也更加容易。关于jsp、servlet方面,这是这个学期的核心内容,学生考试系统中大量使用,此外还有session域、request域、request转发,response重定向等,在系统的实现过程中也得到了广泛应用。在编程过程中,我对这些知识点也有了更深刻的认识。

完整代码或技术交流联系邮箱:3214541099@qq.com

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
开发语言:Jsp Java 服务器: Tomcat 5.0 数据库:sql server 数据库 =================系统简介=========================== (1) 用户类别:登录系统的身份定为二种,一是管理员(普通老师),二是学生,只有被授权的用户才可以使用本系统的资源。 (2) 权限管理:系统需要经过有效的身份验证可以登录。用户的身份不同,使用的系统资源也不同。考生只可以参加在线考试;管理员(普通教师)可以在线制作试卷,进行考生管理,添加学生信息、控制考试、成绩查询、试卷管理、题库管理等。 (3) 在线考试功能:考生输入准号证号登陆系统后,选择对应的试卷可进行考试。答题完毕后,可自动交卷,系统将自动评分,考生可同时获得考试成绩。 (4) 在线制作试卷:管理员(教师)可在线制作试卷,可设定试题的类型、难易程度、分值。 (5) 控制考试功能:可设定每次的考试时间,可禁止或允许考生参加考试,同时可查看考生的考试状态。 (6) 学生管理功能:可注册新增学生用户,同时查看学生的信息,也可设定学生的考试状态:允许或禁止考试。 (7) 考生成绩查询功能:提供考生各科目成绩的详细查询。 (8) 系统管理功能:管理员只可更改登陆密码,并可以控制考生是否能登录使用本系统、查询和添加科目的功能。 (9) 题库管理功能:管理员可以在线进行题库的制作,并可查询、编辑题库的相关内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值