ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

快递管理控制台简易版——加入多线程与网络编程(完整版,附完整源码)(Java)

2021-09-03 23:01:33  阅读:214  来源: 互联网

标签:多线程 express System 快递 源码 println 完整版 public out


文章目录


数组存储版可参考文章:快递管理控制台简易版——数组存储版(Java)

List集合存储版可参考文章:快递管理控制台简易版——List集合存储版(Java)

Map集合存储版可参考文章:快递管理控制台简易版——Map集合存储版(Java)

基于Map集合存储版使用IO技术实现数据存储可参考文章:快递管理控制台简易版——IO流的使用(Java)

  • 数组存储版采用二维数组对快递进行存储,快递位置对应二维数组的两个下标

  • List集合存储版采用List集合对快递进行存储

  • Map集合存储版采用Map集合对快递进行存储,用Map集合进行存储的优势在于,Map是键-值(key-value)对,key为快递单号,value 为快递对象,保证快递单号唯一

  • IO流的使用 以Map集合存储版为基础进行优化,使用IO技术将快递数据存储到文件中,并从文件中读取数据,文件存储快递信息后,可以在每次启动应用时读取文件中的内容,从而实现程序数据的一直存在

  • 关于多线程和网络编程加入了多线程和网络编程技术,实现客户端和服务器的数据交互,并且使用多线程,使得每一个用户发送登录请求到服务器后,服务器端就分配一个线程去处理这个请求
    tips:本文仅仅涉及到如何加入多线程和运用网络编程技术,不涉及完整的控制台操作


具体需求

  1. 实现基于网络编程模式下的用户登录功能,要求:
    (1)用户包含管理员和普通用户两个角色进行测试
    管理员用户名:admin,密码:abc 普通用户名:user 密码:123
    (2)用户从客户端发起登录请求,客户端将数据传递到服务器端,
    由服务器做验证。服务器端保存用户数据,用户登录成功提示登录成功
    并显示功能模块,登录失败提示:用户名或密码不正确
  2. 基于上一个练习,了解客户端和服务器端的概念,客户端用来获取用户信息,服务器端用于进行数据存储和逻辑判断
    在网络编程的基础上,在服务器端启用多线程模式,要求每一个用户发送登录请求到服务器后,服务器端就分配一个线程去处理这个请求,以实现服务器端多线程模式下的用户登录

涉及知识点

  1. 面向对象
  2. 集合
  3. IO
  4. 多线程
  5. 网络编程

思路及代码实现

一、 自定义异常

创建一个exception包,新建类OutNumberBoundException

OutNumberBoundException

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

二、 工具包

创建一个util包,新建类IOUtil

IOUtil

文件读写工具类,因此方法都推荐静态static

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

三、 对象

创建一个pojo包,新建类Express

Express

  • 定义属性并用setter和getter设置和获取值
	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;
    }
  • 定义无参和全参构造方法
/**
     * 定义无参构造方法
     */
    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;
    }
  • 重写toString将信息转换为字符串
    /**
     * toString将信息转化为字符串形式
     */
    @Override
    public String toString() {
        return "快递信息[" +
                "快递单号:" + getNumber() + ' ' +
                ", 快递公司:" + getCompany() + ' ' +
                ", 取件码:" + getCode() + " , 在第" + (getX() + 1) + "行 第" + (getY() + 1) + "列柜子" +
                ']';
    }

四、数据处理

创建一个dao包,新建类Dao

Dao

  • 创建文件并初始化数据
    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());
        }
    }
  • 添加快递
    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;
    }

  • 判断当前位置是否已存在快递
    public static boolean isExist(int x, int y) {
        for (Express express : expressList) {
            if (express.getX() == x && express.getY() == y) {
                return true;
            }
        }
        return false;
    }
  • 判断随机产生的取件码是否存在
    public static boolean isExistCode(int code) {
        for (Express express : expressList) {
            if (express.getCode() == code) {
                return true;
            }
        }
        return false;
    }
  • 删除快递
    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;
    }
  • 根据快递单号查询快递
    public static int findByNumber(String number) {
        int i = 0;
        for (Express express : expressList) {
            if (number.equals(express.getNumber())) {
                return i;
            }
            i++;
        }
        return -1;
    }
  • 更新快递
    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;
    }
  • 获得所有快递信息
    public static List<Express> getExpressList() {
        return expressList;
    }
  • 取快递
    public Express findByCodeAndDelete(int code) throws Exception {
        Express express = findExpressByCode(code);
        if (express!=null){
            if (delete(express.getNumber())){
                return express;
            }
        }
        return null;
    }
  • 通过取件码查找快递
    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;
    }

