SpringBoot

目录

SpringBoot简介

入门案例

SpringBoot概述

基础配置

配置文件格式

yaml

多环境启动

配置文件分类

整合第三方技术

SpringBoot整合junit

SpringBoot整合mybatis

案例


SpringBoot简介

入门案例

SpringBoot 是由 Pivotal 团队提供的全新框架,
其设计目的是用来简化 Spring 应用的初始搭建以及开发过程。

回顾一下,以 SpringMVC 开发为例 

1. 创建工程,并在 pom.xml 配置文件中配置所依赖的坐标

 2. 编写 web3.0 的配置类

作为 web 程序, web3.0 的配置类不能缺少,而这个配置类还是比较麻烦的,代码如下

 3. 编写 SpringMVC 的配置类

@Configuration
@ComponentScan({"com.green.controller"})
@EnableWebMvc
public class SpringMvcConfig {
}

 4. 编写 Controller

从上面的 SpringMVC 程序开发可以看到,前三步都是在搭建环境,而且这三步基本都是固定的
SpringBoot 就是对这三步进行简化了。
接下来通过一个入门案例来体现 SpingBoot 简化 Spring 开发。

 创建新模块

选中 Web ,然后勾选 Spring  Web

 

 

注意:
1. 在创建好的工程中不需要创建配置类
2. 创建好的项目会自动生成其他的一些文件,而这些文件目前来说没有任何作用,
所以可以将这些文件删除。可以删除的目录和文件如下:
.mvn
.gitignore 
HELP.md 
mvnw 
mvnw.cmd

 创建 Controller

@RestController
@RequestMapping("/books")
public class BookController {

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println("id==>" + id);
        return "hello,spring boot!";
    }
}

启动服务器

运行 SpringBoot 工程不需要使用本地的 Tomcat 和 插件,
只运行项目 com.green包下的 Application 类,就可以在控制台看出如下信息

 

 进行测试

在启动服务器时就是执行的该类中的主方法。
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <!--指定了一个父工程,父工程中的东西在该工程中可以继承过来使用-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.green</groupId>
    <artifactId>springboot_01_quickstrart</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--该依赖就是我们在创建 SpringBoot  工程勾选的那个 Spring  Web  产生的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--单元测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--打包是需要的插件依赖-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

对比

坐标
    Spring 程序中的坐标需要自己编写,而且坐标非常多
    SpringBoot 程序中的坐标是在创建工程时进行勾选自动生成的
web3.0配置类
    Spring 程序需要自己编写这个配置类。
    SpringBoot 程序不需要自己书写
配置类
    Spring/SpringMVC 程序的配置类需要自己书写。而 SpringBoot 程序则不需要书写。
注意:基于Idea的Spring Initializr 快速构建 SpringBoot 工程时需要联网。

 官网构建工程

进入SpringBoot官网
https://spring.io/projects/spring-boot
然后点击 Spring Initializr 超链接就会跳转到如下页面

 

 

这和使用 Idea 快速构建 SpringBoot 工程的界面基本相同。在上面页面输入对应的信息

 选择依赖

选择 Spring  Web 可以点击上图右上角的 ADD  DEPENDENCIES...  CTRL  +  B 按钮,就会出现如下界面

 生成工程

在页面的最下方点击 GENERATE  CTRL  +  回车 按钮生成工程并下载到本地,如下图所示

打开下载好的压缩包可以看到工程结构和使用 Idea 生成的一模一样,如下图

 

 SpringBoot工程快速启动

问题导入

前端开发人员协同开发,而前端开发人员需要测试前端程序就需要后端开启服务器,
这就受制于后端开发人员。为了摆脱这个受制,前端开发人员尝试着在自己电脑上安装 Tomcat 和 Idea ,
在自己电脑上启动后端程序,这显然不现实。

后端可以将 SpringBoot 工程打成 jar 包,该 jar 包运行不依赖于 Tomcat 和 Idea 这些工具
也可以正常运行,只是这个 jar 包在运行过程中连接和我们自己程序相同的 Mysql 数据库即可。
这样就可以解决这个问题,如下图

 

 现在问题是如何打包呢?

