DAY25 综合案例

一 项目演示

把模块复制到idea中,分别启动服务器端和客户端

二 项目说明

1 所采用的知识点

​ 本系统采用了我们学过的以下几个核心知识点:

​ 1). IO流技术

​ 服务器端读写本地的文件,我们采用IO流

​ 要求一个学生一行数据,并且学生的属性之间使用","隔开

​ 1,小名,男,20

​ 2,小张,男,20

​ 2). 网络编程技术

​ 客户端和服务器采用"短连接"

​ 每个功能当需要连接完服务器之后,断开连接,执行下一个功能在重写连接服务器

​ 每个功能都连接一次服务器

​ 3). 序列化

​ 客户端根据id查询学生信息,服务器端读取文件,查询学生,给客户端返回一个Student对象

​ 客户端使用反序列化流读取Student对象

​ 客户端查询所有学生信息,服务器读取文件,把查询到的多个Student对象封装到一个ArrayList集合中

​ 客户端使用反序列化流读取ArrayList集合对象

java 复制代码
1,小名,男,20  Student s = new Student("小名","男",20);
2,小张,男,20  Student s = new Student("小名","男",20);
ArrayList<Student> list = new ArrayList<Student> ();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(list); //服务器给客户端写多个学生信息
oos.writeObject(s); // 服务器给客户端写会一个学生信息

ObjectInputStream ois = new ObjectInputStream(is);
ArrayList<Student> list = (ArrayList<Student>)ois.readObject();
Student s = (Student)ois.readObject();

​ 4). 多线程

​ 支持多个客户端,同时连接服务器

​ 服务器每获取一个客户端对象,都开启一个线程,对客户端对象进行增删改查

2 业务交互模式图示

​ 【说明】

​ 1).客户端和服务器端采用TCP连接;

​ 2).数据保存在服务器端;

​ 3). 客户端增删改查发送数据格式说明:

​ a). 添加:"[1]数据",例如:"[1]张三,男,22",意思:没有id字段,由服务器端在写入数据前自动添加。

​ b).根据id查询一条数据:"[2]id",例如:"[2]1",意思:查询id为1的学员信息

​ c). 修改一条数据:"[3]新数据"。例如:"[3]1,张三2,女,19",意思:将id=1的学员改为后面的新数据。

​ d). 查询所有数据:"[4]"。例如:"[4]",意思:后面不用带任何数据。

​ e). 删除一条数据:"[5]id"。例如:"[5]1",意思:删除id为1的记录。

三 案例代码

一.客户端

1.创建实体类Student类

java 复制代码
package com.itheima.pojo;

import java.io.Serializable;

//学生类
public class Student implements Serializable{
    //添加一个序列号,防止序列号冲突异常
    private static final long serialVersionUID = -1L;
    //编号
    private int id;
    //姓名
    private String name;
    //性别
    private String sex;
    //年龄
    private int age;

    public Student() {
    }

    public Student(int id, String name, String sex, int age) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2.创建操作学生的工具类

java 复制代码
package com.itheima.utils;

import com.itheima.pojo.Student;

import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;

/*
    创建操作学生的工具类:里边定义方法都是静态的
 */
public class StudentUtils {
    //私有构造方法:目的让用户使用类名.方法名调用静态方法
    private StudentUtils() { }

    //定义一个打印单个学生的方法
    public static void printStudent(Student s){
        System.out.println("---------------------------------------------------------");
        System.out.println("编号\t\t姓名\t\t性别\t\t年龄");
        System.out.println(s.getId()+"\t\t"+s.getName()+"\t\t"+s.getSex()+"\t\t"+s.getAge());
        System.out.println("---------------------------------------------------------");
    }

    //定义一个打印ArrayList集合中所有学生的方法
    public static void printArrayList(ArrayList<Student> list){
        System.out.println("---------------------------------------------------------");
        System.out.println("编号\t\t姓名\t\t性别\t\t年龄");
        //遍历集合获取每一个学生Student对象
        for (Student s : list) {
            System.out.println(s.getId()+"\t\t"+s.getName()+"\t\t"+s.getSex()+"\t\t"+s.getAge());
        }
        System.out.println("---------------------------------------------------------");
    }
    
