项目界面展示
登入:
登入成功后数据库修改该用户的online值0为未上线1为上线 此程序有有两个表,,一个是注册用户表信息,,一个是每个好友里有哪些好友的信息,,以下是用户注册信息
从以上 图可以看出ych1 ych2 ych3三个用户上线了,
登入成功后进入好友界面:
可以看到ych3只有ych1一个好友,,数据库好友用户信息:
从上图可看出ych3有ych1一个好友
注册界面
注册成功后:注册用户表和好友用户表都会改变,,如下:
登入ych7,,ych7没有好友登入成功后显示如下:
ych7添加好友ych1
ych1显示:
点击同意后,,并不会马上显示对方,,这个问题,,我把它归结于窗体出现后不能再添加组件问题,,或者是我不会怎么添加,,所以要在下次登入后才会显示添加对方
聊天:
现在只可以发消息,,还有很多功能没实现,,以后慢慢增加吧,,
客户端:
分包:bean包,,有用户信息UserBean :
聊天信息发送的不同类型的类:
1 有登入信息类,发送到服务器的内容有 账户和密码
public class LoginBean implements Serializable{ /** * */ private static final long serialVersionUID = 1L; public String loginAccount; public String password; public LoginBean(String loginAccount,String password){ this.loginAccount=loginAccount; this.password=password; };
}
2:聊天信息类:有发送者,和接受者,和信息内容
public class LoginBean implements Serializable{ /** * */ private static final long serialVersionUID = 1L; public String loginAccount; public String password; public LoginBean(String loginAccount,String password){ this.loginAccount=loginAccount; this.password=password; }; }3:好友信息类:这里用的是public 是出于方便,,应该private修饰安全些
public class FriendBean implements Serializable{
public String username; public String friendid; public FriendBean(String username, String friendid) { super(); this.username = username; this.friendid = friendid; }
}
4:public int type; public Object object; public MsgInfo(int type,Object object){ this.type=type; this.object=object; }
此类是用户和服务器发送的类,,包含数据类型,,和数据内容
等等。。。。
常量包:主要是对界面放入图片的管理等
public class ConstantParam { public static String localhost="localhost"; public static int port=11111; public static String clostButton = "image/r2.png"; public static String smallButton = "image/y2.png"; public static String kity = "image/ych.jpg"; public static String register = "image/reglogo.png"; public static String login = "image/login.png"; public static String login1 = "image/login1.png"; public static String register1 = "image/register.png"; public static String bg1 = "image/3.jpg"; public static String bgchat="image/bgf.jpg"; public static String bq="image/motion/0x1f600.png"; public static ActionListener bl; public static JLabel jlabelXitong =new JLabel(""); public static JButton jbuttonXitong=new JButton(""); public static ArrayList<ChatFrame> chatList=new ArrayList<ChatFrame>(); }
方便以后换图片。
socket包,,主要处理业务
public MySocket() { try { s = new Socket(ConstantParam.localhost, ConstantParam.port); InputStream is = s.getInputStream(); OutputStream os = s.getOutputStream(); oos = new ObjectOutputStream(os); ois = new ObjectInputStream(is); } catch (Exception e) { e.printStackTrace(); } }
构造函数初始化socket和流
此类方法中有 关闭流和socket方法 读取数据方法 处理登入方法 处理注册方法 读取好友信息方法,,在登入成功后就调用此方法,会得到好友类,,在创建好友列表界面将此好友类传进去,,在好友列表出现的好友就更据此好友类创建哪些好友
工具包,,主要是StringUtil:
public static boolean isEmpty(String str){ if(str==null||"".equals(str)){ return true; } return false; } 主要针对输入框的内容不为空,在注册登入和发消息时使用
最多类的包就是View包了:
包括:重写的组件包,监听包 和 界面类
界面类,我定义了一个抽象类继承了JFrame,抽象类的构造函数写了一些属性,,继承此抽象类的子类都会有此抽象类的属性
public MyFrame(int width, int high) { setSize(width, high); setUndecorated(true); setLocationRelativeTo(null); setLayout(null); movedFrame(); init(); addCom(); }
MovedFrame是可以拖动窗体的方法
initial()初始化和addCom()在此窗体上添加组件 是抽象方法,约束子类,提供框架,
此抽象类还有一个设置背景图片的方法,,提供给子类使用,代码如下:
public void setBackgroudImage(String path) { if (path == null || "".equals(path)) { return; } ((JPanel) this.getContentPane()).setOpaque(false); ImageIcon img = new ImageIcon(path); JLabel lb = new JLabel(img); lb.setBounds(0, 0, img.getIconWidth(), img.getIconHeight()); this.getLayeredPane().add(lb, new Integer(Integer.MIN_VALUE)); }
监听类使用了接口回掉:
public class Listener { interface Lis{ public abstract void actionListener(ActionEvent e); } public void setListener(JButton j,final Lis l){ j.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { if(l!=null){ l.actionListener(e); } }}); } }
此方法可以一起测试哪些监听没加进去,,处理也很灵活,,
在好友界面的构造函数分一个线程专门处理读数据,,
服务器端没有界面就比较简单:
1:有和客户端完全一样的bean包,,
2:jdbc包专门用于和数据库打交道的包
/** * 通过用户名修改online方法 */ public void alterOnlineByName(String name, int online) { String sql = "update ych set online=? where username=?"; UtilSql.updateSql(sql, online, name); }
/** * 通过姓名查询 */ public UserBean queryByName(String name) { String sql = "select *from ych where username=?"; UserBean ub = UtilSql.querySql(sql, name); return ub; }
/**插入一条记录*/
public boolean insert(UserBean ub) { String sql = "insert into ych(username,password,tel,sex) values(?,?,?,?)"; UserBean ub1 = UtilSql.querySql("select *from ych where username=?", ub.getUsername()); UserBean ub2 = UtilSql.querySql("select *from ych where tel=?", ub.getTel()); if (ub1 == null && ub2 == null) { UtilSql.updateSql(sql, ub.getUsername(), ub.getPassword(), ub.getTel(), ub.getSex()); System.out.println("添加成功"); return true; } else { System.out.println("有用户名或者电话号码存在,,添加失败"); return false; } }此方法:在插入之前会先检查数据库是否有用户名和电话号码重复,,若其中之一重复则插入不进去
querySql()方法代码如下:
public static UserBean querySql(String sql, Object name) { Connection connection = getConnection(); PreparedStatement pre; try { pre = connection.prepareStatement(sql); pre.setObject(1, name); ResultSet set = pre.executeQuery(); while (set.next()) { String username = set.getString("username"); String password = set.getString("password"); String tel = set.getString("tel"); String sex = set.getString("sex"); int online = set.getInt("online"); return new UserBean(username, password, tel, sex, online); } } catch (SQLException e) { e.printStackTrace(); } return null; }
3:server服务器开启和处理业务的包
这个东西还有进步的空间是可以用电话号码登上去,,