打包

由于在构建 SpringBoot 工程时已经在 pom.xml 中配置了如下插件
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
所以只需要使用 Maven 的 package 指令打包就会在 target 目录下生成对应的 Jar 包。
注意:该插件必须配置,不然打好的 jar 包也是有问题的。

启动

进入 jar 包所在位置,在 命令提示符 中输入如下命令
java -jar springboot_01_quickstart-0.0.1-SNAPSHOT.jar
执行上述命令就可以看到 SpringBoot 运行的日志信息

SpringBoot概述

原始 Spring 环境搭建和开发存在以下问题:
    配置繁琐
    依赖设置繁琐
SpringBoot 程序优点恰巧就是针对 Spring 的缺点
    自动配置。这个是用来解决 Spring 程序配置繁琐的问题
    起步依赖。这个是用来解决 Spring 程序依赖设置繁琐的问题
    辅助功能(内置服务器,...)。在启动 SpringBoot 程序时既没有使用本地的 tomcat 
    也没有使用 tomcat 插件,而是使用 SpringBoot 内置的服务器。

起步依赖

 探索父工程

从上面的文件中可以看到指定了一个父工程,进入到父工程,发现父工程中又指定了一个父工程,如下图所示

再进入到该父工程中,在该工程中可以看到配置内容结构如下图所示

 

上图中的 properties 标签中定义了各个技术软件依赖的版本,
避免了在使用不同软件技术时考虑版本的兼容问题
dependencyManagement 标签是进行依赖版本锁定,但是并没有导入对应的依赖;
如果工程需要那个依赖只需要引入依赖的 groupid 和 artifactId 不需要定义 version 。

 探索依赖

进入到该依赖,查看 pom.xml 的依赖会发现它引入了如下的依赖

 

里面的引入了 spring-web 和 spring-webmvc 的依赖
而依赖spring-boot-starter-tomcat ,从名字基本能确认内部依赖了tomcat ,所以工程才能正常启动

 结论:以后需要使用技术,只需要引入该技术对应的起步依赖即可

starter
    SpringBoot 中常见项目名称,定义了当前项目使用的所有项目坐标,以达到减少依赖配置的目的
parent
    所有 SpringBoot 项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),
    以达到减少依赖冲突的目的spring-boot-starter-parent (2.5.0)与 
    spring-boot-starter-parent (2.4.6)共计57处坐标版本不同
实际开发
    使用任意坐标时,仅书写GAV中的G和A,V由SpringBoot提供
    G:groupid 
    A:artifactId 
    V:version
如发生坐标错误,再指定version(要小心版本冲突)

程序启动

创建的每一个 SpringBoot 程序时都包含一个类似于下面的类,将这个类称作引导类
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
注意:
SpringBoot 在创建项目时,采用jar的打包方式
SpringBoot 的引导类是项目的入口,运行 main 方法就可以启动项目

 切换web服务器

现在启动工程使用的是 tomcat 服务器,那能不能不使用 tomcat 而使用 jetty 服务器, 
而要切换 web 服务器就需要将默认的 tomcat 服务器给排除掉,怎么排除呢?
使用exclusion 标签
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>
引入 jetty 服务器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

基础配置

配置文件格式

现在启动服务器默认的端口号是 8080 ,访问路径可以书写为
http://localhost:8080/books/1
在线上环境希望将端口号改为 80 ,这样在访问的时候就可以不写端口号了,如下
http://localhost/books/1
而 SpringBoot 程序如何修改呢? SpringBoot 提供了多种属性配置方式
application.properties
server.port=80
application.yml
server: port: 81
application.yaml
server: port: 82
注意: SpringBoot 程序的配置文件名必须是 application ,只是后缀名不同而已。

环境准备

 注意:在配合文件中如果没有提示,可以使用一下方式解决

 

 三种配合文件的优先级

 application.properties > application.yml > application.yaml

yaml

