快递管理系统 - 数据存储在服务器端
还记得之前的快递管理系统吗,现在把需要存储的数据都存储在服务器中,客户端后续只用来收集用户的操作,为了确保服务器能同时连接多个客户端,记得在服务器引入多线程技术。
代码:
1.Express类
这一个类生成对应的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 +
"号柜"+
'}';
}
}
2.Function类
这一类就是功能类,包括了程序使用到的大部分方法,是项目的核心类。需要注意的就是对在载入数据时(序列化技术)对文件的处理,载入数据详细分析我 这一篇博客有提到
/**
* @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("数据存储成功");
}
}
3.Server服务器类
服务器与客户端的交互最重要的一点就是只能是一边输出一边接收,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();
}
}
}
4.Clients客户端类
连接服务器端,收发与服务器端匹配即可。
/**
* @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,有时间的话我会进行更新。