综合项目
Posted luodongyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了综合项目相关的知识,希望对你有一定的参考价值。
Java课程设计
(综合项目文档)
多人聊天室
二〇二〇年七月
目 录
1 绪论 1
1.1 项目概述 1
1.2 项目意义 1
2 开发工具和相关技术简介 2
2.1 Eclipse简介 2
2.2 Java语言介绍 2
3 系统需求分析 4
3.1 系统可行性分析 4
3.2 系统需求分析 4
3.3 组内成员分工 4
3.4 项目进度安排 5
4 系统设计 6
4.1 系统设计 6
5 系统实现 8
6 系统测试 10
7 结论和心得 11
1 绪论
1.1 项目概述
聊天室:使用图形用户界面,能实现一个聊天室中多人聊天,能收到发送的内容,有客户端与服务器。
1.2 项目意义
用团队合作的方式,来锻炼同学们动手能力,独立思考的能力和团队合作的能力,并且能很好的巩固Java知识。
考验分析能力:1.要对项目进行概念分析,分析项目相对于客户,要怎么样才能达到满意。2.必要性分析。3.需求分析,考虑到用户需要什么样的功能,要怎么简单的去实现它,才能使用户满意
通过此次项目,使我们能更好的了解概念和掌握开发方法,提高自己的运用能力和自身的编程能力。
2 开发工具和相关技术简介
本项目是多人聊天界面。开发环境:Eclipse;开发语言:Java语言
2.1 Eclipse简介(或者MyEclipse或者IEDA简介)
开发工具:Eclipse
Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。
Eclipse最初是由IBM公司开发的替代商业软件Visual Age for Java的下一代IDE开发环境,2001年11月贡献给开源社区,它由非营利软件供应商联盟Eclipse基金会(Eclipse Foundation)管理。2003年,Eclipse 3.0选择OSGi服务平台规范为运行时架构。2007年6月,稳定版3.3发布;2008年6月发布代号为Ganymede的3.4版;2009年6月发布代号为Galileo的3.5版;2010年6月发布代号为Helios的3.6版;2011年6月发布代号为Indigo的3.7版;2012年6月发布代号为Juno的4.2版;2013年6月发布代号为Kepler的4.3版;2014年6月发布代号为Luna的4.4版;2015年6月项目发布代号为Mars的4.5版。
2.2 Java语言介绍
Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。
2009年,甲骨文公司宣布收购Sun 。2010年,Java编程语言的共同创始人之一詹姆斯·高斯林从Oracle公司辞职。2011年,甲骨文公司举行了全球性的活动,以庆祝Java7的推出,随后Java7正式发布。2014年,甲骨文公司发布了Java8正式版。
3 系统需求分析
3.1 系统可行性分析
- 技术可行性
本次程序运用所需软件为eclipse,采用的Java语言,所以技术上是可行的。
- 经济可行性
本次程序所使用的eclipse软件是免费的,我们不需要额外的开销,经济上是可行的
- 操作可行性
本次程序运用了简单的用户键盘录入操作,简单易懂,很好操作,因此在操作上是可行的
3.2 系统需求分析
仿照QQ运行界面,实现账号登录、界面聊天、好友上线功能、服务器。
3.3 组内成员分工
表3-1 组内成员分工情况表
序号 |
姓名 |
组内角色 |
小组分工 |
备注 |
1 |
罗东杨 |
项目经理 |
写代码 |
|
2 |
王卓 |
编码师 |
写代码 |
|
3 |
刘嘉豪 |
测试员 |
写文档 写代码 |
负责小组文档 |
4 |
齐书纬 |
构架师 |
找资料 写代码 |
找图片 和视频资料 |
说明:组内角色:组长为项目经理;其他人分别为编码、测试、架构师等。
3.4 进度安排
进度安排如表3-2所示。
表3-2 进度安排表
阶段 |
持续时间 |
阶段描述 |
输出 |
构思阶段 |
1天 |
需求分析 |
需求说明,功能模块图 |
设计阶段 |
1天 |
系统设计 |
设计说明 |
是现阶段 |
3天 |
编写代码 |
项目工程源代码 |
1天 |
系统测试 |
进行黑盒测试(功能测试) |
|
运行阶段 |
1天 |
部署、运行 |
系统使用说明、运维报告-答辩 |
4 系统设计
4.1 系统设计
设计类似QQ聊天的界面
思想来源:
登录界面:
聊天界面:
通过对QQ的分析得到了启发 可以根据仿照QQ去实现
5 系统实现
package qqclient;
/**
* 这是客户端和服务器端保持通讯的线程.
*/
import java.io.ObjectInputStream;
import java.net.Socket;
import qqserver.Message;
import qqserver.MessageType;
public class ClientConServerThread extends Thread {
private Socket s;
//构造函数
public ClientConServerThread(Socket s){
this.s=s;
}
public void run(){
while(true){
//不停的读取从服务器端发来的消息
try {
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
Message m=(Message)ois.readObject();
/* System.out.println("读取到从服务发来的消息"+ m.getSender() +" 给 "+m.getGetter()+" 内容"+
m.getCon());*/
if(m.getMesType().equals(MessageType.message_comm_mes)){
//把从服务器获得消息,显示到该显示的聊天界面
QqChat qqChat=ManageQqChat.getQqChat(m.getGetter()+" "+m.getSender());
//显示
qqChat.showMessage(m);
}else if(m.getMesType().equals(MessageType.message_ret_onLineFriend)){
System.out.println("客户端接收到"+m.getCon());
String con=m.getCon();
String friends[]=con.split(" ");
String getter=m.getGetter();
System.out.println("getter="+getter);
//修改相应的好友列表.
QqFriendList qqFriendList=ManageQqFriendList.getQqFriendList(getter);
// if(qqFriendList)
//更新在线好友.
if(qqFriendList!=null){
qqFriendList.upateFriend(m);
}
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
}
public Socket getS() {
return s;
}
public void setS(Socket s) {
this.s = s;
}
}
package qqclient;
/**
* 这是一个管理客户端和服务器保持通讯的线程类
*/
import java.util.HashMap;
public class ManageClientConServerThread {
private static HashMap hm=new HashMap<String, ClientConServerThread>();
//把创建好的ClientConServerThread放入到hm
public static void addClientConServerThread(String qqId,ClientConServerThread ccst){
hm.put(qqId, ccst);
}
//可以通过qqId取得该线程
public static ClientConServerThread getClientConServerThread(String qqId){
return (ClientConServerThread)hm.get(qqId);
}
}
package qqclient;
/**
* 这是一个管理用户聊天界面的类
*/
import java.util.HashMap;
public class ManageQqChat {
private static HashMap hm=new HashMap<String, QqChat>();
//加入
public static void addQqChat(String loginIdAnFriendId,QqChat qqChat){
hm.put(loginIdAnFriendId, qqChat);
}
//取出
public static QqChat getQqChat(String loginIdAnFriendId ){
return (QqChat)hm.get(loginIdAnFriendId);
}
}
package qqclient;
/**
* 管理好友、黑名单..界面类
*/
import java.util.HashMap;
public class ManageQqFriendList {
private static HashMap hm=new HashMap<String, QqFriendList>();
public static void addQqFriendList(String qqid,QqFriendList qqFriendList){
hm.put(qqid, qqFriendList);
}
public static QqFriendList getQqFriendList(String qqId){
return (QqFriendList)hm.get(qqId);
}
}
package qqclient;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ObjectOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import qqserver.Message;
import qqserver.MessageType;
public class QqChat extends JFrame implements ActionListener{
JTextArea jta;
JTextField jtf;
JButton jb;
JPanel jp;
String ownerId;
String friendId;
public static void main(String[] args) {
// TODO Auto-generated method stub
//QqChat qqChat=new QqChat("1");
}
public QqChat(String ownerId,String friend){
this.ownerId=ownerId;
this.friendId=friend;
jta=new JTextArea();
jtf=new JTextField(15);
jb=new JButton("发送");
jb.addActionListener(this);
jp=new JPanel();
jp.add(jtf);
jp.add(jb);
this.add(jta,"Center");
this.add(jp,"South");
this.setTitle(ownerId+" 正在和 "+friend+" 聊天");
this.setIconImage((new ImageIcon("image/qq.gif").getImage()));
this.setSize(300, 200);
this.setVisible(true);
}
//写一个方法,让它显示消息
public void showMessage(Message m){
String info=m.getSender()+" 对 "+m.getGetter()+" 说:"+m.getCon()+" ";
this.jta.append(info);
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if(arg0.getSource()==jb){
//如果用户点击了,发送按钮
Message m=new Message();
m.setMesType(MessageType.message_comm_mes);
m.setSender(this.ownerId);
m.setGetter(this.friendId);
m.setCon(jtf.getText());
m.setSendTime(new java.util.Date().toString());
//发送给服务器.
try {
ObjectOutputStream oos=new ObjectOutputStream
(ManageClientConServerThread.getClientConServerThread(ownerId).getS().getOutputStream());
oos.writeObject(m);
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
}
}
package qqclient;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import qqserver.Message;
import qqserver.User;
public class QqClientConServer {
public Socket s;
//发送第一次请求
public boolean sendLoginInfoToServer(Object o){
boolean b=false;
try {
System.out.println("服务器运行");
s=new Socket("127.0.0.1",9999);
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
oos.writeObject(o);
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
Message ms=(Message)ois.readObject();
//这里就是验证用户登录的地方
if(ms.getMesType().equals("1")){
//就创建一个该qq号和服务器端保持通讯连接得线程
ClientConServerThread ccst=new ClientConServerThread(s);
//启动该通讯线程
ccst.start();
ManageClientConServerThread.addClientConServerThread
(((User)o).getUserId(), ccst);
b=true;
}else{
//关闭Scoket
s.close();
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}finally{
}
return b;
}
public void SendInfoToServer(Object o){
}
}
package qqclient;
/**
功能:qq客户端登录界面
*/
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ObjectOutputStream;
import javax.swing.*;
import qqserver.Message;
import qqserver.MessageType;
import qqserver.User;
public class QqClientLogin extends JFrame implements ActionListener{
//定义北部需要的组件
JLabel jbl1; //用于放北部的图片背景
//定义中部需要的组件
JTabbedPane jtp;
JPanel jp2,jp3,jp4; //分别用于设置 北部 中部 南部
JLabel jp2_jbl1,jp2_jbl2;
JTextField jp2_jtf;
JPasswordField jp2_jpf;
JCheckBox jp2_jcb1,jp2_jcb2;
//定义南部需要的组件
JPanel jp1;
JButton jp1_jb1,jp1_jb2,jp1_jb3;
public static void main(String[] args) {
// TODO Auto-generated method stub
QqClientLogin qqClientLogin=new QqClientLogin();
}
public QqClientLogin(){
//处理北部
jbl1=new JLabel(new ImageIcon("image/tou.gif"));
//处理中部
jp2=new JPanel(new GridLayout(3,2));
jp2_jbl1=new JLabel("Q Q 号 码",JLabel.CENTER);
jp2_jbl2=new JLabel("Q Q 密 码",JLabel.CENTER);
//jp2_jbl3.setForeground(Color.blue);
jp2_jtf=new JTextField();
jp2_jpf=new JPasswordField();
jp2_jcb1=new JCheckBox("隐身登录");
jp2_jcb2=new JCheckBox("记住密码");
//把控件按照顺序加入到jp2
jp2.add(jp2_jbl1);
jp2.add(jp2_jtf);
jp2.add(jp2_jbl2);
jp2.add(jp2_jpf);
jp2.add(jp2_jcb1);
jp2.add(jp2_jcb2);
//创建选项卡窗口
jtp=new JTabbedPane();
jtp.add("QQ号码",jp2);
jp3= new JPanel();
jtp.add("手机号码",jp3);
jp4=new JPanel();
jtp.add("电子邮件",jp4);
//处理南部
jp1=new JPanel();
jp1_jb1=new JButton(new ImageIcon("image/denglu.gif"));
//响应用户点击登录
jp1_jb1.addActionListener(this);
jp1_jb2=new JButton(new ImageIcon("image/quxiao.gif"));
jp1_jb3=new JButton(new ImageIcon("image/xiangdao.gif"));
//把三个按钮放入到jp1
jp1.add(jp1_jb1);
jp1.add(jp1_jb2);
jp1.add(jp1_jb3);
this.add(jbl1,"North");
this.add(jtp,"Center");
//..把jp1放在南部
this.add(jp1,"South");
this.setSize(350, 240);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
//如果用户点击登录
if(arg0.getSource()==jp1_jb1){
QqClientUser qqClientUser=new QqClientUser();
User u=new User();
u.setUserId(jp2_jtf.getText().trim());
u.setPasswd(new String(jp2_jpf.getPassword()));
if(qqClientUser.checkUser(u)){
try {
//把创建好友列表的语句提前.
QqFriendList qqList=new QqFriendList(u.getUserId());
ManageQqFriendList.addQqFriendList(u.getUserId(), qqList);
//发送一个要求返回在线好友的请求包.
ObjectOutputStream oos=new ObjectOutputStream
(ManageClientConServerThread.getClientConServerThread(u.getUserId()).getS().getOutputStream());
//做一个Message
Message m=new Message();
m.setMesType(MessageType.message_get_onLineFriend);
//指明我要的是这个qq号的好友情况.
m.setSender(u.getUserId());
oos.writeObject(m);
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
//关闭掉登录界面
this.dispose();
}else{
JOptionPane.showMessageDialog(this,"用户名密码错误");
}
}
}
}
package qqclient;
import qqserver.User;
public class QqClientUser {
public boolean checkUser(User u){
return new QqClientConServer().sendLoginInfoToServer(u);
}
}
package qqclient;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import qqserver.Message;
public class QqFriendList extends JFrame implements ActionListener,MouseListener{
//处理第一张卡片.
JPanel jphy1,jphy2,jphy3;
JButton jphy_jb1,jphy_jb2,jphy_jb3;
JScrollPane jsp1;
String owner;
//处理第二张卡片(陌生人).
JPanel jpmsr1,jpmsr2,jpmsr3;
JButton jpmsr_jb1,jpmsr_jb2,jpmsr_jb3;
JScrollPane jsp2;
JLabel []jb1s;
//把整个JFrame设置成CardLayout
CardLayout cl;
public static void main(String[] args) {
// TODO Auto-generated method stub
// QqFriendList qqFriendList=new QqFriendList();
}
//更新在线的好友情况
public void upateFriend(Message m){
String onLineFriend[]=m.getCon().split(" ");
for(int i=0;i<onLineFriend.length;i++){
jb1s[Integer.parseInt(onLineFriend[i])-1].setEnabled(true);
}
}
public QqFriendList(String ownerId){
this.owner=ownerId;
//处理第一张卡片(显示好友列表)
jphy_jb1=new JButton("我的好友");
jphy_jb2=new JButton("陌生人");
jphy_jb2.addActionListener(this);
jphy_jb3=new JButton("黑名单");
jphy1=new JPanel(new BorderLayout());
//假定有50个好友
jphy2=new JPanel(new GridLayout(50,1,4,4));
//给jphy2,初始化50好友.
jb1s =new JLabel[50];
for(int i=0;i<jb1s.length;i++){
jb1s[i]=new JLabel(i+1+"",new ImageIcon("image/mm.jpg"),JLabel.LEFT);
jb1s[i].setEnabled(false);
if(jb1s[i].getText().equals(ownerId)){
jb1s[i].setEnabled(true);
}
jb1s[i].addMouseListener(this);
jphy2.add(jb1s[i]);
}
jphy3=new JPanel(new GridLayout(2,1));
//把两个按钮加入到jphy3
jphy3.add(jphy_jb2);
jphy3.add(jphy_jb3);
jsp1=new JScrollPane(jphy2);
//对jphy1,初始化
jphy1.add(jphy_jb1,"North");
jphy1.add(jsp1,"Center");
jphy1.add(jphy3,"South");
//处理第二张卡片
jpmsr_jb1=new JButton("我的好友");
jpmsr_jb1.addActionListener(this);
jpmsr_jb2=new JButton("陌生人");
jpmsr_jb3=new JButton("黑名单");
jpmsr1=new JPanel(new BorderLayout());
//假定有20个陌生人
jpmsr2=new JPanel(new GridLayout(10,1,4,4));
//给jphy2,初始化20陌生人.
JLabel []jb1s2=new JLabel[10];
for(int i=0;i<jb1s2.length;i++){
jb1s2[i]=new JLabel(i+1+"",new ImageIcon("image/mm.jpg"),JLabel.LEFT);
jpmsr2.add(jb1s2[i]);
}
jpmsr3=new JPanel(new GridLayout(2,1));
//把两个按钮加入到jphy3
jpmsr3.add(jpmsr_jb1);
jpmsr3.add(jpmsr_jb2);
jsp2=new JScrollPane(jpmsr2);
//对jphy1,初始化
jpmsr1.add(jpmsr3,"North");
jpmsr1.add(jsp2,"Center");
jpmsr1.add(jpmsr_jb3,"South");
cl=new CardLayout();
this.setLayout(cl);
this.add(jphy1,"1");
this.add(jpmsr1,"2");
//在窗口显示自己的编号.
this.setTitle(ownerId);
this.setSize(300, 500);
this.setVisible(true);
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
//如果点击了陌生人按钮,就显示第二张卡片
if(arg0.getSource()==jphy_jb2){
cl.show(this.getContentPane(), "2");
}else if(arg0.getSource()==jpmsr_jb1){
cl.show(this.getContentPane(), "1");
}
}
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
//响应用户双击的事件,并得到好友的编号.
if(arg0.getClickCount()==2)
{
//得到该好友的编号
String friendNo=((JLabel)arg0.getSource()).getText();
//System.out.println("你希望和 "+friendNo+" 聊天");
QqChat qqChat=new QqChat(this.owner,friendNo);
//把聊天界面加入到管理类
ManageQqChat.addQqChat(this.owner+" "+friendNo, qqChat);
}
}
public void mouseEntered(MouseEvent arg0) {
JLabel jl=(JLabel)arg0.getSource();
jl.setForeground(Color.red);
}
public void mouseExited(MouseEvent arg0) {
JLabel jl=(JLabel)arg0.getSource();
jl.setForeground(Color.black);
}
public void mousePressed(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
}
}
package qqserver;
import java.util.HashMap;
import java.util.Iterator;
public class ManageClientThread {
public static HashMap hm=new HashMap<String, SerConClientThread>();
//向hm中添加一个客户端通讯线程
public static void addClientThread(String uid,SerConClientThread ct){
hm.put(uid, ct);
}
public static SerConClientThread getClientThread(String uid){
return (SerConClientThread)hm.get(uid);
}
//返回当前在线的人的情况
public static String getAllOnLineUserid(){
//使用迭代器完成
Iterator it=hm.keySet().iterator();
String res="";
while(it.hasNext()){
res+=it.next().toString()+" ";
}
return res;
}
}
package qqserver;
public class Message implements java.io.Serializable{
private String mesType;
private String sender;
private String getter;
private String con;
private String sendTime;
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getGetter() {
return getter;
}
public void setGetter(String getter) {
this.getter = getter;
}
public String getCon() {
return con;
}
public void setCon(String con) {
this.con = con;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getMesType() {
return mesType;
}
public void setMesType(String mesType) {
this.mesType = mesType;
}
}
package qqserver;
/**
* 定义包的种类
*/
public interface MessageType {
String message_succeed="1";//表明是登陆成功
String message_login_fail="2";//表明登录失败
String message_comm_mes="3";//普通信息包
String message_get_onLineFriend="4";//要求在线好友的包
String message_ret_onLineFriend="5";//返回在线好友的包
}
package qqserver;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class MyQqServer {
public MyQqServer(){
try {
//在9999监听
System.out.println("我是服务器,在9999监听");
ServerSocket ss=new ServerSocket(9999);
//阻塞,等待连接
while(true){
Socket s=ss.accept();
//接收客户端发来的信息.
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
User u=(User)ois.readObject();
System.out.println("服务器接收到用户id:"+u.getUserId()+" 密码:"+u.getPasswd());
Message m=new Message();
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
if(u.getPasswd().equals("123456")){
//返回一个成功登陆的信息报
m.setMesType("1");
oos.writeObject(m);
//这里就单开一个线程,让该线程与该客户端保持通讯.
SerConClientThread scct=new SerConClientThread(s);
ManageClientThread.addClientThread(u.getUserId(), scct);
//启动与该客户端通信的线程.
scct.start();
//并通知其它在线用户.
scct.notifyOther(u.getUserId());
}else{
m.setMesType("2");
oos.writeObject(m);
//关闭Socket
s.close();
}
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}finally{
}
}
}
package qqserver;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* 这是服务器端的控制界面,可以完成启动服务器,关闭服务器
* 可以管理和监控用户.
*/
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyServerFrame extends JFrame implements ActionListener {
JPanel jp1;
JButton jb1,jb2;
public static void main(String[] args) {
// TODO Auto-generated method stub
MyServerFrame mysf=new MyServerFrame();
}
public MyServerFrame(){
jp1=new JPanel();
jb1=new JButton("启动服务器");
jb1.addActionListener(this);
jb2=new JButton("关闭服务器");
jp1.add(jb1);
jp1.add(jb2);
this.add(jp1);
this.setSize(500, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if(arg0.getSource()==jb1){
new MyQqServer();
}
}
}
package qqserver;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
/**
* 功能:是服务器和某个客户端的通信线程
*/
import java.util.HashMap;
import java.util.Iterator;
public class SerConClientThread extends Thread{
Socket s;
public SerConClientThread(Socket s){
//把服务器和该客户端的连接赋给s
this.s=s;
}
//让该线程去通知其它用户
public void notifyOther(String iam){
//得到所有在线的人的线程
HashMap hm=ManageClientThread.hm;
Iterator it=hm.keySet().iterator();
while(it.hasNext()){
Message m=new Message();
m.setCon(iam);
m.setMesType(MessageType.message_ret_onLineFriend);
//取出在线人的id
String onLineUserId=it.next().toString();
try {
ObjectOutputStream oos=new ObjectOutputStream(ManageClientThread.getClientThread(onLineUserId).s.getOutputStream());
m.setGetter(onLineUserId);
oos.writeObject(m);
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
}
public void run(){
while(true){
//这里该线程就可以接收客户端的信息.
try {
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
Message m=(Message)ois.readObject();
// System.out.println(m.getSender()+" 给 "+m.getGetter()+" 说:"+m.getCon());
//对从客户端取得的消息进行类型判断,然后做相应的处理
if(m.getMesType().equals(MessageType.message_comm_mes)){
//一会完成转发.
//取得接收人的通信线程
SerConClientThread sc=ManageClientThread.getClientThread(m.getGetter());
ObjectOutputStream oos=new ObjectOutputStream(sc.s.getOutputStream());
oos.writeObject(m);
}else if(m.getMesType().equals(MessageType.message_get_onLineFriend)){
System.out.println(m.getSender()+" 要他的好友");
//把在服务器的好友给该客户端返回.
String res=ManageClientThread.getAllOnLineUserid();
Message m2=new Message();
m2.setMesType(MessageType.message_ret_onLineFriend);
m2.setCon(res);
m2.setGetter(m.getSender());
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
oos.writeObject(m2);
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
}
}
package qqserver;
/**
* 这是用户信息类
*/
public class User implements java.io.Serializable {
private String userId;
private String passwd;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
6 系统测试
主要对聊天项目的登录,好友界面,服务器,聊天界面块进行测试,测试结果如表6-1所示。
表6-1 花盆监控模块测试表
编号 |
测试功能 |
输入描述 |
预期结果 |
运行结果 |
HP01 |
登录 |
输入账号,密码 点击登录按钮 |
跳到好友列表 |
正常,与预期结果一致 |
HP02 |
聊天 |
双击好友 写好信息后,点发送按钮 |
好友收到发送的信息 |
正常,与预期结果一致 |
HP03 |
好友上线 |
好友登录
|
好友头像有灰色变为彩色 |
正常,与预期结果一致 |
登录界面,聊天界面,好友界面均测试成功。
主要是对该课题设计并实现的所有功能模块进行测试,并给出测试表格和验证结果。结果表明本课题经过测试,所有功能都符合需求分析并且均能正常实现。
7 结论和心得
罗东杨的心得:
通过此次课程设计,使我更加扎实的掌握了有关Java方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。 过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘。
王卓的心得:
兴趣,感觉学习工作中兴趣很关键,只是一个引发人积极性的问题,有了兴趣就自觉了,效率自然就高了。再次要敢于尝试和挑战。不要安于现成的程序,而且不要害怕失败,在程序调试的过程中这点尤为重要,“发现出问题然后解决问题”是一个积累经验的过程,而且很高效。最后要不懈追求。对于源代码进行不断的完善,要尽可能的实现课题所要求的功能。对于初学者或者开发较少的人来说,大量大写程序还是有必要的,但同时要注意思考,理解其实现的内在意义。还可以自己添加一些有意义的功能来实现。当看到自己编写的程序正常运行时,兴趣也会随之而来,乐此不疲,形成一个良性循环。
刘嘉豪的心得:
我从这次的设计中还感受到坚持的重要性。做事情不能轻言谈放弃,虽然过程不顺利,与想象中相去甚远。但是只要我们能坚持,朝着自己既定的目标前进,就一定会走到终点。一点小小的挫折实际上是在为最后的美景做铺垫,当我们守得云开见月明的时候,就会发现,沿途的曲折其实是在考验我们的目标是否坚定。坚持下来,我们会收获丰硕的果实。
齐书纬的心得:
原本我们之间只是各自编程,没有多少交流,通过本次实训,我们发现一开始编好的代码放在一起有时无法运行,通过几天的讨论研究学习,我们改良了一次又一次代码,推翻了一个又一个方案,最终确定下来了最好的方案,很有成就感。
以上是关于综合项目的主要内容,如果未能解决你的问题,请参考以下文章