XXXX学院Java课程设计 设计(论文)题目: 校内通信 所 在 院: 专 业 班 级: 学 生 姓 名: 学 号: 指 导 教 师: 年 月 日 XXXX学院课程设计(论文)任务书设计题目: 校内通信 专业班级: 学号 姓名 主要内容 校园企业内部通信工具可以很好的解决企业通信问题,使每个用户都能及时地了解自己的工作内容和获取需要的资料为解决这一问题,开发一个界面友好、易于操作的内部通信软件。
本系统应用了JDK 6.0新增的系统托盘技术和JavaDB数据库系统托盘可以在程序主窗体最小化使用托盘控制窗体的相应操作,例如打开主窗体;JavaDB使用灵活,可以应用到不同的系统平台中,只要该平台有支持Java的环境基本要求:整个系统从操作简便、界面友好、灵活、实用、安全的要求出发,实现信息通信、系统设置、搜索用户、访问公共资源、互访对方主机等功能完成期限: 年月日 指导教师签名: 评审小组负责人签名: 目 录1前言 12概述 12.1 开发背景 12.2 课题现状 22.3 软硬件需求 23系统分析 33.1 需求功能分析 33.2 可行性分析 33.2.1可行性要求、目标 33.2.2技术可行性分析 43.2.3经济可行性分析 44系统设计 54.1系统目标 54.2 系统功能 54.3数据库结构设计 64.3.1数据库分析 64.3.2校园企业内部通信系统的E-R图 64.3.3数据库结构设计 75详细设计和代码实现 85.1主窗体模块的设计与实现代码 85.1.1界面设计 115.1.2实现过程 125.2公共模块的设计与实现 145.2.1界面设计 145.2.2实现过程 145.3系统托盘模块的设计与实现 175.3.1界面设计 175.3.2实现过程 185.4系统工具模块的设计与实现 195.4.1界面设计 195.4.2实现过程 205.5 用户管理模块的设计与实现 235.5.1界面设计 235.5.2实现过程 246通信模块的设计与实现 296.1界面设计 296.2实现过程 337总结 378致谢 37参考文献 381前言要问到网络时代发展最快的领域,无疑的,答案是即时通讯。
即时通讯工具的实时交互、资费低廉等优点深受用户的喜爱,已经成为网络生活中不可或缺的一部分,比如大家都很熟悉的腾讯,MSN等网民们通过即时通信进行沟通交流、结识新朋友、娱乐消遣时间、实现异地文字、语音、视频的实时互通交流同时,人们也认识到即时信息工具能够带来极高的生产力,诸多企事业单位借助它的使用,来提高业务协同性及反馈的敏感度和快捷度作为使用频率最高的网络软件,即时通讯已经突破了作为技术工具的极限,被认为是现代交流方式的象征 即时通讯软件是通过即时通讯技术来实现聊天、交流的软件目前有2种架构形式,1、一种是C/S架构,采用客户端/服务器形式,用户使用过程中需要下载安装客户端软件,典型的代表有:、百度HI 、Skype、Gtalk、新浪UC、MSN等;2、采用B/S架构,即浏览器/服务端形式,这种形式的即时通讯软件,直接借助互联网为媒介、客户端无需安装任何软件,既可以体验服务器端进行沟通对话,一般运用在电子商务网站的服务商,典型的代表、53KF、live800等校园企业内部通信工具可以很好的解决企业通信问题,面对工作目标和团队工作中可能出现的问题,必须加强团队的沟通,使每个用户都能及时地了解自己的工作内容和获取需要的资料。
本系统应用了JDK 6.0新增的系统托盘技术和JavaDB数据库系统托盘可以在程序主窗体最小化之后,使用托盘控制窗体的相应操作,例如打开主窗体;JavaDB使用灵活,可以应用到不同的系统平台中,只要该平台有支持Java的环境2概述2.1 开发背景近几年,随着网络的迅速发展和全球信息化速度的加快,网络通信已经不算是新鲜事物了,但大多数网络通信需要借助Internet上的服务器,这就给那些具有大规模内部网络的用户造成了许多问题,如遭遇到网络攻击、病毒入侵等等由于互联网上的网络通信工具有时会给企业内部信息交流带来不便,所以为了方便校园和内部用户之间的沟通、保证校园内部局域网的安全,需要开发一个基于局域网的信息收发系统的即时通信工具2.2 课题现状校园内部通信系统是基于局域网的即时通信工具,可以说是一个internet通信工具的小规模版本,一般采用UDP或者TCP协议体系等来实现,开发技术已经比较成熟,国外的通信工具较有名的有ICQ、MSN Messenger、国产的、新浪UC都实现了广域网的即时通信在最近几年,国内的局域网通信工具较有代表性有飞鸽传书、飞秋,这两款软件的快速、实效、迷你、简单的特点受到了广大用户的好评。
这些工具的实现方式具体细节不易得之,但它无非是利用各种平台上的网络通信接口,基于TCP/IP或者UDP/IP协议架构下的软件产品对于一个企业内网,这些功能的实现相比于广域网更加简单所以还是有很大研究价值的[1]2.3 软硬件需求本系统运行时需要以下条件硬件平台:CPU:Pentium4 1.8GHz内存:128MB以上硬盘空间:100MB软件平台:操作系统:Windows 2000、Windows XP、Windows 2003等开发工具:Eclipse、JDK6.0数据库:JavaDB3系统分析3.1 需求功能分析本系统的设计目标是实现一个校园局域网通信系统,可以方便的进行交流,可以大大的提高校园企业内部的工作效率根据内部局域网通信的需求,本系统主要包括信息通信、系统设置、搜索用户、访问公共资源、访问对方主机五大功能各功能概述: 信息通信:信息通信是内部通信系统的核心功能,它用于不同职工之间的通信,这种通信方式能够实现多个职工之间的通信,而不存在类似占线的问题,增加了任务分配的新方式,从而提高企业的工作效率系统设置:系统设置用于设置用户界面、公共路径、公告栏等的功能用户搜索:用户搜索用于搜索局域网内的其他用户,系统会根据用户所设置的IP搜索范围搜索所有计算机上的用户。
访问公共资源:访问公共资源用于实现内部公共服务器上资源访问的功能访问对方主机:访问对方主机用于两人聊天情况下对对方主机的访问和控制的功能3.2 可行性分析3.2.1可行性要求、目标企业内部通信系统必须提供网络通信功能,在通信过程中禁止使用聊天表情、文件传送等功能,避免资料外泄,或因发送错误而导致上机资料的丢失以及其他损失最重要的是必须适应任何操作系统,也就是实现跨平台技术,因为企业内部的工作需要,工作环境中使用了多个操作系统来完成不同的工作另外,系统不需要使用服务器中转和记录通信内容,可以独立完成通信任务,排除职工对领导监视工作进度等行为的逆反心理企业内部通信系统的目标是实现企业的信息化通信,提高企业通信能力,提高任务理解和执行能力,减少没有必要的人员流动和资金损耗,以最快的速度提升企业的市场竞争力3.2.2技术可行性分析局域网通信系统的技术已经非常成熟,首先,从硬件上讲,计算机硬件速度现在已经不是问题,高速便捷的网络已经十分普遍,这些为本系统的运行打下坚实的基础从软件的角度上讲,数据库技术已经相当成熟(目前用得比较多的有SQL Server, JavaDB等),并且处理能力也非常强,这为海量数据的存储和处理打下了坚实的基础,同时,使用java开发图形界面程序也相当普遍。
有了这些技术的支持,我们成功开发一个局域网通信系统没有任何技术风险3.2.3经济可行性分析经济可行性主要是对项目的经济效益进行评价本系统开发完成后可缩减工作时间,提高工作效率,而且简单易操作,不需对使用人员进行培训,不管是在资金上还是效率上都能达到预期的效果本系统开发经费对于企业在经济上是可以接受的,并且本系统实施后可以显著提高工作效率,有助于企业的信息化管理,所以该企业内部通信系统在经济上是可行的4系统设计4.1系统目标系统根据企业对内部通信系统的要求,本系统可以实现以下目标:1.操作简单、界面简洁美观2.更方便访问企业公共资源3.及时显示企业公共信息4.在通信窗口显示对方IP信息5.局域网内网用户自动搜索6.系统运行稳定、安全可靠 4.2 系统功能系统功能结构图如下:企业内部通信系统信息通信系统设置用户搜索访问公共资源访问对方主机图4.1系统功能结构图4.3数据库结构设计4.3.1数据库分析该系统是一个桌面应用程序,它不像web应用那样需要配置到指定的服务器上,所以数据库和该系统应存在于同一计算机中,这样,不仅节省了开销,而且还提高了系统的安全性该系统所用数据库为JAVADB数据库。
由于该数据库的运行环境平台要求较低,一般的电脑都可以满足它的硬件条件[2]4.3.2校园企业内部通信系统的E-R图该系统的实体包括用户和窗口位置两个实体,分别记录着通信窗口的绝对位置和用户的信息 (1)用户实体用户实体主要包括IP信息、PC名称、用户信息、系统信息等,它记录了搜索到的用户和所有的用户信息用户实体的E-R图如下所示:用户实体头 像提示文本用户信息IP地 址主机名称 (2)窗口位置实体窗口位置实体记录着窗体最后的移动位置和窗体大小等信息,主要包括窗体位置的横坐标和竖坐标(下图用X、Y轴坐标表示)、窗体的高度和宽度窗口实体的E-R图如下所示:X坐标窗口实体Y坐标窗体高度窗体宽度图4.3窗口实体E-R图4.3.3数据库结构设计在该系统中的数据库db_EQ包含两个数据表,分别为用户信息表tb_users和窗体位置信息表tb_location1)tb_users(用户信息表)用户信息表用来保存内的通信用户,表tb_users如下所示:表4.1用户信息表—tb_users字段名数据类型是否为空是否主键默认值描述iPVarchar(16)NOYES用户IPhostVarchar(30)YESNONULL主机名称nameVarchar(20)YESNONULL姓名tooltipVarchar(50)YESNONULL提示文本iconVarchar(50)YESNONULL头像图标(2)tb_location(窗体位置信息表)窗体位置表用来保存窗体的位置和大小,表tb_location如下所示:表4.2 窗体位置信息表—tb_location字段名数据类型是否为空是否主键默认值描述xLocationIntYESNONULLX轴坐标yLocationIntYESNONULLY轴坐标heightIntYESNONULL窗体高度widthIntYESNONULL窗体宽度5详细设计和代码实现5.1主窗体模块的设计与实现代码 public EQ() { super(new Frame()); frame = this; dao = Dao.getDao(); location = dao.getLocation(); setTitle("郑科校内通"); setBounds(location); progressBar = new JProgressBar(); progressBar.setBorder(new BevelBorder(BevelBorder.LOWERED)); tabbedPane = new JTabbedPane(); popupMenu = new JPopupMenu(); chatTree = new ChatTree(this); user_dir = System.getProperty("user.dir"); // 程序执行路径用于系统更新 localFile = new File(user_dir + File.separator + "EQ.jar");// 本地EQ文件 stateLabel = new JLabel(); // 状态栏标签 addWindowListener(new FrameWindowListener());// 添加窗体监视器 addComponentListener(new ComponentAdapter() { public void componentResized(final ComponentEvent e) { saveLocation(); } public void componentMoved(final ComponentEvent e) { saveLocation(); } }); try {// 启动通讯服务端口 ss = new DatagramSocket(1111); } catch (SocketException e2) { if (e2.getMessage().startsWith("Address already in use")) showMessageDialog("服务端口被占用,或者本软件已经运行。
"); System.exit(0); } { // 初始化公共信息按钮 messageAlertIcon = new ImageIcon(EQ.class .getResource("/image/messageAlert.gif")); messageAlertNullIcon = new ImageIcon(EQ.class .getResource("/image/messageAlertNull20.gif")); messageStack = new Stack(); messageAlertButton = new JButton(); messageAlertButton.setHorizontalAlignment(SwingConstants.RIGHT); messageAlertButton.setContentAreaFilled(false); final JPanel BannerPanel = new JPanel(); BannerPanel.setLayout(new BorderLayout()); add(BannerPanel, BorderLayout.NORTH); userInfoButton = new JButton(); BannerPanel.add(userInfoButton, BorderLayout.WEST); userInfoButton.setMargin(new Insets(0, 0, 0, 10)); initUserInfoButton();// 初始化本地用户头像按钮 BannerPanel.add(messageAlertButton, BorderLayout.CENTER); messageAlertButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { if (!messageStack.empty()) { showMessageDialog(messageStack.pop()); } } }); messageAlertButton.setIcon(messageAlertIcon); showMessageBar(); } add(tabbedPane, BorderLayout.CENTER); tabbedPane.setTabPlacement(SwingConstants.LEFT); ImageIcon userTicon = new ImageIcon(EQ.class .getResource("/image/tabIcon/tabLeft.PNG")); tabbedPane.addTab(null, userTicon, createUserList(), "用户列表"); ImageIcon sysOTicon = new ImageIcon(EQ.class .getResource("/image/tabIcon/tabLeft2.PNG")); tabbedPane.addTab(null, sysOTicon, createSysToolPanel(), "系统操作"); ImageIcon sysSTicon = new ImageIcon(EQ.class .getResource("/image/tabIcon/tabLeft3.png")); tabbedPane.addTab(null, sysSTicon, createSysSetPanel(), "系统设置"); setAlwaysOnTop(true); }5.1.1界面设计主窗体界面是本系统的用户列表,它由用户列表、系统选项卡、公告提示等组成。
其中系统选项卡用于切换不同的管理界面,包括系统设计和系统工具界面[3]主窗体的效果图如下所示:图5.1 主窗体界面示意图5.1.2实现过程主窗体实现部分包括创建主窗体和记录窗体位置其中创建主窗体的步骤如下:(1)创建JXCFrame类,在类中创建窗体的对象,为窗体添加选项卡面板,并添加用户列表、系统工具、系统设置3个选项卡和状态栏标签、公告按钮等属性在构造方法中初始化窗体上的控件数据库操作类、首选项对象等属性,为窗体添加时间监听器、为公告信息按钮添加监听器等2)初始化Socket服务器,指定端口为1111,如初始化失败,则提示服务器端口被占用或本软件已运行,并退出本系统用于接收其他用户发送的通信信息关键代码如下:try {// 启动通讯服务端口 ss = new DatagramSocket(1111); } catch (SocketException e2) { if (e2.getMessage().startsWith("Address already in use")) showMessageDialog("服务端口被占用,或者本软件已经运行"); System.exit(0); }(3) checkPlacard方法,用于检测系统公告,当公告路径中存在系统公告时,将从文件中获取完整信息,调用pushMessage()方法将信息压入公告信息栈中。
关键代码如下:private void checkpacard() { // 检测公告信息方法 String placardDir = preferences.get("placardPath", null); if (placardDir == null) { pushMessage("未设置公告路径"); return; } File placard = new File(placardDir); try { if (placard.exists() && placard.isFile()) { StringBuilder placardStr = new StringBuilder(); Scanner sc = new Scanner(new FileInputStream(placard)); while (sc.hasNextLine()) { placardStr.append(sc.nextLine()); } pushMessage(placardStr.toString()); } catch (FileNotFoundException e) { pushMessage("公告路径错误,或公告文件不存在"); }(4)initUserInfoButton()方法用于初始化本地用户信息,并在主窗体左上角显示本地用户的头像和名称,会在用户更改本地用户名称时同步更新。
5) main()方法,本方法首先获取用户设置的界面外观,然后调用UIManager类设置指定的外观,生成主窗体对象最后初始化服务器端口和系统栏图标关键代码如下:public static void main(String args[]) { try { String laf = preferences.get("lookAndFeel", "java默认");//获取用户选择的外观 if (laf.indexOf("当前系统")>-1) UIManager.setLookAndFeel(UIManager .getSystemLookAndFeelClassName());//设置外观 EQ frame = new EQ(); frame.setVisible(true);//显示窗体 frame.SystemTrayInitial();// 初始化系统栏 frame.server();//启动服务端口 frame.checkPlacard();//检测系统公告 } catch (Exception e) { e.printStackTrace(); }} 记录窗体的位置步骤如下:(1)为窗体添加监听器,当改变窗体的位置和大小时,将调用saveLocation()方法将窗体和位置大小保存到数据库中。
2)saveLocation(),该方法中调用了DAO类中updateLocation将窗体的位置和大小保存到数据库中5.2公共模块的设计与实现5.2.1界面设计在本系统的项目空间中,有部分模块是公用的,或者多个模块甚至整个系统的配置信息是被多个模块重复调用完成业务的逻辑其中有关数据库的操作、连接数据库、创建本机IP的默认用户(并添加到数据库中)、从数据库中获取窗体位置和大小、添加或删除指定用户、更新用户信息等[4]5.2.2实现过程公共模块包括数据库操作类和系统工具类其中DAO类主要负责有关数据库的操作,该类在构造方法中驱动并连接数据库,然后将构造方法设置为private私有属性,通过静态的getdao()获取DAO类的实例对象,这是简单的单例模式在连接数据库时,可以指定create参数为true直接创建数据库,但在此之前需要调用dbExist()方法判断数据库是否存在Dao类的关键代码如下:public class Dao { // 数据库驱动 private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver"; private static String url = "jdbc:derby:db_EQ";// 数据库URL private static Connection conn = null;// 数据库连接 private static Dao dao = null; private Dao() { try { Class.forName(driver); if (!dbExists()) { conn = DriverManager.getConnection(url + ";create=true"); createTable(); } else conn = DriverManager.getConnection(url); addDefUser(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "数据库连接异常,或者本软件已经运行。
"); System.exit(0); } } private boolean dbExists() {// 测试数据库是否存在 boolean bExists = false; File dbFileDir = new File("db_EQ"); if (dbFileDir.exists()) { bExists = true; } return bExists; } public static Dao getDao() {// 获取DAO实例 if (dao == null) dao = new Dao(); return dao; } public List getUsers() {// 获取所有用户 List users = new ArrayList(); try { String sql = "select * from tb_users"; Statement stm = conn.createStatement(); ResultSet rs = stm.executeQuery(sql); while (rs.next()) { User user = new User(); user.setIp(rs.getString(1)); user.setHost(rs.getString(2)); user.setName(rs.getString(3)); user.setTipText(rs.getString(4)); user.setIcon(rs.getString(5)); users.add(user); } rs.close(); } catch (SQLException e) { e.printStackTrace(); } return users; }Resource类是校园内部通信系统中的工具类,该类中的方法都是静态的,可以直接调用,而不用创建Resource类的实例对象。
这些工具方法包括搜索用户的方法、登录公共资源的方法、信使群发的方法和单条信息发送的方法5.3系统托盘模块的设计与实现5.3.1界面设计系统托盘模块用于定义系统栏图标本系统的主窗体是继承对话框窗体编写的,该窗体在系统任务栏不会显示任务标题,如果主窗体最小化之后将会隐藏,这时必须使用快捷键或者系统托盘中的图标执行显示窗体的命令系统托盘包含相应的菜单,右键点击会弹出选择菜单,菜单包括三个选项,分别是:“访问服务器”、“打开”、“退出”系统托盘的设计效果图如下所示: 图5.2系统托盘示意图5.3.2实现过程在JDK6.0中,AWT新增加了SystemTray类和TrayIcon类,它们可以在系统托盘区创建一个托盘程序SystemTray类表示桌面右下角的系统托盘,系统托盘由运行在桌面上的所有应用程序共享,可以使用getSystemTray()方法获取系统托盘对象,该方法总是对每个应用程序返回相同的实例并不是所有的操作系统都支持系统托盘,如果当前系统不支持托盘的话,该方法将自动抛出异常为避免程序出现错误,在获取系统托盘实例之前,需要检查系统托盘是否支持可以调用isSupport()来实现[5]。
Systemtray类可以包含一个或多个TrayIcon类的实例,即系统栏图标,可以使用add()将它们添加到托盘,TrayIcon对象由图像、弹出菜单和一组相关监听器组成创建系统托盘的关键代码如下:try { String title = "郑科校内通";//系统栏提示文本的标题 String company = "JAVA项目小组";//系统栏提示文本 SystemTray sysTray = SystemTray.getSystemTray();//获取系统托盘对象 Image image = Toolkit.getDefaultToolkit().getImage( EQ.class.getResource("/icons/sysTray.png"));// 系统栏图标 trayicon = new TrayIcon(image, title + "\n" + company, createMenu()); //创建系统栏图标对象trayicon.setImageAutoSize(true);//设置自动大小trayicon.addActionListener(new SysTrayActionListener());//添加监听器 sysTray.add(trayicon);//添加系统栏图标到系统托盘 trayicon.displayMessage(title, company, MessageType.INFO); } catch (Exception e) { e.printStackTrace(); }5.4系统工具模块的设计与实现5.4.1界面设计本系统的工具模块起到维护系统的作用,包括更换程序外观、。
设置IP范围、用户搜索和系统更新、设置系统公告路径、设置公共程序路径、系统登录等功能在该系统第一次运行的时,用户搜索功能可以搜索内部网络中所有正在运行的计算机本系统工具模块中使用了Java的LookAndFeel外观技术,不同的外观中控件的外观也会不同,就比如我们常用的电脑中,windows经典样式和windowsXP样式外观的按钮、列表、菜单、工具栏甚至窗体的外观都不相同在本系统中提供了“当前系统”和“JAVA默认值”两个外观选项,其中“JAVA默认值”是Swing默认的外观,不需要特别设置,而“当前系统”外观需要使用相应的方法获取当前系统的外观名称,然后将该外观应用于默认的外观[6]系统工具的设计效果图如下所示:图5.3系统工具界面示意图5.4.2实现过程(1)createSysToolPanel()方法,用于创建系统工具选项卡,在该选项卡中包括界面选择、用户搜索和系统操作3部分,其中系统操作用于程序更新,它们都被添加到系统工具面板中,createSysToolPanel()方法必须设置好面板的布局和初始化工作关键代码如下:private JScrollPane createUserList() {// 用户列表面板 JScrollPane scrollPane = new JScrollPane(); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); addUserPopup(chatTree, getPopupMenu());// 为用户添加弹出菜单 scrollPane.setViewportView(chatTree); scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0)); chatTree.addMouseListener(new ChatTreeMouseListener()); return scrollPane; }(2)在createSysToolPanel()方法中创建界面选择部分,该部分以列表控件显示了两种外观选择,当用户选择其中以种外观并单击“确定”按钮之后,选择外观会保存到首选项中,然后提示重新运行本软件。
3)在createSysToolPanel()方法中创建用户搜索部分,包括搜索列表、搜索进度条和“搜索新用户”3个控件,当单击“搜索新用户”按钮时,系统会根据用户在系统设置界面所设置的IP搜索范围搜索所有计算机信息,并创建相应的用户对象,然后保存到数据库中4)创建“搜索新用户”按钮的事件SearchUserActionListener类,调用Resource工具类的searchUsers()方法搜索指定IP范围内的所有用户系统工具类中的searchUsers()方法,该方法用于搜索局域网内的通信用户,也就是搜索企业内的所有职工本方法将获取用户指定的IP范围,并在该范围内搜索所有可以访问的计算机,如果用户没有指定IP范围,系统默认的是192.168.0.1-192.168.0.255关键代码如下:try { for (int l = ipsInt[0]; l <= ipeInt[0]; l++) { boolean b0 = l < ipeInt[0]; // 记录第一层循环的条件 int k = l != ipsInt[0] ? 0 : ipsInt[1]; // 从第二次循环以后k赋值0 for (; b0 ? k < 256 : k <= ipeInt[1]; k++) { boolean b1 = b0 || k < ipeInt[1]; // 记录第二层循环的条件 int j = k != ipsInt[1] ? 0 : ipsInt[2]; // 从第二次循环以后j赋值0 for (; b1 ? j < 256 : j <= ipeInt[2]; j++) { boolean b2 = b1 || b1 ? j < 256 : j < ipeInt[2]; int i = j != ipsInt[2] ? 0 : ipsInt[3]; for (; b2 ? i < 256 : i <= ipeInt[3]; i++) { if(!button.isSelected()){ progressBar.setIndeterminate(false); return; } Thread.sleep(100);//线程休息100毫秒 String ip = l + "." + k + "." + j + "." + i; progressBar.setString("正在搜索:" + ip);//取消进度条的滚动 if (tree.addUser(ip, "search"))//添加新用户 model.addElement("添加" + ip + ""); }catch(Exception e){ e.printStackTrace();}5.5 用户管理模块的设计与实现5.5.1界面设计用户管理模块类似于聊天软件的好友列表,其中包含所有用户信息,另外在用户名称上单击鼠标右键,会弹出相应的管理菜单,在该菜单中包含“添加用户”、“更名”、“删除用户”、“信使群发(在没有多选用户的情况下无法进行信使群发)”、“访问主机资源”和“访问公共程序”,其中“访问主机资源”是访问该用户的共享文件夹[7]。
界面设计的效果图如下所示: 图5.4用户管理界面示意图5.5.2实现过程(1)创建UserTreeRanderer类,该类继承Jpanel类成为一个面板控件,同时该类也实现了TreeCellRenderer接口成为树节点的渲染器该类的构造方法接受3个图标参数,分别用于树节点的打开、关闭和叶节点的图标2)在UserTreeRanderer类getTreeCellRendererComponent()方法,渲染树节点的界面样式本方法获取主窗体的宽度,并使用该宽度设置节点的宽度,是节点与窗体同宽度,当选择某个节点时,该方法将使用指定颜色绘制节点的边框,以突出该节点被选择的效果3)创建ChatTree类,该类继承Jtree自定义的树控件,并且使用了之前定义的UserTreeRanderer树节点渲染器, sortUsers()方法,此方法是一个内部线程,该线程获取本地的IP地址,使用该地址从数据库中获取本地用户对象,并将本地用户设置在用户列表首位然后从数据库中获取其它用户对象使第一个用户处于被选择状态,并更新状态栏的用户人数关键代码如下:private synchronized void sortUsers() {//排序用户列表 new Thread(new Runnable() { public void run() { try { Thread.sleep(100); root.removeAllChildren(); String ip = InetAddress.getLocalHost().getHostAddress(); //获取本地IP User localUser = dao.getUser(ip);//从数据库中获取自己的信息 if (localUser != null) {// 把自己显示在首位 DefaultMutableTreeNode node = new DefaultMutableTreeNode( localUser); root.add(node); } userMap = dao.getUsers(); Iterator iterator = userMap.iterator(); while (iterator.hasNext()) { // 遍历用户集合 User user = iterator.next(); if(user.getIp().equals(localUser.getIp())) continue; root.add(new DefaultMutableTreeNode(user));//添加用户到根节点 } treeModel.reload(); ChatTree.this.setSelectionRow(0);//使第一个节点被选择 if (eq != null) eq.setStatic(" 总人数:" + getRowCount());//更新状态栏标签 } catch (Exception e) { e.printStackTrace(); } } }).start();(4)在ChatTree中的delUser()方法,用于删除当前用户列表中选择的用户对象。
该方法首先获取选择的树节点,从该节点中获取绑定的用户对象,经用户确认后删除用户信息,最后调用根节点的remove()方法删除该用户节点另外是addUser()方法,用于在用户列表中添加新用户本方法首先使用传递的IP参数到数据库中获取对应的用户对象,如成功获取,说明数据库已存在该用户,系统会提示“已存在”,当确定该IP可以访问后,为该IP地址创建一个新的用户并添加到数据库中关键代码如下:public boolean addUser(String ip, String opration) {// 添加用户 try { if (ip == null) return false;User oldUser = dao.getUser(ip);//从数据库中获取IP相同用户 if (oldUser == null) {// 如果数据库中不存在该用户 InetAddress addr = InetAddress.getByName(ip);//该用户可以访问 if (addr.isReachable(1500)) { String host = addr.getHostName();//获取它的主机名称 root.add(new DefaultMutableTreeNode(new User(host, ip))); User newUser = new User();//创建新用户对象 newUser.setIp(ip); //设置IP newUser.setHost(host);//设置主机名称 newUser.setName(host);//设置用户姓名 newUser.setIcon("1.gif");//设置头像 dao.addUser(newUser);//添加该用户到数据库中 sortUsers();//用于重新加载用户列表 if (!opration.equals("search")) JOptionPane.showMessageDialog(EQ.frame, "用户" + host + "添加成功", "添加用户", JOptionPane.INFORMATION_MESSAGE); return true; } else { //如果该用户IP不可访问 if (!opration.equals("search")) //并且不是系统自动搜索 JOptionPane.showMessageDialog(EQ.frame, "检测不到用户IP:" + ip, "错误添加用户",JOptionPane.ERROR_MESSAGE);//对话框提示错误 return false; } } else { //如果数据库中存在该IP用户 if (!opration.equals("search")) // 并且不是系统自动搜索 JOptionPane.showMessageDialog(EQ.frame, "已经存在用户IP" + ip,"不能添加用户", JOptionPane.WARNING_MESSAGE);//提示已存在! return false; } } catch (Exception e) { e.printStackTrace(); } return false; }6通信模块的设计与实现6.1界面设计通信模块是本系统中的核心模块,它用于局域网内的用户之间的通信,而却这种通信方式能够实现多个用户之间的通信,不会存在像我们打一样时的占线问题,增加了任务分配的方式。
本模块可以使用UDP协议和信史两种方式发送信息[8]通信的聊天界面设计效果图如下所示:图5.7聊天界面示意图我们通常所说的通信工具,都是采用的客户机/服务器(C/S)架构的,C/S结构是这样的一种结构:它包括一个客户机(或前端),一个服务器(或称后端),客户机的作用是访问和处理远程服务器上的数据,服务器的作用是接收和处理客户机的数据请求有时,可能有多个客户向同一个服务器同时请求服务,这就需要服务器决定怎样处理这些请求Client/Server结构是当前数据库应用程序中极为流行的一种方式尤其是网络技术的发展,使得当前很多系统都采用这种方式进行构造,其最大的优点是将计算机工作任务分别由客户端和服务器端来共同完成,这样有利于充分合理的利用系统资源另外它的服务器端还可以将信息集中起来,任何客户机都可以通过访问服务器而获得所需的信息Client/Server模型最终可归结为一种“请求/应答”关系一个请求总是首先被客户发出,然后服务器总是被动地接收请求,返回客户需要的结果在客户发出一个请求之前,服务进程一直处于休眠状态一个客户提出请求后,服务进程被“唤醒”并且为客户提供服务,对客户的请求做出所需要的应答[8]。
其工作示意图如下:工作机工作机工作机工作机工作机工作机工作机工作机服务器图5.5 C/S模式下的网络拓扑图但是本系统如果要做成C/S架构的话,需要在局域网内设置一个服务器,而在企业局域网内,网络结构不是集中式的而是分布式的,可能没有一台机器来充当服务器这个角色,同样用服务器会增加本系统的设置难度,不符合本系统方便、快捷的特色,同时增加服务器后,所有数据都会经过服务器保存处理,需要有专人看管维护服务器,显。