快递综合-网络编程

快递综合-网络编程(包含的知识点 常用类库、集合、IO、多线程、网络编程) 作者:1222-张振亚
下面展示不同模块的代码: 快递源码

  1. 模块1 快递类
  2. 模块2 视图类
  3. 模块3 存储控制类
  4. 模块4 客户端
  5. 模块5 服务器

1.快递类

package Chapter4_Homework05.bean;

import java.io.Serializable;
import java.util.Objects;

/**
 * @program: 新职课作业代码
 * @description: 快递类
 * @author: 张振亚
 * @create: 2021-01-13 23:21
 **/

public class Express implements Serializable {
    private String number;  // 快递单号
    private String company; // 公司
    private int code;       // 取件码
    public int posX, posY;  // 快递所在快递柜中的位置

    // 构造方法
    public Express(String number, String company, int code) {
        this.number = number;
        this.company = company;
        this.code = code;
    }

    public Express() {
    }

    // getter/setter

    public String getNumber() {
        return number;
    }

    public String getCompany() {
        return company;
    }

    public int getCode() {
        return code;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public void setCode(int code) {
        this.code = code;
    }

    // 重写toString 方法

    @Override
    public String toString() {
        return "Express{" +
                "number='" + number + '\'' +
                ", company='" + company + '\'' +
                ", code=" + code +
                '}';
    }

    // 重写equals方法

    /**
     * 只要快递单号相同就认为快递相同
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Express express = (Express) o;
        return Objects.equals(number, express.number);
    }

    @Override
    public int hashCode() {
        return Objects.hash(code);
    }
}

2.视图类

package Chapter4_Homework05.view;

import Chapter4_Homework05.bean.Express;

import javax.print.DocFlavor;
import java.util.Collection;
import java.util.Scanner;

/**
 * @program: 新职课作业代码
 * @description: 视图类
 * @author: 张振亚
 * @create: 2021-01-13 23:22
 **/

/**
 * 视图层
 * 只负责展示视图 不包含其他任何逻辑
 */

public class View {
    public Scanner input = new Scanner(System.in);

    /**
     * 获得用户的角色选择输入,并进入相应的功能
     *
     * @return 返回功能码 1:管理原 2:普通用户 0:退出
     */
    public int menu() {
        System.out.println("根据提示输入功能序号:");
        System.out.println("1,管理员");
        System.out.println("2,普通用户");
        System.out.println("0,退出");
        String s = input.nextLine();
        int funcNum = -1;
        try {
            funcNum = Integer.parseInt(s);
        } catch (NumberFormatException e) {   // 格式异常 递归继续获取功能码
            return menu();
        }
        if (funcNum < 0 || funcNum > 2) {     // 功能码不合法
            return menu();
        }
        return funcNum;
    }

    /*
    -----------------------------------------------------------------
     */

    /**
     * 获得管理员输入的功能码
     *
     * @return 管理员输入的合法功能码 1:录入 2:修改 3:删除 4:查看所有 0:退出
     */
    public int gMenu() {
        System.out.println("根据提示输入功能序号:");
        System.out.println("1,快递录入");
        System.out.println("2,快递修改");
        System.out.println("3,快递删除");
        System.out.println("4,查看所有快递");
        System.out.println("0,退出");
        String s = input.nextLine();
        int funcNum = -1;
        try {
            funcNum = Integer.parseInt(s);
        } catch (NumberFormatException e) {   // 格式异常 递归继续获取功能码
            return gMenu();
        }
        if (funcNum < 0 || funcNum > 4) {     // 功能码不合法
            return gMenu();
        }
        return funcNum;
    }

    /**
     * 1快递员录入信息
     *
     * @return 返回包含了快递单号和快递公司的快递对象
     */
    public Express insert() {
        System.out.println("请根据提示输入快递信息:");
        System.out.print("请输入快递单号:");
        String number = input.nextLine();
        System.out.print("请输入快递公司:");
        String company = input.nextLine();
        Express e = new Express();
        e.setNumber(number);
        e.setCompany(company);
        return e;
    }

    /**
     * 2修改快递信息
     *
     * @param
     */
    public Express update() {
        System.out.print("请输入新的快递单号:");
        String number = input.nextLine();
        System.out.print("请输入新的快递公司");
        String company = input.nextLine();
        Express eNew = new Express();
        eNew.setNumber(number);
        eNew.setCompany(company);
//        eNew.setCode(e.getCode());
//        eNew.posX = e.posX;                                     // 保留快递柜存放快递的位置
//        eNew.posY = e.posY;
        return eNew;
    }

    /**
     * 3询问是否删除
     *
     * @return 给出快递管理员的选择 1:删除 2:取消
     */
    public int delete() {
        System.out.println("确认是否删除:");
        System.out.println("1,确认删除");
        System.out.println("2,取消删除");
        System.out.println("0,退出");
        String s = input.nextLine();
        int num = -1;
        try {
            num = Integer.parseInt(s);
        } catch (NumberFormatException e) {
            return delete();
        }
        if (num < 0 || num > 2) {
            return delete();
        }
        return num;
    }

    /**
     * 4遍历显示所有快递信息
     *
     * @param es
     */
    public void printAll(Collection<Express> es) {
        int count = 0;
        for (Express e : es) {
            count++;
            System.out.print("第" + (e.posX + 1) + "排," + (e.posY + 1) + "列, ");
            printExpress(e);
        }
        if (count == 0) {
            System.out.println("暂无快递信息");
        }
    }

    /**
     * 提示用户输入快递单号
     *
     * @return
     */
    public String findByNumber() {
        System.out.println("请根据提示输入快递信息:");
        System.out.print("请输入需要操作的快递单号:");
        String number = input.nextLine();
        return number;
    }

    /**
     * 显示快递信息
     *
     * @param e
     */
    public void printExpress(Express e) {
        if (e == null) {
            System.out.println("快递信息不存在");
            return;
        }
        System.out.println("快递信息如下:");
        System.out.println("快递公司:" + e.getCompany() + ",快递单号:" + e.getNumber() + ",取件码:" + e.getCode());
    }


    /*
    -----------------------------------------------------------------
     */

    /**
     * 获得用户输入的取件码(这里简化,只要取件码相同,就算取件成功)
     *
     * @return 用户输入的合法功能码(6位)
     */
    public int uMenu() {
        System.out.println("根据提示进行取件:");
        System.out.print("请输入取件码:");
        String s = input.nextLine();
        int funcNum = -1;
        try {
            funcNum = Integer.parseInt(s);
        } catch (NumberFormatException e) {   // 格式异常 递归继续获取功能码
            return uMenu();
        }
        if (funcNum < 100000 || funcNum > 999999) {     // 功能码不合法
            System.out.println("输入有误,请重试!");
            return uMenu();
        }
        return funcNum;
    }

    public void expressExist() {
        System.out.println("此快递单号已存在,请勿重复存储");
    }

    public void printCode(Express e) {
        System.out.println("新快递的取件码为:" + e.getCode());
    }

    public void success() {
        System.out.println("操作成功!");
    }

    public void printNull() {
        System.out.println("快递不存在,请检查输入");
    }
}

3.存储控制类

package Chapter4_Homework05.dao;

import Chapter4_Homework05.bean.Express;

import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Random;

/**
 * @program: 新职课作业代码
 * @description: 快递存储处理操作类
 * @author: 张振亚
 * @create: 2021-01-13 23:21
 **/

// 实现可序列化标记接口 使得dao对象支持序列化与反序列化
public class ExpressDao {
    private Random random = new Random();               // 用于生成随机数

    /**
     *
     * @param e 新加入的快递对象
     * @param cabinet 标记快递柜位置是否已被占用
     * @param data 所有的快递对象
     * @return
     */
    public Express add(Express e, boolean[][] cabinet, HashMap<Integer, Express> data){
        int size = data.size();
        if(size >= 100){
            return null;
        }
        // 1,随机生成两个0-9的下标
        int x = -1, y = -1;
        while (true){
            x = random.nextInt(10);
            y = random.nextInt(10);
            if(cabinet[x][y] == false){
                break;                                  // 此位置未被占用
            }
        }
        // 2,判断取件码是否重复(最简单的 一个个对比)
        int code = randomCode(data.values());            // 获得没有重复的取件码
        e.setCode(code);
        e.posX = x;                                     // 快递柜存放快递的位置
        e.posY = y;
        size++;                                         // 快递数目加一
        cabinet[x][y] = true;                           // 此位置已被占用
        data.put(code, e);                              // 添加键值对
        return e;
    }

    /**
     * 遍历所有对象 生成独一无二的取件码
     * @param expresses 所有的快递对象
     * @return
     */
    private int randomCode(Collection<Express> expresses){
        while (true) {
            int code = random.nextInt(900000) + 100000; // 范围(000000-899999)+1000000
            Express e = findByCode(code, expresses);
            if(e == null) { // 说明取件码未重复
                return code;
            }
        }
    }

    /**
     * 快递员根据快递单号查询HashMap中存放的快递
     * @param number
     * @return
     */
    public Express findByNumber(String number, Collection<Express> expresses){
        // 遍历HashMap中的Express对象 找到其快递单号相对应的那个对象并返回
        for(Express e : expresses) {
            if(e.getNumber().equals(number)) {
                return e;
            }
        }
        return null;
    }

    /**
     * 根据取件码查询快递
     * @param code 取件码
     * @return 查询到结果 查询失败返回null
     */
    public Express findByCode(int code, Collection<Express> expresses){
        for(Express e : expresses) {
            if(e.getCode() == code) {
                return e;
            }
        }
        return null;
    }

    /**
     * 多余的操作 为了MVC更圆润
     * @param oldExpress
     * @param newExpress
     */
    public Express update(Express oldExpress, Express newExpress, boolean[][] cabinet, HashMap<Integer, Express> data){
        newExpress.setCode(oldExpress.getCode());
        newExpress.posX = oldExpress.posX;
        newExpress.posY = oldExpress.posY;
        delete(oldExpress, cabinet, data);
        cabinet[newExpress.posX][newExpress.posY] = true;                           // 此位置已被占用
        data.put(newExpress.getCode(), newExpress);                              // 添加键值对
        return newExpress;
    }
    public void delete(Express e, boolean[][] cabinet, HashMap<Integer, Express> data){
        data.remove(e.getCode());
        cabinet[e.posX][e.posY] = false;
    }

    public HashMap<Integer, Express> load() throws IOException {
        HashMap<Integer, Express> data = new HashMap<>();
        try {
            FileInputStream fis = new FileInputStream("cat.txt");   //这里的路径不能写其他项目序列化出来的文件!!!!!!!!!!!!!!
            ObjectInputStream ois = new ObjectInputStream(fis);
            try (fis;ois) {
                data = (HashMap<Integer, Express>) ois.readObject();
            } catch (IOException | ClassNotFoundException e) {
                data = new HashMap<>();                 // 打开文件异常时 将data初始为空 在main函数结束时进行序列化
            }
        }catch (Exception e){
            data = new HashMap<>();                 // 打开文件异常时 将data初始为空 在main函数结束时进行序列化
        }
        return data;
    }

    //存储数据
    public void store(HashMap<Integer, Express> data) throws IOException {
        FileOutputStream fos = new FileOutputStream("cat.txt");   //这里的路径不能写其他项目序列化出来的文件!!!!!!!!!!!!!!
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(data);
        oos.close();
        fos.close();
        System.out.println("数据存储成功");
    }
}

4.客户端

package Chapter4_Homework05.client_self;

import Chapter4_Homework05.view.View;
import Chapter4_Homework05.bean.Express;
import Chapter4_Homework05.dao.ExpressDao;

import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;

/**
 * @program: 新职课作业代码
 * @description: 客户端(self)
 * @author: 张振亚
 * @create: 2021-01-16 11:51
 **/
public class Client_Self {
    // 这样可以跨方法使用

    private static Scanner input = new Scanner(System.in);

    // 初始化视图对象
    private static View v = new View();

    // 初始化dao对象
    private static ExpressDao dao = new ExpressDao();

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 传入本机地址和端口
        Socket socket = new Socket("127.0.0.1", 65534);
        // 向服务器发送请求
        System.out.println("正在向服务器发送请求");

        // 创建输入输出流
        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(os);
        ObjectInputStream ois = new ObjectInputStream(is);

        boolean[][] cabinet = new boolean[10][];    // 二维数组表示快递柜位置是否被占用
        HashMap<Integer, Express> data;             // HashMap存放 <取件码,快递对象>
        for (int i = 0; i < 10; i++) {
            cabinet[i] = new boolean[10];
        }

        data = (HashMap<Integer, Express>) ois.readObject();   //接收由服务器传过来的数据

        for (Express e : data.values()) {
            cabinet[e.posX][e.posY] = true;   // 表示此位置已被占用
        }

        //引入局部内部类 来解决socket对象无法在主函数外的静态方法内使用的问题!!!(没想到别的更好的办法)
        class UClient {
            void uClient(boolean[][] cabinet, HashMap<Integer, Express> data) throws IOException {
//        Collection<Express> expresses = data.values();// 获得所有快递对象 便于遍历查找
                // 1,获得取件码
                int code = v.uMenu();
                // 2,根据取件码取出快递
                Express e = dao.findByCode(code, data.values());
                if (e == null) {
                    v.printNull();
                } else {
                    oos.writeObject(e);
                    v.success();
                    v.printExpress(e);
                    dao.delete(e, cabinet, data);
                }
            }
        }

        class GClient {
            void gClient(boolean[][] cabinet, HashMap<Integer, Express> data) throws IOException {
                while (true) {
                    int menu = v.gMenu();
                    //给服务器发送用户选择的功能号
                    os.write(menu);
                    switch (menu) {
                        case 0:
                            return;
                        case 1: {                            // 快递录入
                            // 1,提示输入快递信息
                            Express e = v.insert();
                            // 2,此快递是否已经存储过
                            Express e2 = dao.findByNumber(e.getNumber(), data.values());
                            // 3,存储快递
                            if (e2 == null) {                 // 未存储过
                                oos.writeObject(dao.add(e, cabinet, data));   //将添加的快递对象发送给服务器   //data.put(code, e); !!!
                                v.printCode(e);
                            } else {                         // 单号重复
                                v.expressExist();
                            }
                            break;
                        }
                        case 2: {                           // 快递修改
                            // 1,提示输入快递信息
                            String number = v.findByNumber();
                            // 2,查找数据
                            Express e = dao.findByNumber(number, data.values());
                            // 3,打印快递信息
                            if (e == null) {
                                v.printNull();
                            } else {
                                v.printExpress(e);
                                oos.writeObject(e);
                                // 4,提示修改
                                Express eNew = v.update();               // 只穿回来修改了公司和快递单号的类
                                Express eNewUpdate = dao.update(e, eNew, cabinet, data);// 这里只是为了强调 删除-修改的过程
                                oos.writeObject(eNewUpdate);
                                v.printExpress(e);
                            }

                            break;
                        }
                        case 3: {                           // 删除
                            // 1,输入快递单号
                            String number = v.findByNumber();
                            // 2,查找快递对象
                            Express e = dao.findByNumber(number, data.values());
                            if (e == null) {
                                v.printNull();
                            } else {
                                oos.writeObject(e);
                                v.printExpress(e);
                                int type = v.delete();
                                if (type == 1) {
                                    dao.delete(e, cabinet, data);   //data.remove(e.getCode());   用键值删除 键值对
                                } else {
                                    v.success();
                                }
                            }
                            break;
                        }
                        case 4: {                            // 查看所有
                            v.printAll(data.values());      // 在视图层显示
                            break;
                        }
                    }
                }
            }
        }

        m:
        while (true) {
            //输入功能序号
            int menu = v.menu();

            //给服务器发送用户选择的功能号
            os.write(menu);

            switch (menu) {
                case 0:
                    break m;
                case 1:
                    new GClient().gClient(cabinet, data);
                    break;
                case 2:
                    new UClient().uClient(cabinet, data);
                    break;
            }
        }

        //用户使用完毕,将存在客户端内存中的数据发送给服务器!!!
        oos.writeObject(data);
    }
}

5.服务器

package Chapter4_Homework05.server_self;

import Chapter4_Homework05.view.View;
import Chapter4_Homework05.bean.Express;
import Chapter4_Homework05.dao.ExpressDao;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;

/**
 * @program: 新职课作业代码
 * @description: 快递主函数
 * @author: 张振亚
 * @create: 2021-01-13 23:20
 **/

public class Server_Self {
    // 这样可以跨方法使用

