目錄
一,快遞管理訓練任務
1,題目描述
2,源代碼
2.1 bean.Express
2.2 dao.ExpressDao
2.3 main
2.4 view.View
3,總結
3.1 核心資料結構改動
3.2 ExpressDao
3.3 Main與ServerMain、ClientMain
3.4 說明
3.5 遇到的問題
3.6 思考
二,圖書管理訓練任務(選做)
1,題目描述
一,快遞管理訓練任務
1,題目描述
還記得之前的快遞管理嗎?
我們将資料存儲在檔案中,其實資料存儲在客 戶端中是很不安全的,今天我們來學習網絡程式設計,用戶端後續隻用來收集使用者 的操作,需要存儲的資料都存儲在伺服器中。
為了保證伺服器能同時連接配接多個用戶端,記得在伺服器引入多線程技術。 接下來加油學習吧!
![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計
2,源代碼
代碼結構
2.1 bean.Express
package bean;
import java.io.Serializable;
import java.util.Objects;
/**
*
*/
public class Express implements Serializable {
private String number; // 快遞單号
private String company; // 公司
private int code; // 取件碼
public int posX, posY; // 快遞所在快遞櫃中的位置
// 構造方法
public Express(String number, String company, int code) {
this.number = number;
this.company = company;
this.code = code;
}
public Express() {
}
// getter/setter
public String getNumber() {
return number;
}
public String getCompany() {
return company;
}
public int getCode() {
return code;
}
public void setNumber(String number) {
this.number = number;
}
public void setCompany(String company) {
this.company = company;
}
public void setCode(int code) {
this.code = code;
}
// 重寫toString 方法
@Override
public String toString() {
return "Express{" +
"number='" + number + '\'' +
", company='" + company + '\'' +
", code=" + code +
'}';
}
// 重寫equals方法
/**
* 隻要快遞單号相同就認為快遞相同
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Express express = (Express) o;
return Objects.equals(number, express.number);
}
@Override
public int hashCode() {
return Objects.hash(code);
}
}
2.2 dao.ExpressDao
package dao;
import bean.Express;
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
// 實作可序列化标記接口 使得dao對象支援序列化與反序列化
public class ExpressDao {
private File file = new File("SerializedData.txt");
private boolean[][] cabinet = new boolean[10][]; // 二維數組表示快遞櫃位置是否被占用 true已占用 false未占用
private ArrayList<Express> expresses = new ArrayList<>(); // 存放所有的Express對象 便于周遊
private Random random = new Random(); // 用于生成随機數
/**
* 反序列化獲得快遞櫃中存放的對象HashMap<Integer, Express> data
*/
public void readFromFile() {
try (FileInputStream fis = new FileInputStream(file)) {
ObjectInputStream ois = new ObjectInputStream(fis);
expresses = (ArrayList<Express>) ois.readObject(); // 反序列化讀取對象
ois.close(); // 關閉輸入流
} catch (IOException | ClassNotFoundException e) {
expresses = new ArrayList<Express>(); // 打開檔案異常時 将expresses初始為空
}
}
/**
* 序列化存儲對象HashMap<Integer, Express> data
* @throws IOException
*/
public void writeToFile() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(expresses); // 序列化對象
oos.close();
}
/**
* 初始化資料結構:cabinet(表示快遞櫃是否被占用),expresses(存儲)
*/
public void init() {
for(int i = 0; i < 10; i++){
cabinet[i] = new boolean[10];
}
for(Express e : expresses) {
cabinet[e.posX][e.posY] = true; // 表示此位置已被占用
}
}
/**
*
* @param e 新加入的快遞對象
* @return
*/
public synchronized boolean add(Express e){
int size = expresses.size();
if(size >= 100){
return false;
}
// 1,随機生成兩個0-9的下标
int x = -1, y = -1;
while (true){
x = random.nextInt(10);
y = random.nextInt(10);
if(cabinet[x][y] == false){
break; // 此位置未被占用
}
}
// 2,判斷取件碼是否重複(最簡單的 一個個對比)
int code = randomCode(); // 獲得沒有重複的取件碼
e.setCode(code);
e.posX = x; // 快遞櫃存放快遞的位置
e.posY = y;
size++; // 快遞數目加一
cabinet[x][y] = true; // 此位置已被占用
expresses.add(e); //
return true;
}
/**
* 周遊所有對象 生成獨一無二的取件碼
* @return
*/
private int randomCode(){
while (true) {
int code = random.nextInt(900000) + 100000; // 範圍(000000-899999)+1000000
Express e = findByCode(code);
if(e == null) { // 說明取件碼未重複
return code;
}
}
}
/**
* 快遞員根據快遞單号查詢HashMap中存放的快遞
* @param number
* @return
*/
public Express findByNumber(String number){
for(Express e : expresses) {
if(e.getNumber().equals(number)) {
return e;
}
}
return null;
}
/**
* 根據取件碼查詢快遞
* @param code 取件碼
* @return 查詢到結果 查詢失敗傳回null
*/
public Express findByCode(int code){
for(Express e : expresses) {
if(e.getCode() == code) {
return e;
}
}
return null;
}
/**
* 多餘的操作 為了MVC更圓潤
* @param oldExpress
* @param newExpress
*/
public synchronized Boolean update(Express oldExpress, Express newExpress){
delete(oldExpress);
return add(newExpress);
}
/**
* 删除特定的快遞對象
* @param e
*/
public synchronized boolean delete(Express e){
cabinet[e.posX][e.posY] = false;
return expresses.remove(e);// 删除指定對象
}
/**
* 擷取所有的快遞對象
* @return
*/
public synchronized ArrayList<Express> getAll() {
return expresses;
}
}
2.3 main
1)main.ClientMain
package main;
import bean.Express;
import view.View;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ClientMain {
private Socket socket;
private View v = new View();
public static void main(String[] args) throws IOException {
ClientMain client = new ClientMain();
client.link();
}
/**
* 建立套接字,與服務端進行連接配接;
* 建立對象輸入/輸出流,與服務端進行資料互動;
* @throws IOException
*/
public void link() throws IOException {
OutputStream os = null;
InputStream is = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
socket = new Socket("127.0.0.1", 8888);
v.connectSuccess();
is = socket.getInputStream();
os = socket.getOutputStream();
oos = new ObjectOutputStream(os);// 由于伺服器是先ois後oos 為了保證配對 這裡需要順序調換
ois = new ObjectInputStream(is);
o:while (true) {
int num = v.menu();// 獲得角色選擇碼
oos.writeInt(num);
oos.flush();
switch (num) {
case 0:
break o;
case 1:
gClient(oos, ois);
break;
case 2:
uClient(oos, ois);
break;
default:
v.choiceError();
break;
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null) ois.close();
if(oos != null) oos.close();
if(socket != null) socket.close();
}
}
/**
* 用戶端管理者子產品
* @param oos
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
public void gClient(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException {
while (true) {
int num = v.gMenu();// 獲得使用者輸入的功能碼
oos.writeInt(num);// 向伺服器傳送功能碼 保證進入同樣的功能子產品
oos.flush();
switch (num) {
case 0:// 退出
return;
case 1:// 插入
insert(oos, ois);
break;
case 2:// 修改
update(oos, ois);
break;
case 3:// 删除
delete(oos, ois);
break;
case 4:// 顯示所有
printAll(oos, ois);
break;
default:
v.choiceError();
break;
}
}
}
/**
* 用戶端使用者子產品
* @param oos
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
public void uClient(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException {
while (true) {
int num = v.uMenu();
oos.writeInt(num);
oos.flush();
switch (num) {
case 0:
return;
case 1:
int code = v.getExpress();
oos.writeInt(code);
oos.flush();
Express e = (Express) ois.readObject();
if(e != null) {// 查詢到有快遞存在
v.printExpress(e);
if(ois.readBoolean()) v.success();
else v.fail();
} else {
v.printNull();// 取件碼對應快遞不存在
}
break;
default:
v.choiceError();
break;
}
}
}
/**
* 插入快遞對象;
* 利用view對象擷取将要插入快遞對象,并将其傳送給服務端
* @param oos
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
public void insert(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException {
Express e = v.insert();
oos.writeObject(e);
oos.flush();
Express e1 = (Express) ois.readObject();// 傳回對象為空 表示目前快遞單号尚未被使用
if(e1 == null) {
if(ois.readBoolean()) {// 插入成功
v.success();
} else {
v.fail();
}
} else {
v.expressExist();
}
}
/**
* 删除快遞對象
* @param oos
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
public void delete(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException {
String id = v.findByNumber();
oos.writeObject(id);
oos.flush();
Express e = (Express) ois.readObject();
if(e != null) {
int num = v.delete();// 再次向使用者确認是否删除
oos.writeInt(num);
oos.flush();
switch (num) {
case 1:// 确認删除
if(ois.readBoolean()) v.success();
else v.fail();
break;
default:// 取消删除或退出
break;
}
} else {
v.printNull();
}
}
/**
* 更新快遞對象
* @param oos
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
public void update(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException {
String id = v.findByNumber();
oos.writeObject(id);
oos.flush();
Express e = (Express) ois.readObject();
if(e != null) {// 被更新的快遞對象存在
Express e1 = v.update();
oos.writeObject(e1);
oos.flush();
if(ois.readBoolean()) v.success();
else v.fail();
} else {
v.printNull();
}
}
/**
* 列印快遞對象
* @param oos
* @param ois
* @throws IOException
* @throws ClassNotFoundException
*/
public void printAll(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException {
// ArrayList<Express> expresses = (ArrayList<Express>) ois.readObject();
// v.printAll(expresses);
Express[] es = (Express[]) ois.readObject();
List<Express> expresses = Arrays.asList(es);
v.printAll(expresses);
}
}
2)main.ServerMain
package main;
import bean.Express;
import dao.ExpressDao;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ServerMain {
private ServerSocket serverSocket;
private ExpressDao dao = new ExpressDao();
private int numOfClient = 0;
// 伺服器
public static void main(String[] args) throws IOException {
ServerMain server = new ServerMain();
server.start();
}
/**
* 啟動伺服器,并與用戶端進行連接配接
*/
public void start() {
try {
serverSocket = new ServerSocket(8888);
System.out.println("伺服器已啟動");
dao.readFromFile();// 從檔案中讀取資料
dao.init();// 初始化資料結構
System.out.println("資料初始化成功");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("第" + (++numOfClient) + "個用戶端連接配接了");
new Thread() {
@Override
public void run() {
try {
receive(socket);// 準備連接配接 進入主功能子產品
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(serverSocket != null){
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 建立對象輸入/輸出流,與用戶端進行資料互動;
* 進入主子產品,選擇角色;
* @param socket
* @throws IOException
*/
public void receive(Socket socket) throws IOException {
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
ObjectInputStream ois = new ObjectInputStream(is);
ObjectOutputStream oos = new ObjectOutputStream(os);
try(is; os; ois; oos) {// 這種方式可以在try/catch執行結束後 自動關閉資源
o: while (true) {
switch (ois.readInt()) {
case 0:// 退出
dao.writeToFile();// 退出伺服器端 将資料對象寫回檔案
break o;
case 1:
gClient(ois, oos);// 進入管理者操作功能子產品
break ;
case 2:
uClient(ois, oos);// 進入使用者操作功能子產品
break ;
default: break ;
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 服務端——管理者子產品,負責與用戶端——管理者子產品進行資料互動
* @param ois
* @param oos
* @throws IOException
* @throws ClassNotFoundException
*/
public void gClient(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
while (true) {
switch (ois.readInt()) {
case 0:// 退出
return;
case 1:// 插入
insert(ois, oos);
break;
case 2:// 修改
update(ois, oos);
break;
case 3:// 删除
delete(ois, oos);
break;
case 4:// 顯示所有
printAll(ois, oos);
break;
}
}
}
/**
* 服務端——使用者子產品,負責與用戶端——使用者子產品進行資料互動
* @param ois
* @param oos
* @throws IOException
*/
public void uClient(ObjectInputStream ois, ObjectOutputStream oos) throws IOException {
while (true) {
switch (ois.readInt()) {
case 0:
return;
case 1:// 取件
Express e = dao.findByCode(ois.readInt());// 根據用戶端傳過來的取件碼 查找快遞對象
oos.writeObject(e);// 向用戶端傳送查找的對象
oos.flush();
if(e != null) {
oos.writeBoolean(dao.delete(e));
oos.flush();
}
break;
default: break;
}
}
}
/**
* 插入快遞對象;
* 接受用戶端發來的新快遞對象,用dao對象對資料進行操作,并将操作結果返還給用戶端
* @param ois
* @param oos
* @throws IOException
* @throws ClassNotFoundException
*/
public void insert(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
Express e = (Express) ois.readObject();
Express e1 = dao.findByNumber(e.getNumber());// 根據快遞單号判斷對應快遞是否已存在
oos.writeObject(e1);
oos.flush();
if(e1 == null) {
oos.writeBoolean(dao.add(e));
oos.flush();
}
}
/**
* 删除快遞對象
* @param ois
* @param oos
* @throws IOException
* @throws ClassNotFoundException
*/
public void delete(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
String id = (String) ois.readObject();
Express e = dao.findByNumber(id);
oos.writeObject(e);
oos.flush();
if(e != null) {// 快遞對象存在
switch (ois.readInt()) {// 再次向使用者确認是否删除
case 1:
oos.writeBoolean(dao.delete(e));
oos.flush();
break;
default:
break;
}
}
}
/**
* 更新快遞對象
* @param ois
* @param oos
* @throws IOException
* @throws ClassNotFoundException
*/
public void update(ObjectInputStream ois, ObjectOutputStream oos) throws IOException, ClassNotFoundException {
String id = (String) ois.readObject();
Express e = dao.findByNumber(id);
oos.writeObject(e);
oos.flush();
if(e != null) {
Express e1 = (Express) ois.readObject();
oos.writeBoolean(dao.update(e, e1));
oos.flush();
}
}
/**
* 向用戶端傳送所有快遞對象
* @param ois
* @param oos
* @throws IOException
*/
public void printAll(ObjectInputStream ois, ObjectOutputStream oos) throws IOException {
// oos.writeObject(dao.getAll());
// oos.flush();
ArrayList<Express> list = dao.getAll();
Express[] expresses = new Express[list.size()];
list.toArray(expresses);
oos.writeObject(expresses);
oos.flush();
}
}
2.4 view.View
package view;
import bean.Express;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;
/**
* 視圖層
* 隻負責展示視圖 不包含其他任何邏輯
*/
public class View {
public Scanner input = new Scanner(System.in);
/**
* 獲得使用者的角色選擇輸入,并進入相應的功能
* @return 傳回功能碼 1:管理者 2:普通使用者 0:退出
*/
public int menu(){
System.out.println("根據提示輸入功能序号:");
System.out.println("1,管理者");
System.out.println("2,普通使用者");
System.out.println("0,退出");
String s = input.nextLine();
int funcNum = -1;
try{
funcNum = Integer.parseInt(s);
}catch (NumberFormatException e){ // 格式異常 遞歸繼續擷取功能碼
return menu();
}
if(funcNum < 0 || funcNum > 2){ // 功能碼不合法
return menu();
}
return funcNum;
}
/*
-----------------------------------------------------------------
*/
/**
* 獲得管理者輸入的功能碼
* @return 管理者輸入的合法功能碼 1:錄入 2:修改 3:删除 4:檢視所有 0:退出
*/
public int gMenu(){
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();
int funcNum = -1;
try{
funcNum = Integer.parseInt(s);
}catch (NumberFormatException e){ // 格式異常 遞歸繼續擷取功能碼
return gMenu();
}
if(funcNum < 0 || funcNum > 4){ // 功能碼不合法
return gMenu();
}
return funcNum;
}
/**
* 1快遞員錄入資訊
* @return 傳回包含了快遞單号和快遞公司的快遞對象
*/
public Express insert(){
System.out.println("請根據提示輸入快遞資訊:");
System.out.print("請輸入快遞單号:");
String number = input.nextLine();
System.out.print("請輸入快遞公司:");
String company = input.nextLine();
Express e = new Express();
e.setNumber(number);
e.setCompany(company);
return e;
}
/**
* 2修改快遞資訊
*/
public Express update(){
System.out.print("請輸入新的快遞單号:");
String number = input.nextLine();
System.out.print("請輸入新的快遞公司");
String company = input.nextLine();
Express e = new Express();
e.setNumber(number);
e.setCompany(company);
return e;
}
/**
* 3詢問是否删除
* @return 給出快遞管理者的選擇 1:删除 2:取消
*/
public int delete(){
System.out.println("确認是否删除:");
System.out.println("1,确認删除");
System.out.println("2,取消删除");
System.out.println("0,退出");
String s = input.nextLine();
int num = -1;
try {
num = Integer.parseInt(s);
}catch (NumberFormatException e){
return delete();
}
if(num < 0 || num > 2){
return delete();
}
return num;
}
/**
* 4周遊顯示所有快遞資訊
* @param es
*/
public void printAll(List<Express> es){
int count = 0;
for(Express e : es) {
count++;
printExpress(e);
}
if(count == 0){
System.out.println("暫無快遞資訊");
}
}
/**
* 提示使用者輸入快遞單号
* @return
*/
public String findByNumber(){
System.out.println("請根據提示輸入快遞資訊:");
System.out.print("請輸入需要操作的快遞單号:");
String number = input.nextLine();
return number;
}
/**
* 顯示快遞資訊
* @param e
*/
public void printExpress(Express e){
if(e == null){
System.out.println("快遞資訊不存在");
return;
}
System.out.println("快遞資訊如下:");
System.out.println("位置:第" + (e.posX + 1) + "排," + (e.posY + 1) + "列; " +
"快遞公司:" + e.getCompany() + "; " + "快遞單号:" + e.getNumber() + ";" +
"取件碼:" + e.getCode() + ";");
}
/*
-----------------------------------------------------------------
*/
/**
* 獲得使用者輸入的取件碼(這裡簡化,隻要取件碼相同,就算取件成功)
* @return 使用者輸入的合法功能碼(6位)
*/
public int uMenu(){
System.out.println("根據提示輸入功能序号:");
System.out.println("0,退出");
System.out.println("1,取出快遞");
String s = input.nextLine();
int funcNum = -1;
try{
funcNum = Integer.parseInt(s);
}catch (NumberFormatException e){ // 格式異常 遞歸繼續擷取功能碼
System.out.println("格式異常");
return uMenu();
}
if(funcNum < 0 || funcNum > 1){ // 功能碼不合法
System.out.println("功能碼不合法");
return uMenu();
}
return funcNum;
}
/**
* 使用者取件
* @return
*/
public int getExpress() {
System.out.println("根據提示進行取件:");
System.out.print("請輸入取件碼:");
String s = input.nextLine();
int code = -1;
try{
code = Integer.parseInt(s);
}catch (NumberFormatException e){ // 格式異常 遞歸繼續擷取功能碼
System.out.println("格式異常");
return getExpress();
}
if(code < 100000 || code > 999999){ // 功能碼不合法
System.out.println("輸入有誤,請重試!");
return getExpress();
}
return code;
}
public void expressExist(){
System.out.println("此快遞單号已存在,請勿重複存儲");
}
public void printCode(Express e) {
System.out.println("新快遞的取件碼為:" + e.getCode());
}
public void success(){
System.out.println("操作成功!");
}
public void fail(){
System.out.println("操作失敗!");
}
public void choiceError() {
System.out.println("輸入選項有誤,請重新輸入!");
}
public void printNull(){
System.out.println("快遞不存在,請檢查輸入");
}
public void connectSuccess() {
System.out.println("伺服器連接配接成功");
}
}
3,總結
與上一次的任務卡@&再見螢火蟲&【任務卡_03-Java核心類庫_第4節 IO】相比,有着較大的改動。
3.1 核心資料結構改動
将HashMap<Integer, Express> data删除,隻保留Collection<Express> expresses;資料存儲由main函數轉移至dao對象中;
- 雖然可以根據HashMap快速的查找相應的Express對象,但是會導緻快遞對象的重複存儲,也就是說在data中和expresses中存儲了許多重複的快遞對象,是以此次修改,隻保留了expresses資料結構;
- 将資料存儲在main中,利用dao對象對資料進行操作需要傳送大量的參數,使得函數看起來較為冗雜;
- main函數中聲明大量資料結構,使得主函數看起來較為複雜,破壞了整體的結構清晰感;
3.2 ExpressDao
1)将所有快遞對象資料存放在dao的一個屬性中(上一次IO任務卡,把他們放在了main方法中了);
2)取消根據取件碼查找快遞對象的HashMap資料結構,改成用ArrayList存儲。避免對象重複存儲占用大量空間;
3)插入、删除、更新、查詢所有等方法使用synchronized進行修飾,保證線程安全;
3.3 Main與ServerMain、ClientMain
1)将Main拆解成ServerMain和ClientMain兩個方法,一個負責服務端,一個負責用戶端;
2)用戶端和服務端需要保證大緻相同的邏輯結構,即當用戶端由狀态1轉變為狀态2(方法功能,接受資料對象及類型等發生改變),服務端需要偵聽這種狀态轉變,并進行同樣的狀态轉移操作。反之同理;
3)用戶端與服務端的資料交換是一去一回,嚴格配對!即便是在new輸入輸出流時也要保持一緻!![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計 ![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計 4)伺服器啟動專門聲明一個start方法完成,主要作用是:建立ServerSocket、反序列化讀取對象資訊、初始化資料結構、通過while循環實作多線程、線程run方法隻用來調用receive方法(進入角色選擇子產品);
5)服務端的receive和用戶端的link 是互相配對的。在這兩個方法中建立ois(ObjectInoutStream)、oos(ObjectOutputStream),并将它們作為參數,進行資料互動;
3.4 說明
實作了多線程、集合、IO等技術;
較好的進行方法設計,使得項目整體結構清晰,備援度較低;
基本完成題目要求功能:序列化反序列化、多線程、集合等;
3.5 遇到的問題
1)用戶端執行到擷取ObjectInputStream時卡住了,不再向下執行
咨詢老師之後,發現問題。伺服器與用戶端在資料傳輸時,不但需要在互動階段需要配對,聲明指派時也要配對,即輸出對應輸入、輸入對應輸出!![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計 ![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計
2)在dao中對資料進行操作後,快遞對象集合确實發生變化了(在服務端列印出來看過)。但是在用戶端進行printAll時,第一次是對的,後面不管怎麼修改,再次printAll結果都不會改變
注釋掉的,是原先有問題的代碼。請教老師給出的解答是,流用完之後沒有關閉,而且是作為參數進行傳遞,是以借助于流在用戶端和伺服器之間傳遞的集合對象expresses沒有發生改變,依舊是第一次傳輸的資料,因而結果不發生改變。![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計 但是有兩點疑問:(以後再回頭看看吧)![]()
任務卡_03-Java核心類庫_第6節 網絡程式設計
- flush的作用不就是清楚緩沖嗎?為什麼不起作用?
- 為什麼把ArrayList對象轉換為對象數組進行傳輸,就可以解決問題?是因為每次傳輸時,伺服器都重新new了數組嗎?
3.6 思考
1)try/catch與直接抛出異常相比有什麼優缺點?
2)将流作為參數進行傳遞,不管對原資料進行什麼操作,多次調用方法,擷取流中傳輸的資料依舊是最開始傳輸的那一次?那flush的意以何在?
3)服務端、用戶端進行資料互動時,不僅在傳輸資料需要一去一回,建立ois(ObjectInoutStream)、oos(ObjectOutputStream)時也要遵循這樣的規則
二,圖書管理訓練任務(選做)
時間原因,有空再補o( ̄┰ ̄*)ゞ
1,題目描述
還記得之前的圖書管理嗎?我們将資料存儲在檔案中,其實資料存儲在客 戶端中是很不安全的,今天我們來學習網絡程式設計,用戶端後續隻用來收集使用者 的操作,需要存儲的資料都存儲在伺服器中。
為了保證伺服器能同時連接配接多個用戶端,記得在伺服器引入多線程技術。 接下來加油學習吧!
1. 管理者登陸
2. 圖書管理
2.1 圖書新增
2.2 圖書修改
2.3 圖書删除
2.4 根據圖書名稱模糊查找圖書
2.5 檢視所有圖書 (三種排序)
——價格從高到低排序
——價格從低到高排序
——新舊排序(出版日期排序)