java——案例01(在线小说阅读App)

目录

前言:

一、项目介绍

 1、创建客户端、服务器端

2、完成登录、注册、退出功能 

3、完成小说查询列表和阅读功能 

4、 完成小说下载功能

5、 完成小说上传功能

二、 功能模块

1、主要技术

2、文件结构 

3、功能实现

(1)简单通信

(2)[登录、注册、退出]菜单

(3)登录与注册

 (4)[阅读小说、上传小说、下载小说]菜单

 (5)阅读小说功能

(6)上传小说功能 

(7)下载小说功能

、错误解决 

、项目总结与收获

、完整代码 

1、Client客户端

BookClientService类

ClientNovel类

Contain类

DataUtil类

MessageEntity类

ResultUtil类

UserClientService类

UserEntity类

2、Server服务端

Contain类

MessageEntity类同客户端

ServerApp类

UserEntity类同客户端

UserService类

XMLUtil类

前言:

在线小说阅读系统的目的是为读者提供一个便捷、高效的方式来阅读小说作品。通过该系统,读者可以随时随地通过互联网访问和阅读自己喜爱的小说,无需购买实体书籍或前往书店图书馆借阅,大大节省了时间和精力。

通过这段时间对java的学习完成这个在线小说阅读App系统.

  • 应用面向对象的思想编写简单项目

  • 熟练操作Socket编程

  • 熟练操作文件I/O读写的操作

  • 了解配制文件的解析方式

  • 了解多线程的应用

  • 了解xml文件作为轻量级的存储,以及使用dom4j解析xml文件

一、项目介绍

  • 任务1:创建客户端、服务器端,完成简单通信
  • 任务2:完成登录、注册、退出、返回功能
  • 任务3:完成小说查询列表功能
  • 任务4:   完成在线阅读小说功能
  • 任务5:完成小说下载功能
  • 任务6:完成上传小说功能

 1、创建客户端、服务器端

  • 1. 创建服务器端线程类,并循环监听状态
  • 2. 创建客户端,请求服务器并发送消息
  • 3. 服务器端响应客户端

2、完成登录、注册、退出功能 

  • 1. 创建用于保存登录信息的文件
  • 2. 接收用户登录信息并查找登录信息文件,判断是否登录成功
  • 3. 接收用户注册信息并保存至登录信息文件

3、完成小说查询列表和阅读功能 

  • 1.根据用户选择的小说名查找小说文件,并显示小说名
  • 2.根据用户选择小说名,查找小说地址并显示内容

4、 完成小说下载功能

  • 1. 根据用户选择的小说读取小说源文件
  • 2. 把读取的文件写到对应下载路径中

5、 完成小说上传功能

  • 1. 根据用户输入的小说路径,读取源文件
  • 2. 根据文件的各类小说路径,将读取的源文件写入相应位置
  • 3. 根据用户输入的小说名保存至小说列表

二、 功能模块

1、主要技术

  • java类与对象的操作
  • 客户端与服务器之间使用socket通信
  • 对象io流
  • 文件io流

2、文件结构 

1.项目文件分为两个大的部分:客户端与服务端

2.其中存放小说名、页数、用户信息的数据的文件内容必须相等

3.必须引入文件并解析

帮助手册:Overview (dom4j 1.6.1 API)

Dom4j 是一个开源的 XML 解析框架,它基于 Java 的 sax 解析器和 jaxp 解析器开发,提供了灵活简便、性能优良、扩展性强的 XML 解析和生成功能。

3、功能实现

(1)简单通信

连接服务端

    //初始化---连接服务器
    public void clientInit() throws IOException {
        //连接服务器
        socket = new Socket();
        socket.connect(new InetSocketAddress(8080));
    }

连接客户端

    public void init() throws IOException, ClassNotFoundException, DocumentException {
        //监听是否有人来连接
        ServerSocket serverSocket = new ServerSocket();
        //绑定端口号
        serverSocket.bind(new InetSocketAddress(8080));
        System.out.println("服务器已启动,等待客户端连接...");
        //监听
        socket = serverSocket.accept();
        System.out.println("客户端已连接到服务器..."+socket.getInetAddress());
        postClientMessage();
    }

控制器界面实现效果:

(2)[登录、注册、退出]菜单

    //小说界面
    public void welcome() throws IOException {
        System.out.println("土豆在线小说阅读App欢迎您......");
        System.out.println("请选择您所需要进行的项目(1.登录 2.注册 3.退出):");
        //操作选择
        int number = input.nextInt();
        switch (number){
            //登录
            case 1:
                userClientService.login();
                break;
            //注册
            case 2:
                userClientService.register();
                break;
            //退出
            case 3:
                System.exit(0);
        }
    }
  • 1.用Switch进行功能的选择
  • 2.根据用户输入不同数字进入不同功能模块
  • 3.登录--->1;注册--->2;退出--->3 