YAML(YAML Ain't Markup Language),一种数据序列化格式。
xml 格式如下:
<enterprise>
    <name>zhansan</name>
    <age>16</age>
</enterprise>

properties 类型的配置文件如下:
enterprise.name=zhansan
enterprise.age=16 

yaml 类型的配置文件内容如下:
enterprise: 
    name: zhansan
    age: 16
优点:
容易阅读
yaml 类型的配置文件比 xml 类型的配置文件更容易阅读,结构更加清晰
容易与脚本语言交互
以数据为核心,重数据轻格式
yaml 更注重数据,而 xml 更注重格式
YAML 文件扩展名:
.yml (主流)
.yaml

语法规则
大小写敏感
属性层级关系使用多行描述,每行结尾使用冒号结束
使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
空格的个数并不重要,只要保证同层级的左侧对齐即可。
属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
# 表示注释
核心规则:数据前面要加空格与冒号隔开
数组数据在数据书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔,例如
enterprise: 
    name: zhansan
    age: 16
    subject:
        - Java
        - 前端
        -  大数据

 yaml配置文件数据读取

环境准备

在 com.green.controller 包写创建名为 BookController 的控制器,内容如下
@RestController @RequestMapping("/books") 
public class BookController {

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id){
        System.out.println("id ==> "+id);
        return "hello , spring boot!"; 
    }
}

在 com.green.domain 包下创建一个名为Enterprise 的实体类等会用来封装数据,内容如下

@Component
@ConfigurationProperties(prefix = "enterprise")
public class Enterprise {
    private String name;
    private Integer age;
    private String tel;
    private String[] subject;
//setter and getter

//toString 
}
在 resources 下创建一个名为 application.yml 的配置文件,里面配置了不同的数据,内容如下
lesson: SpringBoot

server:
  port: 80

enterprise:
  name: zhansan
  age: 20
  tel: 888888
  subject:
    - java
    - mysql
    - 大数据

 读取配置数据

使用 @Value注解

使用 @Value("表达式") 注解可以从配合文件中读取数据,
注解中用于读取属性名引用方式是: ${一级属性名.二级属性名..}
Environment对象
上面方式读取到的数据特别零散, SpringBoot 还可以使用 @Autowired 注解注入 
Environment 对象的方式读取数据
这种方式 SpringBoot 会将配置文件中所有的数据封装到 Environment 对象中,
如果需要使用哪个数据只需要通过调用Environment对象的getProperty(String name)方法获取

@RestController
@RequestMapping("/books")
public class BookController {

    //读取yaml文件中的信息
    @Value("${lesson}")
    private String lesson;

    @Value("${server.port}")
    private Integer port;

    @Value("${enterprise.subject[0]}")
    private String subject_00;

    @Autowired
    private Environment environment;

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println(lesson);
        System.out.println(port);
        System.out.println(subject_00);
        System.out.println("------------------");
        System.out.println(environment.getProperty("lesson"));
        System.out.println(environment.getProperty("server.port"));
        System.out.println(environment.getProperty("enterprise.subject[2]"));
        return "hello,spring boot!";
    }
}

自定义对象

将实体类 bean 的创建交给 Spring 管理。
在类上添加 @Component 注解
使用 @ConfigurationProperties 注解表示加载配置文件
在该注解中也可以使用 prefix 属性指定只加载指定前缀的数据
在 BookController 中进行注入
@RestController
@RequestMapping("/books")
public class BookController {

    //读取yaml文件中的信息
    @Value("${lesson}")
    private String lesson;

    @Value("${server.port}")
    private Integer port;

    @Value("${enterprise.subject[0]}")
    private String subject_00;

    @Autowired
    private Environment environment;

    @Autowired
    private Enterprise enterprise;

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println(lesson);
        System.out.println(port);
        System.out.println(subject_00);
        System.out.println("------------------");
        System.out.println(environment.getProperty("lesson"));
        System.out.println(environment.getProperty("server.port"));
        System.out.println(environment.getProperty("enterprise.subject[2]"));
        System.out.println("------------------");
        System.out.println(enterprise);
        return "hello,spring boot!";
    }
}

注意:

使用第三种方式,在实体类上有如下警告提示

