SpringBoot-----从前端更新数据到MySql数据库

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: SpringBoot-----从前端更新数据到MySql数据库

参考SpringBoot官网教程:

1.Validating Form Input

2.Handling Form Submission

3.Accessing data with MySQL

(一)连接MySql

在pom.xml中引入以下依赖:

---------连接数据库----------    
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.12</version>
</dependency>
 
 
-------用于启用JPA和Hibernate,实现数据的持久化-------
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
 
 
-----------启用web应用程序----------
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
 
 
--------用于构建交互的WEB应用程序-------
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
 
 
-------启用校验功能----------
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>3.1.5</version>
  </dependency>
 

在application.properties中添加如下代码,连接数据库

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/db_example?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456ab
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.jpa.show-sql: true
# spring.thymeleaf.cache=false
# spring.thymeleaf.prefix=classpath:/templates/
# spring.thymeleaf.suffix=.html

也可以添加application.yml:

application.yml 的功能和 application.properties 是一样的,不过因为yml文件是树状结构,写起来有更好的层次感,更易于理解,所以很多人都选择了yml文件。

spring:
    datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=false
        username: root
        password: 123456ab
(二)创建实体模型

@Entity注解用于将一个类标识为 JPA 实体,它告诉 Hibernate 或其他 JPA 实现框架将这个类映射为数据库中的表

注:想深入学习校验方法及注释的小伙伴可以看看这个:

package com.example.accessingdatamysql;
 
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
 
@Entity // This tells Hibernate to make a table out of this class
public class User {
  @Id
//指定序列生成器,序列生成器的名称为"user_seq"
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
//每次增长值为1
  @SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 1)
  private Integer id;
 
  @NotNull(message = "姓名不能为空")
  @Size(min = 2, max = 30, message = "姓名长度必须在2-30之间")
  private String name;
 
  @Email
  @NotEmpty(message = "邮箱不能为空")
  private String email;
 
  public Integer getId() {
    return id;
  }
 
  public void setId(Integer id) {
    this.id = id;
  }
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public String getEmail() {
    return email;
  }
 
  public void setEmail(String email) {
    this.email = email;
  }
 
  public String toString() {
    return "User(id:" + this.id + ",name:" + this.name + ",email:" + this.email + ")";
  }
}
(三)创建Repository接口

Repository接口,用于定义数据访问的方法

package com.example.accessingdatamysql;
 
import org.springframework.data.repository.CrudRepository;
 
// import com.example.accessingdatamysql.User;
 
// This will be AUTO IMPLEMENTED by Spring into a Bean called userRepository
// CRUD refers Create, Read, Update, Delete
 
//使用Iterable,可以根据条件来查询匹配的用户,并获取到一个包含所有符合条件的迭代的用户列表。
public interface UserRepository extends CrudRepository<User, Integer> {
 
//根据姓名查询用户
    Iterable<User> findByName(String name);
 
//根据邮箱查询用户
    Iterable<User> findByEmail(String email);
 
//根据邮箱和姓名查询用户
    Iterable<User> findByNameAndEmail(String email,String name);
 
}
(四)创建Controller类

Controller类通常用于Web应用程序,它接收用户的HTTP请求,调用业务逻辑处理请求,并返回一个包含响应数据的视图。

package com.example.accessingdatamysql;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
import jakarta.validation.Valid;
 
@Controller
@Validated
public class WebController implements WebMvcConfigurer {
    @Autowired
    private UserRepository userRepository;
 
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/results").setViewName("results");
    }
 
    @GetMapping("/form")
    public String showForm(Model model) {
        model.addAttribute("user", new User());
        return "form";
    }
 
    @PostMapping("/")
    public String submintForm(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "form";
        }
        userRepository.save(user);
        return "redirect:/list";
    }
 
    @GetMapping("/list")
    public String showList(Model model) {
        model.addAttribute("userList", userRepository.findAll());
        return "list";
    }
 
    @GetMapping(path = "/deleteAll")
    public String deleteAllUsers(Model model) {
        userRepository.deleteAll();
        Iterable<User> userList = userRepository.findAll();
        model.addAttribute("userList", userList);
        return "redirect:/list";
    }
 
    @GetMapping(path = "/delete/{id}")
    public String deleteUser(@PathVariable("id") Integer id, Model model) {
        userRepository.deleteById(id);
        Iterable<User> userList = userRepository.findAll();
        model.addAttribute("userList", userList);
        return "redirect:/list"; // 返回list.html模板
    }
 
    @GetMapping(path = "/edit/{id}")
    public String updateUser(@PathVariable("id") Integer id, Model model) {
        User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user ID"));
        model.addAttribute("user", user);
        return "edit";
    }
 
    @PostMapping(path = "/update")
    public String update(@Valid User user, Model model) {
        userRepository.save(user);
        Iterable<User> userList = userRepository.findAll();
        model.addAttribute("userList", userList);
        return "list";
    }
 
    @GetMapping("/find")
    public String findUserByNameAndEmail(@RequestParam("name") String name,
            @RequestParam("email") String email, Model model) {
        Iterable<User> userlist;
 
        if (!name.isEmpty() && !email.isEmpty()) {
            // 根据姓名和邮箱查询用户
            userlist = userRepository.findByNameAndEmail(name, email);
        } else if (!name.isEmpty()) {
            // 根据姓名查询用户
            userlist = userRepository.findByName(name);
        } else if (!email.isEmpty()) {
            // 根据邮箱查询用户
            userlist = userRepository.findByEmail(email);
        } else {
            // 返回所有用户
            userlist = userRepository.findAll();
        }
        model.addAttribute("userlist", userlist);
        return "check";
    }
}

