Spring Boot:Web应用开发之增删改查的实现

Spring Boot

  • 前言
  • 实现增删改查功能

在这里插入图片描述

前言

增删改查功能作为 Web 应用中的基础且重要的组成部分,是基本的数据库操作,也是实现业务逻辑和功能的关键要素。下面简单介绍使用 Spring Boot 实现增删改查的功能。

实现增删改查功能

在上一章 Spring Boot:Web应用开发之登录与退出的实现 文章的案例基础上,进行实现增删改查的功能。

简单示例:
首先,创建一个 PublicTemplate.html ,将 html 的公共代码抽离到这页面上,方便其他页面进行复用(使用方式:th:replace=“模版名称::模版⽚段名称”

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>公共页面-抽离与复用</title>
</head>
<body>
    <!-- th:fragment 属性来定义被包含的模版⽚段,以供其他模版使用。模版⽚段名称为 top -->
    <div class="header" th:fragment="header">
        主页面的头部区域
    </div>

    <div class="center">
        <!-- 通用侧边栏区域 -->
        <div class="sidebar" th:fragment="sidebar">
            <!-- 增强效果设置:th:class="${isActive=='Main.html'?'active':''}" 当切换到该页面时,内容设定为 active 的样式 -->
            <a href="#" th:class="${isActive=='Main.html'?'active':''}" th:href="@{Main.html}">主页</a> <br>
            <a href="#" th:class="${isActive=='UserList.html'?'active':''}" th:href="@{UserList.html}">用户列表</a> <br>
            <a th:href="@{/logout.html}">退出</a>
        </div>
    </div>

    <div class="footer" th:fragment="footer">
        主页面的脚部区域
    </div>
</body>
</html>

创建需要用到的页面,有公共的代码便使用 th:replace 调用

Main.html:主页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>MainDemo</title>
    <!--  存放 css 文件默认在 static 目录下 -->
    <link rel="stylesheet" type="text/css" th:href="@{/css/PublicCss.css}">
</head>
<body>
    <!-- th:replace 替换整个标签到引入的文件。使用方式——th:replace="模版名称::模版⽚段名称" -->
    <div th:replace="PublicTemplate::header"></div>

    <dic class="center">
        <!-- 增强效果设置:(isActive='Main.html') -->
        <div th:replace="PublicTemplate::sidebar(isActive='Main.html')"></div>

        <div class="main">
            主页面内容
        </div>
    </dic>

    <div th:replace="PublicTemplate::footer"></div>
</body>
</html>

UserList.html:显示用户列表页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>UserListDemo</title>
    <!--  存放 css 文件默认在 static 目录下 -->
    <link rel="stylesheet" type="text/css" th:href="@{/css/PublicCss.css}">
</head>
<body>
    <!-- th:replace 替换整个标签到引入的文件。使用方式——th:replace="模版名称::模版⽚段名称" -->
    <div th:replace="PublicTemplate::header"></div>

    <dic class="center">
        <div th:replace="PublicTemplate::sidebar(isActive='UserList.html')"></div>

        <div class="main">
            <form th:action="UserSearch.html" method="post">
                <input type="text" name="searchByUsername" />
                <input type="submit" value="查询" />
                <a th:href="@{/UserAdd.html}">添加</a>
            </form>
            <table>
                <tr>
                    <td>id</td>
                    <td>账号</td>
                    <td>密码</td>
                    <td>注册时间</td>
                    <td>地址</td>
                    <td>操作</td>
                </tr>

                <tr th:each="user:${users}">
                    <td th:text="${user.id}"></td>
                    <td th:text="${user.username}"></td>
                    <td th:text="${user.password}"></td>
                    <td th:text="${user.regDate}"></td>
                    <td th:text="${user.address}"></td>

                    <td>
                        <a th:href="@{/UserDelete.html(id=${user.id})}" onclick="return confirm('确定要删除吗?')">删除</a>
                        <a th:href="@{/UserUpdate.html(id=${user.id})}">修改</a>
                    </td>
                </tr>
            </table>
        </div>
    </dic>

    <div th:replace="PublicTemplate::footer"></div>
    </body>
</html>

UserAdd.html:添加用户页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>UserAddDemo</title>
</head>
<body>
    <form th:action="@{/UserAdd.html}" method="post">
        账号:<input type="text" name="username"/> <br>
        密码:<input type="text" name="password"/> <br>
        地址:
        <select name="address.id">
            <option th:value="${address.id}" th:each="address:${addresses}">[[${address.addressInfo}]]</option>
        </select> <br>

        <input type="submit" th:value="添加">
    </form>
</body>
</html>

UserUpdate.html:修改用户页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>UserUpdateDemo</title>
</head>
<body>
    <div class="main">
        <form th:action="@{/UserUpdate.html}" method="post">
            <input type="hidden" name="id" th:value="${user.id}">
            账号:<input type="text" name="username" th:value="${user.username}"/> <br>
            密码:<input type="text" name="password" th:value="${user.password}"/> <br>
            注册时间:<input type="text" name="regDate" th:value="${#dates.format(user.regDate,'yyyy-MM-dd HH:mm:ss')}"/> <br>
            地址:
            <select name="address.id">
                <option th:value="${address.id}" th:selected="${user.address.id == address.id}" th:each="address:${addresses}">[[${address.addressInfo}]]</option>
            </select> <br>

            <input type="submit" th:value="修改">
        </form>
    </div>
</body>
</html>

然后,在 User 实体类上使用 @DateTimeFormat 注解指定日期样式(否则在修改注册时间时,会出现类型转换问题),再创建一个 Address 类
在这里插入图片描述

package cn.edu.SpringBootWebDemo.Entity;

import jakarta.persistence.*;

@Entity
@Table(name = "address")
public class Address {
    private int id;
    private String addressInfo; // 地址详情

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
    public int getId() {
        return id;
    }

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

    @Column(name = "address_info") // 指定字段名
    public String getAddressInfo() {
        return addressInfo;
    }

    public void setAddressInfo(String addressInfo) {
        this.addressInfo = addressInfo;
    }

    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", addressInfo='" + addressInfo + '\'' +
                '}';
    }
}

