韩顺平Java自学笔记 项目 QQ聊天室

目录

一。项目前的准备

1.为什么选择这个项目

2.项目开发的流程

3.项目的需求

 二。开发阶段

1.登录功能实现

2.拉取在线用户实现

3.无异常退出的实现

 4.私聊功能的实现

 5.群发的实现

6.发送文件的实现

7.服务端推送新闻

三。课后作业

1.离线留言功能的实现代码

2.离线文件发送实现


一。项目前的准备

1.为什么选择这个项目

没有Mysql所以使用一个集合来存储信息

UI没有刻意写,界面写的是控制台 

2.项目开发的流程

1.需求阶段

需求分析师来做,出一个需求分析的报告(白皮书的格式),项目的功能,客户的要求。

需求分析师的要求:1.有技术。2.懂行业。   例如:银行,税务,海关。

2.设计阶段

项目经理或者是架构师来处理

工作:制作类图,流程图,模块,数据库,架构,流量,用户访问量,组建团队(挑选团队成员)等。 

工资:基本工资+项目提成

3.实现阶段

程序员,码农来进行实现。刚进入工作基本上都是实现岗位。

4.测试阶段

测试工程师,找到模块可能出现的bug 。(可能是引用模块的问题。耦合性高的问题)。测试和实现是相互交叉的

5.部署阶段

实施工程师,主要是对环境的配置,要经常出差,将项目部署到客户指定的机子上面。

6.维护阶段

项目部署到对方平台,出现问题之后,进行处理。 项目升级,项目扩展之类的要求。

图示

 项目越大设计阶段花的时间越多

3.项目的需求

1.图示

2.界面设计

 用户登录

 

 拉取在线用户列表

私聊

 群聊

发文件

服务器推送新闻

 推图片,文件和推文字的基本原理是相同的

3.通信功能的整体分析

传输对象,对象当中包含传递的信息,从管道当中运输信息。

Message类来进行装载信息,Socket作为传送信息两端的基站。 线程持有一个socket。socket是线程的一个属性。

因为群发的需求,所以需要一个线程集合来进行管理。可以查找集合当中都有那些线程,确定与服务器链接的用户。

一个客户端也可能与服务端有多个线程的链接。例如:发送文件,视频聊天,文件下载。是不同的。 所以客户端也应该有一个线程的集合来对线程进行统一的管理。

客户端使用对象流来进行读写信息。

图例

 二。开发阶段

1.登录功能实现

1.先创建三个类一个接口(服务端客户端都要有)

User:用于存储用户账号密码信息的

package com.qqcommon;

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1l;

    private String userId; //用户Id
    private String Password; //用户密码

    public User() {
    }

    public User(String userId, String password) {
        this.userId = userId;
        Password = password;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPassword() {
        return Password;
    }

    public void setPassword(String password) {
        Password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId='" + userId + '\'' +
                ", Password='" + Password + '\'' +
                '}';
    }
}

Message:用于存放用户信息

package com.qqcommon;

import java.io.Serializable;

public class Message implements Serializable {
    private static final long serialVersionUID = 1l;

    private String sender; // 发送者
    private String getter; //接收者
    private String content; //消息内容
    private String sendTime; //发送时间
    private String mesType; //消息类型

//    传送文件的成员变量
    private byte[] fileByte;
    private int fileLen =0;
    private String dest;//文件输入地址
    private String src;//文件输出地址

    public byte[] getFileByte() {
        return fileByte;
    }

    public void setFileByte(byte[] fileByte) {
        this.fileByte = fileByte;
    }

    public int getFileLen() {
        return fileLen;
    }

    public void setFileLen(int fileLen) {
        this.fileLen = fileLen;
    }

    public String getDest() {
        return dest;
    }

    public void setDest(String dest) {
        this.dest = dest;
    }

    public String getSrc() {
        return src;
    }

    public void setSrc(String src) {
        this.src = src;
    }

    public Message() {
    }

    public Message(String sender, String getter, String content, String sendTime, String mesType) {
        this.sender = sender;
        this.getter = getter;
        this.content = content;
        this.sendTime = sendTime;
        this.mesType = mesType;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    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 getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    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;
    }
}

MessageType:用于存放消息类型的接口(Message当中的一个属性)

package com.qqcommon;