(3)登录与注册

登录 客户端

    public void login() throws IOException {
        System.out.println("登录账号......");
        System.out.println("请输入用户名:");
        String username = input.next();
        System.out.println("请输入密码:");
        String password = input.next();

        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setPassword(password);

        MessageEntity messageEntity = new MessageEntity();
        messageEntity.setOprator(1);
        messageEntity.setUserEntity(userEntity);

        //把数据发送给服务器
        dataUtil.sendData(messageEntity);

        //接受数据
        String s = dataUtil.receiveData();
        //根据服务器返回的结果完成不同的处理
        resultUtil.postUserResult(s);
    }

注册 客户端 

    public void register() throws IOException {
        System.out.println("注册账号......");
        System.out.println("请输入注册的用户id:");
        int userId = input.nextInt();
        System.out.println("请输入用户名:");
        String username = input.next();
        System.out.println("请输入密码:");
        String password = input.next();

        UserEntity userEntity = new UserEntity();
        userEntity.setId(userId);
        userEntity.setUsername(username);
        userEntity.setPassword(password);

        MessageEntity messageEntity = new MessageEntity();
        messageEntity.setOprator(2);
        messageEntity.setUserEntity(userEntity);

        dataUtil.sendData(messageEntity);
        String s = dataUtil.receiveData();
        resultUtil.postUserResult(s);
    }

登录与注册判断的条件 

    public String login(UserEntity entity) throws DocumentException {
        List<UserEntity> userEntities = XMLUtil.parseXml();
        //通过stream流来判断用户名和密码是否合格
        //解析xml得到的数据----2条
        //count=1 表示有一条数据
        //else 表示没有数据或者数据大于一条,登录失败
        long count = userEntities.stream()
                .filter(s -> s.getUsername().equals(entity.getUsername()))
                .filter(s -> s.getPassword().equals(entity.getPassword())).count();
        if (count == 1){
            //登录成功
            return ServerApp.LOGINSUCRESULT;
        }else {
            //登录失败
            return ServerApp.LOGINFAIRESULT;
        }
    }

    public String register(UserEntity userEntity) {
        try {
            XMLUtil.updateXml(userEntity);
            //注册成功
            return ServerApp.REGISTERSUCRESULT;
        } catch (Exception e) {
            e.printStackTrace();
            //注册失败
            return ServerApp.REGISTERFAiRESULT;
        }
    }

控制器界面实现效果:

登录失败

登录成功

注册成功

 

 注册成功用户信息存入xml文件

 (4)[阅读小说、上传小说、下载小说]菜单

    //登录后的二级菜单
    public String menu(){
        System.out.println("登录or注册成功!!!");
        System.out.println("请选择您所需要进行的项目(1.阅读小说 2.上传小说 3.下载小说 4.退 
        出):");
        String info = input.next();
        return info;
    }

 (5)阅读小说功能

查询服务器上小说列表 客户端

    //查询服务器上小说列表
    public List<String> queryPrintAllBook(DataUtil dataUtil) throws IOException {
        List<String> list = new ArrayList<>();
        MessageEntity messageEntity =new MessageEntity();
        //只需要带一个操作
        messageEntity.setOprator(5);
        dataUtil.sendData(messageEntity);
        //阻塞
        String s = dataUtil.receiveData();
        String[] split = s.split("-");
        for (String s1 : split) {
            list.add(s1);
        }
        return list;
    }

阅读小说 客户端

        //阅读小说
        if (info.equals("1")){
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);
            list.stream().forEach(s -> System.out.println(s));
            System.out.println("请选择你要阅读的小说:");
            //输入小说名
            String bookName = input.nextLine();
            //用来记录有页数
            int page = 1;
            while (true) {
                //每一次都向服务器发送要执行的操作和书的页码,让服务器根据页码来读取相应的内容
                MessageEntity m = new MessageEntity();
                m.setBookName(bookName);
                m.setOprator(6);
                m.setPage(page);
                //向服务器发送书名,和阅读小说的操作
                dataUtil.sendData(m);
                //接受读取到的内容
                String contain = dataUtil.receiveData();
                //打印到控制台
                System.out.println(contain);
                System.out.println("第"+page+"页");
                System.out.println("上一页(0),下一页(1),退出(2)");
                String choose = input.nextLine();
                if (choose.equals("1")){//如果客户端选择下一页,就把页码数加一
                    page++;
                }else if(choose.equals("2")){
                    System.exit(0);
                }else if(choose.equals("0")){//如果客户端要阅读上一页,就把页码数减一
                    //先要判断当前页数是不是第一页
                    if(page == 1){
                        System.out.println("当前已经为第一页");
                    }else {
                        page--;
                    }
                }
                if(contain.equals("end")){
                    break;
                }
            }
            System.out.println("阅读完成");
            String s = clientNovel.menu();
            postbookResult(s);
        }