随之,在 UserDao 接口上声明一个模糊查询方法,在 AddressDao 接口上直接继承 JpaRepository<实体类,主键类型> 即可
在这里插入图片描述
在这里插入图片描述

接着,在 Service 包内创建一个 UserService 接口,声明增删改查方法,并创建一个 UserServiceImpl 实现类实现该接口方法; AddressService 接口与 AddressServiceImpl 实现类同理

UserService 接口:

package cn.edu.SpringBootWebDemo.Service;

import cn.edu.SpringBootWebDemo.Entity.User;

import java.util.List;

public interface UserService {
    public User login(User user);

    //增删改查
    public void add(User user);

    public void delete(int id);

    public void update(User user);

    public User get(int id);

    public List<User> getALLUsers();

    public List<User> getByUsernameLike(String string);
}

UserServiceImpl 实现类:

package cn.edu.SpringBootWebDemo.Service;

import cn.edu.SpringBootWebDemo.Dao.UserDao;
import cn.edu.SpringBootWebDemo.Entity.User;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userService")
@Transactional // 放在类上,类上的所有方法都支持事务;也可以只放在一个方法上,只指定那个方法支持事务
public class UserServiceImpl implements UserService{

    @Autowired
    private UserDao userDao;

    @Override
    public User login(User user) {
        // 根据用户名查询有没有对应的账号
        User user1 = userDao.getByUsername(user.getUsername());
        // 判断是否为空或密码错误,登录失败返回 null
        if (user1 == null) return null;
        if(!user1.getPassword().equals(user.getPassword())) return null;
        // 返回 User 对象,登录成功
        return user1;
    }

    @Override
    public void add(User user) {
        userDao.save(user);
    }

    @Override
    public void delete(int id) {
        userDao.deleteById(id);
    }

    @Override
    public void update(User user) {
        userDao.saveAndFlush(user);
    }

    @Override
    public User get(int id) {
        return userDao.findById(id).get();
    }

    @Override
    public List<User> getALLUsers() {
        return userDao.findAll();
    }

    @Override
    public List<User> getByUsernameLike(String string) {
        return userDao.getByUsernameLike(string);
    }
}

AddressService 接口:

package cn.edu.SpringBootWebDemo.Service;

import cn.edu.SpringBootWebDemo.Entity.Address;

import java.util.List;

public interface AddressService {
    public void add(Address address);

    public void delete(int id);

    public void update(Address address);

    public Address get(int id);

    public List<Address> getAllAddress();
}

AddressServiceImpl 实现类:

package cn.edu.SpringBootWebDemo.Service;

