文章目录
数组存储版可参考文章:快递管理控制台简易版——数组存储版(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)用户从客户端发起登录请求,客户端将数据传递到服务器端,
由服务器做验证。服务器端保存用户数据,用户登录成功提示登录成功
并显示功能模块,登录失败提示:用户名或密码不正确 - 基于上一个练习,了解客户端和服务器端的概念,客户端用来获取用户信息,服务器端用于进行数据存储和逻辑判断
在网络编程的基础上,在服务器端启用多线程模式,要求每一个用户发送登录请求到服务器后,服务器端就分配一个线程去处理这个请求,以实现服务器端多线程模式下的用户登录
涉及知识点
思路及代码实现
一、 自定义异常
创建一个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("快递不存在,取件失败!");
}
}
}