阅读小说 服务端 

            if(m.getOprator() == 6){//阅读小说
                //得到用户需要阅读的小说书名
                String bookName = m.getBookName();
                //去服务器的指定路径找到这本小说的路径
                File bookFile = new File(Contain.bookPath+"\\\\"+bookName);
                //先读取到程序
                FileReader fr = new FileReader(bookFile);
                //跳过字符,根据客户端的页面来定要读取的内容,用户如果要读取第2页的内容,就是跳过 
                前面1000个字符
                fr.skip((m.getPage() - 1) * 1000);
                //一次读一千个字符
                char[] chars = new char[1000];
                int total = fr.read(chars);
                if (total != -1) {
                    String contain = new String(chars, 0, total);
                    //将读取的内容写到网络中
                    os.write(contain.getBytes());
                }
            }

控制器界面实现效果:

(6)上传小说功能 

上传小说 客户端

        if (info.equals("2")){//上传小说
            //需要上传的小说的路径
            System.out.println("输入小说路径和名字:");
            //  D:\\java全栈\\项目\\在线小说阅读项目资料\\资料\\小说\\天龙八部.txt
            String bookPathName = input.nextLine();

            //为了获取文件的大小---百分比
            File file = new File(bookPathName);
            //整个文件的字节数
            long length = file.length();
            double l = (double) length;
            System.out.println("文件长度 = " + length + "个字节");

            //上传---先读取内容---再写出去网络
            FileInputStream fis = new FileInputStream(file);

            //告诉服务器文件名
            String bookName = bookPathName.substring(bookPathName.lastIndexOf("\\\\"));
            int total = 0;//每次读取的字节数---读到文件末尾-1
            double temp = 0.0;//累计读了多少
            while ((total = fis.read(bs)) != -1){
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setOprator(3);
                messageEntity.setBookName(bookName);
                messageEntity.setContent(new String(bs,0,total));
                dataUtil.sendData(messageEntity);
                //如果接收成功 这一次读取的内容上传成功
                String s = dataUtil.receiveData();
                temp += total;
                //模拟网络延迟
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //上传进度
                System.out.print("上传进度:" + String.format("%.2f",(temp/length*100)) +                                                 
                "%\r");
            }
            System.out.println("已经完成:100%");
            System.out.println("上传完成!!!");

            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(3);
            messageEntity.setContent("end");

            String r = clientNovel.menu();
            postbookResult(r);
        }

上传小说 服务端

            if (m.getOprator() == 3) {
                //上传小说
                //当次上传小说的内容
                String content = m.getContent();
                if (content.equals("end")) {
                    //一部小说已经传完
                    uploadFile = null;
                    continue;
                }

                if (uploadFile == null) {
                    //这部分内容写到对应的文件夹当中
                    uploadFile = new File(Contain.bookPath + "\\" + m.getBookName());

                }
                //如果文件不存在则创建
                if (!uploadFile.exists()) {
                    uploadFile.createNewFile();
                } else {
                    if (!XMLUtil.isEmpty(m.getBookName())) {//服务器已经存在小说 重写上传
                        uploadFile.delete();//先删除
                        uploadFile.createNewFile();//重写创建
                    }
                }
                FileWriter fileWriter = new FileWriter(uploadFile, true);

                fileWriter.write(content);

                //这一次成功
                os.write("success".getBytes());

                fileWriter.close();
            }

控制器界面实现效果:

(7)下载小说功能