五 、 C/S网络编程

  • 主要负责服务器与客户端之间的交互

创建一个socket包,新建类Server和Client

Server服务器

在main中创建Server对象,并且调用start方法

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

接下来编写start方法启动服务器:


首先创建服务器

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

1、 创建start方法,进行服务器的搭建运行以及客户端的连接

  • 进入服务器后等待客户端连接
    使用while循环,实现用户的多次连接
	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();

start()方法完整代码如下:

    //开启一个线程 服务端开启的方法
    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、 编写任务run中的init方法实现与客户端数据的交互

  • 收消息
        InputStream is = null;
        ObjectInputStream in = null;
  • 发消息
        OutputStream os = null;
        ObjectOutputStream out = null;
  • 获取流对象
		is = client.getInputStream();
    	os = client.getOutputStream();
   		out = new ObjectOutputStream(os);
    	in = new ObjectInputStream(is);
  • 进入系统
       System.out.println("用户得请求类型" + flag + "线程" + Thread.currentThread().getName() + "为你服务!");
  • 获取用户的具体操作
		String flag = in.readUTF();
		System.out.println(flag);
    • 添加快递
                    //获取客户端发布的参数
                    Express express = (Express) in.readObject();
                    express = dao.add(express);
                    out.writeObject(express);
    • 删除快递
                    String number = in.readUTF();
                    boolean res = dao.delete(number);
                    out.writeObject(res);
    • 修改快递
                    String number =in.readUTF();//旧数据
                    Express newExpress = (Express) in.readObject();
                    boolean res = dao.update(number, newExpress);
    • 打印所有快递
                	//在服务器端打印当前快递存储信息
                    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();
    • 取件
                    Integer code = in.readInt();
                    Express res = dao.findByCodeAndDelete(code);
                    System.out.println("res:"+res);
                    out.writeObject(res);
  • 关闭流
		if (in != null) {
			in.close();
			}
        if (out != null) {
            out.close();
        }

init方法的完整代码如下:

	//接受客户端得请求  读数据 -- 处理完毕之后将结果相应给客户端 ---写数据到客户端
    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客户端

在main中创建Client对象,并且调用start方法实现用户连接服务器

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

首先创建客户端

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

1、创建start方法,运行客户端,连接服务器

  • 收消息
        InputStream is = null;
        ObjectInputStream in = null;
  • 发消息
        OutputStream os = null;
        ObjectOutputStream out = null;
  • 连接服务器
            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);
  • 退出系统,关闭流
		if (objectInputStream != null) {
			objectInputStream.close();
		}
	    if (objectOutputStream != null) {
			objectOutputStream.close();
	    }
		if (client != null) {
			client.close();
		}

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

2、 主菜单

    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()
  • 判断输入是否为有效数字
    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 管理员界面

    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

  • 添加快递
    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("该快递单号已存在!快递添加失败!");
        }
    }
  • 删除快递
    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
  • 修改快递
    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
  • 打印所有快递
    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 用户界面

  • 取件
    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("快递不存在,取件失败!");
        }
    }

完整代码

一、自定义异常

OutNumberBoundException

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

二、 工具包

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
    }

}

三、 对象

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) + "列柜子" +
                ']';
    }
}

四、 数据处理

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

五、 C/S网络编程

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("快递不存在,取件失败!");
        }
    }
    
}

标签:多线程,express,System,快递,源码,println,完整版,public,out
来源: https://blog.csdn.net/m0_50609545/article/details/120090680

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有