这个警告提示解决是在 pom.xml 中添加如下依赖即可
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

多环境启动

 yaml文件

在 application.yml 中使用 --- 来分割不同的配置,内容如下
#设置启动的环境
spring:
  profiles:
    active: test

---
#开发
spring:
  config:
    activate:
      on-profile: dev
server:
  port: 80

---

#生产
spring:
  profiles: pro
server:
   port: 81

---
#测试
spring:
  profiles: test
server:
   port: 82

properties文件

properties 类型的配置文件配置多环境需要定义不同的配置文件
    application-dev.properties 是开发环境的配置文件,在该文件中配置端口号为 80
        server.port=80
    application-test.properties 是测试环境的配置文件。在该文件中配置端口号为 81
        server.port=81
    application-pro.properties 是生产环境的配置文件。在该文件中配置端口号为 82
        server.port=82
SpringBoot 只会默认加载名为 application.properties 的配置文件,
所以需要在 application.properties 配置文件中设置启用哪个配置文件,配置如下:
    spring.profiles.active=pro

 命令行启动参数设置

SpringBoot 开发的程序以后都是打成 jar 包,通过 java  -jar  xxx.jar 的方式启动服务的。
那么就存在一个问题,如何切换环境呢?因为配置文件打到的jar包中了。
SpringBoot 提供了在运行 jar 时设置开启指定的环境的方式,如下
    java –jar xxx.jar –-spring.profiles.active=test
那么这种方式能不能临时修改端口号呢?也是可以的,可以通过如下方式
    java –jar xxx.jar –-server.port=88
当然也可以同时设置多个配置,比如即指定启用哪个环境配置,又临时指定端口,如下
    java –jar springboot.jar –-server.port=88 –-spring.profiles.active=test
如果使用了多种方式配合同一个配置项,优先级高的生效。

配置文件分类

开发完毕后需要测试人员进行测试,由于测试环境和开发环境的很多配置都不相同,
所以测试人员在运行我们的工程时需要临时修改很多配置,如下
java –jar springboot.jar –-spring.profiles.active=test --server.port=85 
-- server.servlet.context-path=/heima --server.tomcat.connection-timeout=-1 .. .. .. .. ..
针对这种情况, SpringBoot 定义了配置文件不同的放置的位置;而放在不同位置的优先级时不同的。
SpringBoot 中4级配置文件放置位置:
1级:classpath:application.yml
2级:classpath:config/application.yml 
3级:file :application.yml
4级:file :config/application.yml
说明:级别越高优先级越高

整合第三方技术

SpringBoot整合junit

回顾 Spring 整合 junit

使用 @RunWith 注解指定运行器,使用 @ContextConfiguration 注解来指定配置类或者配置文件。
而 SpringBoot 整合junit 特别简单,分为以下三步完成

在测试类上添加 SpringBootTest 注解
使用 @Autowired 注入要测试的资源
定义测试方法进行测试

 环境准备

创建接口
public interface BookService {
    void save();
}

创建实现类
@Service
public class BookServiceImpl implements BookService {
    @Override
    public void save() {
        System.out.println("book service running...");
    }
}

 编写测试类

@SpringBootTest
class Springboot05TestApplicationTests {

    @Autowired
    private BookService bookService;

    @Test
    void contextLoads() {
        bookService.save();
    }
}
注意:这里的引导类所在包必须是测试类所在包及其子包。
例如:
引导类所在包是 com.green
测试类所在包是 com.green

如果不满足这个要求的话,就需要在使用 @SpringBootTest 注解时,
使用 classes 属性指定引导类的字节码对象。如
@SpringBootTest(classes = Springboot05TestApplication.class)

SpringBoot整合mybatis

回顾Spring整合Mybatis

Spring 整合 Mybatis 需要定义很多配置类
SpringConfig 配置类
    导入 JdbcConfig 配置类
    导入 MybatisConfig 配置类
