1、视图

  1. package java03.com.app.core.section6.express5;
  2. import java.util.ArrayList;
  3. import java.util.Scanner;
  4. /**
  5. * @Author: deemoHui
  6. * @Description: 视图类,负责显示
  7. * @Date Created in 2020-08-07 21:41
  8. * @Modified By:
  9. */
  10. public class View {
  11. Scanner input = new Scanner(System.in);
  12. /**
  13. * 输出欢迎界面
  14. */
  15. public void welcome() {
  16. System.out.println("欢迎使用战翼快递柜系统!(点击屏幕进入操作菜单)");
  17. }
  18. /**
  19. * 拜拜界面
  20. */
  21. public void bye() {
  22. System.out.println("欢迎下次使用。");
  23. }
  24. /**
  25. * 初始操作选择界面
  26. *
  27. * @return 操作指令
  28. */
  29. public int identityView() {
  30. System.out.println("------------------------------------------------------------------------");
  31. System.out.println("请选择操作类型(输入 0/1/2):");
  32. System.out.println("1:管理快递");
  33. System.out.println("2:取件");
  34. System.out.println("0:退出");
  35. int command;
  36. try {
  37. command = Integer.parseInt(input.nextLine());
  38. } catch (RuntimeException e) {
  39. System.out.println("您输入的命令格式不正确,请重新选择。");
  40. return identityView();
  41. }
  42. if (command < 0 || command > 2) {
  43. System.out.println("您输入的命令不存在,请重新选择。");
  44. return identityView();
  45. }
  46. return command;
  47. }
  48. /**
  49. * 身份验证界面
  50. *
  51. * @return 验证信息
  52. */
  53. public String[] authenticationView() {
  54. System.out.println("------------------------------------------------------------------------");
  55. System.out.println("您选择了管理快递,请进行身份验证:");
  56. System.out.println("请输入您的管理员帐号:");
  57. String account = input.nextLine();
  58. System.out.println("请输入您的管理员密码:");
  59. String password = input.nextLine();
  60. String[] messages = new String[2];
  61. messages[0] = account;
  62. messages[1] = password;
  63. return messages;
  64. }
  65. /**
  66. * 管理员身份验证成功
  67. */
  68. public void authenticationSuccess() {
  69. System.out.println("身份验证成功,欢迎你,亲爱的管理员!");
  70. }
  71. /**
  72. * 管理员身份验证失败
  73. */
  74. public void authenticationFail() {
  75. System.out.println("身份验证失败,请输入正确的账号密码!");
  76. }
  77. /**
  78. * 管理员操作菜单
  79. *
  80. * @return 操作指令
  81. */
  82. public int administratorMenu() {
  83. System.out.println("------------------------------------------------------------------------");
  84. System.out.println("欢迎使用管理员系统,请选择您要执行的操作(输入相应操作的数字:0/1/2/3/4):");
  85. System.out.println("1: 快递信息录入");
  86. System.out.println("2: 删除快递");
  87. System.out.println("3: 快递信息修改");
  88. System.out.println("4: 查看当前所有快递");
  89. System.out.println("0: 退出");
  90. int command;
  91. try {
  92. command = Integer.parseInt(input.nextLine());
  93. } catch (RuntimeException e) {
  94. System.out.println("您输入的命令格式不正确,请重新选择。");
  95. return administratorMenu();
  96. }
  97. if (command < 0 || command > 4) {
  98. System.out.println("您输入的命令不存在,请重新选择。");
  99. return administratorMenu();
  100. }
  101. return command;
  102. }
  103. /**
  104. * 用户操作菜单
  105. *
  106. * @return 取件码
  107. */
  108. public int userMenu() {
  109. System.out.println("------------------------------------------------------------------------");
  110. System.out.println("请输入您的取件码进行取件:");
  111. int code;
  112. try {
  113. code = Integer.parseInt(input.nextLine());
  114. } catch (RuntimeException e) {
  115. System.out.println("格式有误,请重新输入。");
  116. return userMenu();
  117. }
  118. if (code < 100000 || code > 999999) {
  119. System.out.println("取件码格式错误,请重新输入。");
  120. return userMenu();
  121. }
  122. return code;
  123. }
  124. /**
  125. * 快递信息录入
  126. *
  127. * @return 快递
  128. */
  129. public Express addView() {
  130. System.out.println("------------------------------------------------------------------------");
  131. System.out.println("请输入快递单号:");
  132. String number = input.nextLine();
  133. System.out.println("请输入快递公司:");
  134. String company = input.nextLine();
  135. return new Express(number, company);
  136. }
  137. /**
  138. * 获取用户输入的单号
  139. *
  140. * @return 单号
  141. */
  142. public String getExpressNumberView() {
  143. System.out.println("------------------------------------------------------------------------");
  144. System.out.println("请输入要操作的快递单号:");
  145. return input.nextLine();
  146. }
  147. /**
  148. * 显示快递的详细信息
  149. *
  150. * @param express:快递
  151. */
  152. public void showExpressView(Express express) {
  153. System.out.println("快递详细信息:");
  154. System.out.println("------------------------------------------------------------------------");
  155. System.out.println("快递在第" + express.getPosition() + "号柜子:");
  156. System.out.println("快递单号:" + express.getNumber());
  157. System.out.println("快递公司:" + express.getCompany());
  158. System.out.println("取件码:" + express.getCode());
  159. System.out.println();
  160. }
  161. /**
  162. * 根据单号删除快递
  163. *
  164. * @return 是否进行删除
  165. */
  166. public String deleteView() {
  167. System.out.println("------------------------------------------------------------------------");
  168. System.out.println("是否进行删除(y/n)");
  169. String command = input.nextLine();
  170. if (command.equals("y") || command.equals("n")) {
  171. return command;
  172. } else {
  173. System.out.println("命令不存在!, 请重新输入。");
  174. return deleteView();
  175. }
  176. }
  177. /**
  178. * 修改快递信息,相当于不要原来的了,新生成一个新的,把原来的删了
  179. *
  180. * @return 新的快递,或者说修改后的快递
  181. */
  182. public Express updateView() {
  183. System.out.println("------------------------------------------------------------------------");
  184. System.out.println("请输入新的快递单号:");
  185. String number = input.nextLine();
  186. System.out.println("请输入新的快递公司:");
  187. String company = input.nextLine();
  188. return new Express(number, company);
  189. }
  190. /**
  191. * 显示所有快递信息
  192. *
  193. * @param expresses:快递柜
  194. */
  195. public void showAllExpressView(ArrayList<Express> expresses) {
  196. int count = 0;
  197. if (expresses == null) {
  198. System.out.println("当前没有快递。");
  199. } else {
  200. for (int i = 0; i < 101; i++) {
  201. if (expresses.get(i) == null) continue;
  202. count++;
  203. System.out.print("第" + count + "个");
  204. showExpressView(expresses.get(i));
  205. }
  206. }
  207. }
  208. /**
  209. * 提示尽快取走快递
  210. */
  211. void printGet(){
  212. System.out.println("请尽快取走快递");
  213. }
  214. /**
  215. * 操作成功
  216. */
  217. public void success() {
  218. System.out.println("操作成功!");
  219. }
  220. /**
  221. * 添加快递失败
  222. */
  223. public void addFailure() {
  224. System.out.println("操作失败!快递柜已满,请等待取件后重新操作。");
  225. }
  226. /**
  227. * 取件失败
  228. */
  229. public void getFailure() {
  230. System.out.println("取件码错误!");
  231. }
  232. /**
  233. * 没有查找到快递
  234. */
  235. public void getNull() {
  236. System.out.println("查无此快递。");
  237. }
  238. /**
  239. * 快递已经存在
  240. */
  241. public void exist() {
  242. System.out.println("此快递已经存在。");
  243. }
  244. }