import cn.edu.SpringBootWebDemo.Dao.AddressDao;
import cn.edu.SpringBootWebDemo.Entity.Address;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class AddressServiceImpl implements AddressService{
   @Autowired
    private AddressDao addressDao;

    @Override
    public void add(Address address) {
        addressDao.save(address);
    }

    @Override
    public void delete(int id) {
        addressDao.deleteById(id);
    }

    @Override
    public void update(Address address) {
        addressDao.saveAndFlush(address);
    }

    @Override
    public Address get(int id) {
        return addressDao.findById(id).get();
    }

    @Override
    public List<Address> getAllAddress() {
        return addressDao.findAll();
    }
}

再在 Controller 包内的 UserController 控制类上处理用户相关的 HTTP 请求

package cn.edu.SpringBootWebDemo.Controller;

import cn.edu.SpringBootWebDemo.Entity.Address;
import cn.edu.SpringBootWebDemo.Entity.User;
import cn.edu.SpringBootWebDemo.Service.AddressService;
import cn.edu.SpringBootWebDemo.Service.UserService;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.Date;
import java.util.List;

@Controller
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private AddressService addressService;

    @GetMapping("/Login.html")
    public String login(HttpSession httpSession){
        // 成功登录后不能再返回登录页面,而是跳转到主页
        boolean flag = httpSession.getAttribute("loginUser")==null?true:false;
        if (flag){
            return "Login";
        }else {
            return "redirect:/Main.html";
        }
    }

    @GetMapping("/Main.html")
    public String main(){
        return "Main";
    }

    // 判断登录
    @PostMapping("/Login.html")
    public String login(User user, HttpSession httpSession, Model model){
        // 控制层——接受页面的账号和密码。调用服务层的 login 方法,判断登录是否成功。
        // 成功将返回的 user 对象保存到 session 的域空间;反之返回一个错误提示。
        User user1 = userService.login(user);
        if(user1 != null) {
            // 将返回的 user 对象保存到 session 的域空间,页面跳转到主页中
            httpSession.setAttribute("loginUser",user1);
            return "redirect:/Main.html";
        }else {
            // 登录失败,返回错误提示
            model.addAttribute("loginError","用户名或密码错误!");
            return "Login";
        }
    }

    // 退出
    @GetMapping("/logout.html")
    public String logout(HttpSession httpSession){
        // 通过 invalidate 方法清空 httpSession 里的内容
        httpSession.invalidate();
        return "redirect:/Login.html";
    }

    // 显示用户
    @GetMapping("/UserList.html")
    public String userlist(Model model){
        List<User> users = userService.getALLUsers();
        model.addAttribute("users",users);
        System.out.println(users);
        return "UserList";
    }

    // 模糊查询用户
    @PostMapping("/UserSearch.html")
    // 接受的参数,searchByUsername 名字与页面 input 标签的 name 属性值一致
    public String userSearch(String searchByUsername,Model model){
        List<User> users = userService.getByUsernameLike("%" + searchByUsername + "%");
        model.addAttribute("users",users);
        return "UserList";
    }

    // 先获取所有的地址信息,再进行添加用户
    @GetMapping("/UserAdd.html")
    public String addUser(Model model){
        List<Address> addresses = addressService.getAllAddress();
        model.addAttribute("addresses",addresses);
        return "UserAdd";
    }
    @PostMapping("/UserAdd.html")
    public String addUser(User user){
        user.setRegDate(new Date());
        userService.add(user);
        return "redirect:/UserList.html";
    }

    // 修改实现:1.点击修改按钮,打开修改页面
    @GetMapping("/UserUpdate.html")
    public String updateUser(Model model,Integer id){
        // 获取指定用户信息
        User user = userService.get(id);
        model.addAttribute("user",user);
        // 获取指定地址信息
        List<Address> addresses = addressService.getAllAddress();
        model.addAttribute("addresses",addresses);
        return "UserUpdate";
    }
    // 2.修改实现
    @PostMapping("/UserUpdate.html")
    public String updateUserAchieve(User user){
        userService.update(user);
        return "redirect:/UserList.html";
    }

    // 删除用户
    @GetMapping("/UserDelete.html")
    public String deleteUser(Integer id){
        userService.delete(id);
        return "redirect:/UserList.html";
    }
}

最后,在 SpringBootWebDemoApplication 启动类上使用 @EnableTransactionManagement 注解开启事务,并启动 Spring Boot 进行测试

