在我们以往的考试经历中,我们可以看到,每次考试都需要经过出试卷、印试卷、发卷、做卷、收卷、阅卷、统计等过程,这几个过程有着很强的先后次序,不能顺序颠倒。这些过程中,又以出卷、阅卷和统计最为复杂,当一次考试涉及的人数众多时,老师需要批阅非常多的卷子,重复的批阅卷子浪费了大量的时间,此外,不仅效率底下,同时大量的阅卷工作也让老师疲于应付,最后导致阅卷的准确率下降。即便阅卷完成之后,工作还没结束,还需要对这些卷子进行分数登记、成绩统计以及对各个题目进行错误率统计,这些工作消耗时间非常多,因此效率也是非常低的。此外,从学生角度出发,每次做卷都要准备笔和草稿纸,麻烦且不符合环保的要求,从老师的角度出发,如果能够减少出卷、阅卷和统计的时间,那么可以腾出更多的时间用在其他的地方。因此本文基于JavaWeb技术希望开发一套网络考试系统来解决出卷、阅卷、统计花费时间过多的问题,同时为学校教务信息化作出一份贡献。
网络考试系统主要用于实现高校在线考试,基本功能包括:自动组卷、试卷发布、试卷批阅、试卷成绩统计等。本系统结构如下:
(1)学生端:
登录模块:登录功能;
网络考试模块:可参加考试,并查看考试结果,提交试卷后老师允许的情况下查看错题;
(2)超级管理员端:
登录模块:实现管理员登录功能;
用户管理模块:实现用户信息的增加、修改、查看功能;
角色权限管理模块:实现角色的增加、修改、查看功能;
试卷管理模块:实现试卷信息的增加、修改、查看功能;
试题管理模块:实现试题信息的增加、修改、查看功能;
(3)试题管理员端(老师):
试卷管理模块:实现试卷信息的增加、修改、查看功能;
试题管理模块:实现试题信息的增加、修改、查看功能;
本网络考试系统运用了很多的开发工具以及以java为基础的开发语言,在后台的代码编写中主要运用了Java、J2EE;前台的设计中运用了JavaScript、JQuery、css等一些开发语言;通过eclipse来编写这些程序;用mysql进行数据库的设计与分析;另外该网络考试系统的部署容器为tomcat,当需要进行考试时,只需要配置tomcat服务器,便可进行考试。
MyEclipse是一种有集成效果的开发工具。在Eclipse的基础上进行插件的集成,最终形成功能强大的开发软件。目前主要用于JAVA,JAVAEE的开发,也可以用于移动应用的开发,其主要特点是功能强大,应用广泛,并且支持很多开源的产品,应用前景非常广发。
MyEclipse是由Eclipse通过对插件的集成而来,是对IDE的拓展,可以用来开发网页等应用,可以实现程序的开发,调试,发布等,能极大的提高开发效率,能完美支持HTML、STRUTS等,可以说集成后的MyEclipse包含了当前所有主流的开源产品。MyEclpise也经历了很多代的产品,从最开始的到后来的2014版本,2015版本等都说明了它在发展历程中的变化。
MyEclipse的配置使用也非常智能,不需要使用者懂太多的知识,只需要在自己使用的功能中进行了解即可,在完成项目开发之后,也可以直接通过MyEclipse进行项目部署,可以将网页项目进行选中,直接运行在Tomcat中,也可以将项目打包通过导出功能将项目全部导出,然后将项目发布到tomcat中,通过对配置文件的设置,完成布置,布置完项目以后可以在浏览器中进行查看。可以说,有了MyEclipse之后,基本就能支持所有的web开发,就能使用快捷的编译工具进行快速的开发,也能在各种各样的服务器上进行代码测试。在其他方面,MyEclispe也有很多的开发前景,比如在云开发领域,在移动端开发领域,在企业级开发领域等等,因此,MyEclipse的应用场景非常的广泛。
JSP(Java Script Pages)是由Sun公司建立的一种动态网页技术,它是建立在HTML文件基础上的。在传统的网页HTML文件(.htm,.html)中加入Java程序。
首先JSP是跨平台的,因为Java就是可移植跨平台的,而JSP技术是建立在Java平台之上,所以使用JSP开发的Web应用也是跨平台的。
JSP页面不仅可以使用普通网页一样使用标准标记语言的元素(如HTML标记)以外,还可以使用其独有的JSP标记。JSP可以直接向数据库中获取或写入数据,所以通过JSP,我们可以在网页中加入更多动态内容。
JSP有如下优点:
(1)一次编写,到处运行。除了系统之外,代码不用做任何更改。
(2)JSP具有多平台支持。可以在任意平台上的任意环境中开发,在任意环境中进行系统的部署和扩展。相比JSP的多平台支持相比ASP/.net的局限性是显而易见的。
(3)具有可伸缩性。不论是只有一个小的Jar文件就可以运行的Servlet/JSP,还是由多台服务器进行集群和负载均衡,亦或者由多台Application来事务处理,Java显示了其广阔的应用范围和巨大的生命力。
(4)功能强大的多样化的开发工具支持。Java已经有了许多非常优秀的开发工具,其中大部分可以免费得到,并且其中大多都能运行在多平台下。
选取JSP的原因
JSP通过其独有的标签库,使静态HTML网页技术向动态网页技术完善。通过其在网络编程中的使用,可以利用嵌入Java代码使其充分利用Java语言的上手容易,跨平台,运行效率高等优点。具备一定程序设计的基本知识,学习JSP也十分容易。
首先JSP是一种动态网页编程语言,再加上JSP具有跨平台、运行效率高、易学易用等特点和优势,做简单界面比较容易,故选用JSP来实现网络考试系统。
Tomcat 服务器是Apache组织的一个开源子项目。具备基本的web服务的功能,是中小型系统首选的服务器,更是开发和调试JSP 程序的首选。因为Tomcat 技术不仅免费而且性能稳定,我们在本科阶段的很多web项目中也多为使用Tomcat作为服务器,其也成为目前比较流行使用的Web 应用服务器。
如果配置正确,Tomcat 服务器实际上在运行JSP 页面和Servlet容器。此外,Tomcat和其他Web服务器一样,都具有基于处理HTML页面的功能,另外它还是一个Servlet和JSP容器。独立的Servlet容器是Tomcat服务器的默认模式。目前Tomcat服务器最新版本为8.0.0,本次课设我使用的也是Tomcat8。
此外,Tomcat 服务器运行时占用的系统资源较小,可扩展性良好,支持邮件服务和负载平衡等开发应用系统常用的功能。因此利用Tomcat服务器作为网络考试系统的Web应用服务器。
系统功能的划分方式可以分成很多种类,前面是按照功能模块进行划分,将系统分成三个模块,本章节依据网络考试系统的系统角色不同,可以分成用户端和管理员端。用户端包括:登录功能、学生答题、答题得分以及考完试之后的错题解析。管理员端包括:登录功能、系统功能管理、用户管理、角色管理、题目管理、试卷管理。下面本节主要对各个基本的功能进行一个简介。(此处没有对试题管理员进行详细介绍,因为管理员的题目管理跟试卷管理的功能就是他的功能)
登录功能是一个系统的重要组成部分,也是一个系统重要的门户功能,登录功能主要实现了使用者对系统的登录,在本文所设计的体系中,登录主要分成了两种身份:学生用户和管理员。两种身份登陆,能细分系统的功能模块,实现更加方便的操作和管理。
系统答题模块是本系统的一个重要功能,可以实现让用户的答题操作。系统答题功能主要是学生用户登录以后操作的,学生用户在输入正确的用户名和密码以后能开始系统答题,系统答题的题目均来自数据库。
答题得分功能实现了学生用户在答题结束以后对自己得分情况的查看,该功能就实现了登录系统的学生用户在完成自己的试卷以后,点击体提交就能看到自己的得分,因此该功能是一个展示性质的功辅助能。
错题解析功能是系统答题功能的一个辅助或者说优化的功能,只有学生用户在登录系统完成答题以后在老师允许的情况下才能进行该功能的操作,学生答题可能存在一定的错误,对错误题目的查看成为考试系统的子功能。因此本文所设计的错题解析功能,能让学生迅速发现正确或者错误题目,以及解析过程。这样方便自学和改进。学生功能结构图,如下图所示:
系统功能管理主要实现了对系统的其他功能进行管理,主要包括对新功能的添加和编辑,对现有功能的添加和修改,同时能对现有的功能进行子功能的编辑和修改,修改后的功能可以在系统中被查看。
用户管理是一个系统的重要功能之一,对用户的管理可以实现对系统使用者的了解和查看,能让使用者更加方便的使用本系统,用户的种类分为多种,本文主要体现在学生用户和管理者两种用户上面,可以对用户的信息进行添加修改等。
角色管理主要是针对用户来设计的,不同的用户拥有不同的权力。换句话说就是操作的权限是不同的。学生账号只能进行答题等行为,而不能进行后台的管理员操作。管理员账号也拥有不一样的权利。这些权力体现在对账号的操作,试卷和题目的管理上,因此对权限的管理能很好的控制系统用户的行为,有利于系统更加稳定的运行。
题目管理主要是针对管理员的功能,该功能面向系统中试卷所使用的题目库,在本系统中,管理员能通过对题目的添加和修改对题目进行管理,可以查看现有的题目,同时也能对新的题目进行添加,为试卷的生成提供更多题目的选择。
试卷管理是本系统的核心功能,主要实现的是对学生用户考试答题的试卷进行管理,通过系统随机抽取的题目自动生成试卷并且能将试卷存入数据库,供学生考试时进行选择。管理员功能结构图,如下图所示:
字段名 | 数据类型 | 长 度 | 字段含义 | 是否主键 | 是否外键 |
---|---|---|---|---|---|
userid | INTEGER | 11 | 用户ID | 是 | |
roleid | INTEGER | 11 | 角色id | 是 | |
username | VARCHAR | 20 | 用户账户名 | ||
userpwd | VARCHAR | 20 | 用户密码 | ||
usertruename | VARCHAR | 30 | 真实姓名 |
用户id:每一个登陆的用户都有一个特有的编号; 角色id:学生、超级管理员、试题管理员,三个角色分别对应一个编号; 账号:登录时需要用到的; 密码:密码对应相应的账号; 姓名:用户的真实姓名; 状态:1为正常,0为禁用。
字段名 | 数据类型 | 长度 | 字段含义 | 是否主键 | 是否外键 |
---|---|---|---|---|---|
roleid | INTEGER | 11 | 角色id | 是 | |
rolename | VARCHAR | 20 | 角色名 | ||
rolestate | INTEGER | 11 | 角色状态 |
角色id:学生、超级管理员、试题管理员,三个角色分别对应一个编号; 角色名:学生、超级管理员、试题管理员; 角色状态:1为正常,0为禁用。
字段名 | 数据类型 | 长度 | 字段含义 | 是否主键 | 是否外键 |
---|---|---|---|---|---|
funid | INTEGER | 11 | 功能ID | 是 | |
funname | VARCHAR | 20 | 功能名 | ||
funurl | VARCHAR | 200 | 功能地址 | ||
funpid | INTEGER | 11 | 顶层功能ID | ||
funstate | INTEGER | 11 | 功能状态 |
角色id:学生、超级管理员、试题管理员,三个角色分别对应一个编号; 角色名:学生、超级管理员、试题管理员; 角色状态:1为正常,0为禁用。
等表…
计时器(到时自动交卷)功能,交卷时判断试卷是否有未答题、计算得分等功能都在paper.jsp中用javascript来实现
// 交卷功能 判断是否有未答题目 function unAnswer(){ if(unanswer != 0){ layer.open({ title:'警告', content: "还有"+unanswer+"道题目未做!", icon:2, end:function(){ postAnswer(); } }); }else{ postAnswer(); } }
计算得分
function getScore(){ //var spid = n $.post({ url: basePath + 'user/studentPaper?cmd=score&userid='+'${userid}'+'&spid='+ now.getTime(), contentType: false, processData: false, success: function(res) { console.log(res) layer.open({ title:'得分', content: res, icon:1, end:function(){ location.href = basePath+'user/studentPaper?cmd=stupaper'; } }) }, error: function(res) { console.log('error'); } }) }
倒计时功能
//小于10的数字前面补0 function p(n){ return n<10?'0'+n:n; } //获取当前时间 var now=new Date(); //获取结束时间 var endDate=new Date(); //设置考试时间(单位分钟) endDate.setMinutes(now.getMinutes()+20) function getTime(){ var startDate=new Date(); var countDown=(endDate.getTime()-startDate.getTime())/1000; var h=parseInt(countDown/(60*60)%24); var m=parseInt(countDown/60%60); var s=parseInt(countDown%60); $('.time').html(p(h)+'时'+p(m)+'分'+p(s)+'秒'); if(countDown<=0){ document.getElementById('time').innerHTML='考试结束'; layer.open({ title:'警告', content: '考试时间到,试卷已经提交!', icon:5, end:function(){ unAnswer(); } }) }else{ setTimeout('getTime()',500); } } getTime()
在DAO层,利用随机函数,(设置试卷题目和插入题目数量)实现自动组卷
public Integer addpaper(Paper paper) { // TODO Auto-generated method stub String sql = "INSERT INTO paper(pname,sid) SELECT ?,sid FROM " + "subject where sstate = 1 ORDER BY rand() LIMIT ?"; Integer rtn =DBUnitHelper.executeUpdate(sql,paper.getPname(),paper.getScount()); return rtn;
5.3 数据管理
数据管理对代码与数据库之间的连接和交互起作用,数据库交互实现的代码为:
Connection conn = null; try { DbUtils.loadDriver("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/exam", "root", "123456"); } catch (SQLException e) { e.printStackTrace(); } return conn; }
完成数据库的连接,进行一些简单的数据库操作,包括增删改查等,主要代码为:
public static Integer executeUpdate(String sql,Object ...objects){ Connection conn = getConn(); QueryRunner qr = new QueryRunner(); Integer rtn = 0; try { if(objects == null){ rtn = qr.update(conn, sql); }else{ rtn = qr.update(conn, sql, objects); } } catch (Exception e) { e.printStackTrace(); }finally{ try { DbUtils.close(conn); } catch (Exception e) { e.printStackTrace(); } } return rtn; } public static Integer executeUpdate(String sql){ return executeUpdate(sql, null); } public static <T> List<T> executeQuery(String sql,Class<T> cls,Object ...objects){ Connection conn = getConn(); List<T> list = null; try{ QueryRunner rq = new QueryRunner(); if(objects == null){ list = rq.query(conn, sql,new BeanListHandler<T>(cls)); }else{ list = rq.query(conn, sql,new BeanListHandler<T>(cls),objects); } }catch(Exception e){ e.printStackTrace(); }finally{ try { DbUtils.close(conn); } catch (SQLException e) { e.printStackTrace(); } } return list; }
其中分页查找的代码为:
/** * 带分页的查询 * @param sql SQL语句 * @param map SQL参数 * @param pc 分页控制对象,需要传递参数:当前第几页(currentindex),每页显示多少行:(pagesize) * 分页控件显示多少也:showpcount * @return */ public static <T> Pager<T> execlist(String sql,PageControl pc,Class cls,String pk,Object...object){ //获取总记录数sql String sqlcount = "select count(*) as count from ("+sql+") a"; //获取具体数据的SQL语句 Integer min = (pc.getCurrentindex()-1)*pc.getPagesize(); Integer max = pc.getPagesize(); String sqllist = "select * from ("+sql+") a where a."+pk+" limit "+min+","+max; Connection conn = getConn(); Pager<T> pager = new Pager<T>(); try { QueryRunner rq = new QueryRunner(); Object count = rq.query(conn, sqlcount, new ScalarHandler<Object>("count"), object); List<T> list = executeQuery(sqllist,cls,object); //设置总记录数 Integer c = 0; if(count!=null){ c=Integer.parseInt(count.toString()); } pc.setRscount(c); pager.setList(list); pc = dealpage(pc); pager.setPagectrl(pc); DbUtils.close(conn); } catch (Exception e) { e.printStackTrace(); } return pager; }
想要项目源码的私信可以私信我。