下载小说 客户端

        if (info.equals("3")){//下载小说
            //下载之前先要做查询
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);

            System.out.println("请输入下面显示的小说名字进行下载");
            list.stream().forEach(s -> System.out.println(s));
            String bookName="";
            while (true){
                bookName = input.nextLine();
                String finalBookName = bookName;
                long count = list.stream().filter(s -> s.equals(finalBookName)).count();
                if(count==0){//输入的小说名字不存在
                    System.out.println("请输入合理的小说名字");
                }else {
                    break;
                }
            }

            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(4);
            messageEntity.setBookName(bookName);
            dataUtil.sendData(messageEntity);

            File file = new File(Contain.downloadPath + "\\" + bookName);
            if (!file.exists()) {
                file.createNewFile();
            }else {
                file.delete();
                file.createNewFile();
            }
            while (true) {
                String downLoadContent = dataUtil.receiveData();

                if (downLoadContent.endsWith("end")) {
                    System.out.println("下载完成!!!!!!!!!!!!!!!");
                    FileOutputStream fos = new FileOutputStream(file, true);
                    fos.write(downLoadContent.replaceAll("end","").getBytes());
                    break;
                }
                FileOutputStream fos = new FileOutputStream(file, true);
                fos.write(downLoadContent.getBytes());

            }
            String s = clientNovel.menu();
            postbookResult(s);
        }

下载小说 服务端

            if (m.getOprator() == 4) {//下载
                //获取现需要下载的小说的名字
                String bookName = m.getBookName();

                String downLoadPath = Contain.bookPath + "\\" + bookName;

                File downLoadFile = new File(downLoadPath);
                long length = downLoadFile.length();

                FileInputStream fis = new FileInputStream(downLoadFile);
                DecimalFormat df = new DecimalFormat("#.0");
                int total = 0;
                double percent = 0.0;
                while ((total = fis.read(bs)) != -1) {
                    String message = new String(bs, 0, total);
                    os.write(message.getBytes());
                }
                //读完了
                os.write("end".getBytes());
            }

控制器界面实现效果:

三、错误解决 

 服务端错误

客户端错误(由服务端引起) 

解决 

Exception in thread “main“ java.net.SocketException: Connection reset

1.Connection reset连接重置

2.小说文件名多加了一个(.txt)

3.删除(.txt)或者在输入文件名时不输入(.txt)

 四、项目总结与收获

  • 1.跟着老师的思路,渐渐完成了各个项目功能,学会了怎么把所学会的java知识运用到项目中,怎么把项目做的更好
  • 2.遇到问题并渐渐学会了解决问题,在项目中我还是遇到了挺多困难的,通常是不会用代码将所需功能通过客户端与服务端信息进行传递以及运行中出现了各种小问题,但是忘记截图了
  • 3.懂得了怎么思考问题,拿到项目应该分析怎么去实现这些功能模块,大概分为几个大的部分
  • 4.对所学java知识掌握的更加牢固

五、完整代码 

1、Client客户端

BookClientService类

package com.fs.test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class BookClientService {
    //查询服务器上小说列表
    public List<String> queryPrintAllBook(DataUtil dataUtil) throws IOException {
        List<String> list = new ArrayList<>();
        MessageEntity messageEntity =new MessageEntity();
        //只需要带一个操作
        messageEntity.setOprator(5);
        dataUtil.sendData(messageEntity);
        //阻塞
        String s = dataUtil.receiveData();
        String[] split = s.split("-");
        for (String s1 : split) {
            list.add(s1);
        }
        return list;
    }
}

ClientNovel类

package com.fs.test;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;

public class ClientNovel {
    static Socket socket = null;
    static UserClientService userClientService;
    Scanner input = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        ClientNovel clientNovel = new ClientNovel();
        clientNovel.clientInit();
        //封装了接收数据和发送数据的api 功能
        DataUtil dataUtil = new DataUtil(socket);
        userClientService = new UserClientService(dataUtil,new ResultUtil(clientNovel,dataUtil));
        clientNovel.welcome();
    }

    //初始化---连接服务器
    public void clientInit() throws IOException {
        //连接服务器
        socket = new Socket();
        socket.connect(new InetSocketAddress(8080));
    }

    //小说界面
    public void welcome() throws IOException {
        System.out.println("土豆在线小说阅读App欢迎您......");
        System.out.println("请选择您所需要进行的项目(1.登录 2.注册 3.退出):");
        //操作选择
        int number = input.nextInt();
        switch (number){
            //登录
            case 1:
                userClientService.login();
                break;
            //注册
            case 2:
                userClientService.register();
                break;
            //退出
            case 3:
                System.exit(0);
        }
    }

    //登录后的二级菜单
    public String menu(){
        System.out.println("登录or注册成功!!!");
        System.out.println("请选择您所需要进行的项目(1.阅读小说 2.上传小说 3.下载小说 4.退出):");
        String info = input.next();
        return info;
    }
}

Contain类

package com.fs.test;

public class Contain {
    //客户端下载小说的默认存放路径
    public static final String downloadPath = "D:\\java全栈\\项目\\在线小说阅读项目资料\\book";
    //服务器上存放小说的路径
    public static final String bookPath = "D:\\code\\les12-13(NovelReading)\\server\\book";
    //注册成功
    public static final String REGISTERSUCRESULT = "100";
    //注册失败
    public static final String REGISTERFAIRESULT = "101";
    //登录成功
    public static final String LOGINSUCRESULT = "200";
    //登录失败
    public static final String LOGINFAIRESULT = "201";