2、快递类

package java03.com.app.core.section6.express5;

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

/**
 * @Author: deemoHui
 * @Description: 快递类,属性包括 快递单号,快递公司,取件码,快递位置,取件码可以不要了,不过先保留
 * @Date Created in 2020-08-07 21:41
 * @Modified By:
 */
public class Express implements Serializable {
    /**
     * 单号
     */
    private String number;
    /**
     * 快递公司
     */
    private String company;
    /**
     * 取件码
     */
    private int code;
    // 位置 初始值为 -1 ,因为int默认初始值为0,但是每个快递刚开始是没有位置的
    private int position = -1;

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Express express = (Express) o;
        return number.equals(express.number);
    }

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


    public Express() {
    }

    public Express(String number, String company) {
        this.number = number;
        this.company = company;
    }

    public String getNumber() {
        return number;
    }

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

    public String getCompany() {
        return company;
    }

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

    public int getCode() {
        return code;
    }

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

3、快递数据类

package java03.com.app.core.section6.express5;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

/**
 * @Author: deemoHui
 * @Description: 快递数据类,主要负责快递数据的存入,删除,更改
 * @Date Created in 2020-08-07 21:41
 * @Modified By:
 */
public class ExpressData implements Serializable {
    // 快递柜大小为 100,为了使快递柜号码从 1 开始,设置为101
    private ArrayList<Express> expresses = new ArrayList<>(101);
    // 取件码 --> 快递柜号码
    private HashMap<Integer, Integer> codeToExpressCabinetNumber = new HashMap<>();
    // 快递单号 --> 快递柜号码
    private HashMap<String, Integer> numberToExpressCabinetNumber = new HashMap<>();
    // 定义一个 count 用来记录存储了多少快递
    private int count = 0;
    // 实例化一个随机器,用来随机生成取件码
    private final Random random = new Random();