package cn.edu.SpringBootWebDemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@EnableTransactionManagement // 开启事务
@SpringBootApplication
public class SpringBootWebDemoApplication {
    // 获取事务管理器类型
//    @Bean
//    public Object testBean(PlatformTransactionManager platformTransactionManager){
//        System.out.println("事务管理器类型:" + platformTransactionManager.getClass().getName());
//        return new Object();
//    }

    // 指定事务管理器,设置后会覆盖默认的事务管理器
//    @Bean
//    public PlatformTransactionManager manager(DataSource dataSource){
//        return new DataSourceTransactionManager(dataSource);
//    }

    public static void main(String[] args) {
        SpringApplication.run(SpringBootWebDemoApplication.class, args);
    }

}

结果如图:
1.登录,进入主页
在这里插入图片描述

2.点击用户列表,进入显示用户列表页面
在这里插入图片描述

3.在显示用户列表页面上,进行模糊查询,输入 “刘” 点击查询
在这里插入图片描述
模糊查询结果:
在这里插入图片描述

4.在显示用户列表页面上,点击添加,进入添加页面,输入用户信息,点击添加用户
在这里插入图片描述
添加用户结果:
在这里插入图片描述

5.在显示用户列表页面上,点击修改,进入修改页面,修改用户信息,点击修改用户
在这里插入图片描述
修改用户结果:
在这里插入图片描述

6.在显示用户列表页面上,点击删除,弹出确认窗口,点击确定
在这里插入图片描述
删除用户结果:
在这里插入图片描述

Web 应用开发案例中的主要目录结构:
在这里插入图片描述

PublicCss.css:设置页面样式的文本文件

body{
    background-image: url("../img/background-image.png");
    background-attachment: fixed;
    background-size: cover;
    background-repeat: no-repeat;
}

.header{
    text-align: center;
    height: 90px;
    line-height: 90px;
    width: 100%;
    border: 2px black solid;
}

.center{
    width: 100%;
    height: 450px;
}

.center .sidebar{
    width: 120px;
    height: 550px;
    float: left;
    border: 2px black solid;
}

.center .main{
    width: 100%;
    height: 550px;
    border: 2px black solid;
}

table{
    border-collapse: collapse;
}

th, td {
    border: 1px silver solid;
    padding: 0.3em 1em;
}

.footer{
    text-align: center;
    height: 90px;
    line-height: 90px;
    width: 100%;
    border: 2px black solid;
}

/* 增强效果设置 */
.active{
    color: darkturquoise;
    text-decoration: none;
}

background-image.png:页面背景图片
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/569067.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jvm(JVM快速入门、stack栈、堆、GC垃圾回收、Arthas)

文章目录 1. JVM快速入门1.1. 结构图1.2. 类加载器ClassLoader1.3. 执行引擎Execution Engine1.4. 本地接口Native Interface1.5. Native Method Stack1.6. PC寄存器(程序计数器)1.7. Method Area方法区 2. stack栈3. 堆3.1. 堆体系概述3.1.1. 新生区3.1.2. 老年代3.1.3. 永久代…

分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测

分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测 目录 分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类…

小程序AI智能名片商城系统直连:打造用户与企业无缝对接的新时代!

在高度不确定性的商业环境中&#xff0c;企业如何快速响应市场变化&#xff0c;实现与用户的零距离接触&#xff1f;答案就是——小程序AI智能名片商城系统直连&#xff01;这一创新工具不仅为企业打开了与用户直接连接的大门&#xff0c;更为企业提供了持续收集用户反馈、快速…

AI图书推荐:如何用ChatGPT和Python进行数据可视化

《如何用ChatGPT和Python进行数据可视化》的原版英文图书标题&#xff1a;Python 3 Data Visualization Using ChatGPT - GPT-4 &#xff0c;作者是 Oswald Campesato &#xff0c;2023年出版 本书旨在向读者展示Python 3编程的概念和数据可视化的艺术。它还探讨了使用ChatGPT/…

vuetify3.0+tailwindcss+vite最新框架

1、根据vuetify官网下载项目 安装vuetify项目 2、根据tailwindcss官网添加依赖 添加tailwindcss依赖 3、 配置main.ts // main.ts import "./style.css"4、使用 <template><h1 class"text-3xl font-bold underline">Hello world!</…

SpringBoot学习之Kafka下载安装和启动【Windows版本】(三十四)

一、配置Java环境变量 打开CMD输入java -version检查java环境变量是否配置正确,如果配置正确在CMD窗口输入java -version应该输出如下: ​ 怎么配置Java环境变量这里我就不赘叙了,网上教程很多,请读者自行搜索操作。 二、下载Kafka 1、Kafka官网地址:Apache Kafka,…

