题目 在线考试系统1、 实验目的①熟练运用JAVA 开发环境及工具、并用JAVA 语言编写程序; ②掌握面向对象的概念;③掌握系统功能模块的合理划分,并实现各模块接口的连接; ④掌握C/S 结构的编程方法; ⑤设计数据库模型。
2、 实验内容①编辑生成试题库,随机生成本次考试试题,同时提供在线评分并保存结果。
②选择ACCESS 作为后台的数据库。
3、 实验过程3.1 系统模块部分设计题库管理:用于对单个试题的增、删、改、查等基本维护,还可对题库进行数据备份和数据还原。
我们针对不同题型、不同应用范围及不同科目对试题进行维护。
试卷管理:可进行三种组卷方式的维护:随机组卷、人工组卷、综合组卷。
还可对考生的基本信息进行维护。
考试管理:对考试分配试卷,并对考试的基本信息进行维护。
相当于人工安排考试的过程评卷管理:对试卷的客观题分配评卷人,并对评卷人基本信息进行管理。
成绩管理:对每次考试的学生成绩的基本信息进行维护,并提供学生成绩的统计管理。
用户管理:对使用本系统的用户基本信息进行维护,用户多数为:系统管理员、老师、教务处人员、其他权限管理:对系统的访问权限进行管理,并对用户可进行权限的分配。
系统应该具备的基本功能 各模块需完成以下功能:在线考试系统信息管理评卷管理试卷管理题库管理成绩管理考试管理用户管理权限管理题型维护:对试题的题型进行增、删、改、查操作。
在操作之后会自动刷新主页,以使信息更新。
范围维护:对试题的应用范围进行增、删、改、查操作。
在操作之后会自动刷新主页,以使信息更新。
科目维护:对试题的科目进行增、删、改、查操作。
在操作之后会自动刷新主页,以使信息更新。
试题维护:对试题的基本信息进行增、删、改、查操作。
在操作之后会自动刷新主页,以使信息更新。
其他维护:对试题信息的批量查询,并可进行数据导出、数据备份、数据恢复。
随机组卷:用户只需对试卷题型进行设置就可组卷的方式。
人工组卷:可使用户选择试卷的题型中的试题的组卷方式。
综合组卷:是随机组卷与人工组卷的混合组卷方式,即用户对某一类型的试题可进行选择,也可对试题不进行选择。
试卷其他维护:对试卷信息的批量查询,对试题的数据备份与还原。
考试信息维护:对考试的时间、地点、监考人、考试用的试卷、试卷总分数及答卷总时间等考试的基本要素进行设置。
考生信息维护:对考试的学生的基本信息进行增、删、改、查操作,在操作之后会自动刷新主页,以使信息更新。
分配评卷人:对考试所用试卷的客观题分配评卷人,并对评卷的基本信息进行维护。
评卷人评卷:对分配试卷的评卷人可以在此进行评卷。
考生成绩维护:对考试的考生成绩信息进行统计与汇总,对有权限的人可进行成考试管理 考试信息维护 分配评卷人 评卷管理 成绩管理 评卷人评卷 考生信息维护 考生成绩维护 成绩其他维护 题库管理 试卷管理 试卷其他维护 试卷信息维护 其它 维护 试题 维护 基本 维护 综合组卷 人工组卷 随机组卷 题型维护 科目维护 范围维护绩的增、删、改、查操作。
成绩其他维护:对考生成绩信息的批量查询,并可进行数据导出、数据备份、数据恢复。
用户基本信息维护:对使用本系统的用户进行维护,而用户的权限由权限管理进行维护,并分配给用户,使用户只能访问自己拥有的权限内。
权限信息维护:对基本的权限进行维护,用户可自定义维护权限。
用户分配权限:对未分配权限的用户进行权限的分配,即对 分配权限的增、删、改、查操作。
信息基本维护:我们的信息除了有关考试的信息外,还有公告、新闻、留言信息需要我们维护,其中公告、新闻由后台有权限的人进行增、删、改、查操作,而留言是由前台的用户(学生)或游客录入的,我们要防止垃圾数据显示,即对留言有权更改等操作。
3.2系统结构图○1、本系统分为学生前台子系统和考试管理子系统,整个系统的结构图如下:3.3 数据库设计在线考试系统考生前 台后台管 理题库管理评卷管理 考试管理试卷管理成绩管理用户管理权限管理 学生登陆用户管理 权限管理 信息管理权限信息维护 用户基本信息 信息基本维护 用户分配权限试题类型表(questionType_table):其中包括了试题的类型的基本信息,如类型名称、答题方式、说明信息等字段;录入时,我们将答题方式确定为大概几种类型:填空方式,选择方式,问答方式,判断方式,综合方式。
试题范围表(questionBound_table):用于控制试题应用的范围,如同样的科目语文,在小学、初中、高中、大学都有,由此我们设定了此表,此表中有范围名称、范围说明等基本信息;所属科目表(questionSubject_table):用于录入试题相关的科目应用,它可以有不同的应用范围。
如上所述,我们只需录入一次的科目,就可方便我们在录入试题时每次都录。
各种题库表:我们采用一种类型的题存储在一个表中,由此我们会有填空题表(question_blanc_table)、单选题表(question_selectone_table)、多选题表(question_selectMany_tabel)一题多问表(question_askone_table)、一题多问表(question_askMany_table)、判断题表(question_judge_table)等试题表试卷表(exam_table):用于报存考试中试卷的基本信息,如出卷方式(有随机出卷、人工出卷、综合出卷)、试卷名称、试卷应用范围(与试题范围相对应)、试卷所属科目(与试题科目相对应)、试题标题级别、试题标题内容、试题总类型、试题个数、试题总ID等基本信息。
学生表(student_table):用于保存学生的考试的用户名及登陆密码。
成绩表(grade_table):用于存储学生的考试成绩。
评题表(appraiser_question_table):对于主观题的答案我们须要评卷人(有权限的用户)进行手工评卷,本表用来存储评卷人评卷的一些信息。
答案表(student_answer_table):用于存储学生问答题的答案,如试卷ID,学生ID及各种试题类型的答案字段。
用户表(user_table):用于保存用户的登陆的基本信息及分配的权限。
权限表(purview_table):用于存储用户组织的的权限,通过分配操作模块的权限组织权限。
4、关键代码及其分析4.1----------------ServerGui.java------------------public void actionPerformed(ActionEvent e) {if (e.getSource() == log) {// boolean b=login();String username = JOptionPane.showInputDialog(this, "请输入用户名","输入用户名", JOptionPane.QUESTION_MESSAGE).trim();String password = JOptionPane.showInputDialog(this, "请输入密码","输入密码", JOptionPane.QUESTION_MESSAGE).trim();if (username == null || password == null) {username = "temp";password = "temp";return;}adminCheck(username, password);// 验证管理员if (tf == true) {JOptionPane.showMessageDialog(thi s, "登陆成功!", "成功",RMATION_MESSAGE);toolBar1.setVisible(true);split_one.setVisible(true);} else {JOptionPane.showMessageDialog(thi s, "登陆失败!", "失败",JOptionPane.ERROR_MESSAGE);return;}} else if (e.getSource() == setCount) {userCount = JOptionPane.showInputDialog(this, "请输入本次考试的人数");inittest(); // 数据库信息初始化} else if (e.getSource() == startSer) {if (settime == true && setcount == true) {new ServerManager();serArea.append("服务器已启动\n预设考试人数为:" + userCount + "\n考试时间为:"+ timeCount + "\n");start = true;} else {JOptionPane.showMessageDialog(thi s, "你还没有设置考试信息", "警告信息",RMATION_MESSAGE);}} if (start == true){linkArea.append(ServerManager.linkShow(ServerManager.linkstatu s)+ "\n");} else {JOptionPane.showMessageDialog(thi s, "服务器还没有启动不能进行操作", "警告信息",RMATION_MESSAGE);}} else if (e.getSource() == userButton) {if (start == true){userArea.append(ServerManager.userShow(erstatu s)+ "\n");userArea.append(ServerManager.cou ntShow(ServerManager.ucount));} else {public void adminCheck(String s1, String s2)ConnectBean cb=new ConnectBean();if (!cb.openConnection()) {System.out.println("连接数据失败");System.exit(1);return;}4.2-----------------Server_login.java----------------- // 定义一个接收用户登陆的类public void run() {String s = null;try {s = in.readUTF(); // 接收考试号和密码,然后分别取出StringTokenizer st = new StringTokenizer(s, ",");if (st.hasMoreTokens()) {str1 = st.nextToken();str2 = st.nextToken();System.out.println("username :" + str1);System.out.println("password :" + str2);}} catch (IOException e) {e.printStackTrace();}// 读取数据库里的用户信息并进行验证try {ConnectBean cb = new ConnectBean();if (!cb.openConnection()) {System.out.println("连接数据失败");System.exit(1);return;}cb.createPreparedStatement("selec t flag from stuinfo where sno='"+ str1 + "'ResultSet r = cb.executeQuery();String m ="";while (r.next()) {m=r.getString("flag");}System.out.println("标识:"+m);if ( !m.equals("0") ) {out.writeUTF("用户已经完成考试,不能再考试");} else {cb.createPreparedStatement("select sname,spass from stuinfo where sno='" + str1+ "'", false);ResultSet rs = cb.executeQuery();while (rs.next()) {dbn = rs.getString("sname");dbp =rs.getString("spass");System.out.println("用户: " + str1 + " 你的用户名为:" + dbn+ ", 你的密码为:" + dbp);}// 验证用户密码,如果登录成功将登录标志设为1if(str2.equals(dbp.trim())) {out.writeUTF("用户 " + dbn + " 登陆成功");System.out.println("用户 " + dbn + " 登陆成功");out.close();String sql1 = "update stuinfo set flag = '1' where sno= '"+str1+"'";PreparedStatement ps = cb.createPreparedStatement(sql1);ps.executeUpdate();System.out.println("用户成功登录");}else {out.writeUTF("密码错误");System.out.println("登陆密码错误");out.close();}cb.close();4.3-----------------ServerManager.java----------------public ServerManager() {Thread td1 = new Thread() {public void run() {serstatus= "login thread start!\n";serShow(serstatus);ServerSocket ss1 = null;Socket you = null;int port1 = 8001;try {ss1 = new ServerSocket(port1);serstatus = "listener the port:" + port1;serShow(serstatus);} catch (IOException e) {e.printStackTrace();}while (true) {try {you = ss1.accept();} catch(IOException e) {e.printStackTrace();}if (you != null) {counter++;ucount = "现在参加考试的人数为:" + counter;countShow(ucount);if (counter < Maxcount) {userstatus= "user's IP" + you.getInetAddress()+ " connected " + port1 + "进行登陆";userShow(userstatus);// 第一个线程启动new Server_login(you).start();} else {userstatus = "user's IP" + you.getInetAddress()+ " connected " + port1 + "中断线程启动";userShow(userstatus);// 中断线程启动new Maxcounter(you);};td1.start();// 启动一个响应客户端读取试题的线程Thread td2 = new Thread("two") {public void run() {serstatus= "thread 2 start!";serShow(linkstatus);ServerSocket ss2 = null;int port2 = 8002;try {ss2 = new ServerSocket(port2);linkstatus = "listener the port:" + port2;linkShow(serstatus);} catch (IOException e) {e.printStackTrace();}while (true) {Socket you2 = null;try {you2 = ss2.accept();} catch (IOException e) {e.printStackTrace();}if (you2 != null) {userstatus ="user's IP" + you2.getInetAddress()+ " connected " + port2 + "进行读题";userShow(userstatus);newServer_readTest(you2).start();}}}};td2.start()// 启动一个接收用户答应并存储的线程Thread td3 = new Thread("three") {ServerSocket ss3 = null;int port3 = 8003;public void run() {serstatus="thread 3 start!";serShow(serstatus);try {ss3 = new ServerSocket(port3);linkstatus="listener the port:" + port3;linkShow(linkstatus);} catch (IOException e) {e.printStackTrace();}while (true) {Socket you3 = null;try {you3 = ss3.accept();} catch (IOException e) {e.printStackTrace();}if (you3 != null) {userstatus="user's IP" + you3.getInetAddress()+ " connected " + port3 + "提交答案";userShow(userstatus);// 第3个线程启动newServer_readScore(you3).start();}}}};td3.start();// 启动一个用户查询的线程Thread td4 = new Thread("four") {ServerSocket ss4 = null;int port4 = 8004;public void run() {serstatus="thread 4 start!";serShow(serstatus);try {ss4 = new ServerSocket(port4);linkstatus="listener the port:" + port4;linkShow(linkstatus);} catch (IOException e) {e.printStackTrace();}while (true) {Socket you4 = null;try {you4 = ss4.accept();} catch (IOException e) {e.printStackTrace();}if (you4 != null) {userstatus="user's IP" + you4.getInetAddress()+ " connected " + port4 + "进行查询";userShow(userstatus);4.4-------------Server_readTest.java----------------public void run() {String sql2; // 定义查询语句String dbt = "以下为试题"; // 试题String ts = null; // 接收用户发送的考试科目int tcount = 0; // 试题的数目try {// 网络连接部分out.writeUTF("你连接成功");ts = in.readUTF();System.out.println(ts);// 数据库连接部分// 查询客户端所选试题ConnectBean cb = new ConnectBean();if (!cb.openConnection()) {System.out.println("连接数据失败");System.exit(1);return;}//在数据库选题sql2 = "select * from exam where eid='" + ts + "'";cb.createPreparedStatement(sql2, false);ResultSet rs = cb.executeQuery();while (rs.next()) {dbt += "^"+"\n"+rs.getString(2) +"\t" + "\n" + rs.getString(3) +" ^";tcount++;}cb.close();System.out.println(dbt);System.out.println(tcount);out.writeUTF(Integer.toString(tco unt));out.writeUTF(dbt); // 将读到的试题返回到客户端//传送考试时间out.writeUTF(""+Timecount);out.flush();out.close();System.out.println("读取试题成功!!");} catch (SQLException e) {e.printStackTrace();System.out.println("not connect db");} catch (IOException e1) {System.out.println("not read client select!");}}4.5--------------/Server_readScore.java------------------// 定义一个接收用户答案的类,判断对错,将分数返回到用户端,并将成绩存入数据库public Server_readScore(Socket socket){// ----------------------创建网络连接----------------------------------// this.socket = socket; .........public void run() {// ------------------------- 接收用户提交的答案---------------------------//try {readkey = in.readUTF();System.out.println(readkey);} catch (IOException e1) {e1.printStackTrace();}StringTokenizer stc = new StringTokenizer(readkey, ",");if (stc.hasMoreTokens()) {// 客户传来答案的第一个字符为用户名,第二个字符为考试科目str1 = stc.nextToken().trim();System.out.println("用户为:" + str1);uno = Integer.parseInt(str1);}if (stc.hasMoreTokens()) {//第二个字符为考试科目str2 = stc.nextToken().trim();System.out.println("试题类型为:" + str2);}................//------------------------------在数据库获取正确答案-------------------------//try {ConnectBean cb = new ConnectBean();if (!cb.openConnection()) {System.out.println("连接数据失败");System.exit(1);return;}..............}// ------------------------判断分数---------------------------------//for (int i = 0; i <Integer.parseInt(str4); i++) {if(userAnswer[i].equals(crreAnswer[i])) {count += 10;}}System.out.println("用户:" + str1 + ",你的得分为:" + count);// 将分数返回到客户端try {out.writeUTF(Integer.toString(cou nt));System.out.println("将分数返回到客户端");out.flush();out.close();} catch (IOException e) {e.printStackTrace();}// ------------------------将分数存到数据库------------------------------//try {ConnectBean cb = new ConnectBean();if (!cb.openConnection()) {System.out.println("连接数据失败");System.exit(1);return;}PreparedStatement ps = cb.createPreparedStatement(subject);ps.setInt(1, count);ps.setInt(2, uno);ps.executeUpdate();System.out.println("更新成功");mit();cb.close();} catch (SQLException e) {// TODO 自动生成 catch 块System.out.println("写入数据发生错误!!!/n" + e);}}4.6-------------------------Server.java----------------------............public static void main(String args[]){new Server();.........}}4.7--------------------TestGui.java-------------------public void actionPerformed(ActionEvent e) {if (e.getSource() == callIP) { // 呼叫服务器 if (socket != null && in != null && out != null) // 消除以往的连接信息 { try { socket.close(); in.close(); out.close(); } catch (Exception ee) { } } String login = user + "," + pass; int port1 = 8001; try { // 建立网络连接 socket = new Socket(ip, port1); in = new DataInputStream(socket.getInputStream ()); out = new DataOutputStream(socket.getOutputStre am()); out.writeUTF(login); } catch (IOException ee) // 如果连接失败 { ipField.setText("呼叫失败"); stateField.setText("你呼叫没有成功"); } int port4 = 8004; try { socket = new Socket(ip, port4); in = new DataInputStream(socket.getInputStream ()); out = new DataOutputStream(socket.getOutputStre am()); out.writeUTF(user); stuinfo.setText("请求信息已发送"); } catch (IOException ee) // 如果连接失败 { ipField.setText("呼叫失败"); stateField.setText("你呼叫没有成功"); stuinfo.setText("你呼叫没有成功"); } if (socket != null) // 如果连接成功 { try { String queryInfo = in.readUTF(); // 得到查询结果 stuinfo.setText(queryInfo); out.flush(); out.close(); } catch (IOException e1) { // 出现异常 otherinfo.setText("数据传输错误");}}} else if (e.getSource() == beginExe) { // 生成试题String mgr = (String) subject.getSelectedItem();if (mgr.equals("英语")) { // 选择英语selectT("e");} else if (mgr.equals("数学")) { // 选择数学selectT("m");}stateField.setText("你已经选择了" + mgr + "试题");testinfo.setText("你已经选择了" + mgr + "试题");startTest.setEnabled(true);} else if (e.getSource() == startTest) { // 开始考试stateField.setText("考试开始,时钟计时");timeFlag = true;start();............} else if (e.getSource() == readNext) { // 读下一题目tempStr1 = keyField.getText().trim();uanswer += tempStr1 + "@";if (n <= enu-1) {System.out.println(tempStr1);stateField.setText("第" + n + "题,你选择的答案是:" + tempStr1);++n;// 显示下一题testArea.setText(tempTest[num]);++num;} ...............try {socket.close();in.close();out.close();} catch (Exception ee) {System.out.print("消除以往的连接");}try {socket = new Socket(ip, port3);in = new DataInputStream(socket.getInputStream ());out = new DataOutputStream(socket.getOutputStre am());out.writeUTF(user + "," + sub + "," + uanswer + "," + enu);stateField.setText("你已经提交完毕,请点击查看分数");testinfo.setText("你已经提交完毕,请点击查看分数");} catch (UnknownHostException e1) {stateField.setText("未找到服务器");} catch (IOException e1) {stateField.setText("数据传输出错");}timeFlag = false;lookScore.setEnabled(true);} else if (e.getSource() == lookScore) { // 查看分数public void run() {--minute;while (minute >= 0 && timeFlag) {try {sleep(1000);} catch (InterruptedException e) {System.out.println(e.getMessage() );e.printStackTrace();}second--;if (second == 0) {minute--;second = 59;}lastTimeF.setText(Integer.toStrin g(minute) + " : "+Integer.toString(second));if (minute == 0 && second == 59) {JOptionPane.showMessageDialog(nul l, "离考试结束还有1分钟,请抓紧答题!","时间提示对话框", RMATION_MESSAGE);}if (minute == 0 && second == 0) {System.exit(0);}}}public void selectT(String mgr) { tempTest = new String[100];String str1 = null, str2 = null;if (socket != null && in != null && out != null) // 消除以往的连接信息try {socket.close();in.close();out.close();} catch (Exception ee) {otherinfo.setText("消除以往的连接");}............4.8-----------------------Client.java--------------------------public void actionPerformed(ActionEvent e){if(e.getSource()==timer1){i=i+1;j=(j+2)%360;Color color=new Color((3*i)%255,(7*i)%255,(11*i)%255) ;label.setForeground(color);progress.setValue(progress.getValue() + 1);if(i>=150) {JFrame.setDefaultLookAndFeelDecor ated(true);new TestGui(); this.dispose(); timer1.stop(); timer2.stop(); } }if(e.getSource()==timer2) {if(n<12){label.setText(s.substring(0,n)); if(n==10) n=0; } n++; } }//public static void main(String args[]) {new Client();} }。