    public ExpressData() {
        // 初始化快递柜,值默认为null
        for (int i = 0; i < 101; i++) {
            expresses.add(null);
        }
    }

    /**
     * 用来往快递柜添加快递
     *
     * @param express:快递
     * @return 是否添加成功
     */
    public boolean add(Express express) {
        // 快递满了就直接返回
        if (count == 100) {
            return false;
        }

        // 说明一定有位置
        int cabinetNumber = 1;
        // 如果能得到值,说明快递柜有快递
        while (expresses.get(cabinetNumber) != null) {
            cabinetNumber++;
        }
        // 每放入一个快递,都应该生成一个取件码,一定要注意要在生成取件码之后,再把快递存入
        int code = generateCode();
        express.setCode(code);
        express.setPosition(cabinetNumber);
        // 向cabinetNumber位置放入快递,用set因为固定长度,用add它会导致扩容
        expresses.set(cabinetNumber, express);
        // 把取件码和快递柜号码关联
        codeToExpressCabinetNumber.put(code, cabinetNumber);
        // 把快递单号和快递柜号码关联
        numberToExpressCabinetNumber.put(express.getNumber(), cabinetNumber);
        count++;
        return true;
    }

    /**
     * 生成不重复的取件码
     *
     * @return 取件码
     */
    private int generateCode() {
        // 取件码生成和去重
        while (true) {
            // 取件码范围 100000 - 999999;
            int code = random.nextInt(900000) + 100000;
            // 根据生成的取件码寻找快递
            Express express = findExpressByCode(code);
            // 如果不存在这个快递,说明取件码不重复
            if (express == null) {
                return code;
            }
        }
    }


    /**
     * 删除快递
     *
     * @param express:快递
     * @return 是否删除成功
     */
    public boolean delete(Express express) {
        // 根据单号得到快递的位置,返回null,说明没有这个单号
        Integer cabinetNumber = numberToExpressCabinetNumber.get(express.getNumber());
        // cabinetNumber不为null,说明有
        if (cabinetNumber != null) {
            // 根据快递位置,删除快递,其实是把这个位置变为null
            expresses.set(cabinetNumber, null);
            // 把另外的映射删掉
            numberToExpressCabinetNumber.remove(express.getNumber());
            codeToExpressCabinetNumber.remove(express.getCode());
            // 删除快递之后,需要减少快递数量
            count--;
            return true;
        }
        return false;

    }

    /**
     * 更新快递柜中快递,删除要修改的,增加新的
     *
     * @param oldExpress 要修改的快递
     * @param newExpress 修改过的快递
     */
    public void update(Express oldExpress, Express newExpress) {
        // 删除旧快递
        delete(oldExpress);
        // 添加新快递
        add(newExpress);
    }

    /**
     * 返回所有快递
     *
     * @return 所有快递
     */
    public ArrayList<Express> findAll() {
        // 如果count > 0, 说明有快递,否则说明没有
        return count > 0 ? expresses : null;
    }

    /**
     * 根据取件码寻找快递
     *
     * @param code 取件码
     * @return 快递
     */
    public Express findExpressByCode(int code) {
        // cabinetNumber 引用类型,可能为null,需要判断
        Integer cabinetNumber = codeToExpressCabinetNumber.get(code);
        if (cabinetNumber != null) {
            return expresses.get(cabinetNumber);
        }
        return null;

    }

    /**
     * 根据快递单号寻找快递
     *
     * @param number 快递单号
     * @return 快递
     */
    public Express findExpressByNumber(String number) {
        // cabinetNumber 引用类型,可能为null,需要判断
        Integer cabinetNumber = numberToExpressCabinetNumber.get(number);
        if (cabinetNumber != null) {
            return expresses.get(cabinetNumber);
        }
        return null;
    }