    public static final String FLAGSTR="j#";
}

DataUtil类

package com.fs.test;

import java.io.*;
import java.net.Socket;

public class DataUtil {
    Socket socket;
    ObjectOutputStream oos = null;
    static byte[] bs = new byte[512];

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

    public void sendData(MessageEntity messageEntity) throws IOException {
        OutputStream os = socket.getOutputStream();
        if (oos == null){
            oos = new ObjectOutputStream(os);
        }
        //写到服务器
        oos.writeObject(messageEntity);
    }

    //接收数据
    public String receiveData() throws IOException {
        InputStream is = socket.getInputStream();
        int total = is.read(bs);
        //把服务器响应的消息 判断一下
        String result = new String(bs, 0, total);
        return result;
    }
}

MessageEntity类

package com.fs.test;

import java.io.Serializable;

public class MessageEntity implements Serializable {
    //执行什么操作
    /*
    1.登录
    2.注册
    3.选择阅读小说
    4.上传小说
    5.下载小说
     */
    private String bookName;
    private String content;
    private int oprator;
    private UserEntity userEntity;
    private int page;

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookName() {
        return bookName;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    public int getOprator() {
        return oprator;
    }

    public void setOprator(int oprator) {
        this.oprator = oprator;
    }

    public UserEntity getUserEntity() {
        return userEntity;
    }

    public void setUserEntity(UserEntity userEntity) {
        this.userEntity = userEntity;
    }
}

ResultUtil类

package com.fs.test;

import java.io.*;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class ResultUtil {
    ClientNovel clientNovel;
    DataUtil dataUtil;
    BookClientService bookClientService = new BookClientService();
    ObjectInputStream ois = null;

    byte[] bs = new byte[1024];

    Scanner input = new Scanner(System.in);

    public ResultUtil(ClientNovel clientNovel, DataUtil dataUtil) {
        this.clientNovel = clientNovel;
        this.dataUtil = dataUtil;
    }

    public void postUserResult(String result) throws IOException {
        if (result.equals(Contain.LOGINSUCRESULT)){
            System.out.println("登录成功......");
            String info = clientNovel.menu();
             postbookResult(info);
        }else if (result.equals(Contain.LOGINFAIRESULT)){
            System.out.println("登录失败---重新登录");
            clientNovel.welcome();
        }else if (result.equals(Contain.REGISTERSUCRESULT)){
            System.out.println("注册成功......");
            String info = clientNovel.menu();
            postbookResult(info);
        }else if (result.equals(Contain.REGISTERFAIRESULT)){
            System.out.println("注册失败---重新注册");
            clientNovel.welcome();
        }
    }

    //处理二级菜单 操作序号
    public void postbookResult(String info) throws IOException {
        //阅读小说
        if (info.equals("1")){
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);
            list.stream().forEach(s -> System.out.println(s));
            System.out.println("请选择你要阅读的小说:");
            //输入小说名
            String bookName = input.nextLine();
            //用来记录有页数
            int page = 1;
            while (true) {
                //每一次都向服务器发送要执行的操作和书的页码,让服务器根据页码来读取相应的内容
                MessageEntity m = new MessageEntity();
                m.setBookName(bookName);
                m.setOprator(6);
                m.setPage(page);
                //向服务器发送书名,和阅读小说的操作
                dataUtil.sendData(m);
                //接受读取到的内容
                String contain = dataUtil.receiveData();
                //打印到控制台
                System.out.println(contain);
                System.out.println("第"+page+"页");
                System.out.println("上一页(0),下一页(1),退出(2)");
                String choose = input.nextLine();
                if (choose.equals("1")){//如果客户端选择下一页,就把页码数加一
                    page++;
                }else if(choose.equals("2")){
                    System.exit(0);
                }else if(choose.equals("0")){//如果客户端要阅读上一页,就把页码数减一
                    //先要判断当前页数是不是第一页
                    if(page == 1){
                        System.out.println("当前已经为第一页");
                    }else {
                        page--;
                    }
                }
                if(contain.equals("end")){
                    break;
                }
            }
            System.out.println("阅读完成");
            String s = clientNovel.menu();
            postbookResult(s);


        }else if (info.equals("2")){//上传小说
            //需要上传的小说的路径
            System.out.println("输入小说路径和名字:");
            //  D:\\java全栈\\项目\\在线小说阅读项目资料\\资料\\小说\\天龙八部.txt
            String bookPathName = input.nextLine();

            //为了获取文件的大小---百分比
            File file = new File(bookPathName);
            //整个文件的字节数
            long length = file.length();
            double l = (double) length;
            System.out.println("文件长度 = " + length + "个字节");

            //上传---先读取内容---再写出去网络
            FileInputStream fis = new FileInputStream(file);

            //告诉服务器文件名
            String bookName = bookPathName.substring(bookPathName.lastIndexOf("\\\\"));
            int total = 0;//每次读取的字节数---读到文件末尾-1
            double temp = 0.0;//累计读了多少
            while ((total = fis.read(bs)) != -1){
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setOprator(3);
                messageEntity.setBookName(bookName);
                messageEntity.setContent(new String(bs,0,total));
                dataUtil.sendData(messageEntity);
                //如果接收成功 这一次读取的内容上传成功
                String s = dataUtil.receiveData();
                temp += total;
                //模拟网络延迟
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //上传进度
                System.out.print("上传进度:" + String.format("%.2f",(temp/length*100)) + "%\r");
            }
            System.out.println("已经完成:100%");
            System.out.println("上传完成!!!");

            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(3);
            messageEntity.setContent("end");

            String r = clientNovel.menu();
            postbookResult(r);
        }else if (info.equals("3")){//下载小说
            //下载之前先要做查询
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);

            System.out.println("请输入下面显示的小说名字进行下载");
            list.stream().forEach(s -> System.out.println(s));
            String bookName="";
            while (true){
                bookName = input.nextLine();
                String finalBookName = bookName;
                long count = list.stream().filter(s -> s.equals(finalBookName)).count();
                if(count==0){//输入的小说名字不存在
                    System.out.println("请输入合理的小说名字");
                }else {
                    break;
                }
            }

            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(4);
            messageEntity.setBookName(bookName);
            dataUtil.sendData(messageEntity);

            File file = new File(Contain.downloadPath + "\\" + bookName);
            if (!file.exists()) {
                file.createNewFile();
            }else {
                file.delete();
                file.createNewFile();
            }
            while (true) {
                String downLoadContent = dataUtil.receiveData();

                if (downLoadContent.endsWith("end")) {
                    System.out.println("下载完成!!!!!!!!!!!!!!!");
                    FileOutputStream fos = new FileOutputStream(file, true);
                    fos.write(downLoadContent.replaceAll("end","").getBytes());
                    break;
                }
                FileOutputStream fos = new FileOutputStream(file, true);
                fos.write(downLoadContent.getBytes());

            }
            String s = clientNovel.menu();
            postbookResult(s);
        }else if (info.equals("4")){//退出
            System.exit(0);
        }
    }
}

