首页 > 编程语言 >Java项目--实现一个小说在线阅读系统

Java项目--实现一个小说在线阅读系统

时间:2024-10-30 23:20:51浏览次数:3  
标签:xml map Java 在线 -- System new out String

登录,注册

用户信息保存到哪里?

  • 集合中, 临时存储, 存储在内存中, 当程序退出运行, 占用内存释放, 数据就没有了

  • 使用IO流, 把用户信息保存到本地文件, 推荐xml(数据一定的格式) 适合一些微小型项目

  • 使用数据库: 比如mysql, Oracle,… 适合中大型项目

我们这个项目: 使用xml存储

xml类似于html, 使用标签包裹数据

html中的标签固定的, w3c标准组织定义的, 作为页面展示

xml中的标签自定义, 作用: 1) 配置文件, 2) 轻量级的存储  

 xml格式:

<!--文档声明: 固定的-->
<?xml version="1.0" encoding="utf-8"?>
<根标签>
    <子标签 属性名1=值1  属性名2=值2>
        <!--其他标签-->
    </子标签>
     <子标签 属性名1=值1  属性名2=值2>
        <!--其他标签-->
    </子标签>
</根标签>

使用xml描述一组学生(学号,姓名, 性别,年龄):

students.xml

<?xml version="1.0" encoding="utf-8"?>
<stus>
    <student id="1">
        <stuNo>1001</stuNo>
        <name>张三</name>
        <sex>男</sex>
        <age>21</age>
    </student>
    <student>
         <stuNo>1002</stuNo>
        <name>李四</name>
        <sex>男</sex>
        <age>22</age>
    </student>
</stus> 

java: 对应类来描述

Student{

​    stuNo, name, age,sex

}
List<Student> students;
Student[] students;

java对象与xml之间的转换:

  • 把xml中的数据读取出来, 变成一个一个对象 xml的读操作

  • 把java对象转换为xml,保存到xml文件 xml写操作

需要第三方的jar: dom4j

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

帮助手册:dom4j 1.6.1 API

      Dom4J通过SAXReader对象加载并解析xml文件,把它转换为内存中的Document对象,接着对Document对象中的元素进行添加、更新和删除操作,并且通过XMLWriter对象把修改后的Document对象保存到xml文件中。  

加载第三方jar:

1.在项目中创建一个lib文件夹

2.把第三方jar拷贝到lib目录

3.解压jar

Dom4J核心对象:

  • SAXReader: xml解析器
  1. 创建SAXReader对象, 无参构造方法

  2. 调用read(xml文件资源) 读取并解析xml, 得到Document对象

  •  Document: xml文档

调用Element getRootElement() 得到根标签对象

  • Element: 标签对象  
  1. 获取第一个子标签: Element element(标签名)

  2. 获取所有的子标签: List elements(标签名)

  3. 获取属性: Attribute attribute(属性名)

  4. 获取标签的内容: elementText()

  5. 获取属性的值: attributeValue()

登录

 客户端实现

