文章目录
1. 任务要求2. 代码分层3. 关键代码3.1 ExpressDao类(持久层操作类)3.2 Client客户端类3.3 Server服务器类3.4 Tools类 (与本地数据进行交互)3.5 Views 视图层3.6 Express实体类
4. 总结
1. 任务要求
基于之前的快递管理系统对其进行重构从而实现数据存储于客户端的分离
2. 代码分层
3. 关键代码
3.1 ExpressDao类(持久层操作类)
package com
.java
.Express12
.dao
;
import com
.java
.Express12
.bean
.Express
;
import com
.java
.Express12
.bean
.Location
;
import com
.java
.Express12
.util
.Tools
;
import java
.io
.IOException
;
import java
.util
.ArrayList
;
import java
.util
.Random
;
public class ExpressDao {
private ArrayList
<Express> expressList
= new ArrayList<Express>();
private Random random
= new Random();
private int size
= 0;
private static Tools tool
= new Tools();
public void setExpressList(ArrayList
<Express> expressList
) {
this.expressList
= expressList
;
}
public boolean add(Express e
) throws IOException
{
if (size
== 100) {
return false;
}
int x
= -1;
int y
= -1;
while (true) {
x
= random
.nextInt(10);
y
= random
.nextInt(10);
if (!(expressList
.contains(x
) && expressList
.contains(y
))) {
break;
}
}
Location l
= new Location();
l
.setX(x
);
l
.setY(y
);
e
.setLocation(l
);
expressList
.add(e
);
int code
= randomCode();
e
.setCode(code
);
tool
.storeExpress(expressList
);
return true;
}
private int randomCode() {
while (true) {
int code
= random
.nextInt(900000) + 100000;
Express e
= findByCode(code
);
if (e
== null
) {
return code
;
}
}
}
public Express
findByNumber(String number
) {
Express e
= new Express();
e
.setNumber(number
);
for (Express express
: expressList
) {
String num
= express
.getNumber();
if (num
.equals(number
)) {
return express
;
}
}
return null
;
}
public Express
findByCode(int code
) {
for (Express express
: expressList
) {
int code1
= express
.getCode();
if (code
== code1
) {
return express
;
}
}
return null
;
}
public void update(Express oldExpress
, Express newExpress
) throws IOException
{
delete(oldExpress
);
add(newExpress
);
tool
.storeExpress(expressList
);
}
public void delete(Express e
) throws IOException
{
for (Express express
: expressList
) {
if (e
.equals(express
)) {
expressList
.remove(express
);
size
--;
break;
}
}
tool
.storeExpress(expressList
);
}
public ArrayList
<Express> findAll() throws IOException
{
return tool
.loadExpress();
}
}
3.2 Client客户端类
package com
.java
.Express12
.cloud
;
import com
.java
.Express12
.bean
.Express
;
import com
.java
.Express12
.view
.Views
;
import java
.io
.*
;
import java
.net
.Socket
;
import java
.util
.ArrayList
;
import java
.util
.Scanner
;
public class Client {
public static Views v
= new Views();
public static void main(String
[] args
) throws IOException
, ClassNotFoundException
{
Scanner input
= new Scanner(System
.in
);
Socket socket
= new Socket("127.0.0.1", 52101);
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) {
int num
= v
.courierMenu();
os
.write(num
);
switch (num
) {
case 0:
break w1
;
case 1: {
oos
.writeObject(v
.insert());
String text
= br
.readLine();
System
.out
.println(text
);
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
);
System
.out
.println("成功取出快递");
}
break;
}
case 3: {
ArrayList
<Express> list
= new ArrayList<Express>();
list
= (ArrayList
<Express>) ois
.readObject();
for (Express e
: list
) {
System
.out
.println(e
.toString());
}
break;
}
case 4: {
System
.out
.println("请输入需要删除快递的单号:");
String text
= input
.nextLine();
ps
.println(text
);
Express e
= (Express
) ois
.readObject();
if (e
== null
) {
String s
= br
.readLine();
System
.out
.println(s
);
break;
} else {
System
.out
.println("快递被成功删除~");
break;
}
}
case 5: {
System
.out
.println("请输入需要修改的快递单号:");
String text
= input
.nextLine();
ps
.println(text
);
Express e2
= (Express
) ois
.readObject();
if (e2
== null
) {
System
.out
.println("快递不存在请重新操作");
} else {
System
.out
.println("请输入新的快递单号: ");
String number
= input
.nextLine();
System
.out
.println("请输入新的快递公司: ");
String company
= input
.nextLine();
e2
.setNumber(number
);
e2
.setCompany(company
);
oos
.writeObject(e2
);
}
String s
= br
.readLine();
if (s
!= null
) {
System
.out
.println(s
);
v
.printExpress(e2
);
}
break;
}
case 6: {
String s
= br
.readLine();
System
.out
.println(s
);
break;
}
default:
break;
}
}
os
.close();
is
.close();
oos
.close();
ois
.close();
ps
.close();
br
.close();
}
}
3.3 Server服务器类
package com
.java
.Express12
.cloud
;
import com
.java
.Express12
.bean
.Express
;
import com
.java
.Express12
.dao
.ExpressDao
;
import com
.java
.Express12
.util
.Tools
;
import com
.java
.Express12
.view
.Views
;
import java
.io
.*
;
import java
.net
.ServerSocket
;
import java
.net
.Socket
;
import java
.util
.ArrayList
;
public class Server {
public static Views v
= new Views();
public static ExpressDao dao
= new ExpressDao();
public static Tools tool
= new Tools();
public static void main(String
[] args
) throws IOException
, ClassNotFoundException
{
ServerSocket server
= new ServerSocket(52101);
System
.out
.println("等待客户端连接");
Socket socket
= server
.accept();
System
.out
.println("一个客户端连接成功");
InputStream is
= socket
.getInputStream();
InputStreamReader isr
= new InputStreamReader(is
);
ObjectInputStream ois
= new ObjectInputStream(is
);
BufferedReader br
= new BufferedReader(isr
);
OutputStream os
= socket
.getOutputStream();
PrintStream ps
= new PrintStream(os
);
ObjectOutputStream oos
= new ObjectOutputStream(os
);
ArrayList
<Express> list
= tool
.loadExpress();
dao
.setExpressList(list
);
w1
:
while (true) {
int num
= is
.read();
switch (num
) {
case 0: {
if ("程序结束".equals(br
.readLine())) {
break w1
;
}
}
case 1: {
Express e1
= (Express
) ois
.readObject();
boolean flag
= dao
.add(e1
);
if (flag
) {
ps
.println("服务器: 添加成功");
} else {
ps
.println("服务器: 添加失败");
}
break;
}
case 2: {
int code
= Integer
.parseInt(br
.readLine());
Express e
= dao
.findByCode(code
);
if (e
== null
) {
String text
= null
;
ps
.println(text
);
} else {
String text
= e
.toString();
ps
.println(text
);
v
.success();
dao
.delete(e
);
}
break;
}
case 3: {
oos
.writeObject(dao
.findAll());
break;
}
case 4: {
String text
= br
.readLine();
Express e
= dao
.findByNumber(text
);
oos
.writeObject(e
);
if (e
== null
) {
ps
.println("快递不存在, 请重新输入!");
break;
} else {
dao
.delete(e
);
break;
}
}
case 5: {
String text
= br
.readLine();
Express e
= dao
.findByNumber(text
);
oos
.writeObject(e
);
Express e2
= (Express
) ois
.readObject();
dao
.update(e
, e2
);
String s
= "操作成功";
ps
.println(s
);
}
case 6: {
ArrayList
<Express> expressList
= dao
.findAll();
tool
.storeExpress(expressList
);
String s
= "保存数据成功,并且重新载入数据";
ps
.println(s
);
ArrayList
<Express> list1
= tool
.loadExpress();
dao
.setExpressList(list1
);
break;
}
}
}
is
.close();
isr
.close();
ois
.close();
br
.close();
os
.close();
ps
.close();
oos
.close();
}
}
3.4 Tools类 (与本地数据进行交互)
package com
.java
.Express12
.util
;
import com
.java
.Express12
.bean
.Express
;
import java
.io
.*
;
import java
.util
.ArrayList
;
public class Tools {
public void storeExpress(ArrayList
<Express> expressList
) throws IOException
{
FileOutputStream fos
= new FileOutputStream("D://networkExpress.txt");
ObjectOutputStream oos
= new ObjectOutputStream(fos
);
oos
.writeObject(expressList
);
oos
.close();
fos
.close();
System
.out
.println("保存快递数据到本地成功");
}
public ArrayList
<Express> loadExpress() throws IOException
{
ArrayList
<Express> expressList
= new ArrayList<>();
try {
FileInputStream fis
= new FileInputStream("D://networkExpress.txt");
ObjectInputStream ois
= new ObjectInputStream(fis
);
try (fis
; ois
) {
expressList
= (ArrayList
<Express>) ois
.readObject();
System
.out
.println("载入数据成功");
} catch (IOException | ClassNotFoundException e
) {
System
.out
.println("载入数据失败");
}
return expressList
;
} catch (FileNotFoundException fileNotFoundException
) {
System
.out
.println("未找到文件");
return expressList
;
} catch (EOFException eofException
) {
System
.out
.println("未存储数据");
return expressList
;
}
}
}
3.5 Views 视图层
package com
.java
.Express12
.view
;
import com
.java
.Express12
.bean
.Express
;
import com
.java
.Express12
.bean
.Location
;
import java
.util
.ArrayList
;
import java
.util
.Scanner
;
public class Views {
private Scanner input
= new Scanner(System
.in
);
public int courierMenu() {
System
.out
.println("请根据提示, 输入功能序号: ");
System
.out
.println("0. 退出");
System
.out
.println("1. 快递录入");
System
.out
.println("2. 取出快递");
System
.out
.println("3. 查看所有快递");
System
.out
.println("4. 快递删除");
System
.out
.println("5. 快递修改");
System
.out
.println("6. 保存快递数据到本地且重新载入数据");
String text
= input
.nextLine();
int num
= -1;
try {
num
= Integer
.parseInt(text
);
} catch (NumberFormatException e
) {
e
.printStackTrace();
}
if (num
< 0 || num
> 6) {
System
.out
.println("请输入以上数字哦!!");
return courierMenu();
}
return num
;
}
public Express
insert() {
System
.out
.println("添加快递, 请输入快递信息: ");
System
.out
.println("请输入快递单号: ");
String number
= input
.nextLine();
System
.out
.println("请输入快递公司: ");
String company
= input
.nextLine();
Express e
= new Express();
e
.setNumber(number
);
e
.setCompany(company
);
return e
;
}
public void printExpress(Express e
) {
System
.out
.println("快递信息如下:");
System
.out
.println("快递公司: " + e
.getCompany() + ", 快递单号: " + e
.getNumber() + ", 取件码: " + e
.getCode());
}
public void update(Express e
) {
System
.out
.println("请输入新的快递单号: ");
String number
= input
.nextLine();
System
.out
.println("请输入新的快递公司: ");
String company
= input
.nextLine();
e
.setNumber(number
);
e
.setCompany(company
);
}
public void printAll(ArrayList
<Express> es
) {
int count
= 0;
for (Express express
: es
) {
if (express
!= null
) {
count
++;
Location lo
= express
.getLocation();
System
.out
.println("第" + (lo
.getX() + 1) + "排" + (lo
.getY() + 1) + "列快递");
printExpress(express
);
}
}
if (count
== 0) {
System
.out
.println("暂无快递信息~");
}
}
public void success() {
System
.out
.println("操作成功");
}
}
3.6 Express实体类
package com
.java
.Express12
.bean
;
import java
.io
.Serializable
;
import java
.util
.Objects
;
public class Express implements Serializable {
private String number
;
private String company
;
private int code
;
private Location location
;
public Location
getLocation() {
return location
;
}
public void setLocation(Location location
) {
this.location
= location
;
}
@Override
public boolean equals(Object o
) {
if (this == o
) {
return true;
}
if (o
== null
|| getClass() != o
.getClass()) {
return false;
}
Express express
= (Express
) o
;
return number
.equals(express
.number
);
}
@Override
public int hashCode() {
return Objects
.hash(number
);
}
@Override
public String
toString() {
return "Express{" +
"number='" + number
+ '\'' +
", company='" + company
+ '\'' +
", code=" + code
+
", location=" + location
+
'}';
}
public Express() {
}
public Express(String number
, String company
, int code
) {
this.number
= number
;
this.company
= company
;
this.code
= code
;
}
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
;
}
}
4. 总结
中途遇到了很多难题, 而且由于粗心大意, 会报很多bug
如:
客户端和服务端的IO流操作一定要一来一回, 你输出他就要接收
有一个bug, 每次选择查看所有快递功能后, 虽然我在dao层的最后都进行了本地数据的存储, 但是直接去查看所有快递的时候仍然会出问题, 后面发现需要对查看所有快递直接对接本地数据读取才行
修改前
=>
public ArrayList
<Express> findAll() throws IOException
{
return expressList
;
}
修改后
=>
public ArrayList
<Express> findAll() throws IOException
{
return tool
.loadExpress();
}
原因是查看所有快递查看的依然是dao里没有变的ExpressList, 除非在查看的时候就应该重新从本地数据中读入
删除功能需要已删除完就对本地数据进行修改, 因为是建立在服务器上的, 所以每一次的操作都和本地数据的存取息息相关~
一开始添加了6号功能将数据保存至本地并刷新的功能, 发现后期服务端和本地数据的各种交互bug, 因此几乎在dao层的每一个方法的结尾都进行了对本地数据的存储和修改, 因此, 6号功能也就名存实亡了, 就放在这不删当作给自己的警醒和思考了
网络编程的学习让我知道最不方便的就是服务端数据与本地数据的交互, 数据传输极为麻烦且冗余代码过多, 相信后期通过将数据层的代码提取出来后会极大的简化这一部分的开发
若需要连接多个客户端直接将代码放至Thread类中重写run()方法即可
大家加油 !! 网络编程看的就是细心呀!!
源代码下载