    /*
        创建一个获取客户端Socket对象的方法,供每一个功能使用
     */
    public static Socket getSocket(){
        Socket socket = null;
        try {
            socket = new Socket("127.0.0.1",8888);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return socket;
    }
}

3.创建主类StudentClient类

java 复制代码
package com.itheima.main;

import java.util.Scanner;

/*
    客户端的主程序,包含main方法==>启动客户端
    1.定义一个静态的成员Scanner对象,供所有的方法使用
    2.打印主菜单
    3.定义一个死循环,让系统功能重复执行
    4.打印功能选项
    5.获取用户输入的功能选项
    6.根据用户输入的功能选项,选择对应的功能(调用增删改查的方法)
 */
public class StudentClient {
    //1.定义一个静态的成员Scanner对象,供所有的方法使用
    public static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        //2.打印主菜单
        System.out.println("欢迎使用学生管理系统~~~");
        //3.定义一个死循环,让系统功能重复执行
        while (true){
            //4.打印功能选项
            System.out.println("--------------------------------------------------------------------------");
            System.out.println("1.添加学生  2.根据id查询学生  3.修改学生  4.查看所有学生 5.删除学生  6.退出");
            //5.获取用户输入的功能选项
            System.out.println("请选择您要执行的功能:");
            int choose = sc.nextInt();
            //6.根据用户输入的功能选项,选择对应的功能(调用增删改查的方法)
            switch (choose){
                case 1:
                    //1.添加学生
                    addStudent();
                    break;
                case 2:
                    //2.根据id查询学生
                    findStudentById();
                    break;
                case 3:
                    //3.修改学生
                    updateStudent();
                    break;
                case 4:
                    //4.查看所有学生
                    findAllStudent();
                    break;
                case 5:
                    //5.删除学生
                    deleteStudent();
                    break;
                case 6:
                    //6.退出系统
                    System.out.println("欢迎您下次继续使用本系统!");
                    System.exit(0);//终止JVM
                default:
                    System.out.println("您输入的功能选项不存在,请重新输入!");
                    break;
            }
        }
    }

    /*
        5.删除学生的方法
     */
    private static void deleteStudent() {
    }

    /*
        4.查看所有学生的方法
     */
    private static void findAllStudent() {
    }

    /*
        3.修改学生的方法
     */
    private static void updateStudent() {
    }

    /*
        2.根据id查询学生的方法
     */
    private static void findStudentById() {
    }

