Express management console simple version - adding multi-threading and network programming (full version, complete source code attached) (Java)


For the array storage version, please refer to the article: Express Management Console Simple Version - Array Storage Version (Java)

For the List collection storage version, please refer to the article: Express Management Console Simple Version - List Collection Storage Version (Java)

For the Map collection storage version, please refer to the article: Express Management Console Simple Version - Map Collection Storage Version (Java)

Using IO technology to implement data storage based on the Map collection storage version can refer to the article: Express Management Console Simple Version - Use of IO Streams (Java)

  • The array storage version usesTwo-dimensional arrayTo store express delivery, the express delivery position corresponds to the two subscripts of the two-dimensional array.

  • List collection storage version adoptsList collectionStore express delivery

  • Map collection storage version adoptsMap collectionThe advantage of using a Map collection to store express delivery is that Map is a key-value pair , the key is the express delivery number, and the value is the express delivery object, ensuring that the express delivery number is unique

  • The use of IO streams is optimized based on the Map collection storage version. IO technology is used to store express data in files and read data from files. After the file stores express information, it can be read from the file every time the application is started . content, so that the program data always exists

  • Regarding multi-threading and network programming , multi-threading and network programming technology are added to realize data interaction between the client and the server, and multi-threading is used so that after each user sends a login request to the server, the server allocates a thread to process the request.


specific requirement

  1. Implement the user login function based on network programming mode, and understand the concepts of client and server. The client is used to obtain user information, and the server is used for data storage and logical judgment.
  2. On the basis of network programming, multi-threading mode is enabled on the server side and each user is required to send a login request to the server. The server side allocates a thread to process the request to realize user login in server-side multi-threading mode.

Involving knowledge points

  1. object-oriented
  2. gather
  3. IO
  4. Multithreading
  5. network programming

Ideas and code implementation

1. Custom exceptions

Create an exception package and create a new class OutNumberBoundException

OutNumberBoundException

public class OutNumberBoundException extends Throwable {
    
    
    public OutNumberBoundException(String s) {
    
    
        super(s);
    }
}

2. Tool Kit

Create a util package and create a new class IOUtil

IOUtil

File reading and writing tool class, so static methods are recommended

  • Read data from the specified file
public static Object readFile(String fileName) throws IOException, ClassNotFoundException {
    
    
        FileInputStream fis = new FileInputStream(fileName);//指定文件
        ObjectInputStream ois = new ObjectInputStream(fis);
        return ois.readObject();//读出数据
    }
  • Write data to the specified file
 public static void writeFile(Object obj,String fileName) throws IOException {
    
    
        FileOutputStream fos = new FileOutputStream(fileName);//指定文件
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);//写入数据obj
    }

3. Object

Create a pojo package and create a new class Express

Express

  • Define properties and set and get values ​​with setters and getters
	private String number;//快递单号
    private String company;//公司
    private int code;//取件码
    private int x;
    private int y;
    
	 /**
     * 使用setter和getter设置和获取值
     */
    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;
    }

    public int getX() {
    
    
        return x;
    }

    public void setX(int x) {
    
    
        this.x = x;
    }

    public int getY() {
    
    
        return y;
    }

    public void setY(int y) {
    
    
        this.y = y;
    }
  • Define no-parameter and full-parameter constructors
/**
     * 定义无参构造方法
     */
    public Express() {
    
    
    }

    /**
     * 定义全参构造方法
     */
    public Express(String number, String company, int code, int x, int y) {
    
    
        this.number = number;
        this.company = company;
        this.code = code;
        this.x = x;
        this.y = y;
    }
  • Override toString to convert information into a string
    /**
     * toString将信息转化为字符串形式
     */
    @Override
    public String toString() {
    
    
        return "快递信息[" +
                "快递单号:" + getNumber() + ' ' +
                ", 快递公司:" + getCompany() + ' ' +
                ", 取件码:" + getCode() + " , 在第" + (getX() + 1) + "行 第" + (getY() + 1) + "列柜子" +
                ']';
    }

4. Data processing

Create a dao package and create a new class Dao

