快递管理控制台简易版——加入多线程与网络编程(完整版,附完整源码)(Java)
2021/9/4 1:07:23
本文主要是介绍快递管理控制台简易版——加入多线程与网络编程(完整版,附完整源码)(Java),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 具体需求
- 涉及知识点
- 思路及代码实现
- 一、 自定义异常
- OutNumberBoundException
- 二、 工具包
- IOUtil
- 三、 对象
- Express
- 四、数据处理
- Dao
- 五 、 C/S网络编程
- Server服务器
- Client客户端
- 完整代码
- 一、自定义异常
- OutNumberBoundException
- 二、 工具包
- IOUtil
- 三、 对象
- Express
- 四、 数据处理
- Dao
- 五、 C/S网络编程
- Server
- Client
数组存储版可参考文章:快递管理控制台简易版——数组存储版(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)用户包含管理员和普通用户两个角色进行测试
管理员用户名:admin,密码:abc 普通用户名:user 密码:123
(2)用户从客户端发起登录请求,客户端将数据传递到服务器端,
由服务器做验证。服务器端保存用户数据,用户登录成功提示登录成功
并显示功能模块,登录失败提示:用户名或密码不正确 - 基于上一个练习,了解客户端和服务器端的概念,客户端用来获取用户信息,服务器端用于进行数据存储和逻辑判断
在网络编程的基础上,在服务器端启用多线程模式,要求每一个用户发送登录请求到服务器后,服务器端就分配一个线程去处理这个请求,以实现服务器端多线程模式下的用户登录
涉及知识点
- 面向对象
- 集合
- IO
- 多线程
- 网络编程
思路及代码实现
一、 自定义异常
创建一个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("快递不存在,取件失败!"); } } }
这篇关于快递管理控制台简易版——加入多线程与网络编程(完整版,附完整源码)(Java)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-28MQ底层原理资料详解:新手入门教程
- 2024-11-28MQ项目开发资料详解:新手入门教程
- 2024-11-28MQ项目开发资料详解:入门与初级用户指南
- 2024-11-28MQ消息队列资料入门教程
- 2024-11-28MQ消息队列资料:新手入门详解
- 2024-11-28MQ消息中间件资料详解与应用教程
- 2024-11-28MQ消息中间件资料入门教程
- 2024-11-28MQ源码资料详解与入门教程
- 2024-11-28MQ源码资料入门教程
- 2024-11-28RocketMQ底层原理资料详解