    public ArrayList<Express> getExpresses() {
        return expresses;
    }

    public void setExpresses(ArrayList<Express> expresses) {
        this.expresses = expresses;
    }

    public HashMap<Integer, Integer> getCodeToExpressCabinetNumber() {
        return codeToExpressCabinetNumber;
    }

    public void setCodeToExpressCabinetNumber(HashMap<Integer, Integer> codeToExpressCabinetNumber) {
        this.codeToExpressCabinetNumber = codeToExpressCabinetNumber;
    }

    public HashMap<String, Integer> getNumberToExpressCabinetNumber() {
        return numberToExpressCabinetNumber;
    }

    public void setNumberToExpressCabinetNumber(HashMap<String, Integer> numberToExpressCabinetNumber) {
        this.numberToExpressCabinetNumber = numberToExpressCabinetNumber;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "ExpressData{" +
                "expresses=" + expresses +
                '}';
    }
}

4、服务器

package java03.com.app.core.section6.express5;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: deemoHui
 * @Description: 快递管理服务器
 * @Date Created in 2020-08-10 21:51
 * @Modified By:
 */
public class ExpressServer {
    // 快递柜
    private ExpressData expressData;
    // 服务器套接字
    private ServerSocket ss;
    // 缓存线程池
    private ExecutorService service;
    // 管理员账号数组 假设只有三个管理员,账密位置一一对应
    private final String[] accountData = {"admin1", "admin2", "admin3"};
    // 管理员密码数组 假设只有三个管理员
    private final String[] passwordData = {"123", "456", "789"};

    public ExpressServer() {
        initial();
    }

    /**
     * 程序入口,负责启动服务器
     *
     * @param args 参数
     */
    public static void main(String[] args) {
        ExpressServer expressServer = new ExpressServer();
    }