UserClientService类

package com.fs.test;

import java.io.IOException;
import java.util.Scanner;

public class UserClientService {
    DataUtil dataUtil;
    ResultUtil resultUtil;

    public UserClientService(DataUtil dataUtil, ResultUtil resultUtil) {
        this.dataUtil = dataUtil;
        this.resultUtil = resultUtil;
    }

    Scanner input = new Scanner(System.in);

    public void login() throws IOException {
        System.out.println("登录账号......");
        System.out.println("请输入用户名:");
        String username = input.next();
        System.out.println("请输入密码:");
        String password = input.next();

        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setPassword(password);

        MessageEntity messageEntity = new MessageEntity();
        messageEntity.setOprator(1);
        messageEntity.setUserEntity(userEntity);

        //把数据发送给服务器
        dataUtil.sendData(messageEntity);

        //接受数据
        String s = dataUtil.receiveData();
        //根据服务器返回的结果完成不同的处理
        resultUtil.postUserResult(s);
    }

    public void register() throws IOException {
        System.out.println("注册账号......");
        System.out.println("请输入注册的用户id:");
        int userId = input.nextInt();
        System.out.println("请输入用户名:");
        String username = input.next();
        System.out.println("请输入密码:");
        String password = input.next();

        UserEntity userEntity = new UserEntity();
        userEntity.setId(userId);
        userEntity.setUsername(username);
        userEntity.setPassword(password);

        MessageEntity messageEntity = new MessageEntity();
        messageEntity.setOprator(2);
        messageEntity.setUserEntity(userEntity);

        dataUtil.sendData(messageEntity);
        String s = dataUtil.receiveData();
        resultUtil.postUserResult(s);
    }
}

UserEntity类

package com.fs.test;

import java.io.Serializable;

