springmvc实战在线考试系统

springmvc实战在线考试系统,学生自主注册账号,选择自己所在班级,进行在线模拟考试。 项目主要分为用户管理,资源管理,考试管理,试卷管理,作业管理,成绩管理等几个大的模块,针对每个模块划分管理员、教室、学生三种角色,给予每个不同角色相应的页面,操作逻辑以及权限。

技术选型:

  • 前端

    • Html/Css/JavaScript

    • Bootstrap

    • jQuery

    • UploadFive

  • 后端

    • Spring/SpringMVC/Hibernate

    • Spring Security

    • slf4j/log4j

    • Gson

    • POI

    • Druid

  • 数据库

    • MySQL

本地访问地址


http://localhost:8090

管理员帐号admin, 密码admin

项目结构


项目结构.png

项目截图


  • 注册


    注册.png
  • 管理员-公告管理


    管理员-公告管理.png
  • 管理员-教师管理


    管理员-教师管理.png
  • 教师-试卷管理


    教师-试卷管理.png
  • 教师-题库管理


    教师-题库管理.png
  • 教师-作业管理


    教师-作业管理.png
  • 学生-考试


    学生-考试中.png
  • 学生-考试结果


    学生-考试结果.png
  • 学生-试题讨论


    学生-试题讨论.png
  • 学生-作业下载


    学生-作业下载.png

数据库配置:



db.driver=com.mysql.jdbc.Driver

db.url=jdbc:mysql://localhost:3306/exam?useSSL=false&characterEncoding=UTF-8

db.username=root

db.password=root123

具体实现:


1.老师角色添加试卷


//前端试卷创建

<div class="panel-body">

  <form:form action="${ctx}/exampaper/save" method="post" cssClass="form-horizontal"

    enctype="multipart/form-data" modelAttribute="entity">

    <form:hidden path="id" />

    <div class="form-group">

      <label for="name" class="col-sm-2 control-label"> 试卷名 </label>

      <div class="col-sm-4">

        <form:input cssClass="form-control" path="name"  autocomplete="off"/>

      </div>

    </div>

    <div class="form-group">

      <label for="description" class="col-sm-2 control-label">描述</label>

      <div class="col-sm-4">

        <form:textarea cssClass="form-control" path="description" />

      </div>

    </div>

    <div class="form-group">

      <label for="content" class="col-md-2 control-label">题目文件</label>

      <div class="col-md-5">

        <input name="file" type="file" accept="application/vnd.ms-excel,

          application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/>

      </div>

    </div>

    <div class="col-md-8 text-center">

      <button class="btn btn-primary" type="submit">提交</button>

      &emsp;&emsp;&emsp;&emsp;

      <a class="btn btn-warning" href="${ctx}/exampaper/list">返回</a>

    </div>

  </form:form>

</div>

//后端处理

public String save( @ModelAttribute("entity") ExamPaper examPaper, @RequestParam("file") MultipartFile file) { CallBackMessage msg;

    try {

        InputStream inputStream = file.getInputStream();

        List<Question> questions = ExcelToQuestionUtils.readQuestions(inputStream);

        inputStream.close();

        examPaper.setQuestions(questions);

        examPaper.setClassId(Integer.valueOf(CurrentUtils.getCurrentUser().getClassId()));

        return baseSave(examPaper);

    } catch (IOException e) {

        e.printStackTrace();

        msg = CallBackMessage.createDangerMsg("服务器异常,请重试!");

    } catch (EncryptedDocumentException e) {

        e.printStackTrace();

        msg = CallBackMessage.createDangerMsg("题目文档已被加密,无法识别!");

    } catch (InvalidFormatException e) {

        e.printStackTrace();

        msg = CallBackMessage.createDangerMsg("题目文档格式有误!");

    } catch (IllegalArgumentException e) {

        e.printStackTrace();

        msg = CallBackMessage.createDangerMsg(e.getMessage());

    }

    msg.addToCurrentSession();

    return redirect(LIST_PATH);

}

  1. 创建考试,与试卷绑定

//前端JSP代码