    /**
     * 初始化视图和快递柜,读取快递资料
     */
    public void initial() {
        // 初始化服务器套接字
        try {
            ss = new ServerSocket(9276);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 初始化缓存线程池
        service = Executors.newCachedThreadPool();

        // 和Expresses.data链接
        File data = new File("D:\\data\\Expresses.data");
        // 如果存在
        if (data.exists()) {
            // 加载数据
            ObjectInputStream ois = null;
            try {
                // 反序列化对象
                ois = new ObjectInputStream(new FileInputStream(data));
                expressData = (ExpressData) ois.readObject();
                // 关闭读取对象
                ois.close();
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }finally {
                if (ois != null){
                    try {
                        ois.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 不存在则需要初始化
        } else {
            expressData = new ExpressData();
        }
        System.out.println("服务器初始化完毕,等待链接");
        management();

    }

    /**
     * 快递管理,接收客户端链接
     */
    public void management() {
        while (true) {
            try {
                Socket socket = ss.accept();
                System.out.println("一个客户端已经连接");
                service.execute(() -> receive(socket));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 接收到的客户端命令
     *
     * @param socket 客户端链接服务器的套接字
     */
    void receive(Socket socket) {
        InputStream is = null;
        OutputStream os = null;
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
        try {
            is = socket.getInputStream();
            os = socket.getOutputStream();
            ois = new ObjectInputStream(is);
            oos = new ObjectOutputStream(os);
            w:
            while (true) {
                switch (ois.readInt()) {
                    case 0:
                        saveData();
                        System.out.println("快递信息已更新");
                        System.out.println("一个客户端断开连接");
                        break w;
                    case 1:
                        if (login(ois, oos)) {
                            adminCommand(ois, oos);
                        }
                        break;
                    case 2:
                        userCommand(ois, oos);
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            try {
                if(ois!=null) {
                    ois.close();
                }
                if(oos!=null) {
                    oos.close();
                }
                if(socket!=null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    // ------------------------------- 管理员 --------------------------------------------- //

    /**
     * 登录
     *
     * @param ois 反序列化
     * @param oos 序列化
     * @return 登录成功与否
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    boolean login(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        String[] messages = (String[]) ois.readObject();
        // 账号
        String account = messages[0];
        // 密码
        String password = messages[1];
        boolean state = authentication(account, password);
        oos.writeObject(state);
        oos.flush();
        return state;
    }

    /**
     * 身份验证
     *
     * @param account  :账号
     * @param password : 密码
     * @return 验证是否成功
     */
    public boolean authentication(String account, String password) {
        for (int i = 0; i < 3; i++) {
            if (accountData[i].equals(account)) {
                if (passwordData[i].equals(password)) return true;
            }
        }
        return false;
    }

    /**
     * 管理员管理操作
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void adminCommand(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        while (true) {
            // 获取操作命令
            int command = ois.readInt();
            switch (command) {
                case 1: {
                    insert(ois, oos);
                    break;
                }
                case 2: {
                    // 删除快递
                    delete(ois, oos);
                    break;
                }
                case 3: {
                    // 快递信息修改
                    update(ois, oos);
                    break;
                }
                case 4: {
                    // 查看当前所有快递
                    showAll(oos);
                    break;
                }
                // 退出
                case 0:
                    return;
            }
        }

    }

    /**
     * 增加快递
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void insert(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        Express express = (Express) ois.readObject();
        boolean exist = (findByNumber(express.getNumber()) != null);
        oos.writeObject(exist);
        oos.flush();
        if (!exist) {
            oos.writeObject(expressData.add(express));
            oos.flush();
        }
    }

    /**
     * 删除
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void delete(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        String expressNumber = (String) ois.readObject();
        Express express = findByNumber(expressNumber);
        oos.writeObject(express);
        oos.flush();
        if (express == null) {
            return;
        }
        String command = (String) ois.readObject();
        if (command.equals("y")) {
            oos.writeObject(expressData.delete(express));
            oos.flush();
        }

    }

    /**
     * 修改快递
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void update(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        String expressNumber = (String) ois.readObject();
        Express oldExpress = findByNumber(expressNumber);
        oos.writeObject(oldExpress);
        oos.flush();
        // 不存在此快递
        if (oldExpress == null) {
            return;
        }
        Express newExpress = (Express) ois.readObject();
        expressData.update(oldExpress, newExpress);
        newExpress = findByNumber(newExpress.getNumber());
        oos.writeObject(newExpress);
        oos.flush();
    }

    /**
     * 根据单号查找快递
     *
     * @param expressNumber 单号
     * @return 快递
     */
    Express findByNumber(String expressNumber) {
        return expressData.findExpressByNumber(expressNumber);
    }


    /**
     * 显示所有快递
     *
     * @param oos 输出流
     * @throws IOException 异常
     */
    void showAll(ObjectOutputStream oos) throws IOException {
        ArrayList<Express> expresses = expressData.findAll();
        if (expresses != null) System.out.println(expresses.toString());
        oos.writeObject(expresses);
        oos.flush();
    }


    // ------------------------------- 用户 --------------------------------------------- //

    /**
     * 用户命令
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException 异常
     */
    void userCommand(ObjectInputStream ois, ObjectOutputStream oos) throws IOException {
        int code = ois.readInt();
        Express express = getExpress(code);
        oos.writeObject(express);
        oos.flush();
        if (express == null) return;
        // 取件之后不要忘记从快递柜子删除
        expressData.delete(express);

    }

    /**
     * 取快递
     *
     * @param code 取件码
     * @return 快递
     */
    Express getExpress(int code) {
        return expressData.findExpressByCode(code);
    }

    /**
     * 保存快递信息
     */
    void saveData() {
        // 保存本次的快递资料
        try {
            File data = new File("D:\\data\\Expresses.data");
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(data));
            oos.writeObject(expressData);
            oos.flush();
            // 关闭输出流
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5、客户端

package java03.com.app.core.section6.express5;

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;

/**
 * @Author: deemoHui
 * @Description: 客户端
 * @Date Created in 2020-08-12 9:36
 * @Modified By:
 */
public class Client {
    // 视图
    View view = new View();
    Socket socket;

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    /**
     * 客户端启动
     */
    void start() {
        InputStream is;
        OutputStream os;
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
        // 连接服务器
        try {
            socket = new Socket("127.0.0.1", 9276);
            view.welcome();
            os = socket.getOutputStream();
            oos = new ObjectOutputStream(os);
            is = socket.getInputStream();
            ois = new ObjectInputStream(is);
            w:
            while (true) {
                int IDCommand = view.identityView();
                oos.writeInt(IDCommand);
                oos.flush();
                switch (IDCommand) {
                    // 管理
                    case 1: {
                        if (login(ois, oos)) {
                            view.authenticationSuccess();
                            administrator(ois, oos);
                        } else {
                            view.authenticationFail();
                        }
                        break;
                    }
                    // 取件
                    case 2: {
                        user(ois, oos);
                        break;
                    }
                    // 退出
                    case 0:
                        view.bye();
                        break w;
                }

            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            try {
                if(ois!=null) {
                    ois.close();
                }
                if(oos!=null) {
                    oos.close();
                }
                if(socket!=null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    // ------------------------------ 管理员 ------------------------------------------- //

    /**
     * 登录
     *
     * @param ois 输入流
     * @param oos 输出流
     * @return 是否登陆成功
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    boolean login(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        // 得到身份验证视图返回的验证信息
        String[] messages = view.authenticationView();
        oos.writeObject(messages);
        oos.flush();
        return (boolean) ois.readObject();
    }

    /**
     * 管理员操作
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void administrator(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        while (true) {
            // 获取操作命令
            int command = view.administratorMenu();
            // 只要这边一操作,就告诉服务器
            oos.writeInt(command);
            oos.flush();
            switch (command) {
                case 1: {
                    insert(ois, oos);
                    break;
                }
                case 2: {
                    // 删除快递
                    delete(ois, oos);
                    break;
                }
                case 3: {
                    // 快递信息修改
                    update(ois, oos);
                    break;
                }
                case 4: {
                    // 查看当前所有快递
                    showAll(ois);
                    break;
                }
                // 退出
                case 0:
                    return;
            }
        }
    }


    /**
     * 添加快递
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void insert(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        // 添加快递 需要考虑这个快递是否已经在快递柜
        Express express = view.addView();
        oos.writeObject(express);
        oos.flush();
        boolean exist = (boolean) ois.readObject();
        // 已经存在
        if (exist) {
            view.exist();
            return;
        }
        // 不存在 需要考虑能否添加成功(即快递柜是否还有位置)
        if ((boolean) ois.readObject()) {
            view.success();
        } else {
            view.addFailure();
        }
    }

    /**
     * 删除快递
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void delete(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        // 得到需要操作的快递单号
        String expressNumber = view.getExpressNumberView();
        oos.writeObject(expressNumber);
        oos.flush();
        // 根据单号查找快递
        Express express = (Express) ois.readObject();
        // 不存在此快递
        if (express == null) {
            view.getNull();
        } else {
            // 打印快递信息
            view.showExpressView(express);
            String deleteCommand = view.deleteView();
            oos.writeObject(deleteCommand);
            oos.flush();
            if (deleteCommand.equals("y")) {
                if ((boolean) ois.readObject()) view.success();
            }
        }
    }

    /**
     * 修改快递
     *
     * @param ois 输入流
     * @param oos 输出流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void update(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
        // 输入要修改的快递单号
        String expressNumber = view.getExpressNumberView();
        oos.writeObject(expressNumber);
        oos.flush();
        // 按照快递单号从服务器找到快递
        Express oldExpress = (Express) ois.readObject();

        // 不存在此快递
        if (oldExpress == null) {
            view.getNull();
        } else {
            // 显示快递信息
            view.showExpressView(oldExpress);
            // 更新快递
            Express newExpress = view.updateView();
            oos.writeObject(newExpress);
            oos.flush();
            // 接收服务器更新之后的快递,这样更新之后才有取件码
            newExpress = (Express) ois.readObject();
            view.showExpressView(newExpress);
            view.success();
        }
    }

    /**
     * 显示所有快递
     *
     * @param ois 输入流
     * @throws IOException            异常
     * @throws ClassNotFoundException 异常
     */
    void showAll(ObjectInputStream ois) throws IOException, ClassNotFoundException {
//        String e = (String) ois.readObject();
//        ArrayList<Express> expresses = new ArrayList<>(Integer.parseInt(e));
        ArrayList<Express> expresses = (ArrayList<Express>) ois.readObject();
        if (expresses != null) System.out.println(expresses.toString());
        view.showAllExpressView(expresses);
    }


    // --------------------------------- 用户 ---------------------------- //

    /**
     * 用户
     *
     * @param ois 输入流
     * @param oos 输出流
     */

    void user(ObjectInputStream ois, ObjectOutputStream oos) {
        // 输入取件码
        int code = view.userMenu();
        Express express = null;
        try {
            // 把取件码传回服务器查询到快递
            oos.writeInt(code);
            oos.flush();
            express = (Express) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 没有找到快递就认为取件码不正确,因为取件码只有放进柜子才会有取件码
        if (express == null) {
            view.getFailure();
        } else {
            view.showExpressView(express);
            view.printGet();
            view.success();
        }
    }

}