public class UserEntity implements Serializable {
    private String username;
    private String password;
    private Integer id;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

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

2、Server服务端

Contain类

package com.fs.test;

public class Contain {
    //服务器上存放小说的路径
    public static final String bookPath = "D:\\code\\les12-13(NovelReading)\\server\\book";

    public static final String FLAGSTR="j#";
}

MessageEntity类同客户端

ServerApp类

package com.fs.test;

import org.dom4j.DocumentException;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;

public class ServerApp {
    UserService userService = new UserService();
    byte[] bs = new byte[126];

    Socket socket = null;
    InputStream is = null;
    OutputStream os = null;
    ObjectInputStream ois = null;
    File uploadFile = null;

    //注册成功
    public static final String REGISTERSUCRESULT = "100";
    //注册失败
    public static final String REGISTERFAiRESULT = "101";
    //登录成功
    public static final String LOGINSUCRESULT = "200";
    //登录失败
    public static final String LOGINFAIRESULT = "201";
    public static void main(String[] args) throws IOException, ClassNotFoundException, DocumentException {
        ServerApp serverApp = new ServerApp();
        serverApp.init();
    }

    public void init() throws IOException, ClassNotFoundException, DocumentException {
        //监听是否有人来连接
        ServerSocket serverSocket = new ServerSocket();
        //绑定端口号
        serverSocket.bind(new InetSocketAddress(8080));
        System.out.println("服务器已启动,等待客户端连接...");
        //监听
        socket = serverSocket.accept();
        System.out.println("客户端已连接到服务器..."+socket.getInetAddress());
        postClientMessage();
    }

    public void postClientMessage() throws IOException, ClassNotFoundException, DocumentException {
        if (ois == null){
            //服务器可能需要和客户端发送消息
            //由于发送的不是对象,所以不需要对象流
            os = socket.getOutputStream();

            //发送一个对象
            //获取输入流--->客户端可能给我发消息 读取客户端发送的消息
            is = socket.getInputStream();
            //由于约定了发送的是MessageEntity对象 所有通过对象流获取发送过来的对象
            ois = new ObjectInputStream(is);
        }

        while (true) {
            //接收客户端的数据
            MessageEntity m = (MessageEntity) ois.readObject();
            //登录--->1  注册--->2  上传小说--->3  下载小说--->4  小说列表--->5  阅读小说--->6
            if (m.getOprator() == 1) {
                //客户端输入的用户名,密码
                String result = userService.login(m.getUserEntity());
                //把登录结果write给客户端
                os.write(result.getBytes());

            } else if (m.getOprator() == 2) {
                //客户端输入的用户id,用户名,密码
                String register = userService.register(m.getUserEntity());
                //把注册结果write给客户端
                os.write(register.getBytes());

            } else if (m.getOprator() == 3) {
                //上传小说
                //当次上传小说的内容
                String content = m.getContent();
                if (content.equals("end")) {
                    //一部小说已经传完
                    uploadFile = null;
                    continue;
                }

                if (uploadFile == null) {
                    //这部分内容写到对应的文件夹当中
                    uploadFile = new File(Contain.bookPath + "\\" + m.getBookName());

                }
                //如果文件不存在则创建
                if (!uploadFile.exists()) {
                    uploadFile.createNewFile();
                } else {
                    if (!XMLUtil.isEmpty(m.getBookName())) {//服务器已经存在小说 重写上传
                        uploadFile.delete();//先删除
                        uploadFile.createNewFile();//重写创建
                    }
                }
                FileWriter fileWriter = new FileWriter(uploadFile, true);

                fileWriter.write(content);

                //这一次成功
                os.write("success".getBytes());

                fileWriter.close();
            } else if (m.getOprator() == 4) {//下载
                //获取现需要下载的小说的名字
                String bookName = m.getBookName();

                String downLoadPath = Contain.bookPath + "\\" + bookName;

                File downLoadFile = new File(downLoadPath);
                long length = downLoadFile.length();

                FileInputStream fis = new FileInputStream(downLoadFile);
                DecimalFormat df = new DecimalFormat("#.0");
                int total = 0;
                double percent = 0.0;
                while ((total = fis.read(bs)) != -1) {
                    String message = new String(bs, 0, total);
                    os.write(message.getBytes());
                }
                //读完了
                os.write("end".getBytes());
            } else if (m.getOprator() == 5) {//查询小说列表
                String bookList = "";
                File file = new File(Contain.bookPath);
                String[] list = file.list();
                for (String s : list) {
                    bookList += s + "-";
                }
                os.write(bookList.getBytes());
            } else if(m.getOprator() == 6){//阅读小说
                //得到用户需要阅读的小说书名
                String bookName = m.getBookName();
                //去服务器的指定路径找到这本小说的路径
                File bookFile = new File(Contain.bookPath+"\\\\"+bookName + ".txt");
                //先读取到程序
                FileReader fr = new FileReader(bookFile);
                //跳过字符,根据客户端的页面来定要读取的内容,用户如果要读取第2页的内容,就是跳过前面1000个字符
                fr.skip((m.getPage() - 1) * 1000);
                //一次读一千个字符
                char[] chars = new char[1000];
                int total = fr.read(chars);
                if (total != -1) {
                    String contain = new String(chars, 0, total);
                    //将读取的内容写到网络中
                    os.write(contain.getBytes());
                }
            }
        }
    }
}

UserEntity类同客户端

UserService类

package com.fs.test;

import org.dom4j.DocumentException;

import java.util.List;

public class UserService {
    public String login(UserEntity entity) throws DocumentException {
        List<UserEntity> userEntities = XMLUtil.parseXml();
        //通过stream流来判断用户名和密码是否合格
        //解析xml得到的数据----2条
        //count=1 表示有一条数据
        //else 表示没有数据或者数据大于一条,登录失败
        long count = userEntities.stream()
                .filter(s -> s.getUsername().equals(entity.getUsername()))
                .filter(s -> s.getPassword().equals(entity.getPassword())).count();
        if (count == 1){
            //登录成功
            return ServerApp.LOGINSUCRESULT;
        }else {
            //登录失败
            return ServerApp.LOGINFAIRESULT;
        }
    }