    /*
        1.添加学生的方法
     */
    private static void addStudent() {
    }
}

4.添加学生功能

java 复制代码
/*
    1.添加学生的方法
    a.获取用户输入的学生信息(姓名,性别,年龄)
    b.获取客户端Socket对象,连接服务器
    c.客户端往服务器发送数据==>添加"[1]张三,男,18"
    d.读取服务器回写的数据 约定(1:表示成功,0:表示失败)
    e.给用户展示结果
    f.释放资源
 */
private static void addStudent() {
    System.out.println("------------------------------您选择的是添加学生功能,请输入学生的信息-----------------------------------");
    //a.获取用户输入的学生信息(姓名,性别,年龄)
    System.out.println("请输入学生的姓名:");
    String name = sc.next();
    System.out.println("请输入学生的性别:");
    String sex = sc.next();
    System.out.println("请输入学生的年龄:");
    int age = sc.nextInt();

    //b.获取客户端Socket对象,连接服务器
    Socket socket = StudentUtils.getSocket();
    if(socket==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }

    try(OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();) {
        //c.客户端往服务器发送数据==>添加"[1]张三,男,18"
        os.write(("[1]"+name+","+sex+","+age+",").getBytes());

        //d.读取服务器回写的数据 约定(1:表示成功,0:表示失败)
        int len = is.read();

        //e.给用户展示结果
        if(len==1){
            System.out.println("[恭喜您,学生添加成功!]");
        }else{
            System.out.println("[学生添加失败,请联系管理员!]");
        }

        //f.释放资源
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

5.根据id查询学生

java 复制代码
/*
    2.根据id查询学生的方法
        a.获取用输入的数据(学生id)
        b.获取客户端Socket对象,连接服务器
        c.客户端往服务器发送数据==>根据id查询 [2]id
        d.读取服务器回写的数据,服务器回写一个Student对象,使用反序列化流读取对象
        e.给用户展示结果
        f.释放资源
 */
private static void findStudentById() {
    System.out.println("------------------------------您选择的是根据id查询学生功能-----------------------------------");
    //a.获取用输入的数据(学生id)
    System.out.println("请输入您要查询的学生id:");
    int id = sc.nextInt();
    //b.获取客户端Socket对象,连接服务器
    Socket socket = StudentUtils.getSocket();
    if(socket==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }
    try {
        //c.客户端往服务器发送数据==>根据id查询 [2]id
        OutputStream os = socket.getOutputStream();
        os.write(("[2]"+id).getBytes());
        //d.读取服务器回写的数据,服务器回写一个Student对象,使用反序列化流读取对象
        InputStream is = socket.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(is);
        Student student = (Student)ois.readObject();

        //e.给用户展示结果
        if(student==null){
            //没有查询到对应id的学生
            System.out.println("[查无此人!]");
        }else{
            //查询到了学生,调用工具类中打印学生的方法
            StudentUtils.printStudent(student);
        }

        //f.释放资源
        ois.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

6.查询所有学生

java 复制代码
/*
    4.查看所有学生的方法
    a.获取用输入的数据-->是查询所有学生,不用获取数据
    b.获取客户端Socket对象,连接服务器
    c.客户端往服务器发送数据==>查看所有[4]
    d.读取服务器回写的数据,服务器回写一个ArrayList<Student>集合,使用反序列化流读取集合对象
    e.给用户展示结果
    f.释放资源
 */
private static void findAllStudent() {
    System.out.println("------------------------------您选择的是查询所有学生功能-----------------------------------");
    //a.获取用输入的数据-->是查询所有学生,不用获取数据
    //b.获取客户端Socket对象,连接服务器
    Socket socket = StudentUtils.getSocket();
    if(socket==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }
    try(OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();) {
        //c.客户端往服务器发送数据==>查看所有[4]
        os.write("[4]".getBytes());

        //d.读取服务器回写的数据,服务器回写一个ArrayList<Student>集合,使用反序列化流读取集合对象
        ObjectInputStream ois = new ObjectInputStream(is);
        ArrayList<Student> list = (ArrayList<Student>)ois.readObject();

        //e.给用户展示结果
        if(list==null || list.size()==0){
            //没有查询到学生数据
            System.out.println("[服务器暂时没有学生的数据,请添加学生之后再试!]");
        }else{
            //查询到了学生,调用工具类中打印集合的方法
            StudentUtils.printArrayList(list);
        }
        //f.释放资源
        ois.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

7.根据id修改学生

java 复制代码
/*
    3.修改学生的方法
    a.获取用户输入的数据(学生id)
    我们在修改学生之前,首先要根据id查询学生信息
        如果没有查询到,提示用户"不存在该id的学生"
        如果查询到,学生存在,再让用户继续输入要修改的学生信息(新的姓名,新的性别,新的年龄)
    b.获取客户端Socket对象,连接服务器
    c.客户端往服务器发送数据==>修改 [3]1,张三,男,18
    d.读取服务器回写的数据 约束(1:表示成功,0:表示失败)
    e.给用户展示结果
    f.释放资源
 */
private static void updateStudent() {
    System.out.println("------------------------------您选择的是根据修改学生功能-----------------------------------");
    //a.获取用输入的数据(学生id)
    System.out.println("请输入要修改的学生id:");
    int id = sc.nextInt();
    //我们在修改学生之前,首先要根据id查询学生信息
    //b.获取客户端Socket对象,连接服务器
    Socket socket = StudentUtils.getSocket();
    if(socket==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }
    Student student = null;
    try(OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();) {
        //c.客户端往服务器发送数据==>根据id查询 [2]id
        os.write(("[2]" + id).getBytes());
        //d.读取服务器回写的数据,服务器回写一个Student对象,使用反序列化流读取对象
        ObjectInputStream ois = new ObjectInputStream(is);
        student= (Student) ois.readObject();

        //e.给用户展示结果
        if (student == null) {
            //如果没有查询到,提示用户"不存在该id的学生"
            System.out.println("[不存在该id的学生]");
            return;
        }
        //f.释放资源
        ois.close();
        socket.close();
    }catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    //如果查询到,学生存在,再让用户继续输入要修改的学生信息(新的姓名,新的性别,新的年龄)
    System.out.println("请输入新的学生的姓名(输入0保留原值):");
    String name = sc.next();
    System.out.println("请输入新的学生的性别(输入0保留原值):");
    String sex = sc.next();
    System.out.println("请输入新的学生的年龄(输入0保留原值):");
    int age = sc.nextInt();
    //用户输入完之后,我们判断输入的是否为0
    if(!"0".equals(name)){
        student.setName(name);
    }
    if(!"0".equals(sex)){
        student.setSex(sex);
    }
    if(age!=0){
        student.setAge(age);
    }

    //b.获取客户端Socket对象,连接服务器
    Socket socket2 = StudentUtils.getSocket();
    if(socket2==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }
    try(OutputStream os = socket2.getOutputStream();
        InputStream is = socket2.getInputStream();) {
        //c.客户端往服务器发送数据==>修改 [3]1,张三,男,18
        os.write(("[3]"+id+","+student.getName()+","+student.getSex()+","+student.getAge()).getBytes());
        //d.读取服务器回写的数据 约束(1:表示成功,0:表示失败)
        int len = is.read();

        //e.给用户展示结果
        if(len==1){
            System.out.println("[恭喜您,用户修改成功!]");
        }else{
            System.out.println("[用户修改失败,请联系管理员!]");
        }
        //f.释放资源
        socket2.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

a.把id查询学生的代码封装到一个方法中

java 复制代码
/*
    把id查询学生的代码封装到一个方法中
 */
public static Student getStudentById(int id){
    //b.获取客户端Socket对象,连接服务器
    Socket socket = StudentUtils.getSocket();
    if(socket==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return null;//结束添加学生的方法
    }
    Student student = null;
    try(OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();) {
        //c.客户端往服务器发送数据==>根据id查询 [2]id
        os.write(("[2]" + id).getBytes());
        //d.读取服务器回写的数据,服务器回写一个Student对象,使用反序列化流读取对象
        ObjectInputStream ois = new ObjectInputStream(is);
        student= (Student) ois.readObject();

        //e.给用户展示结果
        if (student == null) {
            //如果没有查询到,提示用户"不存在该id的学生"
            System.out.println("[不存在该id的学生]");
        }
        //f.释放资源
        ois.close();
        socket.close();
    }catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return student;
}

b.优化修改学生的代码

java 复制代码
private static void updateStudent() {
    System.out.println("------------------------------您选择的是根据修改学生功能-----------------------------------");
    //a.获取用输入的数据(学生id)
    System.out.println("请输入要修改的学生id:");
    int id = sc.nextInt();
    //我们在修改学生之前,首先要根据id查询学生信息
    Student student = getStudentById(id);
    if(student == null){
        //没有获取到学生信息,结束方法
        return;
    }

    //如果查询到,学生存在,再让用户继续输入要修改的学生信息(新的姓名,新的性别,新的年龄)
    System.out.println("请输入新的学生的姓名(输入0保留原值):");
    String name = sc.next();
    System.out.println("请输入新的学生的性别(输入0保留原值):");
    String sex = sc.next();
    System.out.println("请输入新的学生的年龄(输入0保留原值):");
    int age = sc.nextInt();
    //用户输入完之后,我们判断输入的是否为0
    if(!"0".equals(name)){
        student.setName(name);
    }
    if(!"0".equals(sex)){
        student.setSex(sex);
    }
    if(age!=0){
        student.setAge(age);
    }

    //b.获取客户端Socket对象,连接服务器
    Socket socket2 = StudentUtils.getSocket();
    if(socket2==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }
    try(OutputStream os = socket2.getOutputStream();
        InputStream is = socket2.getInputStream();) {
        //c.客户端往服务器发送数据==>修改 [3]1,张三,男,18
        os.write(("[3]"+id+","+student.getName()+","+student.getSex()+","+student.getAge()).getBytes());
        //d.读取服务器回写的数据 约束(1:表示成功,0:表示失败)
        int len = is.read();

        //e.给用户展示结果
        if(len==1){
            System.out.println("[恭喜您,用户修改成功!]");
        }else{
            System.out.println("[用户修改失败,请联系管理员!]");
        }
        //f.释放资源
        socket2.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

c.优化根id查询学生的代码

java 复制代码
private static void findStudentById() {
    System.out.println("------------------------------您选择的是根据id查询学生功能-----------------------------------");
    //a.获取用输入的数据(学生id)
    System.out.println("请输入您要查询的学生id:");
    int id = sc.nextInt();
    //调用根据id查询学生的方法
    Student student = getStudentById(id);
    if(student != null){
        //调用打印学生信息的方法
        StudentUtils.printStudent(student);
    }
}

8.根据id删除学生

java 复制代码
/*
    5.删除学生的方法
    a.获取用户输入的数据(学生id)
    由于删除学生的时候,先根据id查询学习信息,把学生的信息给用户展示,先调用根id查询学生的方法
    b.获取客户端Socket对象,连接服务器
    c.客户端往服务器发送数据==>删除 "[5]id"
    d.读取服务器回写的数据 约束(1:表示成功,0:表示失败)
    e.给用户展示结果
    f.释放资源
 */
private static void deleteStudent() {
    System.out.println("------------------------------您选择的是删除生功能-----------------------------------");
    //a.获取用户输入的数据(学生id)
    System.out.println("请输入您要删除学生的id:");
    int id = sc.nextInt();
    //由于删除学生的时候,先根据id查询学习信息,把学生的信息给用户展示,先调用根id查询学生的方法
    Student student = getStudentById(id);
    if(student==null){
        return;
    }
    //增加一个判断,判断用户是否确定删除
    System.out.println("你确定要删除以上信息的学习吗?(y|n?)");
    String flag = sc.next();
    if(!"y".equalsIgnoreCase(flag)){
        System.out.println("[删除的操作已经取消!]");
        return;
    }
    //b.获取客户端Socket对象,连接服务器
    Socket socket = StudentUtils.getSocket();
    if(socket==null){
        System.out.println("服务器暂时无法连接,请稍后重试...");
        return;//结束添加学生的方法
    }
    try(OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();){
        //c.客户端往服务器发送数据==>删除 "[5]id"

        os.write(("[5]"+id).getBytes());
        //d.读取服务器回写的数据 约束(1:表示成功,0:表示失败)

        int len = is.read();

        //e.给用户展示结果
        if(len==1){
            System.out.println("[恭喜您,删除学生成功!]");
        }else{
            System.out.println("[删除学生失败,请联系管理员!]");
        }
        //f.释放资源
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

二.服务器端

1.创建实体类Student类

java 复制代码
package com.itheima.pojo;

import java.io.Serializable;

//学生类
public class Student implements Serializable{
    //添加一个序列号,防止序列号冲突异常
    private static final long serialVersionUID = -1L;
    //编号
    private int id;
    //姓名
    private String name;
    //性别
    private String sex;
    //年龄
    private int age;

    public Student() {
    }

    public Student(int id, String name, String sex, int age) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2.创建服务器端增删改查工具类

java 复制代码
package demo01.day25_StudentServer.src.cn.itcast.dao;


import java.io.*;
import java.net.URLDecoder;
import java.util.ArrayList;

public class StudentDao {
    //将集合中所有学生对象,写入到文件中
    public static void writeAll(ArrayList<Student> stuList) {
        try (FileWriter out = new FileWriter("student.txt")) {
            for (Student stu : stuList) {
                //格式: id,姓名,性别,年龄
                out.write(stu.getId() + "," + stu.getName() + "," + stu.getSex() + "," + stu.getAge());
                //换行
                out.write("\r\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //从文件中读取所有学生的信息,返回学生集合
    public static ArrayList<Student> readAll() {
        ArrayList<Student> stuList = new ArrayList<>();
        /*
		  1.创建File对象
		    如果没等添加学生呢,就开始读取学生了,那么我们需要先把文件创建出来
		*/
        File file = new File("student.txt");
        if (!file.exists()) {
            try {
                //2.如果不存在,则创建,否则读取会抛异常
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //3.读数据,一次一行 格式: id,姓名,性别,年龄
        try (BufferedReader bufIn = new BufferedReader(
                new FileReader("student.txt"))) {
            String line = null;
            while ((line = bufIn.readLine()) != null) {
                //4.一行切割成一个数组,[id,姓名,性别,年龄]
                String[] rowArray = line.split(",");
                //5.创建学生对象,封装数据
                Student stu = new Student();
				//因为获取出来0索引的元素是String,所以我们需要将String变成int
                stu.setId(Integer.parseInt(rowArray[0]));
                stu.setName(rowArray[1]);
                stu.setSex(rowArray[2]);
                stu.setAge(Integer.parseInt(rowArray[3]));
                //6.添加到集合中
                stuList.add(stu);
            }
        } catch (IOException e) {
            return null;
        }
        //7.返回整个集合
        return stuList;
    }

    //添加一个学生,返回boolean代表是否添加成功
    public static boolean addStudent(Student student) {
        //1.先读取所有学生
        ArrayList<Student> stuList = readAll();
        if (stuList == null) {//说明读取文件出错
            return false;
        }

        //2.获取最后一个学生的id,加1后作为新学生的id
        if (stuList.size() != 0) {
            student.setId(stuList.get(stuList.size() - 1).getId() + 1);//取最后一个对象的id + 1
        } else {
            //3.如果没有学生,说明是第一个,则id设置为1
            student.setId(1);//第一次添加,文件中没有内容
        }
        //4.添加到集合中
        stuList.add(student);
        //5.把集合重写写入到文件中
        writeAll(stuList);
        //6.返回添加成功
        return true;
    }
	
    //根据id删除一个学生,返回boolean代表是否删除成功
    public static boolean deleteById(int id) {
        //1.先读取所有学生
        ArrayList<Student> stuList = readAll();
        if (stuList == null) {//说明读取文件出错
            return false;
        }
        //2.遍历集合
        for (int i = 0; i < stuList.size(); i++) {
            Student stu = stuList.get(i);
            //3.判断学生的id是否和要删除的id相等
            if (stu.getId() == id) {
                //4.从集合中删除学生
                stuList.remove(i);
                //5.重写写入到文件中
                writeAll(stuList);
                //6.返回成功
                return true;
            }
        }
        //7.如果没找到学生返回失败
        return false;
    }
    //修改学生,返回boolean代表是否修改成功
    public static boolean updateStudent(Student student) {
        //1.先读取所有学生
        ArrayList<Student> stuList = readAll();
        if (stuList == null) {//说明读取文件出错
            return false;
        }
        System.out.println("修改的数据:" + student);
        //2.遍历集合
        for (int i = 0; i < stuList.size(); i++) {
            Student stu = stuList.get(i);
            //3.判断哪个学生id和要修改的学生id相同
            if (stu.getId() == student.getId()) {
                //4.将学生改为新的学生
                stuList.set(i, student);
                //5.重写将集合写入到文集中
                writeAll(stuList);//写回文件
                //6.返回成功
                return true;
            }
        }
        //7.返回失败
        return false;//没找到
    }
    //根据id查询学生,返回查询到的学生
    public static Student findById(int id) {
        //1.先读取所有学生
        ArrayList<Student> stuList = readAll();
        if (stuList == null) {//说明读取文件出错
            return null;
        }
        //2.遍历集合
        for (int i = 0; i < stuList.size(); i++) {
            Student stu = stuList.get(i);
            //3.比较id
            if (stu.getId() == id) {
                //4.找到返回学生对象
                return stu;
            }
        }
        //5.找不到返回null
        return null;
    }
}

3.创建服务器端主类StudentServer类

java 复制代码
package com.itheima.main;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/*
    服务器的主程序:包含main方法
        每个客户端连接服务器之后,服务器都需要开启一个线程,来处理这个客户端的请求(增删改查)
    实现步骤:
        1.创建服务器ServerSocket对象,和系统要指定的端口号
        2.写一个循环,一直监听客户端的请求
        3.获取一个客户端连接的对象Socket,就开启一个线程
 */
public class StudentServer {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器已经启动,客户端可以请求服务器了...");
        //1.创建服务器ServerSocket对象,和系统要指定的端口号
        ServerSocket server = new ServerSocket(8888);
        //2.写一个循环,一直监听客户端的请求
        while (true){
            //3.获取一个客户端连接的对象Socket,就开启一个线程
            Socket socket = server.accept();
            new ServerThread(socket).start();
        }
    }
}
java 复制代码
package com.itheima.main;

import java.net.Socket;

public class ServerThread extends Thread{
    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    //重写run方法,设置线程任务:根据客户端的请求进行增删改查
    @Override
    public void run() {
    }
}

4.服务端之解析功能序号执行对应方法

java 复制代码
package com.itheima.main;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ServerThread extends Thread{
    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    //重写run方法,设置线程任务:根据客户端的请求进行增删改查
    @Override
    public void run() {
        //把客户端想要执行的功能序号取出来,我们才能判断应该执行什么功能
        /*
            1.读取每一个客户端发送过来的请求信息 [1]张三,男,18
            2.根据获取的字符串,截取出序号 1 2  3  4  5
            3.根据客户端的请求,选择对应的功能
         */
        try(InputStream is = socket.getInputStream();){
            //1.读取每一个客户端发送过来的请求信息 [1]张三,男,18
            byte[] bytes = new byte[1024];
            int len = is.read(bytes);
            String msg = new String(bytes, 0, len);

            //2.根据获取的字符串,截取出序号 1 2  3  4  5
            int choose = Integer.parseInt(msg.substring(1, 2));
            switch (choose){
                case 1:
                    //1.添加学生
                    addStudent(msg);
                    break;
                case 2:
                    //2.根据id查询学生
                    findStudentById(msg);
                    break;
                case 3:
                    //3.修改学生
                    updateStudent(msg);
                    break;
                case 4:
                    //4.查看所有学生
                    findAllStudent();
                    break;
                case 5:
                    //5.删除学生
                    deleteStudent(msg);
                    break;
                default:
                    System.out.println("服务器没有此功能!");
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
        5.删除学生的方法
     */
    private void deleteStudent(String msg) {
    }

    /*
        4.查看所有学生的方法
     */
    private void findAllStudent() {
    }

    /*
        3.修改学生的方法
     */
    private void updateStudent(String msg) {
    }

    /*
        2.根据id查询学生的方法
     */
    private void findStudentById(String msg) {
    }

    /*
        1.添加学生的方法
     */
    private void addStudent(String msg) {
    }
}

5.添加学生功能

java 复制代码
/*
    1.添加学生的方法 [1]张三,男,18
        1.把客户端传递过来的学生信息封装为Student对象
        2.调用StudentDao工具类中添加学生的方法,获取方法的返回值
        3.使用Socket中的方法getOutputstream,获取网络字节输出流
        4.根据添加方法的返回值(true,false),给客户端回写对应的结果(1:添加成功,0:添加失败)
        5.释放资源
 */
private void addStudent(String msg) {
    //1.把客户端传递过来的学生信息封装为Student对象
    String stuMsg = msg.substring(3);//[1]张三,男,18==>张三,男,18
    String[] arr = stuMsg.split(",");
    Student student = new Student(0, arr[0], arr[1], Integer.parseInt(arr[2]));
    //2.调用StudentDao工具类中添加学生的方法,获取方法的返回值
    boolean b = StudentDao.addStudent(student);
    //3.使用Socket中的方法getOutputstream,获取网络字节输出流
    try(OutputStream os = socket.getOutputStream();) {
        //4.根据添加方法的返回值(true,false),给客户端回写对应的结果(1:添加成功,0:添加失败)
        if(b){
            //true:添加成功
            os.write(1);
        }else{
            //false:添加失败
            os.write(0);
        }
        //5.释放资源
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

6.查询所有学生

java 复制代码
/*
    4.查看所有学生的方法
        1.调用StudentDao工具类中查询所有学生的方法,获取方法的返回值ArrayList<Student>
        2.获取网络字节输出流
        3.获取序列化流对象,参数网络字节输出流
        4.使用序列化流对象中的方法writeObject,把集合对象写回到客户端
        5.释放资源
 */
private void findAllStudent() {
    //1.调用StudentDao工具类中查询所有学生的方法,获取方法的返回值ArrayList<Student>
    ArrayList<Student> list = StudentDao.readAll();
    try {
        //2.获取网络字节输出流
        OutputStream os = socket.getOutputStream();
        //3.获取序列化流对象,参数网络字节输出流
        ObjectOutputStream oos = new ObjectOutputStream(os);
        //4.使用序列化流对象中的方法writeObject,把集合对象写回到客户端
        oos.writeObject(list);
        //5.释放资源
        os.close();
        oos.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

7.根据id查询学生

java 复制代码
/*
    2.根据id查询学生的方法 msg:[2]1  [2]2
        1.把客户端传递过来的学生信息中的学生的id截取出来[2]1 ==>1
        2.调用StudentDao工具类中根据id查询学生的方法,获取方法的返回值(Student对象)
        3.使用Socket中的方法getOutputstream,获取网络字节输出流
        4.获取序列化流对象,参数网络字节输出流
        5.使用序列化流对象中的方法writeObject,把Student对象写回到客户端
        6.释放资源
 */
private void findStudentById(String msg) {
    //1.把客户端传递过来的学生信息中的学生的id截取出来[2]10 ==>10
    int id = Integer.parseInt(msg.substring(3));
    //2.调用StudentDao工具类中根据id查询学生的方法,获取方法的返回值(Student对象)
    Student student = StudentDao.findById(id);
    try {
        //3.使用Socket中的方法getOutputstream,获取网络字节输出流
        OutputStream os = socket.getOutputStream();
        //4.获取序列化流对象,参数网络字节输出流
        ObjectOutputStream oos = new ObjectOutputStream(os);
        //5.使用序列化流对象中的方法writeObject,把Student对象写回到客户端
        oos.writeObject(student);
        //6.释放资源
        os.close();
        oos.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

8.根据id修改学生

java 复制代码
/*
    3.修改学生的方法 msg:[3]2,小明,男,10
        1.把客户端传递过来的学生信息封装为Student对象
        2.调用StudentDao工具类中修改学生的方法,并获取方法的返回值(true,false)
        3.使用Socket中的方法getOutputstream,获取网络字节输出流
        4.根据方法的返回值进行判断,给客户端回写对应的结果 1:修改成功 0:修改失败
        5.释放资源
 */
private void updateStudent(String msg) {
    //1.把客户端传递过来的学生信息封装为Student对象
    String stuMsg = msg.substring(3);//[3]2,小明,男,10==>2,小明,男,10
    String[] arr = stuMsg.split(",");
    Student student = new Student(Integer.parseInt(arr[0]),arr[1],arr[2],Integer.parseInt(arr[3]));
    //2.调用StudentDao工具类中修改学生的方法,并获取方法的返回值(true,false)
    boolean b = StudentDao.updateStudent(student);
    //3.使用Socket中的方法getOutputstream,获取网络字节输出流
    try(OutputStream os = socket.getOutputStream();){
        //4.根据方法的返回值进行判断,给客户端回写对应的结果 1:修改成功 0:修改失败
        if(b){
            //true:修改数据成功
            os.write(1);
        }else{
            //false:修改数据失败
            os.write(0);
        }
        //5.释放资源
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

9.根据id删除学生

java 复制代码
/*
    5.删除学生的方法
        1.把客户端传递过来的学生信息中的学生的id截取出来[5]1 ==>1
        2.调用StudentDao工具类中根据id删除学生的方法,获取方法的返回值(true,false)
        3.使用Socket中的方法getOutputstream,获取网络字节输出流
        4.根据方法的返回值进行判断,给客户端回写对应的结果1:删除成功 0:删除失败
        5.释放资源
 */
private void deleteStudent(String msg) {
    //1.把客户端传递过来的学生信息中的学生的id截取出来[5]1 ==>1
    int id = Integer.parseInt(msg.substring(3));
    //2.调用StudentDao工具类中根据id删除学生的方法,获取方法的返回值(true,false)
    boolean b = StudentDao.deleteById(id);
    //3.使用Socket中的方法getOutputstream,获取网络字节输出流
    try(OutputStream os = socket.getOutputStream();) {
        //4.根据方法的返回值进行判断,给客户端回写对应的结果1:删除成功 0:删除失败
        if(b){
            //true:删除成功
            os.write(1);
        }else{
            //false:删除失败
            os.write(0);
        }
        //5.释放资源
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
相关推荐
-雷阵雨-3 小时前
数据结构——优先级队列(堆)
java·开发语言·数据结构·intellij-idea
好家伙VCC3 小时前
**全息显示技术的发散创新与深度探索**一、引言随着科技的飞速发展,全息显示技术已成为显示领域的一大研究热点。本文将带你
java·图像处理·python·科技·计算机视觉
步行cgn3 小时前
Java项目包结构设计与功能划分详解
java·开发语言·架构·mvc
ss2733 小时前
手写MyBatis第92弹:SqlSource体系、SqlNode树与Trim标签实现原理全揭秘
java·开发语言
235164 小时前
【LeetCode】46. 全排列
java·数据结构·后端·算法·leetcode·职场和发展·深度优先
_extraordinary_4 小时前
Java Linux --- 基本命令,部署Java web程序到线上访问
java·linux·前端
heyCHEEMS4 小时前
最长连续序列 Java
java·开发语言·算法
MFine5 小时前
Rhythmix(流式数据规则表达式),一行就够了!
java·物联网·数据分析
华仔啊5 小时前
面试官问:流量突然暴增100倍,系统怎么扛?我的方案是...
java