Dao

  • Create files and initialize data
    public static final String FILE_NAME = "快递信息.txt";
    
    //静态 代码块
    static {
    
    
        File file = new File(FILE_NAME);
        if (!file.exists()){
    
    //如果文件不存在,创建文件
            try {
    
    
                if (file.createNewFile()){
    
    //创建文件名为FILE_NAME的文件
                    System.out.println("第一次启动项目,创建储存文件成功!");
                }
            } catch (IOException e) {
    
    
                System.out.println(e.getMessage());
            }
        }
    }
    
    //初始化数据
    public Dao() {
    
    
        //从文件中读取数据
        try {
    
    
            Object obj = IOUtil.readFile(FILE_NAME);
            if (obj!=null && obj instanceof List){
    
    
                expressList = (List<Express>) obj;
            }
        }catch (IOException | ClassNotFoundException e) {
    
    
            System.out.println(e.getMessage());
        }
    }
  • Add courier
    public static Express add(Express express) throws Exception {
    
    
        Random random = new Random();
        if (expressList.size() == 100) {
    
    
            System.out.println("快递柜已存满!");
            return null;
        }
        int x, y;
        do {
    
    
            x = random.nextInt(10);
            y = random.nextInt(10);
        } while (isExist(x, y));

        int code;
        do {
    
    
            code = random.nextInt(900000) + 100000;
        } while (isExistCode(code));
        express.setCode(code);
        express.setX(x);
        express.setY(y);
        expressList.add(express);
        IOUtil.writeFile(expressList,FILE_NAME);//更新文档中的数据
        return express;
    }

  • Determine whether a courier already exists at the current location
    public static boolean isExist(int x, int y) {
    
    
        for (Express express : expressList) {
    
    
            if (express.getX() == x && express.getY() == y) {
    
    
                return true;
            }
        }
        return false;
    }
  • Determine whether the randomly generated pickup code exists
    public static boolean isExistCode(int code) {
    
    
        for (Express express : expressList) {
    
    
            if (express.getCode() == code) {
    
    
                return true;
            }
        }
        return false;
    }
  • Delete express
    public static boolean delete(String number) throws Exception {
    
    
        int index = findByNumber(number);
        if (index == -1) {
    
    
            return false;
        }
        expressList.remove(index);//删除快递的操作
        IOUtil.writeFile(expressList,FILE_NAME);
        return true;
    }
  • Query express delivery based on express delivery number
    public static int findByNumber(String number) {
    
    
        int i = 0;
        for (Express express : expressList) {
    
    
            if (number.equals(express.getNumber())) {
    
    
                return i;
            }
            i++;
        }
        return -1;
    }
  • Update Express
    public static boolean update(String number, Express newExpress) throws Exception {
    
    
        int index = findByNumber(number);
        if (index == -1) {
    
    
            System.out.println("快递不存在!");
            return false;
        }
        Express express1 = expressList.get(index);
        express1.setNumber(newExpress.getNumber());
        express1.setCompany(newExpress.getCompany());
        IOUtil.writeFile(expressList,FILE_NAME);//数据加入
        return true;
    }
  • Get all courier information
    public static List<Express> getExpressList() {
    
    
        return expressList;
    }
  • Pick up courier
    public Express findByCodeAndDelete(int code) throws Exception {
    
    
        Express express = findExpressByCode(code);
        if (express!=null){
    
    
            if (delete(express.getNumber())){
    
    
                return express;
            }
        }
        return null;
    }
  • Find a courier by pickup code
    public static Express findExpressByCode(int code){
    
    
        for (int i = 0;i<expressList.size();i++) {
    
    
            if (expressList.get(i).getCode() == code){
    
    
                return expressList.get(i);
            }
        }
        return null;
    }

5. C/S network programming

  • Mainly responsible for the interaction between server and client

Create a socket package and create new classes Server and Client

Serverserver

Create the Server object in main and call the start method

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

Next, write the start method to start the server:


First create the server

	//端口号
    private final int PORT = 10086; 
    
    //创建一个服务器
    private ServerSocket server; 

1. Create the start method to set up and run the server and connect the client

  • After entering the server, wait for the client to connect.
    Use a while loop to realize multiple connections from the user.
	server = new ServerSocket(PORT);//端口号传入到服务器
	System.out.println("服务器已经准备好!服务端口:" + PORT);
	//等待客户端得连接
	while (true) {
    
    //实现多用户连接,使用用while循环
		Socket client = server.accept();//连接服务器得客户端
        System.out.println("客户端" + client.hashCode() + "连接成功");//不同的hashcode表示不同的对象
    }
  • Join multi-threading and use anonymous inner classes
	//为每个客户单独开一个线程处理请求
	new Thread(new Runnable() {
    
    
		@Override
		public void run() {
    
    
        //客户端得请求   接受客户端得请求  读数据 -- 处理完毕之后将结果相应给客户端 ---写数据到客户端
        	try {
    
    
            	init(client);//用户的方法  方法里包括了序列化和反序列化
            } catch (IOException|Exception e) {
    
    
            	e.printStackTrace();
            } 
        }
     }).start();

