
文章分类:APP热点新闻 发布时间:2017-11-29 原文作者:Shi Yongfeng 阅读( )
一个人的一生要经历很多种考试,在学校有课程考试,在工作中有技能考试,在社会上有例如考驾照等各种考试。随着计算机的发展,考试也开始自动化,学生通过计算机来完成考试,老师通过计算机完成出题和判卷。例如Java语言有SCJP、SCJD等认证考试,考试试题是通过网络随机提取位于美国的题库,当考生考试完毕后,将立刻显示考试成绩,我们本次就来开发这样一个系统。
麻雀虽小,五脏俱全。本系统虽然不能声称多么的完善强大,但是绝对满足最基本的在线考试要求,对于软件开发的新人来说,绝对属于不可多得的干货。话说这可以本人写的用时最长的一篇文章了,真是累死宝宝了(从整理源码到写完这个,差不多一个礼拜了)!
我们会涉及的知识体系:
了解在线考试系统的基本需求
学会如何分析和设计数据库
学会如何使用Struts2+Hibernate进行开发
学会MySQL数据库的基本使用
学会使用MyEclipse进行Struts2+Hibernate整合开发
需求分析:
该系统的使用者有两种用户,分别是老师和学生。学生进入考试系统后,就是进行答题。试题应该是不固定的,要随机产生。学生提交试卷或者考试时间到后,要能够看到考试成绩,并且能够看到正确答案。
老师进入在线考试系统后,首先要做的就是录入试题,并且能够对已经录入的试题进行管理。老师还可以看到学生的考试成绩和一个班的考试成绩。
功能分析:
学生进入考试系统后,要能够完成如下功能:
从数据库中随机获取一张试卷;
进行考试,在考卷中填写自己的答案,并提交答案;
查看自己试卷的正确答案。
老师进入考试系统后,要完成的功能是比较多的,我们根据管理的内容可以分为老师管理试题模块和老师管理学生模块。
在老师管理试题模块中,要能够完成如下功能:
录入试题;
对已经录入的试题进行管理,包括查看、修改、和删除
查看已经录入的试题。
在老师管理学生模块中,要能够完成如下功能:
查询指定学生的成绩;
查询某一个班中所有学生的成绩。
系统设计:
绘制用例设计系统功能:
绘制系统流程图:
系统演示:
在线考试系统首页,登录页面:
不管是学生还是老师都要通过该登录页面进入系统。这个功能是通过一个单选按钮和一个表单来完成的。
老师登入系统后界面如下:
学生进入系统,进入答题界面:
学生答完试题,提交后可以看到考试结果:
学生点击查看答案可以看到试题正确答案:
以上,是在线考试系统的基本功能演示。接下来我们着手开发。
本系统的开发工具具体如下:
系统开发平台:MyEclipse10;
数据库管理系统软件:MySQL5.0;
运行平台:Windows;
Java 开发平台:JDK5.0以上(我怕使用的是7.0)。
本系统采用Struts2 MVC三层架构模式开发,具体技术如下:
显示层:使用Struts2标签技术开发;
控制层:使用Struts2技术开发;
模型层:使用JavaBean+Hibernate技术开发。
包的组织结构:
在编码之前,首先要将系统中可能用到的包建好,这样可以方便网站开发工作,同时还可以规范网站的整体架构。本系统的包结构图如下:
数据库分析与设计:
由于在线考试系统中的人员都是相对固定的,所以并没有注册功能。
数据库名称命名为:db_examsystem,其中包含三张表,分别用来储存老师、学生和试题信息,如图:
数据库概念设计:
本系统一共规划处3个实体,分别是老师信息实体、学生信息实体以及试题信息实体。
老师信息实体E-R图、学生信息实体E-R图、试题信息实体E-R图分别如下:
数据库逻辑结构设计:
根据设计好的各实体E-R图创建数据库的逻辑结构,数据库各表结构如下:
老师信息表:
学生信息表:
试题信息表:
创建数据库及数据表:
创建数据库db_examsystem,其SQL语句代码如下:
CREATE DATABASE `db_examsystem`
创建老师信息表tb_teacher,包含老师ID和老师登录密码两个字段。其SQL语句代码如下:
CREATE TABLE `tb_teacher` (
`teacherID` varchar(20) NOT NULL default '',
`password` varchar(20) default NULL,
PRIMARY KEY (`teacherID`)
)
创建学生信息表tb_student,包含学生ID、学生登录密码、学生名称、考试成绩和所属班级字段。其SQL语句代码如下:
CREATE TABLE `tb_student` (
`studentID` varchar(20) NOT NULL default '',
`studentName` varchar(20) default NULL,
`result` int(11) default NULL,
`sclass` varchar(20) default NULL,
PRIMARY KEY (`studentID`)
创建试题信息表tb_subject,包含试题ID、试题题试题的四个选项、试题答案和试题解析字段。其SQL语句代码如下:
CREATE TABLE `tb_subject` (
`subjectID` int(11) NOT NULL auto_increment,
`subjectTitle` varchar(255) default NULL,
`subjectOptionA` varchar(50) default NULL,
`subjectOptionB` varchar(50) default NULL,
`subjectOptionC` varchar(50) default NULL,
`subjectOptionD` varchar(50) default NULL,
`subjectAnswer` varchar(1) default NULL,
`subjectParse` text,
PRIMARY KEY (`subjectID`)
公共类设计:
在该系统中,采用的是Hibernate技术操作数据,并没有使用JDBC,所以公共类中也就不存在封装数据库操作类,而是换成了Hibernate会话工厂类。在进行数据访问时要用到三种实体类,分别是老师类、学生类和试题类。在进行试题管理时,由于试题比较多,是要用到分页技术的,所以要使用分页公共类。
由于在线考试系统使用的是Hibernate技术进行数据库操作,Hibernate需要进行数据库配置,这里我们把该配置文件也放在这里进行学习。
Hibernate配置文件:
使用Hibernate技术进行数据库操作时,需要hibernate.cfg.xml,在其中需要对数据库的基本信息进行设置,例如驱动、url、用户名和密码等。除此之外还要设置数据库方言,每种数据库的方言是不同的,具体方言串可以在Hibernate帮助文档中查询到。
Hibernate配置如下(为了保持代码格式整洁,我采用截图的方式,有需要的同学可以留言要源码):
Hibernate会话工厂类
在使用Hibernate操作数据库时,需要得到一个Session对象。通过调用Session对象的方法,才能完成数据库操作,如添加记录、删除记录等等。
Session对象可以通过调用SessionFactory的openSession方法来获得。Session对象必须是要求线程安全的,也就是说每个线程必须拥有一个独立的Session对象。如果不是这样的话,很有可能出现一个线程在进行数据库操作,而另一个线程将Session对象关闭而抛出异常的情况。
那如何才能做到线程安全呢?这时就要求SessionFactory能够根据不同的线程创建不同的Session对象。在使用MyEclipse进行Hibernate3支持操作时,会自动添加一个HibernateSessionFactory.java文件,该文件定义了一个会话工厂类。下面就来看看HibernateSessionFactory是如何实现线性安全操作的。
老师信息类:
老师信息类封装了老师的所有信息,包括老师ID和老师登录密码。老师信息类是比较简单的。
在Hibernate中,需要对实体类进行配置:
首先把包结构看一下:
老师信息类的实体类配置:
学生信息类:
学生信息类中封装了学生的全部信息,包括学生ID、学生登录密码、学生名称、考试成绩和所属班级。
同样,需要对学生信息实体类进行配置:
试题信息类:
试题信息类中封装了试题的所有信息,包括ID、试题题目、试题的四个选项、试题答案和试题解析(省略获取和设置属性的方法):
对试题信息实体类进行配置:
老师管理试题模块:
老师管理模块包括录入试题、查看试题、更新试题、删除试题和查询试题。
录入试题DAO方法:
在本次在线考试系统中,我们采用四层架构的方式来进行开发,分别是表现层、控制层、业务逻辑层和数据访问层。在实际开发中,是以反向顺序开发的,其中数据访问层仍然采用DAO的方式开发。
老师执行录入试题操作时,在数据访问层中首先要判断该试题是否已经被录入过,如果没有录入过,则执行录入操作。
(1)判断是否已经录入(SubjectDAOImpl.java中)
(2)执行录入:
执行录入就是将老师输入的各种试题信息保存到数据库中(SubjectDAOImpl.java中):
录入试题业务方法:
在四层架构中,控制层是不会直接访问数据访问层的,在Struts2+Hibernate整合开发的项目中,Action是不直接调用DAO方法的。他们之间的访问需要经过业务逻辑层。在实际项目开发中,通常要将所有的业务功能的实现都放在业务逻辑层中。
如下,调用findSubjectByTitle获取指定题目的方法,当得到的结果为null时,调用addSubject录入试题方法,从而完成录入试题的功能:
录入试题Action
在登录页面中,单机“录入”按钮后,将提交到录入试题Action中。在录入试题Action中将获取页面中的所有信息,将这些信息设置到试题对象中后,调用录入试题业务方法:
开发完该Action后,是要进行配置的,如下:
录入试题页面:
以上JSP代码比较简单,给大家直接截图为网站运行页面:
管理试题DAO方法:
当以老师的身份登录系统后,在试题管理栏目录中,单机“管理试题”超链接即可进入管理试题页面:
在管理试题页面中可以对试题进行管理,包括查看、更新、和删除,这些功能在业务上是比较相似的,所以我们放在一起来讲。
(1)查看试题:
在管理试题页面中某一道试题的后边,单机“查看”超链接就会进行查看试题操作,在数据访问层中定义了查看试题的方法。当查看试题时,最少要给出要查看试题的ID。
(2)更新试题:
在管理试题页面中试题的后边,单机“更新”超链接,就会进入更新试题页面。在更新试题页面中,会首先将远信息显示在页面中,单机“更新”按钮聚会执行更新操作。
(1)删除试题:
在管理页面中的试题后边,单机“删除”超链接,就会将该试题删除,所以要在数据访问层中创建删除方法:
管理试题业务方法:
在管理试题的业务方法中同样具有查看、更新和删除的方法,由于业务功能是比较简单的,所以业务处理方法也是比较简单的。
在这些管理试题的方法中都调用了DAO中的相应方法。
管理试题Action:
在管理试题时,具有查看、更新和删除三种操作,但是Action中不只这三种,因为更新试题时,首先要获取试题的原信息,所以还要有一个获取试题信息的Action。
(1)查看试题Action:
在查看试题Action中要首先获取要查看试题的ID信息,然后根据试题ID调用查看试题的业务方法。
在管理试题页面中,在每一道试题的后面有“查看”、“更新”和“删除”三个超链接。单机其中的“查看”超链接,就会进入查看试题页面,如下图:
(2)获取被更新试题Action:
获取被更新试题Action和查看试题Action非常相似,同样也是先获取试题ID,然后根据试题ID获取试题对象。将试题对象保存到request内置对象中,跳转到显示更新试题页面将试题信息显示到页面中。
在管理试题页面,单机“跟新”超链接,就会进入跟新试题页面,如图:
(3)更新试题Action:
在执行获取被更新试题Action成功后,会跳转到更新试题页面,当修改试题信息后,单机“更新”按钮,就会将信息发送给更新试题Action中.
在更新试题Action中,首先获取试题的所有信息,然后设置到试题对象中,最后调用更新业务方法。
配置Struts.xml:
(4)删除试题Action:
删除试题和查看试题一样,也需要获取试题ID。通过试题ID来判断是对哪一道试题进行操作。
页面如下,点击“删除”就会将该试题删除:
查询试题DAO方法:
在试题管理栏目中,单机“查询试题”超链接,就会进入查询试题页面,如图:
在查询试题页面中,可以在文本框中输入要查询试题的关键字,例如查询“计算机”相关试题,输入“计算机”字符串后,单机“查询”按钮,运行结果如图:
(1)获取查询试题的数量:
由于这里采用了分页技术,所以我们要获取查询试题的数量,通过总数量设置应该分为几页。
(2)查询试题:
获取查询试题的总数量后,就可以根据总数量获取查询的所有试题,在其中具有分页信息。
查询试题业务方法:
因为这里我们采用了分页技术,所以在查询试题业务方法中,不但要具有试题题目参数,还要分页信息参数,从而获取当前的查询结果。
查询试题Action
在查询试题Action中,要首先获取查询的试题题目和分页信息。通过这些信息调用查询试题业务方法,从而完成查询试题的功能。
老师管理学生模块:
在老师管理学生模块中,老师可以对学生的成绩进行管理,这里主要进行查询操作,其中包括对指定学生进行成绩查询和对某一班级中的所有学生进行查询。
查询学生成绩DAO方法
在查询学生成绩页面中,老师将输入学生名称。在数据访问层中,只要根据学生名称就能获取该学生的全部信息,当然其中也包括该学生的成绩信息。
查询学生成绩业务方法
在查询学生成绩Action中不会直接调用查询成绩DAO方法,而是首先调用查询学生成绩的也去方法,通过业务方法再调用DAO方法。
查询学生成绩Action
在查询学生成绩Action中,首先获取老师输入的学生名称信息,然后根据学生名称调用查询学生成绩方法,最后将查询的结果保存到request内置对象中。
在学生管理栏中,单机“通过姓名查找学生成绩”超链接,就会进入查询指定学生成绩页面:
查询班级成绩DAO方法:
在查询班级成绩页面中,老师填写班级信息后,就会查询该班级所有学生的成绩。在数据访问层中定义了查询班级成绩的DAO方法。
查询班级成绩业务方法:
查询班级成绩业务方法和查询学生成绩业务方法一样,都是非常简单的,它仅仅起到了一个转发的作用。
查询班级成绩Action:
在查询班级成绩Action中,首先获取老师输入的班级信息,然后根据班级信息调用查询班级成绩业务方法,最后将查询出来的学生集合报讯到request内置对象中。
在学生管理栏中,单机“查找某班级全部学生成绩”超链接,就会进入查询班级成绩页面,如图:
学生考试模块:
学生通过登录进入在线考试系统后,首先获取一张试卷,这时随机获取的。学生答题完毕后,能看到自己的开始成绩,同时也可以查看试题正确答案和解析。下面我们在学生考试模块中来完成这些功能。
登录系统DAO方法:
在本在线考试系统中,老师和学生都是需要登录才能进入系统,但是老师的登录不是必须的,老师可以通过后台访问页面直接进入在线考试系统。所以我们将登录功能放在学生考试模块中进行讲解。
在完成登录功能时,要通过查询数据库来判断学生输入的信息是否正确,当学生输入的编号和密码匹配时,才能正常进入在线考试系统。
登录系统业务方法:
登录功能的实现,主要是通过登录系统业务方法完成的。在登录系统牙舞方法中首先根据学生ID获取学生对象,在判断学生对象中的密码是否和输入的密码相同。从而判断是否能够正常登陆。
登陆系统Action :
在登录系统页面中,单机“登录”按钮,就会将学生编号、登录密码和角色信息提交给登录系统Action。
在登录系统Action中首先获取用户输入的登录信息,在登录系统Action中根据用户选择的角色执行不同的登录方法。
配置struts.xml:
随机获取试题DAO方法:
想要完成随机获取试题的功能,就需要在试题数据库中,随机查询出指定数量的记录。该操作通过Hibernate是很容易实现的。
随机获取试题业务方法:
随机获取试题业务方法是非常简单的,在其中只是完成一个传递功能,通过它来调用随机获取试题DAO方法。
随机获取试题Action:
学生在登录页面中输入正确的编号和登录密码后,会进行跳转从而执行随机获取试题Action。所以在随机获取的试题保存到request内置对象中。
考试试卷页面:
考试试卷页面中不但要将随机获取的试题显示在页面中,还要显示学生的姓名和考试时间。其中显示试题是比较简单的,只需要对试题集合进行遍历就可以得到试题的所有信息。
这里我们主要来看一下,如何显示考试时间,该功能是通过JavaScript技术完成的。
进入系统考试页面:
获取考试成绩业务方法:
在考试试卷页面中,学生单机“提交试卷”按钮,或者考试时间到都会将学生的答案提交,从而立刻计算出学生的成绩。因为实现该功能使用到的DAO方法,前面已经讲过,这里就不在赘述。
获取考试成绩后,还要将考试成绩更新到学生对象中,从而将学生考试成绩保存到数据库中。
获取考试成绩Action:
在考试试卷页面中进行提交答案就会将随机获取的试题ID提交给获取考试成绩Action。在考试成绩Action中,首先要获取所有试题ID的,然后调用获取考试成绩业务方法完成功能。因为我们要为学生所有的考试题目给出解析,所以要将学生所有试题保存到Session中,方便以后使用:
查看答案Action:
当执行查看答案时,和老师进行查看试题操作一样。它们之间的不同就是显示的数量不同,老师查看试题时只查看一道试题,而学生查看答案时是查看的自己考试试卷中的所有试题。
在获取考试成绩页面中,有一个“查看答案”超链接,单机该链接,就会提交到查看答案Action中。
以上就是本系统的全部介绍,能看到的代码基本是全部的源代码,当然还有部分省略的代码,特别是JSP页面基本都是省略处理。有需要的童鞋可以留下联系方式或者找我要源代码(本人QQ:1016923828,源代码和数据库我会全部打包)。
本系统难点分析:
在开发本系统之前,必须清楚地认识分层思想。一个好的应用一般都采用多层设计。Web系统的四层结构。如图:
最上一层为表现层,该层主要负责和用户进行交互,并通过调用业务逻辑层代码实现判断等操作。第二层为业务逻辑层,该层专注于实现业务逻辑功能,通过调用持久层代码来操作数据库。第三层为持久化层,该层专注于持久化操作,而不用涉及业务逻辑。第四层为数据库层,即为使用的数据库。
还有一个难点就是Struts2与Hibernate整合开发:
前面已经分析了Web开发中的四层架构,从中可以知道Struts2框架和Hibernate框架的整合重点在于业务逻辑层和DAO层。