这里的注释

@Valid:用于验证注释是否符合要求,例如

这里就是检验密码是否为空

@RestController
@RequestMapping("/user")
public class UserController {
    @PostMapping
    public User create (@Valid @RequestBody User user) {
        System.out.println(user.getId());
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        user.setId("1");
        return user;
    }
}    
 
public class User {
    private String id;  
 
    @NotBlank(message = "密码不能为空")
    private String password;
}

@RequestParam:将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)

//url参数中的name必须要和@RequestParam("name")一致
    @RequestMapping("show16")
    public ModelAndView test16(@RequestParam("name")String name){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("hello");
        mv.addObject("msg", "接收普通的请求参数:" + name);
        return mv;
    }

得到结果

url:localhost:8080/hello/show16?name=cc

页面:

接收普通的请求参数:cc

(五)运行AccessingDataMysqlApplication
package com.example.accessingdatamysql;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class AccessingDataMysqlApplication {
 
  public static void main(String[] args) {
    SpringApplication.run(AccessingDataMysqlApplication.class, args);
  }
}
(六)HTML页面设置

check.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
 
<head>
    <meta charset="UTF-8">
    <title>Check User List</title>
    <style>
        body {
            display: flex;
            align-items: stretch;
            height: 100vh;
            background-color: #f2f2f2;
            justify-content: space-between;
            flex-wrap: wrap;
            flex-direction: column;
            align-content: center;
        }
 
        table {
            width: 600px;
            margin-top: 20px;
            border-collapse: collapse;
            background-color: #fff;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
 
        table th,
        table td {
            padding: 10px;
            text-align: center;
            border: 1px solid #ccc;
        }
 
        table th {
            background-color: #f2f2f2;
        }
 
        a {
            display: block;
            text-align: center;
            margin-top: 20px;
            text-decoration: none;
            color: #4CAF50;
            font-weight: bold;
        }
 
        a:hover {
            color: #45a049;
        }
 
        .btn-edit,
        .btn-delete {
            display: inline-block;
            padding: 5px 10px;
            border: none;
            background-color: #4CAF50;
            color: white;
            text-decoration: none;
            cursor: pointer;
        }
 
        .btn-edit:hover,
        .btn-delete:hover {
            background-color: #45a049;
        }
    </style>
</head>
 
<body>
    <h1 style="text-align: center; margin-bottom: 20px;">Check User List</h1>
    <form th:action="@{/find}" method="get" style="text-align: center;">
        <input type="text" name="name" placeholder="姓名">
        <input type="text" name="email" placeholder="邮箱">
        <button type="submit">查询</button>
    </form>
    <table>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>操作</th>
        </tr>
        <tr th:each="user : ${userlist}">
            <td th:text="${user.name}"></td>
            <td th:text="${user.email}"></td>
            <td>
                <a th:href="@{'/edit/' + ${user.id}}" class="btn-edit">编辑</a>
                <a th:href="@{'/delete/' + ${user.id}}" class="btn-delete">删除</a>
            </td>
        </tr>
    </table>
    <a href="/form" style="text-align: center; margin-top: 20px; display: block;">添加新信息</a>
</body>
 
</html>

edit.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
 
<head>
    <meta charset="UTF-8">
    <title>Edit User</title>
    <style>
        body {
            display: flex;
            align-items: center;
            height: 100vh;
            background-color: #f2f2f2;
            flex-direction: column;
            flex-wrap: wrap;
            align-content: center;
            justify-content: center;
        }
 
        form {
            width: 400px;
            padding: 20px;
            background-color: #fff;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            text-align: center;
        }
 
        label {
            display: block;
            margin-bottom: 10px;
            font-weight: bold;
        }
 
        input {
            width: 100%;
            padding: 8px;
            margin-bottom: 20px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
 
        button {
            padding: 10px 20px;
            border: none;
            background-color: #4CAF50;
            color: white;
            text-decoration: none;
            cursor: pointer;
        }
 
        button:hover {
            background-color: #45a049;
        }
 
        a {
            display: block;
            margin-top: 20px;
            text-align: center;
            text-decoration: none;
            color: #4CAF50;
            font-weight: bold;
        }
 
        a:hover {
            color: #45a049;
        }
    </style>
</head>
 
<body>
    <h1>编辑信息</h1>
 
    <form th:action="@{/update}" method="post">
        <input type="hidden" th:name="id" th:value="${id}" />
 
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" th:value="${name}" />
 
        <label for="email">Email:</label>
        <input type="email" id="email" name="email" th:value="${email}" />
 
        <button type="submit">保存</button>
    </form>
 
    <a href="/list">返回列表</a>
</body>
 
</html>

form.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
 
<head>
    <meta charset="UTF-8">
    <title>Form</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f2f2f2;
        }
 
        .form-container {
            width: 400px;
            padding: 20px;
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
 
        .form-container h1 {
            text-align: center;
            margin-bottom: 20px;
        }
 
        .form-container label {
            display: block;
            margin-bottom: 10px;
        }
 
        .form-container input[type="text"],
        .form-container input[type="email"] {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
 
        .form-container button[type="submit"] {
            display: block;
            width: 100%;
            padding: 10px;
            margin-top: 20px;
            background-color: #4CAF50;
            color: #fff;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
 
        .form-container button[type="submit"]:hover {
            background-color: #45a049;
        }
 
        .form-container button[type="reset"] {
            display: block;
            width: 100%;
            padding: 10px;
            margin-top: 20px;
            background-color: #4CAF50;
            color: #fff;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
 
        .form-container button[type="reset"]:hover {
            background-color: #45a049;
        }
 
        .form-container button[type="delete"] {
            display: block;
            width: 100%;
            padding: 10px;
            margin-top: 20px;
            background-color: #4CAF50;
            color: #fff;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
 
        .form-container button[type="delete"]:hover {
            background-color: #45a049;
        }
 
        .form-container span {
            color: red;
            font-size: 12px;
            margin-top: 5px;
        }
    </style>
</head>
 
 
<body>
    <div class="form-container">
        <h1>表格</h1>
        <form action="#" th:action="@{/}" th:object="${user}" method="post">
            <div>
                <label for="name">Name:</label>
                <input type="text" id="name" th:field="*{name}" required>
                <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span>
            </div>
            <div>
                <label for="email">Email:</label>
                <input type="text" id="email" th:field="*{email}" required>
                <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</span>
            </div>
            <div>
                <button type="submit">Submit</button>
                <button type="reset">Reset</button>
                <button type="delete">Delete</button>
            </div>
        </form>
    </div>
</body>
 
</html>

list.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
 
<head>
    <meta charset="UTF-8">
    <title>List</title>
    <style>
        body {
            display: flex;
            align-items: stretch;
            height: 100vh;
            background-color: #f2f2f2;
            justify-content: space-between;
            flex-wrap: wrap;
            flex-direction: column;
            align-content: center;
        }
 
        table {
            width: 600px;
            margin-top: 20px;
            border-collapse: collapse;
            background-color: #fff;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
 
        table th,
        table td {
            padding: 10px;
            text-align: center;
            border: 1px solid #ccc;
        }
 
        table th {
            background-color: #f2f2f2;
        }
 
        a {
            display: block;
            text-align: center;
            margin-top: 20px;
            text-decoration: none;
            color: #4CAF50;
            font-weight: bold;
        }
 
        a:hover {
            color: #45a049;
        }
 
        .btn-edit,
        .btn-delete {
            display: inline-block;
            padding: 5px 10px;
            border: none;
            background-color: #4CAF50;
            color: white;
            text-decoration: none;
            cursor: pointer;
        }
 
        .btn-edit:hover,
        .btn-delete:hover {
            background-color: #45a049;
        }
 
        .btn-delete-all {
            display: block;
            text-align: center;
            margin-top: 20px;
            text-decoration: none;
            color: #f44336;
            font-weight: bold;
        }
 
        .btn-delete-all:hover {
            color: #d32f2f;
        }
    </style>
</head>
 
<body>
    <h1 style="text-align: center; margin-bottom: 20px;">信息系统</h1>
    <form th:action="@{/find}" method="get" style="text-align: center;">
        <input type="text" name="name" placeholder="姓名">
        <input type="text" name="email" placeholder="邮箱">
        <button type="submit">查询</button>
    </form>
    <table>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>操作</th>
        </tr>
        <tr th:each="user : ${userList}">
            <td th:text="${user.name}"></td>
            <td th:text="${user.email}"></td>
            <td>
                <a th:href="@{'/edit/' + ${user.id}}" class="btn-edit">编辑</a>
                <a th:href="@{'/delete/' + ${user.id}}" class="btn-delete">删除</a>
            </td>
        </tr>
    </table>
    <a href="/form" style="text-align: center; margin-top: 20px; display: block;">添加新信息</a>
    <a href="/deleteAll" class="btn-delete-all">删除全部用户信息</a>
</body>
 
</html>
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
11天前
|
canal 消息中间件 关系型数据库
Canal作为一款高效、可靠的数据同步工具,凭借其基于MySQL binlog的增量同步机制,在数据同步领域展现了强大的应用价值
【9月更文挑战第1天】Canal作为一款高效、可靠的数据同步工具,凭借其基于MySQL binlog的增量同步机制,在数据同步领域展现了强大的应用价值
88 4
|
19天前
|
关系型数据库 MySQL 数据库
RDS MySQL灾备服务协同解决方案构建问题之数据库备份数据的云上云下迁移如何解决
RDS MySQL灾备服务协同解决方案构建问题之数据库备份数据的云上云下迁移如何解决
|
14天前
|
SQL 存储 缓存
MySQL是如何保证数据不丢失的?
文章详细阐述了InnoDB存储引擎中Buffer Pool与DML操作的关系。在执行插入、更新或删除操作时,InnoDB为了减少磁盘I/O,会在Buffer Pool中缓存数据页进行操作,随后将更新后的“脏页”刷新至磁盘。为防止服务宕机导致数据丢失,InnoDB采用了日志先行(WAL)机制,通过将DML操作记录为Redo Log并异步刷新到磁盘,结合双写机制和合理的日志刷新策略,确保数据的持久性和一致性。尽管如此,仍需合理配置参数以平衡性能与数据安全性。
MySQL是如何保证数据不丢失的?
|
20天前
|
安全 Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+jsp实现的健身房管理系统(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和JSP技术实现的健身房管理系统。随着健康生活观念的普及,健身房成为日常锻炼的重要场所,高效管理会员信息、课程安排等变得尤为重要。该系统旨在通过简洁的操作界面帮助管理者轻松处理日常运营挑战。技术栈包括:JDK 1.8、Maven 3.6、MySQL 8.0、JSP、Shiro、Spring Boot 2.0等。系统功能覆盖登录、会员管理(如会员列表、充值管理)、教练管理、课程管理、器材管理、物品遗失管理、商品管理及信息统计等多方面。
|
18天前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的前后端分离的考试管理系统(含教程&源码&数据库数据)
在数字化时代背景下,本文详细介绍了如何使用Spring Boot框架结合Vue.js技术栈,实现一个前后端分离的考试管理系统。该系统旨在提升考试管理效率,优化用户体验,确保数据安全及可维护性。技术选型包括:Spring Boot 2.0、Vue.js 2.0、Node.js 12.14.0、MySQL 8.0、Element-UI等。系统功能涵盖登录注册、学员考试(包括查看试卷、答题、成绩查询等)、管理员功能(题库管理、试题管理、试卷管理、系统设置等)。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的前后端分离的考试管理系统(含教程&源码&数据库数据)
|
11天前
|
存储 关系型数据库 MySQL
|
11天前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
70 0
|
17天前
|
存储 前端开发 关系型数据库
Linux 技术架构:前端、后端与数据库的完美融合
【8月更文挑战第25天】本文深入剖析了Linux操作系统的技术架构,重点介绍了前端、后端及数据库三大核心组成部分。Linux前端技术不仅涵盖了图形用户界面(GUI),包括GNOME、KDE等桌面环境,还涉及HTML、CSS、JavaScript等Web前端技术及其相关框架。后端技术则聚焦于Python、Java等多种编程语言、Apache和Nginx等Web服务器以及MySQL、PostgreSQL等数据库管理系统。Linux数据库技术覆盖了关系型和非关系型数据库,如MySQL、MongoDB等,并提供了多种数据库管理工具。
39 0
|
19天前
|
SQL 关系型数据库 MySQL
mysql误删数据后,你会怎么办?
mysql误删数据后,你会怎么办?
40 0
|
21天前
|
运维 前端开发 Serverless
中后台前端开发问题之降低数据库使用门槛和运维成本如何解决
中后台前端开发问题之降低数据库使用门槛和运维成本如何解决
21 0