The complete code of the start() method is as follows:

    //开启一个线程 服务端开启的方法
    public void start() {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                try {
    
    
                    server = new ServerSocket(PORT);//端口号传入到服务器
                    System.out.println("服务器已经准备好!服务端口:" + PORT);
                    //等待客户端得连接
                    while (true) {
    
    //实现多用户连接,使用用while循环
                        Socket client = server.accept();//连接服务器得客户端
                        System.out.println("客户端" + client.hashCode() + "连接成功");//不同的hashcode表示不同的对象
                        //为每个客户单独开一个线程处理请求
                        new Thread(new Runnable() {
    
    
                            @Override
                            public void run() {
    
    
                                //客户端得请求   接受客户端得请求  读数据 -- 处理完毕之后将结果相应给客户端 ---写数据到客户端
                                try {
    
    
                                    init(client);//用户的方法  方法里包括了序列化和反序列化
                                } catch (IOException|Exception  e) {
    
    
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();
    }

2. Write the init method in task run to implement interaction with client data

  • receive messages
        InputStream is = null;
        ObjectInputStream in = null;
  • send message
        OutputStream os = null;
        ObjectOutputStream out = null;
  • Get stream object
		is = client.getInputStream();
    	os = client.getOutputStream();
   		out = new ObjectOutputStream(os);
    	in = new ObjectInputStream(is);
  • enter the system
       System.out.println("用户得请求类型" + flag + "线程" + Thread.currentThread().getName() + "为你服务!");
  • Get the user's specific operations
		String flag = in.readUTF();
		System.out.println(flag);
    • Add courier
                    //获取客户端发布的参数
                    Express express = (Express) in.readObject();
                    express = dao.add(express);
                    out.writeObject(express);
    • Delete express
                    String number = in.readUTF();
                    boolean res = dao.delete(number);
                    out.writeObject(res);
    • Modify express delivery
                    String number =in.readUTF();//旧数据
                    Express newExpress = (Express) in.readObject();
                    boolean res = dao.update(number, newExpress);
    • Print all shipments
                	//在服务器端打印当前快递存储信息
                    System.out.println("-----------------------------------执行findadll");
                    List<Express> expressList = dao.getExpressList();
                    //获取处理结果 返回给客户端写数据
                    if (expressList != null && expressList.size() != 0) {
    
    
                        System.out.println("----------------当前快递信息如下,准备发给客户端---------------------------");
                        for (Express express : expressList) {
    
    //遍历
                            System.out.println("--" + express);
                        }
                        out.reset();
                        out.writeObject(expressList);
                        System.out.println("发送成功!");
                    } else
                        out.writeObject("快递柜中暂时没有任何快递");
                        out.flush();
    • Pickup
                    Integer code = in.readInt();
                    Express res = dao.findByCodeAndDelete(code);
                    System.out.println("res:"+res);
                    out.writeObject(res);
  • close stream
		if (in != null) {
    
    
			in.close();
			}
        if (out != null) {
    
    
            out.close();
        }

The complete code of the init method is as follows:

	//接受客户端得请求  读数据 -- 处理完毕之后将结果相应给客户端 ---写数据到客户端
    public void init(Socket client) throws Exception {
    
    
        OutputStream os = null;
        ObjectOutputStream out = null;
        InputStream is = null;
        ObjectInputStream in = null;

        //获取流对象
        try {
    
    
            is = client.getInputStream();
            os = client.getOutputStream();
            out = new ObjectOutputStream(os);
            in = new ObjectInputStream(is);
            //获取客户端得发送得请求类型
            while (true) {
    
    
                System.out.println("用户得请求类型" + flag + "线程" + Thread.currentThread().getName() + "为你服务!");
                
                String flag = in.readUTF();
                System.out.println(flag);
                if ("printAll".equals(flag)) {
    
    
                	//在服务器端打印当前快递存储信息
                    System.out.println("-----------------------------------执行findadll");
                    List<Express> expressList = dao.getExpressList();
                    //获取处理结果 返回给客户端写数据
                    if (expressList != null && expressList.size() != 0) {
    
    
                        System.out.println("----------------当前快递信息如下,准备发给客户端---------------------------");
                        for (Express express : expressList) {
    
    //遍历
                            System.out.println("--" + express);
                        }
                        out.reset();
                        out.writeObject(expressList);
                        System.out.println("发送成功!");
                    } else
                        out.writeObject("快递柜中暂时没有任何快递");
                        out.flush();
                    continue;
                } else if ("insert".equals(flag)) {
    
    
                    //获取客户端发布的参数
                    Express express = (Express) in.readObject();
                    express = dao.add(express);
                    out.writeObject(express);
                    continue;
                } else if ("update".equals(flag)) {
    
    
                    String number =in.readUTF();//旧数据
                    Express newExpress = (Express) in.readObject();
                    boolean res = dao.update(number, newExpress);
                    out.writeObject(res);
                    continue;
                } else if ("delete".equals(flag)) {
    
    
                    String number = in.readUTF();
                    boolean res = dao.delete(number);
                    out.writeObject(res);
                    continue;
                } else if ("findByCode".equals(flag)) {
    
    //取件 先查询后删除
                    Integer code = in.readInt();
                    Express res = dao.findByCodeAndDelete(code);
                    System.out.println("res:"+res);
                    out.writeObject(res);
                    continue;
                } else {
    
    
                    out.writeObject("你的请求服务器暂时处理不了");
                    continue;
                }
            }//end while
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (in != null) {
    
    
                in.close();
            }
            if (out != null) {
    
    
                out.close();
            }
        }
    }//end void

Client client

Create a Client object in main and call the start method to allow users to connect to the server.

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

First create the client

    private final int PORT = 10086;//客户端要链接的端口号
    
    private Socket client;//客户端

1. Create the start method , run the client, and connect to the server

  • receive messages
        InputStream is = null;
        ObjectInputStream in = null;
  • send message
        OutputStream os = null;
        ObjectOutputStream out = null;
  • connect to the server
            do {
    
    
                if (client == null || client.isClosed()) {
    
    
                    client = new Socket("127.8.0.1", PORT);
                    in = client.getInputStream();
                    out = client.getOutputStream();
                    objectOutputStream = new ObjectOutputStream(out);
                    objectInputStream = new ObjectInputStream(in);
                    System.out.println("客户端连接服务器成功!");
                }
            } while (mainMenu(objectInputStream, objectOutputStream) != 0);
  • Exit the system and close the stream
		if (objectInputStream != null) {
    
    
			objectInputStream.close();
		}
	    if (objectOutputStream != null) {
    
    
			objectOutputStream.close();
	    }
		if (client != null) {
    
    
			client.close();
		}

The complete method of start is as follows:

    //客户端启动的方法
    public void start() {
    
    
        OutputStream out = null;
        ObjectOutputStream objectOutputStream = null;
        InputStream in = null;
        ObjectInputStream objectInputStream = null;
        //获取流对象
        try {
    
    
            do {
    
    
                if (client == null || client.isClosed()) {
    
    
                    client = new Socket("127.8.0.1", PORT);
                    in = client.getInputStream();
                    out = client.getOutputStream();
                    objectOutputStream = new ObjectOutputStream(out);
                    objectInputStream = new ObjectInputStream(in);
                    System.out.println("客户端连接服务器成功!");
                }
            } while (mainMenu(objectInputStream, objectOutputStream) != 0);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } catch (OutNumberBoundException e) {
    
    
            e.printStackTrace();
        } finally {
    
    //关闭流
            try {
    
    
                if (objectInputStream != null) {
    
    
                    objectInputStream.close();
                }
                if (objectOutputStream != null) {
    
    
                    objectOutputStream.close();
                }
                if (client != null) {
    
    
                    client.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }//end finally
    }//end void start

2. Main menu

    public static int mainMenu(ObjectInputStream in, ObjectOutputStream out) throws OutNumberBoundException, Exception {
    
    
        int mainNum = 0;
        do{
    
    
            System.out.println("----------欢迎使用快递管理系统----------");
            System.out.println("请选择您的身份:");
            System.out.println("1.管理员");
            System.out.println("2.普通用户");
            System.out.println("0.退出");
            String s = input.nextLine();
            try{
    
    
                mainNum = validNum(s,0,2);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
    
    
                System.out.println(e.getMessage());
            }
        }while(true);
        switch(mainNum){
    
    
            case 0://结束使用
                System.out.println("感谢使用快递管理系统!");
                break ;
            case 1://进入管理员平台
                managerPlatform(in,out);
                break ;
            case 2://进入用户平台
                userPlatform(in,out);
                break ;
        }
        return mainNum;
    }//end mainMenu()
  • Determine whether the input is a valid number
    private static int validNum(String s,int begin,int end) throws NumberFormatException, OutNumberBoundException {
    
    
        try{
    
    
            int num = Integer.parseInt(s);
            if (num < begin || num > end){
    
    
                throw new OutNumberBoundException("数字的范围必须在" + begin + "和" + end +"之间");
            }
            return num;
        }catch(NumberFormatException | OutNumberBoundException e){
    
    
            throw new NumberFormatException("输入的必须是数字!");
        }
    }

2.1 Administrator interface

    public static void managerPlatform(ObjectInputStream in, ObjectOutputStream out) throws OutNumberBoundException, Exception{
    
    
        w:while(true){
    
    
            int managerNum = 0;
            do{
    
    
                System.out.println("尊敬的管理员,您好!");
                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();
                try{
    
    
                    managerNum = validNum(s,0,4);
                    break;
                }catch(NumberFormatException | OutNumberBoundException e){
    
    
                    System.out.println(e.getMessage());
                }
            }while(true);
            switch(managerNum){
    
    
                case 0:{
    
    //返回上一级页面
                    return;
                }
                case 1:{
    
    //1.录入快递
                    insert(in,out);
                }
                break w;
                case 2:{
    
    //2.删除快递
                    delete(in,out);
                }
                break w;
                case 3:{
    
    //3.修改快递
                    update(in,out);
                }
                break w;
                case 4:{
    
    //4.查看所有快递
                    printAll(in,out);
                }
                break w;
            }// end switch
        }//end while
    }//end managerPlatform

  • Add courier
    private static void insert(ObjectInputStream in, ObjectOutputStream out) {
    
    
        System.out.println("---------存快递----------");
        Express express = new Express();
        System.out.print("请输入快递单号:");
        express.setNumber(input.nextLine());
        System.out.print("请输入快递公司:");
        express.setCompany(input.nextLine());
        //当前快递单号不存在,存快递
        if(Server.dao.findByNumber(express.getNumber()) == -1){
    
    
            try {
    
    
                out.writeUTF("insert");
                out.writeObject(express);
                out.flush();
                //接受服务器端的响应---读数据
                Object object = in.readObject();
                if (object instanceof Express) {
    
    
                    express = (Express) object;
                    System.out.println("添加成功!快递在第" + (express.getX() + 1) + "排,第" + (express.getY() + 1) + "列");
                } else {
    
    
                    System.out.println("添加失败" + object);
                }
            } catch (Exception exception) {
    
    
                System.out.println("系统异常,添加失败!");
                System.out.println(exception.getMessage());
            }
        }else{
    
    
            System.out.println("该快递单号已存在!快递添加失败!");
        }
    }
  • Delete express
    private static void delete(ObjectInputStream in, ObjectOutputStream out) {
    
    
        System.out.println("删除快递");
        System.out.print("请输入要删除的快递单号:");
        String number = input.nextLine();
        int exist = Server.dao.findByNumber(number);
        if (exist == -1) {
    
    
            System.out.println("快递不存在!");
        } else {
    
    
            int deleteNum;
            do {
    
    
                System.out.println("是否进行删除操作?");
                System.out.println("1.确认删除");
                System.out.println("0.取消操作");
                String s = input.nextLine();
                deleteNum = -1;
                try {
    
    
                    deleteNum = validNum(s, 0, 1);
                    break;
                } catch (NumberFormatException | OutNumberBoundException e) {
    
    
                    System.out.println(e.getMessage());
                }
            } while (true);
            if (deleteNum == 0) {
    
    
                System.out.println("取消删除成功!");
            } else {
    
    
                try {
    
    
                    out.writeUTF("delete");
                    out.writeUTF(number);
                    out.flush();
                    Object obj = in.readObject();
                    if (obj instanceof Boolean) {
    
    
                        boolean res = (boolean) obj;
                        if (res == true) {
    
    
                            System.out.println("删除成功");
                        } else {
    
    
                            System.out.println("删除失败");
                        }
                    } else {
    
    
                        System.out.println("删除失败!!!!!!");
                    }
                } catch (Exception e) {
    
    
                    System.out.println("系统异常,删除失败!");
                    System.out.println(e.getMessage());
                }
            }// end else  option of delete
        }//end else express exist
    }//end method
  • Modify express delivery
    private static void update(ObjectInputStream in, ObjectOutputStream out) {
    
    
        System.out.println("---------修改快递-----------");
        System.out.print("请输入要修改的快递单号:");
        String number = input.nextLine();
        int exist = Server.dao.findByNumber(number);
        if(exist == -1){
    
    
            System.out.println("快递不存在!");
        }else{
    
    
            Express newExpress = new Express();
            System.out.print("请输入新的快递单号:");
            newExpress.setNumber(input.nextLine());
            System.out.print("请输入新的公司名称:");
            newExpress.setCompany(input.nextLine());
            try {
    
    
                out.writeUTF("update");
                out.flush();
                out.writeUTF(number);
                out.flush();
                out.writeObject(newExpress);
                out.flush();
                Object obj = in.readObject();
                if (obj instanceof Boolean) {
    
    
                    boolean res = (boolean) obj;
                    if (res == true) {
    
    
                        System.out.println("更新成功!");
                    } else {
    
    
                        System.out.println("更新失败!");
                    }
                } else{
    
    
                    System.out.println("更新失败!!!!!!");
                }
            } catch (Exception e) {
    
    
                System.out.println("系统异常,更新失败!");
                System.out.println(e.getMessage());
            }
        }// end else(option of exist then update)
    }//end update method
  • Print all shipments
    public static void printAll(ObjectInputStream in, ObjectOutputStream out) throws IOException, ClassNotFoundException {
    
    
        System.out.println("--------当前快递存储情况---------");
        out.writeUTF("printAll");//与Server相对应,发送给服务器请求类型
        out.flush();
        Object obj = in.readObject();
        if (obj instanceof List) {
    
    
            List<Express> expressList = (List<Express>) obj;//强转
            for (Express express : expressList) {
    
    //遍历输出
                System.out.println(express);
            }
        }else {
    
    
            System.out.println(obj);
        }
    }

2.2 User interface

  • Pickup
    public static void userPlatform(ObjectInputStream in, ObjectOutputStream out) throws OutNumberBoundException, Exception {
    
    
        int code = -1;
        do {
    
    
            System.out.print("请输入取件码:");
            String s = input.nextLine();
            try {
    
    
                code = validNum(s, 100000, 999999);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
    
    
                System.out.println(e.getMessage());
            }
        } while (true);
        out.writeUTF("findByCode");
        out.writeInt(code);
        out.flush();
        Object obj = in.readObject();
        if (obj instanceof Express) {
    
    
            Express e = (Express) obj;
            System.out.println("快递信息:" + e);
            System.out.println("您的快递存储在快递柜的第" + (e.getX() + 1) + "排,第" + (e.getY() + 1) + "列,取件愉快~");

        } else {
    
    
            System.out.println("快递不存在,取件失败!");
        }
    }

Complete code

1. Custom exceptions

OutNumberBoundException

public class OutNumberBoundException extends Throwable {
    
    
    public OutNumberBoundException(String s) {
    
    
        super(s);
    }
}

2. Tool Kit

IOUtil

/**
 * 文件读写技术
 *
 */
public class IOUtil {
    
    
    /**
     * 从指定的文件中读取数据
     * Reader
     * InputStream
     */
    public static Object readFile(String fileName) throws IOException, ClassNotFoundException {
    
    
        FileInputStream fis = new FileInputStream(fileName);//指定文件
        ObjectInputStream ois = new ObjectInputStream(fis);
        return ois.readObject();//读出数据
    }

    /**
     * 写入数据到指定文件
     * Writer
     * OutputStream
     */
    public static void writeFile(Object obj,String fileName) throws IOException {
    
    
        FileOutputStream fos = new FileOutputStream(fileName);//指定文件
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);//写入数据obj
    }

}

3. Object

Express

public class Express implements Serializable {
    
    
    private String number;//快递单号
    private String company;//公司
    private int code;//取件码
    private int x;
    private int y;

    /**
     * 定义无参构造方法
     */
    public Express() {
    
    
    }

    /**
     * 定义全参构造方法
     */
    public Express(String number, String company, int code, int x, int y) {
    
    
        this.number = number;
        this.company = company;
        this.code = code;
        this.x = x;
        this.y = y;
    }

    /**
     * 使用setter和getter设置和获取值
     */
    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;
    }

    public int getX() {
    
    
        return x;
    }

    public void setX(int x) {
    
    
        this.x = x;
    }

    public int getY() {
    
    
        return y;
    }

    public void setY(int y) {
    
    
        this.y = y;
    }

    /**
     * toString将信息转化为字符串形式
     */
    @Override
    public String toString() {
    
    
        return "快递信息[" +
                "快递单号:" + getNumber() + ' ' +
                ", 快递公司:" + getCompany() + ' ' +
                ", 取件码:" + getCode() + " , 在第" + (getX() + 1) + "行 第" + (getY() + 1) + "列柜子" +
                ']';
    }
}

4. Data processing

Dao

public class Dao {
    
    
    //链表的初始设置
    private static List<Express> expressList = new ArrayList<>(100);
    //存储快递的文件名
    public static final String FILE_NAME = "快递信息.txt";

    //静态 代码块
    static {
    
    
        File file = new File(FILE_NAME);
        if (!file.exists()){
    
    //如果文件不存在,创建文件
            try {
    
    
                if (file.createNewFile()){
    
    //创建文件名为FILE_NAME的文件
                    System.out.println("第一次启动项目,创建储存文件成功!");
                }
            } catch (IOException e) {
    
    
                System.out.println(e.getMessage());
            }
        }
    }
    
    //初始化数据
    public Dao() {
    
    
        //从文件中读取数据
        try {
    
    
            Object obj = IOUtil.readFile(FILE_NAME);
            if (obj!=null && obj instanceof List){
    
    
                expressList = (List<Express>) obj;
            }
        }catch (IOException | ClassNotFoundException e) {
    
    
            System.out.println(e.getMessage());
        }
    }


    /**
     * 获得快递的所有信息
     * @return
     */
    public static List<Express> getExpressList() {
    
    
        return expressList;
    }


    /**
     * 添加快递
     * @param express
     * @return
     * @throws Exception
     */
    public static Express add(Express express) throws Exception {
    
    
        Random random = new Random();
        if (expressList.size() == 100) {
    
    
            System.out.println("快递柜已存满!");
            return null;
        }
        int x, y;
        do {
    
    
            x = random.nextInt(10);
            y = random.nextInt(10);
        } while (isExist(x, y));

        int code;
        do {
    
    
            code = random.nextInt(900000) + 100000;
        } while (isExistCode(code));
        express.setCode(code);
        express.setX(x);
        express.setY(y);
        expressList.add(express);
        IOUtil.writeFile(expressList,FILE_NAME);//更新文档中的数据
        return express;
    }


    /**
     * 添加快递中,判断当前位置是否已经存在快递
     * @param x
     * @param y
     * @return
     */
    public static boolean isExist(int x, int y) {
    
    
        for (Express express : expressList) {
    
    
            if (express.getX() == x && express.getY() == y) {
    
    
                return true;
            }
        }
        return false;
    }

    /**
     * 判断取件码是否已经存在
     * @param code
     * @return
     */
    public static boolean isExistCode(int code) {
    
    
        for (Express express : expressList) {
    
    
            if (express.getCode() == code) {
    
    
                return true;
            }
        }
        return false;
    }

    /**
     * 根据快递单号查找快递,如果不存在返回-1
     * @param number
     * @return
     */
    public static int findByNumber(String number) {
    
    
        int i = 0;
        for (Express express : expressList) {
    
    
            if (number.equals(express.getNumber())) {
    
    
                return i;
            }
            i++;
        }
        return -1;
    }


    /**
     * 删除快递
     * @param number
     * @return
     * @throws Exception
     */
    public static boolean delete(String number) throws Exception {
    
    
        int index = findByNumber(number);
        if (index == -1) {
    
    
            return false;
        }
        expressList.remove(index);//删除快递的操作
        IOUtil.writeFile(expressList,FILE_NAME);
        return true;
    }


    /**
     * 更新快递
     * @param number
     * @param newExpress
     * @return
     * @throws Exception
     */
    public static boolean update(String number, Express newExpress) throws Exception {
    
    
        int index = findByNumber(number);
        if (index == -1) {
    
    
            System.out.println("快递不存在!");
            return false;
        }
        Express express1 = expressList.get(index);
        express1.setNumber(newExpress.getNumber());
        express1.setCompany(newExpress.getCompany());
        IOUtil.writeFile(expressList,FILE_NAME);//数据加入
        return true;
    }

    /**
     * 通过取件码查找快递
     * @param code
     * @return
     */
    public static Express findExpressByCode(int code){
    
    
        for (int i = 0;i<expressList.size();i++) {
    
    
            if (expressList.get(i).getCode() == code){
    
    
                return expressList.get(i);
            }
        }
        return null;
    }

    /**
     * 取件,删除快递
     * @param code
     * @return
     * @throws IOException
     */
    public Express findByCodeAndDelete(int code) throws Exception {
    
    
        Express express = findExpressByCode(code);
        if (express!=null){
    
    
            if (delete(express.getNumber())){
    
    
                return express;
            }
        }
        return null;
    }
}

5. C/S network programming

Server

public class Server {
    
    
    public static Dao dao = new Dao();
    public static void main(String[] args) {
    
    
        Server server = new Server();
        server.start();
    }

    private final int PORT = 10086; //端口号

    private ServerSocket server; //建立一个服务器

    //开启一个线程 服务端开启的方法
    public void start() {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                try {
    
    
                    server = new ServerSocket(PORT);//端口号传入到服务器
                    System.out.println("服务器已经准备好!服务端口:" + PORT);
                    //等待客户端得连接
                    while (true) {
    
    //实现多用户连接,使用用while循环
                        Socket client = server.accept();//连接服务器得客户端
                        System.out.println("客户端" + client.hashCode() + "连接成功");//不同的hashcode表示不同的对象
                        //为每个客户单独开一个线程处理请求
                        new Thread(new Runnable() {
    
    
                            @Override
                            public void run() {
    
    
                                //客户端得请求   接受客户端得请求  读数据 -- 处理完毕之后将结果相应给客户端 ---写数据到客户端
                                try {
    
    
                                    init(client);//用户的方法  方法里包括了序列化和反序列化
                                } catch (IOException|Exception  e) {
    
    
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();
    }

	//接受客户端得请求  读数据 -- 处理完毕之后将结果相应给客户端 ---写数据到客户端
    public void init(Socket client) throws Exception {
    
    
        OutputStream os = null;
        ObjectOutputStream out = null;
        InputStream is = null;
        ObjectInputStream in = null;

        //获取流对象
        try {
    
    
            is = client.getInputStream();
            os = client.getOutputStream();
            out = new ObjectOutputStream(os);
            in = new ObjectInputStream(is);
            //获取客户端得发送得请求类型
            while (true) {
    
    
                System.out.println("用户得请求类型" + flag + "线程" + Thread.currentThread().getName() + "为你服务!");
                
                String flag = in.readUTF();
                System.out.println(flag);
                if ("printAll".equals(flag)) {
    
    
                	//在服务器端打印当前快递存储信息
                    System.out.println("-----------------------------------执行findadll");
                    List<Express> expressList = dao.getExpressList();
                    //获取处理结果 返回给客户端写数据
                    if (expressList != null && expressList.size() != 0) {
    
    
                        System.out.println("----------------当前快递信息如下,准备发给客户端---------------------------");
                        for (Express express : expressList) {
    
    //遍历
                            System.out.println("--" + express);
                        }
                        out.reset();
                        out.writeObject(expressList);
                        System.out.println("发送成功!");
                    } else
                        out.writeObject("快递柜中暂时没有任何快递");
                        out.flush();
                    continue;
                } else if ("insert".equals(flag)) {
    
    
                    //获取客户端发布的参数
                    Express express = (Express) in.readObject();
                    express = dao.add(express);
                    out.writeObject(express);
                    continue;
                } else if ("update".equals(flag)) {
    
    
                    String number =in.readUTF();//旧数据
                    Express newExpress = (Express) in.readObject();
                    boolean res = dao.update(number, newExpress);
                    out.writeObject(res);
                    continue;
                } else if ("delete".equals(flag)) {
    
    
                    String number = in.readUTF();
                    boolean res = dao.delete(number);
                    out.writeObject(res);
                    continue;
                } else if ("findByCode".equals(flag)) {
    
    //取件 先查询后删除
                    Integer code = in.readInt();
                    Express res = dao.findByCodeAndDelete(code);
                    System.out.println("res:"+res);
                    out.writeObject(res);
                    continue;
                } else {
    
    
                    out.writeObject("你的请求服务器暂时处理不了");
                    continue;
                }
            }//end while
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (in != null) {
    
    
                in.close();
            }
            if (out != null) {
    
    
                out.close();
            }
        }
    }//end void

}

Client

public class Client {
    
    
    private static Scanner input = new Scanner(System.in);
    private Express express = new Express();
    private final int PORT = 10086;//客户端要链接的端口号
    private Socket client;//客户端

    public static void main(String[] args) {
    
    
        Client c = new Client();
        c.start();
    }
  
    //客户端启动的方法
    public void start() {
    
    
        OutputStream out = null;
        ObjectOutputStream objectOutputStream = null;
        InputStream in = null;
        ObjectInputStream objectInputStream = null;
        //获取流对象
        try {
    
    
            do {
    
    
                if (client == null || client.isClosed()) {
    
    
                    client = new Socket("127.8.0.1", PORT);
                    in = client.getInputStream();
                    out = client.getOutputStream();
                    objectOutputStream = new ObjectOutputStream(out);
                    objectInputStream = new ObjectInputStream(in);
                    System.out.println("客户端连接服务器成功!");
                }
            } while (mainMenu(objectInputStream, objectOutputStream) != 0);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } catch (OutNumberBoundException e) {
    
    
            e.printStackTrace();
        } finally {
    
    //关闭流
            try {
    
    
                if (objectInputStream != null) {
    
    
                    objectInputStream.close();
                }
                if (objectOutputStream != null) {
    
    
                    objectOutputStream.close();
                }
                if (client != null) {
    
    
                    client.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }//end finally
    }//end void start
    
    /**
     * 主菜单,系统界面
     * @return
     */
    public static int mainMenu(ObjectInputStream in, ObjectOutputStream out) throws OutNumberBoundException, Exception {
    
    
        int mainNum = 0;
        do{
    
    
            System.out.println("----------欢迎使用快递管理系统----------");
            System.out.println("请选择您的身份:");
            System.out.println("1.管理员");
            System.out.println("2.普通用户");
            System.out.println("0.退出");
            String s = input.nextLine();
            try{
    
    
                mainNum = validNum(s,0,2);
                break;
            }catch(NumberFormatException | OutNumberBoundException e){
    
    
                System.out.println(e.getMessage());
            }
        }while(true);
        switch(mainNum){
    
    
            case 0://结束使用
                System.out.println("感谢使用快递管理系统!");
                break ;
            case 1://进入管理员平台
                managerPlatform(in,out);
                break ;
            case 2://进入用户平台
                userPlatform(in,out);
                break ;
        }
        return mainNum;
    }//end mainMenu()

    /**
     * 判断输入是否为数字、是否在有效范围内
     * @param s
     * @param begin
     * @param end
     * @return
     * @throws NumberFormatException
     */
    private static int validNum(String s,int begin,int end) throws NumberFormatException, OutNumberBoundException {
    
    
        try{
    
    
            int num = Integer.parseInt(s);
            if (num < begin || num > end){
    
    
                throw new OutNumberBoundException("数字的范围必须在" + begin + "和" + end +"之间");
            }
            return num;
        }catch(NumberFormatException | OutNumberBoundException e){
    
    
            throw new NumberFormatException("输入的必须是数字!");
        }
    }


    /**
     * 管理员操作界面
     * @param in
     * @param out
     * @throws OutNumberBoundException
     * @throws Exception
     */
    public static void managerPlatform(ObjectInputStream in, ObjectOutputStream out) throws OutNumberBoundException, Exception{
    
    
        w:while(true){
    
    
            int managerNum = 0;
            do{
    
    
                System.out.println("尊敬的管理员,您好!");
                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();
                try{
    
    
                    managerNum = validNum(s,0,4);
                    break;
                }catch(NumberFormatException | OutNumberBoundException e){
    
    
                    System.out.println(e.getMessage());
                }
            }while(true);
            switch(managerNum){
    
    
                case 0:{
    
    //返回上一级页面
                    return;
                }
                case 1:{
    
    //1.录入快递
                    insert(in,out);
                }
                break w;
                case 2:{
    
    //2.删除快递
                    delete(in,out);
                }
                break w;
                case 3:{
    
    //3.修改快递
                    update(in,out);
                }
                break w;
                case 4:{
    
    //4.查看所有快递
                    printAll(in,out);
                }
                break w;
            }// end switch
        }//end while
    }//end managerPlatform


    /**
     * 打印所有快递
     * @param in
     * @param out
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void printAll(ObjectInputStream in, ObjectOutputStream out) throws IOException, ClassNotFoundException {
    
    
        System.out.println("--------当前快递存储情况---------");
        out.writeUTF("printAll");//与Server相对应,发送给服务器请求类型
        out.flush();
        Object obj = in.readObject();
        if (obj instanceof List) {
    
    
            List<Express> expressList = (List<Express>) obj;//强转
            for (Express express : expressList) {
    
    //遍历输出
                System.out.println(express);
            }
        }else {
    
    
            System.out.println(obj);
        }
    }


    /**
     * 添加快递
     * @param in
     * @param out
     */
    private static void insert(ObjectInputStream in, ObjectOutputStream out) {
    
    
        System.out.println("---------存快递----------");
        Express express = new Express();
        System.out.print("请输入快递单号:");
        express.setNumber(input.nextLine());
        System.out.print("请输入快递公司:");
        express.setCompany(input.nextLine());
        //当前快递单号不存在,存快递
        if(Server.dao.findByNumber(express.getNumber()) == -1){
    
    
            try {
    
    
                out.writeUTF("insert");
                out.writeObject(express);
                out.flush();
                //接受服务器端的响应---读数据
                Object object = in.readObject();
                if (object instanceof Express) {
    
    
                    express = (Express) object;
                    System.out.println("添加成功!快递在第" + (express.getX() + 1) + "排,第" + (express.getY() + 1) + "列");
                } else {
    
    
                    System.out.println("添加失败" + object);
                }
            } catch (Exception exception) {
    
    
                System.out.println("系统异常,添加失败!");
                System.out.println(exception.getMessage());
            }
        }else{
    
    
            System.out.println("该快递单号已存在!快递添加失败!");
        }
    }


    /**
     * 删除快递
     * @param in
     * @param out
     */
    private static void delete(ObjectInputStream in, ObjectOutputStream out) {
    
    
        System.out.println("删除快递");
        System.out.print("请输入要删除的快递单号:");
        String number = input.nextLine();
        int exist = Server.dao.findByNumber(number);
        if (exist == -1) {
    
    
            System.out.println("快递不存在!");
        } else {
    
    
            int deleteNum;
            do {
    
    
                System.out.println("是否进行删除操作?");
                System.out.println("1.确认删除");
                System.out.println("0.取消操作");
                String s = input.nextLine();
                deleteNum = -1;
                try {
    
    
                    deleteNum = validNum(s, 0, 1);
                    break;
                } catch (NumberFormatException | OutNumberBoundException e) {
    
    
                    System.out.println(e.getMessage());
                }
            } while (true);
            if (deleteNum == 0) {
    
    
                System.out.println("取消删除成功!");
            } else {
    
    
                try {
    
    
                    out.writeUTF("delete");
                    out.writeUTF(number);
                    out.flush();
                    Object obj = in.readObject();
                    if (obj instanceof Boolean) {
    
    
                        boolean res = (boolean) obj;
                        if (res == true) {
    
    
                            System.out.println("删除成功");
                        } else {
    
    
                            System.out.println("删除失败");
                        }
                    } else {
    
    
                        System.out.println("删除失败!!!!!!");
                    }
                } catch (Exception e) {
    
    
                    System.out.println("系统异常,删除失败!");
                    System.out.println(e.getMessage());
                }
            }// end else  option of delete
        }//end else express exist
    }//end method


    /**
     * 更新快递
     * @param in
     * @param out
     */
    private static void update(ObjectInputStream in, ObjectOutputStream out) {
    
    
        System.out.println("---------修改快递-----------");
        System.out.print("请输入要修改的快递单号:");
        String number = input.nextLine();
        int exist = Server.dao.findByNumber(number);
        if(exist == -1){
    
    
            System.out.println("快递不存在!");
        }else{
    
    
            Express newExpress = new Express();
            System.out.print("请输入新的快递单号:");
            newExpress.setNumber(input.nextLine());
            System.out.print("请输入新的公司名称:");
            newExpress.setCompany(input.nextLine());
            try {
    
    
                out.writeUTF("update");
                out.flush();
                out.writeUTF(number);
                out.flush();
                out.writeObject(newExpress);
                out.flush();
                Object obj = in.readObject();
                if (obj instanceof Boolean) {
    
    
                    boolean res = (boolean) obj;
                    if (res == true) {
    
    
                        System.out.println("更新成功!");
                    } else {
    
    
                        System.out.println("更新失败!");
                    }
                } else{
    
    
                    System.out.println("更新失败!!!!!!");
                }
            } catch (Exception e) {
    
    
                System.out.println("系统异常,更新失败!");
                System.out.println(e.getMessage());
            }
        }// end else(option of exist then update)
    }//end update method


    /**
     * 用户操作界面
     * @throws OutNumberBoundException
     * @throws Exception
     */
    public static void userPlatform(ObjectInputStream in, ObjectOutputStream out) throws OutNumberBoundException, Exception {
    
    
        int code = -1;
        do {
    
    
            System.out.print("请输入取件码:");
            String s = input.nextLine();
            try {
    
    
                code = validNum(s, 100000, 999999);
                break;
            } catch (NumberFormatException | OutNumberBoundException e) {
    
    
                System.out.println(e.getMessage());
            }
        } while (true);
        out.writeUTF("findByCode");
        out.writeInt(code);
        out.flush();
        Object obj = in.readObject();
        if (obj instanceof Express) {
    
    
            Express e = (Express) obj;
            System.out.println("快递信息:" + e);
            System.out.println("您的快递存储在快递柜的第" + (e.getX() + 1) + "排,第" + (e.getY() + 1) + "列,取件愉快~");

        } else {
    
    
            System.out.println("快递不存在,取件失败!");
        }
    }
    
}

Guess you like

Origin blog.csdn.net/m0_50609545/article/details/120090680