<div class="col-xs-10">

  <div class="panel panel-info">

    <div class="panel-heading">

      <h3 class="panel-title">

        <span class="glyphicon glyphicon-align-justify"></span> &nbsp;考试管理

      </h3>

    </div>

    <div class="panel-body">

      <form:form action="${ctx}/exam/save" method="post"

        cssClass="form-horizontal" modelAttribute="entity">

        <form:hidden path="id" />

        <div class="form-group">

          <label for="name" class="col-sm-2 control-label">考试名称</label>

          <div class="col-sm-4">

            <form:input cssClass="form-control" path="name" autocomplete="off" />

          </div>

        </div>

        <div class="form-group">

          <label for="description" class="col-sm-2 control-label">描述</label>

          <div class="col-sm-4">

            <form:textarea cssClass="form-control" path="description" />

          </div>

        </div>

          <div class="form-group">

              <label for="description" class="col-sm-2 control-label">截止提交日期</label>

              <div class="col-sm-4">

                  <div class='input-group date' id='datetimepicker2'>

                      <form:input cssClass="form-control" path="endTime" autocomplete="off"/>

                      <span class="input-group-addon">  <span class="glyphicon glyphicon-calendar"></span> </span>

                  </div>

              </div>

          </div>

        <div class="form-group">

          <label for="description" class="col-sm-2 control-label">考试时间(分钟)</label>

          <div class="col-sm-4">

            <form:input cssClass="form-control" path="time" type="number" min="0" autocomplete="off"  />

          </div>

        </div>

        <div class="form-group">

          <label for="description" class="col-sm-2 control-label">考试试卷</label>

          <div class="col-sm-4">

            <form:select path="exampaperId" cssClass="form-control"

              items="${exampapers}" itemLabel="name" itemValue="id" />

          </div>

        </div>

        <div class="col-md-8 text-center">

          <button class="btn btn-primary" type="submit">提交</button>

          &emsp;&emsp;&emsp;&emsp;

          <a class="btn btn-warning" href="${ctx}/exam/list">返回</a>

        </div>

      </form:form>

    </div>

  </div>

</div>

//后端入库处理

public String save( @RequestParam("exampaperId") Long exampaperId,@ModelAttribute(ENTITY_ATTRIBUTE_NAME) Exam entity) {

    ExamPaper examPaper = exampaperService.findByID(exampaperId);

    examPaper.setClassId(Integer.valueOf(CurrentUtils.getCurrentUser().getClassId()));

    entity.setExampaper(examPaper);

    entity.setClassId(Integer.valueOf(CurrentUtils.getCurrentUser().getClassId()));

    return baseSave(entity);

}

  1. 试卷题目

<div class="panel-body">

    <form:form action="${ctx}/question/save" method="post"

              cssClass="form-horizontal" modelAttribute="entity">

        <form:hidden path="id"/>

        <div class="form-group">

            <label for="type" class="col-md-2 control-label">题目类型</label>

            <div class="col-md-5">

                <form:select cssClass="form-control" path="type" disabled="true">

                    <form:option value="判断"/>

                    <form:option value="单选"/>

                    <form:option value="多选"/>

                </form:select>

            </div>

        </div>

        <div class="form-group">

            <label for="content" class="col-md-2 control-label">题干</label>

            <div class="col-md-5">

                <form:textarea cssClass="form-control" path="content" disabled="true"/>

            </div>

        </div>

        <c:forEach items="${entity.choices}" var="choice" varStatus="st">

            <div class="form-group _oldChoice">

                <input type="hidden" name="choices[${st.index}].id" value="${choice.id}"/>

                <label class="col-md-2 control-label">选项</label>

                <div class="col-md-5">

      <textarea name="choices[${st.index}].content" class="form-control" readonly><c:out value="${choice.content}" />

      </textarea>

                </div>

                <div class="col-md-2">

                    <label class="control-label">是否为正确选项</label>

                    <input type="checkbox" name="choices[${st.index}].answer"

                        ${choice.answer == true ? 'checked="checked"' : ''} disabled="true"/>

                </div>

            </div>

        </c:forEach>

        <div id="newChoiceDiv"></div>

        <div id="choiceAnswerDiv"></div>

        <div class="form-group">

            <label for="content" class="col-md-2 control-label">所属试卷</label>

            <div class="col-md-5">

                <form:checkboxes path="exampaperIds" delimiter="<br/>"

                                items="${exampapers}" itemLabel="name" itemValue="id" disabled="true"/>

            </div>

        </div>

        <div class="col-md-9 text-center"><hr/>

            <a class="btn btn-warning" href="${ctx}/question/list">返回</a>

        </div>

    </form:form>

</div>

  1. 学生考试作答

//前端jsp代码

<div class="container">