private void login() {
    System.out.println("\n\n------------登录操作-------------");
    System.out.print("请输入用户名:");
    String username = input.next();
    System.out.print("请输入密码:");
    String password = input.next();
    try (
            Socket socket = new Socket("127.0.0.1", 8888);
            //对象IO流
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
    ) {
        //HashMap对象: key, value
        HashMap<String, Object> map = new HashMap<>();
        map.put("op", OptionEnum.LOGIN.name());
        map.put("data", new User(username, password));
        oos.writeObject(map);

        //接受服务器端响应
        //String result = br.readLine();
        Map rsMap = (Map) ois.readObject();
        if (ResultEnum.SUCCESS.name().equals(rsMap.get("rs"))) {
            System.out.println("!!【友情提示】!!登录成功!");
            //显示二级菜单
            showSeceondMenu();
        } else {
            System.out.println("!!【友情提示】!!用户名或者密码错误!");
            //显示一级菜单
            showFirstMenu();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

服务器端实现 

        在服务器端,由于我们需要反复连接客户端,所以在服务器端创建一个死循环,能够保证多次连接客户端,也就是一对多的连接,然后创建一个ServerThread来简化服务器的启动工程,在这个线程里实现系统的功能。

NovelServer.java:

public class NovelServer {
    public static void main(String[] args){
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            while(true){
                Socket socket = serverSocket.accept();
                System.out.println("有一个客户端连接了....");
                //创建一个线程来处理客户的请求,只要有一个客户端的请求过来,就创建一个线程过来处理
                new ServerThread(socket).start();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

ServerThread.java,登录功能的实现:

 

private void doLogin(Map map, ObjectOutputStream oos) throws DocumentException {
    Map rsMap=new HashMap();
    rsMap.put("rs",ResultEnum.FAIL.name());
    User userMap=(User)map.get("data");
    for (User user:users) {
        if(user.getUsername().equals(userMap.getUsername()) && user.getPassword().equals(userMap.getPassword())){
            rsMap.put("rs",ResultEnum.SUCCESS.name());
            break;
        }

    }
    try {
        oos.writeObject(rsMap);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

代码完善

  1. 创建静态代码块,实现,在系统一启动就开始解析xml文件中存储的用户信息,来判断用户是否能够登录成功

  2. 创建一级菜单和二级菜单

ServerThread中的static静态代码块,用户信息保存: 集合中: 使用User类封装一个用户所有信息 :

import java.io.Serializable;

public class User implements Serializable {
    private int UserId;
    private String username;
    private String password;

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

    public void setUserId(int userId) {
        UserId = userId;
    }

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

    public int getUserId() {
        return UserId;
    }

    public String getPassword() {
        return password;
    }

    public String getUsername() {
        return username;
    }

    public User(int UserId,String username, String password){
        this.UserId=UserId;
        this.username=username;
        this.password=password;
    }

    public User(String username, String password){
        this.username=username;
        this.password=password;
    }

    public User(){}
}

static {
    SAXReader saxReader=new SAXReader();
    Document document= null;
    try {
        System.out.println("解析xml");
        document = saxReader.read("user.xml");
        Element rootEle=document.getRootElement();
        List<Element> UserElements = rootEle.elements("user");
        for (Element UserEle : UserElements) {
            String username = UserEle.elementText("username");
            String pwd = UserEle.elementText("pwd");
            int userId = Integer.parseInt(UserEle.attributeValue("userId"));
            User user=new User(userId,username,pwd);
            users.add(user);
        }
    } catch (DocumentException e) {
        throw new RuntimeException(e);
    }

}

异常: 

解决方案:

 

项目登录功能控制台的实现 :

 

注册 

注册流程与登录流程相似:

登录: 读取user.xml文件

注册: 往user.xml添加数据

  • OutputFormat: 设置xml的格式: 有两种格式: 压缩(所有的标签在一行,没有缩进) createCompactFormat(), 格式化(有缩进) createPrettyPrint()
  • XMLWriter: 往xml写入内容

private void doRegister(Map map, ObjectOutputStream oos) throws DocumentException, IOException {
    Map rsMap=new HashMap();
    User userMap=(User)map.get("data");
    userMap.setUserId(users.size()+1);
    //修改xml文件
    SAXReader saxReader=new SAXReader();
    Document document=saxReader.read("user.xml");
    Element rootElement= document.getRootElement();
    //添加子标签
    Element newUserELe=rootElement.addElement("user");
    //给user标签添加一个属性
    newUserELe.addAttribute("userId",userMap.getUserId()+"");
    //添加子标签
    newUserELe.addElement("username").addText(userMap.getUsername());
    newUserELe.addElement("pwd").addText(userMap.getPassword());
    //把修改Document对象写到文件中
    //OutputFormat outputFormat = OutputFormat.createCompactFormat(); //压缩模式
    OutputFormat outputFormat = OutputFormat.createPrettyPrint();
    outputFormat.setEncoding("UTF-8");
    //XMLWriter 把Document对象写到文件中
    XMLWriter xmlWriter=new XMLWriter(new FileWriter("user.xml"),outputFormat);
    //写
    xmlWriter.write(document);
    xmlWriter.close();

    //数据校验
    for (User user:users) { //判断用户名是否存在,用户名是否为空
        if(user.getUsername().equals(userMap.getUsername()) || user.getUsername()==null){
            rsMap.put("rs",ResultEnum.FAIL.name());
            return;
        }
    }
    users.add(userMap);
    rsMap.put("rs",ResultEnum.SUCCESS.name());
    try {
        oos.writeObject(rsMap);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

在线阅读

小说列表查询

        小说信息保存在服务器端的xml文件中, 客户端查询小说列表, 需要发送请求, 服务器把信息返回给客户端,同样的思路,创建一个静态代码块,解析book.xml文件。

static:

static {
    SAXReader saxReader=new SAXReader();
    Document document= null;
    try {
        System.out.println("解析xml");
        document = saxReader.read("book.xml");
        Element rootEle=document.getRootElement();
        List<Element> BookElements = rootEle.elements("book");
        for (Element BookEle : BookElements) {
            String name = BookEle.elementText("name");
            String author = BookEle.elementText("author");
            String description = BookEle.elementText("description");
            String type = BookEle.elementText("type");
            String path = BookEle.elementText("path");
            int bookId = Integer.parseInt(BookEle.attributeValue("bookId"));
            Book book=new Book(bookId,name,author,type,description,path);
            bookList.add(book);
        }
    } catch (DocumentException e) {
        throw new RuntimeException(e);
    }
}

ServerThread.java:

private void doNovelList(ObjectOutputStream oos) throws IOException {
    Map map=new HashMap<>();
    map.put("books",bookList);
    oos.writeObject(map);
    oos.flush();
}

 Cilent:

private void novelList() {
    System.out.println("--------------小说列表-------------\n\n");
    //发送请求,查询
    try(
            Socket socket = new Socket("127.0.0.1",8888);
            //对象IO流
            ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
    ){
        //HashMap对象: key, value
        HashMap<String,Object> map=new HashMap<>();
        map.put("op",OptionEnum.LIST.name());
        oos.writeObject(map);

        //接受服务器端响应
        Map rsMap=(Map) ois.readObject();
        bookList=(List<Book>) rsMap.get("books");
        //显示小说列表
        System.out.println("================================");
        System.out.println("序号\t\t书名\t\t作者\t\t类型\t\t描述");
        if(bookList==null || bookList.isEmpty()){
            System.out.println("【友情提示】 没有小说!^_^");
        }else {
            for (int i = 0; i < bookList.size(); i++) {
                Book book=bookList.get(i);
                System.out.println((i+1)+"\t\t"+book.getName()+"\t\t"+book.getAuthor()+"\t\t"+book.getType()+"\t\t"+book.getDescription());
            }
        }
        System.out.println("================================");
        showSeceondMenu();
    }catch (Exception e){
        e.printStackTrace();
    }
}

 

运行结果:

在线小说阅读: 分页查询

客户端思路:

  1. 先显示小说列表 1. 天龙八部   2.…

  2. 让用户选择阅读的小说序号, 获取对应的小说名

  3. 发送请求到服务器 默认第一页

  4. 显示小说内容

 Cilen:

private List<Book> bookList;
int page = 1;
Boolean isLast=false;

public void sendToServer(String bookName) {
    try (
            Socket socket = new Socket("127.0.0.1", 8888);
            //对象IO流
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
    ) {
        //HashMap对象: key, value
        HashMap<String, Object> map = new HashMap<>();
        map.put("op", OptionEnum.ON_LINE_READ.name());
        map.put("name", bookName);
        map.put("page", page);
        oos.writeObject(map);

        //接受服务器端响应
        Map rsMap = (Map) ois.readObject();
        String content = (String) rsMap.get("data");
        System.out.println(content);
        if(content==""){
            isLast=true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void showPage(String bookName){
    System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    System.out.println("0.上一页\t1.下一页\t2.评论\t3.返回二级菜单");
    System.out.print("请输入:");
    int num = input.nextInt();
    switch (num) {
        case 0:
            if (page > 1) {
                page--;
                sendToServer(bookName);
            } else {
                System.out.println("【友情提示】 已经是第一页了!!!");
            }
            break;
        case 1:
            if(isLast){
                System.out.println("【友情提示】 已经是最后一页了!!!");
                return;
            }else{
                page++;
                sendToServer(bookName);
            }
            break;
        case 2:
            comments();
            showPage(bookName);
            break;
        case 3:
            showSeceondMenu();
            return;
    }
    showPage(bookName);
}

ServerThread:

private String getPathByName(String bookName){
    String path="";
    for (Book book : bookList) {
        if(bookName.equals(book.getName())){
            path=book.getPath();
            break;
        }
    }
    return path;
}

private void doReadLine(Map map, ObjectOutputStream oos){
    String name=(String) map.get("name");
    int page=(Integer) map.get("page");
    String path=getPathByName(name);
    //分页读取
    try(
            FileReader fr=new FileReader(path);
    ){
        int limit = (page-1)*1000;
        fr.skip(limit);
        int i = 0;
        StringBuffer content = new StringBuffer("");
        int data = -1;
        while(i < 1000 && (data = fr.read()) != -1){
            i++;
            content.append((char)data);
        }
        Map rsMap = new HashMap();
        rsMap.put("data",content.toString());
        oos.writeObject(rsMap);
        oos.flush();
    }catch (IOException e){
        e.printStackTrace();
    }

}

运行效果:

 

 下载

服务流程:

代码实现:

Cilent:

private void download() {
    String bookName = chooseNovel();
    try (
            Socket socket = new Socket("127.0.0.1", 8888);
            //对象IO流
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            FileWriter fw = new FileWriter("E:\\"+bookName+".txt");
    ) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("op", OptionEnum.DOWNLOAD.name());
        map.put("name", bookName);
        oos.writeObject(map);

        //接受服务器端响应
        //String result = br.readLine();
        Map rsMap = (Map) ois.readObject();
        String content = (String) rsMap.get("data");
        //写到客户端硬盘上面,IO流
        fw.write(content);
        fw.flush();
        if (ResultEnum.SUCCESS.name().equals(rsMap.get("rs"))) {
            System.out.println("【友情提示】下载成功!");
            showSeceondMenu();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

ServerThread:

private void doDownLoad(Map map, ObjectOutputStream oos) {
    String name=(String) map.get("name");
    String path=getPathByName(name);
    try(
            FileReader fr=new FileReader(path);
    ){
        StringBuffer content = new StringBuffer("");
        int data = -1;
        while( (data = fr.read()) != -1){
            content.append((char)data);
        }
        Map rsMap = new HashMap();
        rsMap.put("data",content.toString());
        rsMap.put("rs",ResultEnum.SUCCESS.name());
        oos.writeObject(rsMap);
        oos.flush();
    }catch (IOException e){
        e.printStackTrace();
    }
}

 

运行效果: 

 上传

与下载和用户注册有相似之处,二者的结合,上传文件路径时注意绝对路径和相对路径的问题!!!

Cilent:

private void upload(){
    System.out.println("\n\n--------------上传小说---------------");
    System.out.print("请输入小说名称:");
    String bookName = input.next();
    System.out.print("请输入小说作者:");
    String author = input.next();
    System.out.print("请输入小说类型:");
    String type = input.next();
    System.out.print("请输入小说描述:");
    String description = input.next();
    System.out.print("请输入小说路径:");
    String path = input.next();
    String path1="D:\\upload\\上传\\"+bookName+".txt";
    String path2="E:\\upload1\\上传\\"+bookName+".txt";
    System.out.println("\t请选择上传到哪个路径:");
    System.out.println("\t路径1:"+path1);
    System.out.println("\t路径2:"+path2);
    System.out.print("请选择:");
    int choose = input.nextInt();
    HashMap<String, Object> map = new HashMap<>();
    switch(choose){
        case 1:
            map.put("path",path1);
            break;
        case 2:
            map.put("path",path2);
            break;
    }
    File file = new File(path);
    try (
            Socket socket = new Socket("127.0.0.1", 8888);
            //对象IO流
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            FileReader fr = new FileReader(file);
    ) {
        //HashMap对象: key, value
        map.put("op", OptionEnum.UPLOAD.name());
        map.put("data", new Book(bookName,author,type,description,path));
        oos.writeObject(map);

        //接受服务器端响应
        Map rsMap = (Map) ois.readObject();
        String content = (String) rsMap.get("data");
        if (ResultEnum.SUCCESS.name().equals(rsMap.get("rs"))) {
            System.out.println("【友情提示】上传成功!");
            //显示二级菜单
            showSeceondMenu();
        } else {
            System.out.println("【友情提示】上传失败!");
            //显示一级菜单
            showFirstMenu();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

ServerThread :

private void doUpload(Map map, ObjectOutputStream oos) throws DocumentException, IOException {
    Map rsMap=new HashMap();
    Book bookMap=(Book)map.get("data");
    String path=map.get("path").toString();
    boolean flag = false;
    for (Book book:bookList) {
        if(book.getName().equals(bookMap.getName())){
            flag=true;
            break;
        }
    }
    if(!flag){
        bookMap.setBookId(bookList.size()+1);
        //修改xml文件
        SAXReader saxReader=new SAXReader();
        Document document=saxReader.read("book.xml");
        Element rootElement= document.getRootElement();
        //添加子标签
        Element newBookELe=rootElement.addElement("book");
        //给book标签添加一个属性
        newBookELe.addAttribute("bookId",bookMap.getBookId()+"");
        //添加子标签
        newBookELe.addElement("name").addText(bookMap.getName());
        newBookELe.addElement("author").addText(bookMap.getAuthor());
        newBookELe.addElement("type").addText(bookMap.getType());
        newBookELe.addElement("description").addText(bookMap.getDescription());
        newBookELe.addElement("path").addText(bookMap.getPath());
        //把修改Document对象写到文件中
        //OutputFormat outputFormat = OutputFormat.createCompactFormat(); //压缩模式
        OutputFormat outputFormat = OutputFormat.createPrettyPrint();
        outputFormat.setEncoding("UTF-8");
        //XMLWriter 把Document对象写到文件中
        XMLWriter xmlWriter=new XMLWriter(new FileWriter("book.xml"),outputFormat);
        //写
        xmlWriter.write(document);
        xmlWriter.close();
        //
        FileReader fr=new FileReader(bookMap.getPath());
        FileWriter fw=new FileWriter(path);
        StringBuffer content = new StringBuffer("");
        int data = -1;
        while( (data = fr.read()) != -1){
            content.append((char)data);
        }
        rsMap.put("data",content.toString());
        fw.write(content.toString());
        fw.close();
        bookList.add(bookMap);
    }
    if (flag){
        rsMap.put("rs",ResultEnum.FAIL.name());
    }else {
        rsMap.put("rs",ResultEnum.SUCCESS.name());
    }
    oos.writeObject(rsMap);
    oos.flush();
}

运行效果:

在我们选择的上传路径文件中可找到这个作品,以及里面也有内容: 

 

book.xml文件中也加入了这本书的信息,可进行小说列表查询、在线阅读和下载功能,都能在里面看到这本书,这样系统也就较为完善了

总结 

  1. 整合了之前学过的知识,有复习的效果
  2. 增加了写项目的经验,对这部分有了一定的认识
  3. 这个系统还有很多未完善的部分,希望有好心人能提出意见,让我多多完善,也能多增加几个功能^_^!!!

标签:xml,map,Java,在线,--,System,new,out,String
From: https://blog.csdn.net/2301_76890677/article/details/143303143

相关文章

  • Springboot计算机毕业设计高校教学辅助管理系统95xv7
    Springboot计算机毕业设计高校教学辅助管理系统本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表项目功能:学生,教师,课程类别,网上课堂,学生考勤,学生成绩开题报告内容一、项目背景与意义随着信息技术的快......
  • 体验国产系统Deepin:很爽
    最近开始把之前一直吃亏的旧电脑拿出来再利用了,先还是选择了熟悉的ubuntu系列。安装了Ubuntu22.04之后,风风火火地把需要的开发环境搭建起来,虽然桌面有些卡顿,但瑕不掩瑜玉。趁着热情又想着把它升级到24.04。结果不巧在升级过程中遇到了网络中断,导致内核模块破碎,重启之后无法顺利进......
  • 2024博鳌新型电力系统国际论坛——电力系统与新能源技术创新论坛 2024 Boao New Pow
    @目录一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题一、会议详情二、重要信息大会官网:https://ais.cn/u/vEbMBz提交检索:EICompendex、IEEEXplore、Scopus大会时间:2024年12月8-12月10日大会地点:中国·海南博鳌三、大会介绍2023年3月22日至23日,2023......
  • 程序员必备单品:超级常用的linux指令+实际操作案例
    Linux常用命令在Linux系统中,有许多常用的命令可以帮助用户进行文件管理、系统监控、网络配置等操作。以下是一些常见的Linux命令及其具体使用案例:ls:列出目录内容基本用法:ls[选项][目录]常见参数:-a:显示所有文件,包括以.开头的隐藏文件。-l:使用长列表格式显示文件详......
  • 程序员必备单品:超级常用的linux指令+实际操作案例
    Linux常用命令在Linux系统中,有许多常用的命令可以帮助用户进行文件管理、系统监控、网络配置等操作。以下是一些常见的Linux命令及其具体使用案例:ls:列出目录内容基本用法:ls[选项][目录]常见参数:-a:显示所有文件,包括以.开头的隐藏文件。-l:使用长列表格式显示文件详细信......
  • VM+ubuntu,编译huawei EC6109 SDK 报错"[u-boot.bin] Error 1" ,未找到原因
    环境:ubuntu14,内核3.13.0-24-generic源代码:https://kgithub.com/tegzwn/HiSTBLinuxV100R005C00SPC050编译问题如下:make-C/home/andy1224/Downloads/HiSTBLinuxV100R005C00SPC050-master/out/hi3798mv200/hi3798mv2dmg/obj/source/boot/fastboot/arch/arm/cpu/hi3798mv2x/u-......
  • Python学习15天
    if 条件表达式:(条件为真,执行代码块1,否则执行代码块2)   代码块1else:   代码块2#键盘输入成绩,若成绩大于60,输出及格,否则输出不及格score=int(input("请输入成绩:"))ifscore>60:   print("及格")else:   print("不及格")#键盘输入年份,判断是......
  • Python学习第14天
    ~:按位取反,把数据的每个二进制按位取反~5:5=00000101(原码=反码=补码)~5=11111010(补码)-(反码=补码-1)=11111001-原码=00000110=6~5=6print(~5)~-3=2print(~-3)-3>原码=10000011>反码=11111100>补码=11111101~-3=00000010(补码=反码=原码)=2&:按位与:两个值都为1则......
  • 第二章 Linux基础入门和帮助
    文章目录第二章Linux基础入门和帮助内容概述1.Linux基础1.1用户类型1.2远程连接工具1.2.1WindowsPowerShell工具1.2.2Xshell软件使用1.2.3MobaXterm软件使用1.3终端terminal1.3.1终端类型1.3.2查看当前的终端设备1.4交互式接口1.4.1交互式接口类型1.4.2......
  • Springboot大学生心理健康评测系统9701n
    Springboot大学生心理健康评测系统9701n本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表项目功能:学生,心理教师,类型,减压大本营,音乐类型,音乐信息,学生心理健康开题报告内容一、研究背景随着社会的发展......