C++进阶--异常

C语言传统的处理方式 终止程序&#xff1a;在发生错误时直接终止程序的运行&#xff0c;可以通过assert宏来进行实现。如assert(condition)&#xff0c;其中condition不满足要求时&#xff0c;将会使程序立刻停止执行&#xff0c;并输出相关错误信息。这种方式的确定是用户很难…

Golang基础3-函数、nil相关

函数 需要声明原型支持不定参数 func sum(numbers ...int)int支持返回多值支持递归支持命名返回参数 // 命名返回参数 func add(a, b int) (sum int) {sum a breturn // 这里不需要显式地写出返回值&#xff0c;因为已经在函数签名中声明了命名返回参数 } 支持匿名函数、闭包…

Jackson 2.x 系列【30】Spring Boot 集成之数据脱敏

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 本系列Spring Boot 版本 3.2.4 源码地址&#xff1a;https://gitee.com/pearl-organization/study-jaskson-demo 文章目录 1. 概述2. 实现思路3. 案例演示3.1 脱敏规则3.2 自…

图像处理之Retinex算法(C++)

图像处理之Retinex算法&#xff08;C&#xff09; 文章目录 图像处理之Retinex算法&#xff08;C&#xff09;前言一、单尺度Retinex&#xff08;SSR&#xff09;1.原理2.代码实现3.结果展示 二、多尺度Retinex&#xff08;MSR&#xff09;1.原理2.代码实现3.结果展示 三、带色…

Linux加强篇-存储结构与管理硬盘(一)

目录 ⛳️推荐 从“/”开始 物理设备命名规则 文件系统与数据资料 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 从“/”开始 Linux系统中一切都是文件&#xff0c;都是从“…

deep learning

谷歌在线notebook 一、基本数据类型与用法 1.torch.tensor(张量) 按照维度不同(中括号的对数)&#xff0c;可以用torch.tensor创建scalar(标量)、vector(向量)、matrix(矩阵)&#xff0c; 一般的&#xff0c;一维是标量&#xff0c;二维是向量&#xff0c;三维是矩阵&#…

银河麒麟V10 SP1服务器客户端定时数据同步

银河麒麟V10 SP1服务器客户端定时数据同步 0.概述 当前只测试了将数据从客户端往服务端推送&#xff0c;两个客户端分别推送不同的数据 1.环境 三台电脑均为银河麒麟V10SP1桌面操作系统 服务器IP&#xff1a;192.168.1.51 用户名&#xff1a;wlh 客户端IP&#xff1a;192…

LabVIEW和MES系统的智能化车间数据对接

LabVIEW和MES系统的智能化车间数据对接 随着工业4.0时代的到来&#xff0c;智能制造成为推动制造业高质量发展的重要手段。其中&#xff0c;数字化车间作为智能制造的重要组成部分&#xff0c;其设计与实现至关重要。在数字化车间环境下&#xff0c;如何利用LabVIEW软件与MES系…

解析SoC芯片:构建智能设备的核心技术

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

linux磁盘原理

在linux系统中&#xff0c;对磁盘进行管理与windows系统类似&#xff0c;都要先分区&#xff0c;格式化&#xff0c;创建文件系统&#xff0c;挂载目录&#xff0c;数据写入

【PHP开发工程师详细讲解分析】——网站注册账号(头像的上传操作),让自己喜欢的头像更换畅通无阻

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

便携式应急指挥箱规格参数

概况: 微缩型的无线视频音频传输的机动挥所。体积小、重量轻、公配电方便、携带便携、功能齐全。可进行单兵作战&#xff0c;通过此无线音频视频传输的指挥箱能完成现场图像、语音、数据的采集等功能&#xff0c;可以通过5G/4G/WIFI等多种无线网络完成传输的需求&#xff0c;或…

计算机网络相关知识总结

一、概述 计算机网络可以极大扩展计算机系统的功能机器应用范围&#xff0c;提高可靠性&#xff0c;在为用户提供放方便的同时&#xff0c;减少了整体系统费用&#xff0c;提高性价比。 计算机网络的功能主要有&#xff1a;1. 数据共享&#xff1b;2. 资源共享&#xff1b;3. 管…

echart坑

echart坑 原因&#xff1a; 引用了echarts里面的init方法显示没有定义 解决的方法 将import echarts from echarts 的引入方式改为&#xff1a; import * as echarts from echarts