public interface MessageType {
    String MESSAGE_LOGIN_SUCCESS = "1"; //登录验证成功
    String MESSAGE_LOGIN_FAIL = "2";  //验证登录失败
    String MESSAGE_COMM_MES = "3";  //消息类型为普通消息
    String MESSAGE_GET_ONLINE_FRIEND = "4";  //请求得到在线用户信息
    String MESSAGE_RET_ONLINE_FRIEND = "5";  //返回在线用户信息
    String MESSAGE_CLIENT_EXIT = "6"; //退出消息
    String MESSAGE_TO_ALL_MES = "7";//群发文件
    String MESSAGE_FILE_MES = "8";//发送文件
    String MESSAGE_GET_NOT_ONLINE_MES = "9"; //接收离线消息
    String MESSAGE_SET_NOT_ONLINE_MES = "10"; //发送离线消息
}
//可以扩展功能

Utility类

package com.utils;
/**
 工具类的作用:
 处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
 */

import java.util.Scanner;

/**

 */
public class Utility {
    //静态属性。。。
    private static Scanner scanner = new Scanner(System.in);


    /**
     * 功能:读取键盘输入的一个菜单选项,值:1——5的范围
     * @return 1——5
     */
    public static char readMenuSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1, false);//包含一个字符的字符串
            c = str.charAt(0);//将字符串转换成字符char类型
            if (c != '1' && c != '2' &&
                    c != '3' && c != '4' && c != '5') {
                System.out.print("选择错误,请重新输入:");
            } else break;
        }
        return c;
    }

    /**
     * 功能:读取键盘输入的一个字符
     * @return 一个字符
     */
    public static char readChar() {
        String str = readKeyBoard(1, false);//就是一个字符
        return str.charAt(0);
    }
    /**
     * 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
     * @param defaultValue 指定的默认值
     * @return 默认值或输入的字符
     */

    public static char readChar(char defaultValue) {
        String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
        return (str.length() == 0) ? defaultValue : str.charAt(0);
    }

    /**
     * 功能:读取键盘输入的整型,长度小于2位
     * @return 整数
     */
    public static int readInt() {
        int n;
        for (; ; ) {
            String str = readKeyBoard(10, false);//一个整数,长度<=10位
            try {
                n = Integer.parseInt(str);//将字符串转换成整数
                break;
            } catch (NumberFormatException e) {
                System.out.print("数字输入错误,请重新输入:");
            }
        }
        return n;
    }
    /**
     * 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
     * @param defaultValue 指定的默认值
     * @return 整数或默认值
     */
    public static int readInt(int defaultValue) {
        int n;
        for (; ; ) {
            String str = readKeyBoard(10, true);
            if (str.equals("")) {
                return defaultValue;
            }

            //异常处理...
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.print("数字输入错误,请重新输入:");
            }
        }
        return n;
    }

    /**
     * 功能:读取键盘输入的指定长度的字符串
     * @param limit 限制的长度
     * @return 指定长度的字符串
     */

    public static String readString(int limit) {
        return readKeyBoard(limit, false);
    }

    /**
     * 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
     * @param limit 限制的长度
     * @param defaultValue 指定的默认值
     * @return 指定长度的字符串
     */

    public static String readString(int limit, String defaultValue) {
        String str = readKeyBoard(limit, true);
        return str.equals("")? defaultValue : str;
    }


    /**
     * 功能:读取键盘输入的确认选项,Y或N
     * 将小的功能,封装到一个方法中.
     * @return Y或N
     */
    public static char readConfirmSelection() {
        System.out.println("请输入你的选择(Y/N): 请小心选择");
        char c;
        for (; ; ) {//无限循环
            //在这里,将接受到字符,转成了大写字母
            //y => Y n=>N
            String str = readKeyBoard(1, false).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("选择错误,请重新输入:");
            }
        }
        return c;
    }

    /**
     * 功能: 读取一个字符串
     * @param limit 读取的长度
     * @param blankReturn 如果为true ,表示 可以读空字符串。
     * 					  如果为false表示 不能读空字符串。
     *
     *	如果输入为空,或者输入大于limit的长度,就会提示重新输入。
     * @return
     */
    private static String readKeyBoard(int limit, boolean blankReturn) {

        //定义了字符串
        String line = "";

        //scanner.hasNextLine() 判断有没有下一行
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();//读取这一行

            //如果line.length=0, 即用户没有输入任何内容,直接回车
            if (line.length() == 0) {
                if (blankReturn) return line;//如果blankReturn=true,可以返回空串
        
  • 16
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值