<div class="row">

    <!-- 题目导航 -->

    <div class="col-md-3" id="question-nav">

        <div class="panel panel-info">

            <div class="panel-heading">

                <h3 class="panel-title">

                    <span class="glyphicon glyphicon-th-list"></span>&nbsp;题目导航

                </h3>

            </div>

            <div class="panel-body row">

                <c:forEach items="${entity.exampaper.questions}" var="question" varStatus="st">

                    <div class="col-md-3 text-center" style="margin-bottom: 10px;">

                        <a class="btn btn-default btn-xs" href="#question-${question.id}">${st.count}</a>

                    </div>

                </c:forEach>

                <div class="row">

                    <div class="col-md-12 text-center">

                        <h4>剩余时间</h4>

                        <h4 id="left_time">${entity.time}分钟0秒</h4>

                    </div>

                </div>

            </div>

        </div>

    </div>

    <!-- 题目 -->

    <div class="col-md-9">

        <div class="panel panel-info">

            <div class="panel-heading">

                <h3 class="panel-title">

                    <span class="glyphicon glyphicon-th-list"></span>&nbsp;${entity.name}

                </h3>

            </div>

            <!-- 答题div -->

            <div class="panel-body" style="font-size:18px;">

                <form action="${ctx}/exam/subExam" method="post">

                    <input type="hidden" name="examId" value="${entity.id}"/>

                    <c:forEach items="${entity.exampaper.questions}" var="question" varStatus="st">

                        <c:if test="${question.id!=null}">

                            <c:if test="${st.index==0}">

                                <c:if test="${not empty list}">

                                    <div class="panel panel-primary">

                                        <div class="panel-heading">

                                            <h3 class="panel-title">简答题试卷</h3>

                                        </div>

                                        <div class="panel-body" style="font-size: 16px;">

                                            <p class="well">请自行下载简答试卷,答卷完成请及时上传</p>

                                            <p>

                                                <a class="btn btn-success pull-right _download" onclick="_download(${list[0].id});" >点击下载</a>

                                            </p>

                                        </div>

                                    </div>

                                </c:if>

                            </c:if>

                        </c:if>

                        <input type="hidden" name="questionIds[${st.index}]" value="${question.id}"/>

                        <div class="panel panel-default" id="question-${question.id}">

                            <div class="panel-heading">

                                <h3 class="panel-title">${question.type}题</h3>

                            </div>

                            <div class="panel-body _chooseDiv"

                                data-question-type="${question.type == '多选' ? 'checkbox' : 'radio'}">

                                <p>${st.count}.&nbsp;${question.content}</p>

                                <c:forEach items="${question.choices}" var="choice" varStatus="innerSt">

                                    <div class="checkbox">

                                        <label>

                                            <input type="checkbox" value="${choice.id}"

                                                  name="chooses[${st.index}][${innerSt.index}]"/>

                                                ${int2char[innerSt.index]}.&nbsp;${choice.content}

                                        </label>

                                    </div>

                                </c:forEach>

                            </div>

                        </div>

                    </c:forEach>

                    <div class="col-md-9 text-center">

                        <hr/>

                        <button class="btn btn-primary" type="submit" id="submitButton">提交</button>

                        &emsp;&emsp;&emsp;&emsp;

                        <a class="btn btn-warning" href="${ctx}/exam/show">返回</a>

                    </div>

                </form>

            </div>

        </div>

    </div>

</div>

  1. 学生成绩查询

<div class="container">

<div class="row">

  <div class="col-md-offset-1 col-md-10">

    <div class="panel panel-info">

      <div class="panel-heading">

        <h3 class="panel-title">

          <span class="glyphicon glyphicon-th-list"></span>&nbsp;我的成绩

        </h3>

      </div>

      <div class="panel-body">

        <%@include file="/common/show-message.jsp"%>

        <table class="table table-bordered">

          <tr>

            <th>考试名称</th>

            <th>考试试卷</th>

            <th>考试日期</th>

            <th>成绩</th>

          </tr>

          <c:forEach items="${entities}" var="result">

            <tr>

              <td><c:out value="${result.exam.name}" /></td>

              <td><c:out value="${result.exam.exampaper.name}" /></td>

                <td><fmt:formatDate type="date"  value="${result.sysModifyLog.createDate}" /></td>

              <td><c:out value="${result.grade}" /></td>

            </tr>

          </c:forEach>

        </table>

      </div>

    </div>

  </div>

</div>

</div>

操作流程


  1. admin用户创建老师角色并绑定所属班级

  2. 老师角色登录管理后台,上传题库并创建试卷

  3. 将创建的试卷进行考试绑定,明确告知学生考试是具体那一试卷

  4. 学生自行注册并选中所属班级,注册登录后能看到自己所属班级是有考试

  5. 进行考试作答并提交,等待批改

  6. 查看错题及成绩

  7. 额外还有课件下载及作业和公告查看功能

项目后续

其他ssh,ssm,springboot版本后续迭代更新,请持续关注

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容