@Configuration @ComponentScan("com.green")
@PropertySource("classpath:jdbc.properties") 
@Import({JdbcConfig.class,MyBatisConfig.class}) 
public class SpringConfig {
}
JdbcConfig 配置类
定义数据源(加载properties配置项:driver、url、username、password)
public class JdbcConfig {
    @Value("${jdbc.driver}") 
    private String driver;
    @Value("${jdbc.url}") 
    private String url;
    @Value("${jdbc.username}") 
    private String userName;
    @Value("${jdbc.password}") 
    private String password;

    @Bean
    public DataSource getDataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password); 
        return ds;
    }
}
MybatisConfig 配置类
    定义 SqlSessionFactoryBean
    定义映射配置
    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.green.dao");
        return msc;
    }


    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.green.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

 SpringBoot整合mybatis

创建新模块,选择 Spring Initializr ,并配置模块相关基础信息
选择当前模块需要使用的技术集(MyBatis、MySQL)

 定义实体类

在 com.green.domain 包下定义实体类 Book ,内容如下
public class Book { 
    private Integer id; 
    private String name; 
    private String type;
    private String description;
    //setter and   getter
    //toString 
}

定义dao接口

在 com.green.dao 包下定义 BookDao 接口,内容如下
public interface BookDao {
    @Select("select * from tbl_book where id = #{id}") 
    public Book getById(Integer id);
}

定义测试类

在 test/java 下定义包 com.green,在该包下测试类,内容如下
@SpringBootTest
class Springboot08MybatisApplicationTests {

    @Autowired
    private BookDao bookDao;

    @Test
    void testGetById() {
        Book book = bookDao.getById(1); 
        System.out.println(book);
    }
}

编写配置

在 application.yml 配置文件中配置如下内容
spring: 
    datasource:
        driver-class-name: com.mysql.jdbc.Driver 
        url: jdbc:mysql://localhost:3306/ssm_db 
        username: root
        password: root

测试

运行测试方法,会看到如下错误信息

错误信息显示在 Spring 容器中没有 BookDao 类型的 bean 。为什么会出现这种情况呢?

原因是 Mybatis 会扫描接口并创建接口的代码对象交给 Spring 管理,
但是现在并没有告诉 Mybatis 哪个是 dao 接口。
而要解决这个问题需要在 BookDao 接口上使用 @Mapper , BookDao 接口改进为
@Mapper
public interface BookDao {
    @Select("select * from tbl_book where id = #{id}") 
    public Book getById(Integer id);
}
注意:
SpringBoot 版本低于2.4.3(不含),Mysql驱动版本大于8.0时,需要在url连接串中配置时区
jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC ,或在MySQL数据库端配置时区解决此问题

使用Druid数据源

现在并没有指定数据源, SpringBoot 有默认的数据源,也可以指定使用 Druid 数据源,
按照以下步骤实现
导入 Druid 依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>
在 application.yml 配置文件配置
可以通过 spring.datasource.type 来配置使用什么数据源。配置文件内容可以改进为
spring: 
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC 
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource

案例

1. pom.xml
    配置起步依赖,必要的资源坐标(druid)
2. application.yml
    设置数据源、端口等
3. 配置类
    全部删除
4. dao
    设置@Mapper
5. 测试类
6. 页面
    放置在resources目录下的static目录中

创建工程

创建 SpringBoot 工程,在创建工程时需要勾选 web 、 mysql 、 mybatis ,工程目录结构如下

由于工程中使用到了 Druid ,所以需要导入 Druid 的坐标
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>
在 application.yml 配置文件配置
可以通过 spring.datasource.type 来配置使用什么数据源。配置文件内容可以改进为
server:
  port: 80

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db1
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
BookServiceTest 测试需要改成 SpringBoot 整合 junit 的
@SpringBootTest
public class BookServiceTest {

    @Autowired
    private BookService bookService;

    @Test
    public void testGetById() {
        Book book = bookService.getById(1);
        System.out.println(book);
    }

    @Test
    public void testGetAll() {
        List<Book> books = bookService.getAll();
        System.out.println(books);
    }
}

静态资源

在 SpringBoot 程序中是没有 webapp 目录的,那么在 SpringBoot 程序中静态资源需要放在什么位置呢?
静态资源需要放在 resources 下的 static 下
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值