1、惠州学院计算机科学系课程设计指导书课程名称:网络通信程序设计课程设计题 目: 标准化学生评课系统 学生姓名: X X X 学 号: XXXXXXX 班 级: XXXXXXXXXXX 指导教师: X X 时 间: 2011 年 X 月 X 日 标准化学生评课系统软件报告学号: 姓名: 班级: 1、引言软件的开发背景及应用价值1.1 开发背景大学校园又有新鲜事,学生通过学校的网上评课系统给教授评分, “炒” 掉了一些老师。“网上评课”制度明晰了学生为本的观念,将教学质量的判断权放在学生手中,这无疑是有积极意义的。1.2 应用价值价值之一是,弄清了“ 谁为本 ”的问题。在教学活动中, “谁为本”似乎
2、不难理解,但在实践中往往背道而驰。理论上,学生作为教育服务的购买者,有权利对教育的质量作出要求。价值之二是, “网上评课”有机制上的保障,有比较合理的制度安排。制度的力量来源于人们对游戏规则的尊重,来源于制度安排的公平性。“网上评课”制度给了培育学生民主素养很好的实践机会。2、正文软件开发设计内容2.1 需求分析(1) 用户单击选项卡中的“学生登陆”将出现登陆界面。用户在登陆界面输入学号、姓名以及服务器的 IP,并请求服务器建立套接字连接。用户登录的目的是为了将自己的基本信息放到服务器上,以便服务器记录用户的评价结果。因此,用户和服务器建立连接后,服务器将创建一个和用户相关的一个文件,文件的名
3、字由用户的学号和姓名组成。(2) 单击选项卡中的“选择老师”将出现选择老师界面。如果用户成功登录了,即和服务器建立连接并在服务器端创建了和其相关的文件,那么,用户在该界面可以将服务器上需被评课老师的名字存放到客户端界面中的下拉式列表中,然后再在下拉列表中选择一个文件的名字提交给服务器。(3) 单击选项卡中的“开始评价”将出现评价界面。如果用户成功登录,并且用户通过“选择老师”界面选择了老师,那么用户在评价界面可以从服务器读入所选老师文件的评价内容,而且在该界面可以提交自己的评价结果给服务器、服务器将用户提交的结果存入用户登录时服务器所创建的和该用户相关的文件中。提交评价结果后,在该界面也可以查
4、询自己已经评价的结果。2.2 总体设计在设计学生评课系统时,编写了 8 个 java 源文件:Server.java,ReadTeacherFile.java,ServerThread.java,ClientWindow.java,ClientLogin.java,GetTeacherFile.java,ClientTestArea.java,JDesktop.java。其中 Server.java,ReadTeacherFile.java 和 ServerThread.java 为服务器端 java 程序编译产生所需要的类;其他的是客户端 java 程序编译产生所需要的类。除了以上 8 个
5、java 源文件所编译产生的类外,还需要 java 系统提供的一些重要的类,如 ServerSocket,Socket,和 JTabbedPane 等类。所用到的一些重要类以及之间的组合关系如下图 a 和图 b 所示:ClientWindowClientLogin JTabbedPaneClientTestAreaGetTeacherFile图 a 客户端类之间的组合关系ServerReadTestqustionServerSocket ServerThreadLinkedListSocket图 b 服务器端类之间的组合关系2.2.1 被评价老师文件(服务器端)标准化学生评课系统使用文本文件来
6、管理评价内容。即每个被评价老师为一个文本文件。文件和服务器端 java 程序存放在同一目录中。文件的编辑格式有特殊的要求,详见2.3.1 节。2.2.2 Server.java(服务器端主类)Server 类创建的对象负责响应客户请求,该类含有 main 方法,服务器从该类开始执行。Server 类的成员变量中有 4 种重要类型的对象:ServerSocket、LinkedList、Socket 和 ServerThread 对象。Server 类运行效果如图 c 所示:图 c Server 类运行效果2.2.3 ServerThread.java(服务器端)ServerThread 类是 T
7、hread 类的子类,在 Server 类中负责为请求连接的用户启动一个线程对象。2.2.4 ReadTeacherFile.java(服务器端)ReadTeacherFile 类是 ServerThread 类的重要成员之一,负责创建读取被评课老师的对象。2.2.5 ClientWindow.java(客户端主类)ClientWindow 类负责创建标准化评课系统客户端的主窗口,该类含有 main 方法,客户端java 程序从该类开始执行。ClientWindow 类的成员变量中有 4 种重要类型对象:ClientLogin、GetTeacherFile、ClientTestArea、JTa
8、bbedPane 对象。ClientWindow 类的主要成员的作用将在后面的详细设计中阐述,ClientWindow 类创建的窗口以及其中的主要成员对象如图 d 所示:图 d ClientWindow 窗口及主要的成员对象2.2.6 ClientLogin.java(客户端)ClientLogin 类创建的对象是 ClientWindow 类的重要成员之一,负责提供登陆界面。2.2.7 GetTeacherFile.java(客户端)GetTeacherFile 类创建的对象是 ClientWindow 类的重要成员之一,负责提供选择老师界面。2.2.8 ClientTestArea.jav
9、a(客户端)ClientTestArea 类创建的对象是 ClientWindow 类的重要成员之一,负责提供评价老师界面。2.2.9 JDesktop.java(客户端)JDesktop 类创建的对象是 ClientTestArea 类的重要成员之一,负责提供学生打开相关记事本,即记录学生评价的文本文件。2.3 详细设计2.3.1 老师文件的编写该评课系统没有使用数据库,而是使用文件来处理。本评课系统需按特殊的简单格式编写老师文件。具体要求如下:(1) 老师文件的第一行是 n(取决于评价内容数目)个“优秀”,“优秀”之间要有空格。(2) 每条评价内容之后必须有“此处标志”四个字。例如,“肖东
10、.txt”被评老师文件的部分内容:优秀 优秀 优秀 优秀 优秀1.上课用普通话,谈吐优秀!此处标志2.上课幽默大方,有味道!此处标志3.对学生负责任!此处标志4.合理安排上课时间。此处标志5.抛砖引玉此处标志2.3.2 Server 类1. 效果图2. 主要成员变量与方法(1) 成员变量 server 是 ServerSocket 对象,负责等待接收客户的套接请求,当客户请求套接字连接时,server 将接收用户的请求,并调用 accept()方法返回服务器端所建立的 Socket 对象 you,即建立服务器套接字和客户端套接字的连接。 you 是 Socket 对象,该对象是驻留在服务器的套
11、接字对象,由 server 调用 accept()方法所返回。 loginStudent 是 LinkedList链表对象,负责存储用户登录的基本信息。 yourAdress 是 InetAddress 对象,负责存放客户端的 IP。(2) 方法 Server()是构造方法。 Server 对象调用 StartServer(int port)方法相应客户的请求。 main 方法是程序运行的入口方法3. 代码(Server.java)import .*;import java.util.*;import java.io.*;public class ServerServerSocket serv
12、er;Socket you;LinkedList loginStudent;/链表对象,负责存储用户登录的基本信息InetAddress yourAddress;public Server()System.out.println(“我是服务器端程序,负责处理用户的连接请求“); loginStudent=new LinkedList(); public void startServer(int port)/该方法相应客户的请求while(true) tryserver=new ServerSocket(port);catch(IOException e1) System.out.println
13、(“正在监听:“); try System.out.println(“等待用户呼叫.“);you=server.accept(); /等待客户连接:接上后才能继续执行下面语句 yourAddress=you.getInetAddress();System.out.println(“客户的 IP:“+yourAddress);catch (IOException e)if(you!=null) new ServerThread(you,yourAddress,loginStudent).start(); else continue;public static void main(String a
14、rgs)Server server=new Server();server.startServer(6666); 2.3.3 ServerThread 类1. 效果图ServerThread 类驻留在服务器端,没有可显示的效果图。2. 主要成员变量与方法(1) 成员变量 loginStudent 是 LinkedList链表对象,该链表每个节点存放一个用户登录的基本信息,即负责存储 verifyMess 对象。 verifyMess 是 String 字符串,由用户登录时提交的学号、姓名和客户端 IP组成。 socket 是 Socket 对象。 readTest 是 ReadTeacherF
15、ile 对象,负责读取老师文件。 yourAddress 是 InetAddress 对象,负责存放客户端的 IP。(2) 方法 ServerThread(Socket,InetAddress,LinkedListlist)是构造方法,当使用该方法创建线程时,通过该方法的参数将 Server 类中的 you、yourAddress 和 loginStudent 对象传递给 ServerThread 类中的响应对象。 Run()方法是 ServerThread 类重写父类 Thread 的方法,给出了怎样响应用户请求的具体内容。3. 代码import java.io.*;import .*;im
16、port java.util.*;import javax.swing.JOptionPane;public class ServerThread extends ThreadLinkedList loginStudent;String verifyMess; /由用户登录时提交的学号、姓名和 IP 组成InetAddress yourAddress;Socket socket=null;DataOutputStream out=null;DataInputStream in=null;ReadTeacherFile readTest=null;File currentDir,dirStude
17、nt;boolean isLogin=false;ServerThread(Socket t,InetAddress s,LinkedList list)socket=t;yourAddress=s;loginStudent=list; currentDir=new File(System.getProperty(“user.dir“);dirStudent=new File(currentDir,“Student“);dirStudent.mkdir(); try in=new DataInputStream(socket.getInputStream();out=new DataOutpu
18、tStream(socket.getOutputStream();catch (IOException e)readTest=new ReadTeacherFile(); public void run() String s=“; while(true)try s=in.readUTF();if(s.startsWith(“学生“)verifyMess=s+“ “+yourAddress;String s0 = s.substring(2);File file=new File(dirStudent,s0+“.txt“);/存储学生信息的文件file.delete(); /删除旧的文件 byt
19、e bb=verifyMess.getBytes();if(!(file.exists() RandomAccessFile outNumber=new RandomAccessFile(file,“rw“);outNumber.write(bb);outNumber.close();if(loginStudent.contains(verifyMess)out.writeUTF(“已经成功登录了“);break; /如果已经登录过,就消灭因重新登录而创建的当前线程elseloginStudent.add(verifyMess);out.writeUTF(“成功登录!“+verifyMess)
20、;/保留首次登录时的线程,当用户突然离线时,该线程将触发 IOExceptionelse if(s.startsWith(“列出文件:“)verifyMess=s.substring(s.lastIndexOf(“:“)+1);System.out.println(verifyMess);isLogin=loginStudent.contains(verifyMess);if(isLogin) String fileName=currentDir.list(new FilenameFilter()public boolean accept(File dir,String name)return
21、 name.endsWith(“.txt“); ); for(int i=0;i0try LoginThread thread=new LoginThread(hintMess);if(!(thread.isAlive()thread=new LoginThread(hintMess);thread.makeConnection(number,name,IP);thread.start(); catch (Exception ee) hintMess.setText(“登录失败,请查证 ip 是否正确或者服务端是否已开启!“);elseJOptionPane.showMessageDialog
22、(this,“必须输入学号和姓名“,“警告“,JOptionPane.WARNING_MESSAGE); class LoginThread extends ThreadSocket socket;InetSocketAddress socketAddress;DataInputStream in; DataOutputStream out;JLabel hintMess;LoginThread(JLabel hint)hintMess=hint;public void makeConnection(String number,String name,String IP) throws IOE
23、xception InetAddress address=InetAddress.getByName(IP);socketAddress=new InetSocketAddress(address,6666);socket=new Socket();socket.connect(socketAddress);in=new DataInputStream(socket.getInputStream();out=new DataOutputStream(socket.getOutputStream();out.writeUTF(“学生“ +number+“_“+name); public void
24、 run()String s=null;while(true)trys=in.readUTF(); if(s.startsWith(“成功登录!“)String verifyMess=s.substring(s.indexOf(“!“)+1);GetTeacherFile.setVerifyMess(verifyMess);ClientTestArea.setVerifyMess(verifyMess);GetTeacherFile.setSocketAddress(socketAddress);ClientTestArea.setSocketAddress(socketAddress);hi
25、ntMess.setText(s);String tishi=“成功登录,请单击“选择老师界面“;JOptionPane.showMessageDialog(null,tishi,“操作提示“,JOptionPane.PLAIN_MESSAGE);if(socket.isClosed() return;if(s.startsWith(“已经成功登录了“)hintMess.setText(s);String tishi=“已经成功登录了,请单击“选择老师界面“;JOptionPane.showMessageDialog(null,tishi,“操作提示“,JOptionPane.PLAIN_ME
26、SSAGE);if(socket.isClosed() return;catch (Exception ee)hintMess.setText(“服务器暂时关闭了,稍后再请求连接“);return;2.3.7 GetTeacherFile 类1. 效果图2. 主要成员变量与方法(1) 成员变量 list 是 JComboBox 创建的下拉列表,用于显示从服务器得到的老师文件名字。 getTeacherFile 和 jb_submit 是 JButton 创建的对象,这两个按钮都将当前容器注册为自己的 ActionEvent 时间监视器。(2) 方法 GetTestFile()是构造方法。 ac
27、tionPerformed()方法是 GetTeacherFile 类实现的 ActionLisstener 借口中的方法。GetTeacherFile 创建的容器时 getTeacherFile 和 jb_submit 按钮的 ActionEvent 时间监视器,当用户单击 getTeacherFile 或 jb_submit 按钮式,容器都将执行改方法进行相应的操作。3. 代码import java.awt.*;import javax.swing.*;import java.awt.event.*;import java.io.*;import .*;public class GetTe
28、acherFile extends JPanel implements ActionListener,Runnablestatic String verifyMess;static InetSocketAddress socketAddress;String fileName;JLabel hintMess;JButton jb_getTeacherFile,jb_submit;JComboBox list;Socket socket;DataInputStream in; DataOutputStream out; Thread thread;int n=0;public GetTeache
29、rFile()hintMess=new JLabel(“单击“导入老师名字“按纽从服务器得到老师的名字“);hintMess.setBackground(Color.green); jb_getTeacherFile=new JButton(“导入老师名字“);jb_getTeacherFile.setBackground(Color.green);jb_submit=new JButton(“提交“);jb_submit.setBackground(Color.orange);jb_getTeacherFile.addActionListener(this);jb_submit.addAct
30、ionListener(this);list=new JComboBox();Box box1=Box.createHorizontalBox(); box1.add(jb_getTeacherFile);Box box2=Box.createHorizontalBox();box2.add(new JLabel(“选择评课老师:“,JLabel.CENTER); box2.add(list);box2.add(jb_submit);Box boxH=Box.createVerticalBox(); boxH.add(box1);boxH.add(box2);thread=new Thread
31、(this);JPanel pCenter=new JPanel();pCenter.add(boxH); setLayout(new BorderLayout();pCenter.setBackground(Color.pink);add(pCenter,BorderLayout.CENTER);JPanel pNorth=new JPanel();pNorth.add(hintMess); add(pNorth,BorderLayout.NORTH); public static void setVerifyMess(String mess)verifyMess=mess;public s
32、tatic void setSocketAddress(InetSocketAddress address)socketAddress=address;public void actionPerformed(ActionEvent e)if(e.getSource()=jb_getTeacherFile)list.removeAllItems();try makeConnection(); /见后面的 makeConnection()方法out.writeUTF(“列出文件:“+verifyMess); if(!(thread.isAlive()thread=new Thread(this);
33、thread.start();catch(Exception ee)JOptionPane.showMessageDialog(this,“请登录“,“操作提示“,JOptionPane.PLAIN_MESSAGE);if(e.getSource()=jb_submit)n=list.getItemCount();if(n=1)fileName=(String)list.getSelectedItem();File file=new File(fileName);ClientTestArea.setExaminationFile(file);String tishi=“您已经选择了老师“+fi
34、leName+“,请单击“评价界面“;JOptionPane.showMessageDialog(this,tishi,“操作提示“,JOptionPane.PLAIN_MESSAGE);private void makeConnection() throws IOException socket=new Socket();socket.connect(socketAddress);in=new DataInputStream(socket.getInputStream();out=new DataOutputStream(socket.getOutputStream(); public vo
35、id run()String s=null;while(true)trys=in.readUTF(); if(s.startsWith(“列出文件:“)String listItem=s.substring(s.indexOf(“:“)+1);list.addItem(listItem);if(s.startsWith(“已经全部列出:“)hintMess.setText(“需评价老师名字已导入,请在列表中选择并进入评价“);hintMess.setBackground(Color.green);break;if(s.startsWith(“请登录“)JOptionPane.showMessa
36、geDialog(this,“请登录“,“操作提示“,JOptionPane.PLAIN_MESSAGE);break;catch (Exception ee)2.3.8 ClientTestArea 类1. 效果图2. 主要成员变量与方法(1) 成员变量 contentArea 是 JPanel 创建的容器,用于显示评价内容 handAnswer,starTest,和 lookResult 是 JButton 创建的对象,这 3 个按钮都将当前容器注册为自己的 ActionEvent 事件监视器。(2) 方法ClientTestArea()是构造方法,用来创建 clientTestArea
37、对象。3. 代码import java.awt.*;import javax.swing.*;import java.awt.event.*;import java.io.*;import .*;import java.util.*;public class ClientTestArea extends Panel implements ActionListener,Runnablestatic String verifyMess;static InetSocketAddress socketAddress;static File teacherFile;ArrayList choiceLis
38、t;Socket socket; DataInputStream in; DataOutputStream out; Thread thread; static JPanel contentArea;JLabel hintMess; JButton handAnswer,startTest,lookResult;static File dirStudent;static File currentDir;static String tf;public ClientTestArea()thread=new Thread(this);currentDir = new File(System.getP
39、roperty(“user.dir“);dirStudent = new File(currentDir,“Student“);dirStudent.mkdir();choiceList=new ArrayList(); contentArea=new JPanel();contentArea.setForeground(Color.blue); handAnswer=new JButton(“提交评价“); startTest=new JButton(“显示内容“);lookResult=new JButton(“查看结果“);handAnswer.setEnabled(false);loo
40、kResult.setEnabled(false);hintMess=new JLabel(“单击“显示内容“按钮从服务器得到评价内容“);startTest.addActionListener(this);handAnswer.addActionListener(this);lookResult.addActionListener(this); setLayout(new BorderLayout();JPanel pCenter=new JPanel();pCenter.setBackground(Color.yellow);pCenter.setLayout(new BorderLayo
41、ut();pCenter.add(new JScrollPane(contentArea),BorderLayout.CENTER);add(pCenter,BorderLayout.CENTER);JPanel pSouth=new JPanel();pSouth.setBackground(Color.blue);pSouth.add(handAnswer);pSouth.add(startTest);pSouth.add(lookResult);add(pSouth,BorderLayout.SOUTH);JPanel pNorth=new JPanel();pNorth.setBack
42、ground(Color.green);pNorth.add(hintMess);add(pNorth,BorderLayout.NORTH);public static void setVerifyMess(String mess)verifyMess=mess;public static void setSocketAddress(InetSocketAddress address)socketAddress=address;public static void setExaminationFile(File f)teacherFile=f;contentArea.removeAll();
43、public void actionPerformed(ActionEvent e)if(e.getSource()=startTest)choiceList.clear();lookResult.setEnabled(false);try makeConnection();contentArea.removeAll();out.writeUTF(“显示内容:“+verifyMess+“#“+teacherFile.getName();String m=“读入的文件:“+teacherFile+“将刷新当前的内容,是否确认继续“;int ok=JOptionPane.showConfirmDi
44、alog(this,m,“确认对话框“,JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE);if(ok=JOptionPane.YES_OPTION)if(!(thread.isAlive()thread=new Thread(this);thread.start();hintMess.setText(“下面是对“ + teacherFile.getName() + “的评价内容“);handAnswer.setEnabled(true);catch(Exception exp)JOptionPane.showMessageDi
45、alog(this,“您未登录或选择试卷“,“操作提示“,JOptionPane.PLAIN_MESSAGE); if(e.getSource()=handAnswer)String m=“是否确认提交?“;int ok=JOptionPane.showConfirmDialog(this,m,“确认对话框“,JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE);if(ok=JOptionPane.YES_OPTION)StringBuffer str=new StringBuffer();for(int i=0;ichoiceL
46、ist.size();i+)JRadioButton box=choiceList.get(i);if(box.isSelected()str.append(box.getText()+“ “);String myAnswer=new String(str);try makeConnection();out.writeUTF(“评价的结果:“+verifyMess+“#“+myAnswer+“+teacherFile.getName()+“$“);handAnswer.setEnabled(false);lookResult.setEnabled(true);catch(Exception exp)JOptionPane.showMessageDialog(this,“您未登录或选择试卷“,“操作提示“,JOptionPane.PLAIN_MESSAGE);