    public String register(UserEntity userEntity) {
        try {
            XMLUtil.updateXml(userEntity);
            //注册成功
            return ServerApp.REGISTERSUCRESULT;
        } catch (Exception e) {
            e.printStackTrace();
            //注册失败
            return ServerApp.REGISTERFAiRESULT;
        }
    }
}

XMLUtil类

package com.fs.test;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class XMLUtil {
    static List<UserEntity> list = new ArrayList<>();

    public static List<UserEntity> getList(){
        return list;
    }

    static String xmlFilePath = "D:\\code\\les12-13(NovelReading)\\server\\src\\Users.xml";

    static Document document = null;
    /**
     * 获取所有的XML当中的元素
     */
    public static List<UserEntity> parseXml() throws DocumentException {
        list.clear();
        Element rootElement = init();
        //遍历根节点下面所有的节点
        Iterator<Element> iterator = rootElement.elementIterator();
        while (iterator.hasNext()){
            //一个子元素---更元素下面的子元素
            Element element = iterator.next();
            //获取元素的属性
            Element username = element.element("username");
            String usernameValue = username.getStringValue();
            Element pwd = element.element("pwd");
            String pwdValue = pwd.getStringValue();

            UserEntity userEntity = new UserEntity();
            userEntity.setUsername(usernameValue);
            userEntity.setPassword(pwdValue);

            list.add(userEntity);
        }
        return list;
    }

    public static Element init() throws DocumentException {
        List<UserEntity> list = new ArrayList<>();
        File file = new File(xmlFilePath);
        //实例化SAXReader对象   读取xml
        SAXReader saxReader = new SAXReader();
        //整个xml的内容----Document
        document = saxReader.read(file);
        //根元素节点
        Element rootElement = document.getRootElement();
        return rootElement;
    }

    //更新
    public static void updateXml(UserEntity userEntity) throws DocumentException, IOException {
        Element rootElement = init();
        //往根元素下面添加一个属性 user
        Element element = rootElement.addElement("user");
        //给先添加的user元素添加一个属性 userId
        element.addAttribute("userId",userEntity.getId() + "");
        element.addElement("username").setText(userEntity.getUsername());
        element.addElement("pwd").setText(userEntity.getPassword());

        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
        FileWriter fw = new FileWriter(xmlFilePath);
        XMLWriter xw = new XMLWriter(fw,format);
        xw.write(document);
        xw.close();
        fw.close();
    }

    //判断s 是否为null 或者“”
    public static boolean isEmpty(String s){
        if(s==null){
            return true;
        }else if(s.equals("")){
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        isEmpty("");
    }

}


User.xml

<?xml version="1.0" encoding="UTF-8"?>

<users> 
  <user userId="1"> 
    <username>admin</username>  
    <pwd>000</pwd> 
  </user>  
  <user userId="2"> 
    <username>zs</username>  
    <pwd>789</pwd> 
  </user>  
  <user userId="4"> 
    <username>ww</username>  
    <pwd>5666</pwd> 
  </user>  
  <user userId="3">
    <username>ll</username>
    <pwd>666</pwd>
  </user>
</users>

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值