    private static Scanner input = new Scanner(System.in);

    // 初始化视图对象
    private static View v = new View();

    // 初始化dao对象
    private static ExpressDao dao = new ExpressDao();

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //启动服务器
        ServerSocket serverSocket = new ServerSocket(65534);

        //这里接收到客户端的socket,接下来用客户端的 socket对象 来使用方法,获取向客户端的输入流和输出流。
        //只要是用socket调用的输入流或输出流。(eg.OutputStream os = socket.getOutputStream();)
        //如果用socket获取的输入流,那么你所读入的数据来源就是你的客户端。
        //就比如(eg.new FileOutputStream("SerializedData.txt");)你的读入的数据来源就是这个引号里的文件。
        //同理,socket获取的输出流是你要写入文件的位置,即将数据写入(发送给)客户端。
        //然后有了输入输出流的位置以后,将这些字节流经过各种过滤器,将这个原始的数据流包装成你需要的或者对方能接受的编码类型。再进行发送或写入。
        // 等待连接

        System.out.println("服务器端已启动\n等待客户端连接...");

        while (true) {
            Socket socket = serverSocket.accept();
            System.out.println("连接客户端成功");
            System.out.println("等待客户端请求.....");

            //引入多线程技术
            new Thread(){
                // 1,弹出身份选择菜单
                @Override
                public void run() {
                    try {
                        // 创建输入输出流
                        InputStream is = socket.getInputStream();
                        OutputStream os = socket.getOutputStream();

                        ObjectOutputStream oos = new ObjectOutputStream(os);
                        ObjectInputStream ois = new ObjectInputStream(is);

                        boolean[][] cabinet = new boolean[10][];    // 二维数组表示快递柜位置是否被占用
                        HashMap<Integer, Express> data;             // HashMap存放 <取件码,快递对象>
                        for (int i = 0; i < 10; i++) {
                            cabinet[i] = new boolean[10];
                        }

                        try {
                            data = dao.load();   //将文件中的数据反序列化加载到data对象中!!!
                        } catch (IOException e) {
                            data = new HashMap<>();   // 打开文件异常时 将data初始为空 在main函数结束时进行序列化
                        }

                        oos.writeObject(data);   //将数据以序列化文件的格式发给客户端!!!

                        for (Express e : data.values()) {
                            cabinet[e.posX][e.posY] = true;   // 表示此位置已被占用
                        }

//引入局部内部类 来解决socket对象无法在主函数外的静态方法内使用的问题!!!
                        class UClient {
                            void uClient(boolean[][] cabinet, HashMap<Integer, Express> data) {
                                try {
                                    Express e = (Express)ois.readObject();
                                    data.remove(e.getCode(), e);
                                }catch (ClassNotFoundException | IOException e){
                                    System.out.println("取件失败!");
                                }
                            }
                        }

                        class GClient {
                            void gClient(boolean[][] cabinet, HashMap<Integer, Express> data) throws IOException {
                                while (true) {
                                    //接收客户端发送过来的功能号
                                    int menu = is.read();
                                    switch (menu) {
                                        case 0:
                                            return;
                                        case 1: {                            // 快递录入
                                            try {
                                                Express e = (Express)ois.readObject();
                                                data.put(e.getCode(), e);
                                            }catch (ClassNotFoundException e){
                                                System.out.println("添加快递失败!");
                                            }
                                            break;
                                        }
                                        case 2: {                           // 快递修改
                                            try {
                                                Express eOld = (Express)ois.readObject();
                                                Express eNew = (Express)ois.readObject();
                                                data.remove(eOld.getCode());
                                                data.put(eNew.getCode(), eNew);
                                            }catch (ClassNotFoundException e){
                                                System.out.println("修改快递失败!");
                                            }
                                            break;
                                        }
                                        case 3: {                           // 删除
                                            try {
                                                Express e = (Express)ois.readObject();
                                                data.remove(e.getCode(), e);
                                            }catch (ClassNotFoundException e){
                                                System.out.println("删除失败!");
                                            }
                                            break;
                                        }
                                        case 4: {                            // 查看所有
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        m:
                        while (true) {
                            //接收由客户端发送过来的功能号
                            int menu = is.read();

                            switch (menu) {
                                case 0:
                                    break m;
                                case 1:
                                    new GClient().gClient(cabinet, data);
                                    break;
                                case 2:
                                    new UClient().uClient(cabinet, data);
                                    break;
                            }
                        }


                        /**
                         * 序列化由客户端返回回来的数据 HashMap<Integer, Express> data
                         */
                        data = (HashMap<Integer, Express>) ois.readObject();  //接收 客户端使用结束后 传回来的客户端内存中的数据
                        dao.store(data);

                        // 在最后记得关闭连接
                        ois.close();
                        oos.close();
                    } catch (Exception e) {

                    }
                }
            }.start();
        }
    }
}
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值