还记得之前的快递管理系统吗,现在把需要存储的数据都存储在服务器中,客户端后续只用来收集用户的操作,为了确保服务器能同时连接多个客户端,记得在服务器引入多线程技术。 代码:
这一个类生成对应的get/set方法,需要注意的就是实现可序列化接口(implements Serializable)、生成单独的单号(number)的eqauls()方法,因为后续的修改、删除快递操作是以单号未基础进行的
/** * @Author:彭德华 * @Description:Express类 * @Date Created in 2020-10-4 13:40 * @Modified By: */ public class Express implements Serializable { //取件码 private int code; //单号 private String number; //公司 private String company; //电话号码 private String phone; //柜子行列 private int box; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Express1 express1 = (Express1) o; return Objects.equals(number, express1.number); } @Override public int hashCode() { return Objects.hash(number); } //构造方法 public Express() { } public Express(int code, String number, String company, String phone,int box) { this.code = code; this.number = number; this.company = company; this.phone = phone; this.box = box; } public int getCode() { return code; } public String getNumber() { return number; } public String getCompany() { return company; } public String getPhone() { return phone; } public void setCode(int code) { this.code = code; } public void setNumber(String number) { this.number = number; } public void setCompany(String company) { this.company = company; } public void setPhone(String phone){ this.phone = phone; } public int getBox() { return box; } public void setBox(int y) { this.box = box; } @Override public String toString() { return "Express1{" + "code=" + code + ", number='" + number + '\'' + ", company='" + company + '\'' + ", phone='" + phone + '\'' + ", 快递在第"+ box + "号柜"+ '}'; } }这一类就是功能类,包括了程序使用到的大部分方法,是项目的核心类。需要注意的就是对在载入数据时(序列化技术)对文件的处理,载入数据详细分析我 这一篇博客有提到
/** * @Author:彭德华 * @Description:Function类,实现增加、删除、查看、修改、取出的功能 * @Date Created in 2020-10-4 13:52 * @Modified By: */ public class Function extends Express { // 生成6位取件码 // 需要传入快递信息的集合,用于判断该取件码是否存在,避免重复 public int addCode(ArrayList<Express> arrayList) { Random random = new Random(); int code = -1; // 判断是否有快递信息 if (arrayList.size() > 0) { while (true) { // 随机六位取件码 code = random.nextInt(900000) + 100000; for (Express e : arrayList) { if (e.getCode() != code) {// 取件码不存在 //return直接结束addCode()方法 return code; } } } } // 没有快递信息 code = random.nextInt(900000) + 100000; return code; } // 设置快递柜号,范围1-100 // 需要传入快递信息的集合,用于判断该柜号是否被占用,避免重复 public int addBox(ArrayList<Express> arrayList) { Random random = new Random(); int box; if (arrayList.size() > 0) { while (true) { box = random.nextInt(100) + 1; for (Express1 e : arrayList) { if (e.getBox() != box) { // 该位置无快递 return box; } } } } box = random.nextInt(100) + 1; return box; } // 录入快递 // 需要传入快递信息集合 public ArrayList<Express> addExpress(ArrayList<Express> arrayList) { Scanner input = new Scanner(System.in); //全局使用.nextLine()接受数据,会避免输入后Enter键带来的bug System.out.println("输入快递公司"); String company = input.nextLine(); System.out.println("输入快递单号"); String number = input.nextLine(); System.out.println("输入手机号"); String phone = input.nextLine(); // 随机产生取件码,不能重复 int code = addCode(arrayList); // 生成柜号,不能重复 int box = addBox(arrayList); Express1 express = new Express(code,number,company,phone,box); arrayList.add(express); // 返回集合 return arrayList; } //取出快递 //需要传入取件码,用于查找快递 public StringBuffer take(int code) throws IOException { StringBuffer text = new StringBuffer(); Function m = new Function(); ArrayList<Express> list= m.load(); // 遍历查找需要取出的快递 for (Express e : list) { if (e.getCode() == code){ // 输出快递位置,和快递信息 text.append(e.toString()); // 删除快递 list.remove(e); // 存储信息 m.store(list); // 返回快递信息 return text; } } return null; } // 删除快递 // 需要传入快递单号,用于查找快递 public StringBuffer delete(String number) throws IOException { StringBuffer text = new StringBuffer(); Function m = new Function(); ArrayList<Express> list= m.load(); // 遍历查找需要取出的快递 for (Express e : list) { if (e.getNumber().equals(number)){ // 输出快递位置,和快递信息 text.append(e.toString()); // 删除快递 list.remove(e); // 存储信息 m.store(list); // 返回快递信息 return text; } } return null; } //修改快递 //需要传入快递单号,用于查找快递 public StringBuffer change(String number) throws IOException { StringBuffer text = new StringBuffer(); Function m = new Function(); ArrayList<Express> list= m.load(); // 遍历查找需要取出的快递 for (Express e : list) { if (e.getNumber().equals(number)){ // 输出快递位置,和快递信息 text.append(e.toString()); // 删除快递 list.remove(e); // 存储信息 m.store(list); // 返回快递信息 return text; } } return null; } //载入数据 //注意一定要避免载入错误 public ArrayList<Express> load() throws IOException { ArrayList<Express> arrayList = new ArrayList<>(); try { FileInputStream fis = new FileInputStream("d://eExpress"); ObjectInputStream ois = new ObjectInputStream(fis); try(fis;ois){ arrayList = (ArrayList<Express>) ois.readObject(); System.out.println("载入数据成功"); }catch (Exception e){ System.out.println("载入数据失败"); } }catch (FileNotFoundException f) { System.out.println("未找到文件"); }catch (EOFException e){ System.out.println("文件还未存储序列化对象"); } return arrayList; } //存储数据 public void store(ArrayList<Express> arrayList) throws IOException { FileOutputStream fos = new FileOutputStream("d://eExpress"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(arrayList); oos.close(); fos.close(); System.out.println("数据存储成功"); } }服务器与客户端的交互最重要的一点就是只能是一边输出一边接收,TCP程序在我这一篇博客有介绍。另外就是加入多线程技术,一个服务器可以承接无数的客户端,多线程的创建和一般用法这一篇博客有介绍。
/** * @Author:彭德华 * @Description:服务器端 * @Date Created in 2020-10-4 13:51 * @Modified By: */ public class Server { public static void main(String[] args) throws ClassNotFoundException, IOException { ServerSocket serverSocket = new ServerSocket(65534); Function m = new Function(); // 等待连接 System.out.println("服务器端已启动\n等待客户端连接..."); //使用while循环保证可以连接多个客户端,无限等待连接客户端 while (true) { Socket socket = serverSocket.accept(); System.out.println("连接客户端成功"); System.out.println("等待客户端请求....."); //引入多线程技术 new Thread(new Runnable() { @Override public void run() { try { ArrayList<Express> arrayList = new ArrayList<>(); // 创建输入输出流 InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); ObjectInputStream ois = new ObjectInputStream(is); ObjectOutputStream oos = new ObjectOutputStream(os); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream(os); w1: while (true) { // 获取用户输入选项 int choose = is.read(); arrayList = m.load(); // 功能选择 switch (choose) { case 0://结束 System.out.println("结束"); break w1; case 1: {// 录入快递 System.out.println("进入录入快递功能"); //把服务器端信息传入客户端 oos.writeObject(arrayList); // 接收到一个集合形式的快递信息 ArrayList<Express> list = (ArrayList<Express>) ois.readObject(); m.store(list); break; } case 2: {// 取出快递 System.out.println("进入取快递功能"); // 读取客户端发出的String类型的取件码,读取其中的数字 int code = Integer.parseInt(br.readLine()); // 取出快递信息 StringBuffer text = m.take(code); // 发送快递信息给客户端 ps.println(text); break; } case 3: {//查看所有快递 System.out.println("进入查看所有快递功能"); // 发送快递集合信息 给客户端 oos.writeObject(m.load()); break; } case 4: { System.out.println("进入删除快递功能"); //接受客户端输入的快递单号 String number = br.readLine(); //反馈信息 ps.println(m.delete(number)); } case 5: { ArrayList<Express> a = m.load(); System.out.println("进入修改快递功能"); //接受客户端输入的快递单号 String number = br.readLine(); boolean b = false; for (Express1 e : a) { if (e.getNumber().equals(number)) { b = true; ps.println(1); p: while (true) { String select = br.readLine(); switch (select) { case "0": break p; case "1": { String num = br.readLine(); e.setNumber(num); a.remove(e); a.add(e); oos.writeObject(e); break; } case "2": { String company = br.readLine(); e.setCompany(company); a.remove(e); a.add(e); oos.writeObject(e); break; } case "3": { String phone = br.readLine(); e.setPhone(phone); a.remove(e); a.add(e); oos.writeObject(e); break; } } } } } if (b == false) { ps.println((char[]) null); } m.store(a); } default: } } // 在最后记得关闭连接 ois.close(); oos.close(); }catch (Exception e){ System.out.println("异常"); } } }).start(); } } }连接服务器端,收发与服务器端匹配即可。
/** * @Author:彭德华 * @Description:客户端,做到了只用于接受用户输入 * @Date Created in 2020-10-4 13:52 * @Modified By: */ class Clients { public static void main(String[] args) throws IOException, ClassNotFoundException { Scanner input = new Scanner(System.in); Function m = new Function(); // 传入本机地址和端口 Socket socket = new Socket("127.0.0.1",65534); // 向服务器发送请求 System.out.println("正在向服务器发送请求"); //建立 输/入出流 OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); ObjectInputStream ois = new ObjectInputStream(is); PrintStream ps = new PrintStream(os); BufferedReader br = new BufferedReader(new InputStreamReader(is)); w1: while (true){ System.out.println("0.结束\n1.录入快递\n2.取快递\n3.查看所有快递\n4.删除快递\n5.修改快递"); int choose = Integer.parseInt(input.nextLine()); // 将序号发给服务器,功能对应 os.write(choose); switch (choose) { case 0://结束程序 break w1; case 1: {// 录入快递 ArrayList<Express> arrayList = (ArrayList<Express>) ois.readObject(); // 创建快递信息并将此信息发给服务器 oos.writeObject(m.addExpress(arrayList)); System.out.println("快递录入成功"); break; } case 2: {// 取出快递 System.out.println("输入取件码"); // 将取件码传给服务器 ps.println(input.nextLine()); // 读取服务器传过来的快递信息 String text = br.readLine(); if(text == null) System.out.println("未找到指定快递,请重新操作"); else System.out.println("快递信息为:"+text+"请取出"); break; } case 3: {//查看所有快递 ArrayList<Express> list = (ArrayList<Express>)ois.readObject(); // 遍历 for (Express1 e : list) { System.out.println(e.toString()); } break; } case 4:{ System.out.println("请输入需要删除快递的单号:"); String text = input.nextLine(); ps.println(text); String s = br.readLine(); if(s != null) System.out.println("快递:"+s+",已被删除"); else System.out.println("未找到快递信息"); } case 5:{ System.out.println("请输入需要修改的快递单号:"); String text = input.nextLine(); ps.println(text); String s = br.readLine(); if(s != null){ p: while(true) { System.out.println("请输入需要修改的信息:\n1.单号\n2.公司\n3.电话号码\n0.退出"); String select = input.nextLine(); ps.println(select); switch (select) { case "0": break p; case "1": { System.out.println("请输入修改后的单号:"); String number = input.nextLine(); ps.println(number); System.out.println("修改后的信息为:\t"+ois.readObject()); break; } case "2": { System.out.println("请输入修改后的公司:"); String company = input.nextLine(); ps.println(company); System.out.println("修改后的信息为:\t"+ois.readObject()); break; } case "3": { System.out.println("请输入修改后的电话号码:"); String phoneNumber = input.nextLine(); ps.println(phoneNumber); System.out.println("修改后的信息为:\t"+ois.readObject()); break ; } default: System.out.println("输入有误"); break; } } }else System.out.println("未找到快递信息"); } default:break; } } // 在最后记得关闭连接 oos.close(); ois.close(); } }有bug,有时间的话我会进行更新。