spring boot 入门 学习记录

一、spring boot 入门

1、环境搭建

1.1 、jdk1.8
1.2 maven3.39
1.3 idea 2017 x64
1.4 springboot

2、 创建工程与测试

2.1 创建maven工程

项目目录结构

[外链图片转存失败(img-iKejUGaR-1565936411964)(E:\markdowm\image\1535696891649.png)]

####2.2 导入springboot依赖

springboot 父项目工程依赖

 <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.12.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

引入springboot web

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
2.3 创建springboot 启动程序

在项目的包的根目录下创建springboot的启动程序,@SpringBootApplication 标注 这个是个springboot 程序。

/**
 *  @SpringBootApplication 标注 这个是个springboot 程序
 *
 */
@SpringBootApplication
public class Springbootmain {

    public static void main(String[] args) {

        SpringApplication.run(Springbootmain.class,args);
}

在这个配置类中,@SpringBootApplication: springboot 配置类

标注在某个类上,表是这个是一个springboot 的配置类;

  @configuration: 配置类上标注这个注解;

   		配置类---配置文件;配置类也是容器的一个组件;@Component

@EnableAutoConfiguration: 开启自动配置功能

	以前我们需要配置的东西,spring boot 帮我们自动配置
@AutoConfigurationPackage 自动配置包

@AutoConfigurationPackage将主配置类,(@SpringBootApplication 标注的类)的所在包及下面所有的种子包里面的组件扫描到spring容器;

**EnableAutoConfigurationImportSelector**:导入哪些组件的选择器;

将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;容器中添加很多自动配置类(xxxAutoConfiguration);就是这个容器中导入场景中所需要使用组件。


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

有了自动配置类,免去了我们手动的配置注入功能组件等功能;

springboot在动动的时候,从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效了,帮我们进行了自动配置以前我们需要自己配置的东西,自动配置类做了。

J2EE的整体整合解决方案和自动配置都在:spring-boot-autoconfigure-1.5.12.RELEASE.jar;

2.5 测试程序编写

创建controller 包,项目

创建helloController.java文件

package com.liu.spring.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;

/**
 * @RestController
 * 这个注解代表 rest  和controller
 *
 */
@RestController
public class HelloController {
    /**
     *  @GetMapping 注解路径 url 访问只能使用get的方式请求
     *
     * @return
     */
    @GetMapping("/hello")
     public Map<String,String>  hello(){
        Map<String,String> result = new HashMap<String, String>();
        result.put("msg","hello world!!");
         return result;
     }
}


2.6 测试程序

运行springboot main程序 进行项目启动

[外链图片转存失败(img-zig47hpE-1565936411965)(E:\markdowm\image\1535696734245.png)]

2.7 使用postman测试

这里测试的时候 注意,使用get 请求进行测试,要不然会报错,拒绝请求,这样就得到了我们想要的结果

[外链图片转存失败(img-IfE9MB15-1565936411966)(E:\markdowm\image\1535697295788.png)]

2.8 springboot 打包部署
2.8.1 springboot 打包

引入maven打包插件

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
2.8.2 maven 工具打包

使用maven lifecycle 下面的package的打包工具

[外链图片转存失败(img-MjCTsfqV-1565936411966)(E:\markdowm\image\1535697500758.png)]

2.8.3 启动项目

通过java -jar springboot-1.0-SNAPSHOT.jar 的方式进行项目的部署,注意看tomcat启动的端口为8080

e:\work>java -jar springboot-1.0-SNAPSHOT.jar

 此处省略N 多的启动日志
2018-08-31 14:40:48.726  INFO 38760 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s):
 8080 (http)
2018-08-31 14:40:48.734  INFO 38760 --- [           main] com.liu.spring.Springbootmain            : Started Springbootmain in
6.357 seconds (JVM running for 7.618)

3、springboot-start

springboot 通过start 来将各个场景的jar包进行项目导入工作,我们只要关注业务场景即可,无需过多的去关注jar包的导入,只需要选取场景即可。

二、spring boot配置

1 、快速创建springboot工程

IDE都支持使用springInitailer 工具来快速创建springboot工程

选择我们需要的模块,想到会联网创建springboot的项目工程

1.1、目录结构

默认生成springboot项目;

[外链图片转存失败(img-A1H1JVbS-1565936411967)(E:\markdowm\image\1535702087253.png)]

  • 主程序已经生成好了,我们需要实现自己的业务逻辑
  • resources文件夹中的目录结构
    • static 保存所有的静态资源 ;js css images ;
    • templates: 保存所有的模板页面;(springboot 默认jar包使用嵌入式的tomcat,默认不支持jsp页面);可以使用模板引擎,freemarker 、thymeleaf;
    • application.properties :springboot 应用的配置文件;可以修改一些默认配置的参数;

2 、配置文件

2.1 整体配置

springboot 使用一个全局的配置文件,配置文件名称是固定的;

application.properties

appication.yml

配置文件的作用,修改springboot的自动配置的默认值;springboot在底层都个我们自动配置好。

以前的配置文件一般为xml格式

yaml :以数据为中心,比json、xml更加简洁

2.2 YAML语法
2.2.1 基本语法

K: 空格v: 表示一对键值对 (空格必须要有)

空格的缩进方式来控制层级关系;只要是左对齐的一列数据都是同一个层级的

server:
  context-path: /springboot
  port: 8090

属性和值也是大小敏感;

2.2.2 值的写法
字面量:普通的值(数值,字符串,布尔)
字符串默认不用加上单引号或者单引号

“” :双引号 ;不会转义字符串联的特殊字符;特殊字符会作为本身的意思

‘’:单引号 ;会转义特殊的字符,特殊字符串会当做字符串输出
对象、map(属性和值)

k:v 在下一行来写对象的属性和值;注意缩进

表示一个对象的书写格式    
user:
  name: zhangsan 
  age: 10
  sort: 100
  money: 2000 

行内写法:

user: { name: "zhangsan",age:10,sort: 100,money: 2000}
数组(list、set)

用-值表示数组中的一个元素

pets:
  - cat
  - dog
  - pig

行内写法:

pets: [cat,dog,pig]

3 配置文件值注入

配置文件:

user:
  lastName: zhangsan
  age: 10
  boss: false
  brithday: 2018/10/01
  maps: {k1: v1,k2: 12}
  list:
    - lisi
    - zhangsan
    - wangwu
  dog:
    name: 小王
    age: 2

实体文件:

package com.liu.bootquick.bean;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * @ConfigurationProperties 配置文件属性和该类的属性相关,进行绑定
 * @Data lombok 生成getset 等方法
 * 只有这个组件是容器中的组件,容器才能提供服务
 */
@Data
@Component
@ConfigurationProperties(prefix = "user")
public class User {
    private String lastName;
    private Integer age;
    private Boolean boss;
    private Date brithday;
    private Map<String,Object> maps;
    private List<Object> list;
    private Dog dog;

}

package com.liu.bootquick.bean;

import lombok.Data;

@Data
public class Dog {

    private String name;

    private Integer age;
}

我们还需要配置文件处理器,配置文件绑定的时候有提示:

<!--导入配置文件处理器-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
3.1 properties的中文乱码问题解决

​ 在idea中,配置文件的默认编码为utf-8,但是在运行的时候默认为ascii码,所以在设置的时候 需要把配置文件的编码更改为utf8,运行时勾选上转换成ascii。

[外链图片转存失败(img-b3I99NXA-1565936411967)(E:\markdowm\image\1537343457248.png)]

3.2 @configurationProperties 和@Value获取值的区别
功能@configurationProperties@Value
基本功能批量注入配置文件中的属性一个个指定
松散绑定(松散语法)支持不支持
spEl不支持支持
JSR303支持不支持
复杂类型封装支持不支持

总结:如果是为了 注入一个对象,或者对象类型复杂,或者做一些数据校验的时候,需要使用@configurationproperties,

如果是使用单独项或者,简单的类型,且不需要校验可以使用@value

@configurationProperties 全局的配置文件

3.3 注入值数据校验
@Data
@Component
@ConfigurationProperties(prefix = "user")
@Validated
public class User {


    @Email
    private String lastName;

    private Integer age;

    private Boolean boss;

    private Date brithday;

    private Map<String,Object> maps;

    private List<Object> list;

    private Dog dog;
}

报错:
    Property: user.lastName
    Value: 李四
    Origin: class path resource [application.properties]:6:16
    Reason: 不是一个合法的电子邮件地址


3.4 @propertiesSource 、@ImportResource @Bean

@propertiesSource 可以加载自定义的配置文件,可以加载多个。使用数组的方式加载 classpath:

//实例中是配置多个配置文件 单个的就不多说了
@PropertySource({
                  "classpath:person.properties""classpath:user.properties"
                })

实体类:
@Data
@Component
@ConfigurationProperties(prefix = "user")
@PropertySource({"classpath:person.properties"})
//@Validated
public class User {


  //  @Email
    private String lastName;

    private Integer age;

    private Boolean boss;

    private Date brithday;

    private Map<String,Object> maps;

    private List<Object> list;

    private Dog dog;
}


配置文件:person.properties
user.age=10
user.boss=true
user.brithday=2017/10/10
user.dog.name=张三
user.dog.age=10
user.last-name=李四
user.list=a,b,c
user.maps.k1=v1
user.maps.k2=v2


@ImportResource 导入spring的配置文件,让配置文件的内容生效。我们自己写的配置文件也不能被自动识别,想让我们的spring的配置文件生效,加载进来,我们需要将这个注解加载到主程序上面

package com.liu.bootquick;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
//将beans 注入到spring容器中
@ImportResource(locations={"classpath:beans.xml"})
public class BootQuickApplication {

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

//  配置文件: beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
      <bean id="helloService" class="com.liu.bootquick.service.HellwordService"/>
  
</beans>



springboot推荐给容器中添加组件的方式:推荐使用全注解的方式添加组件

1、配置类 =====spring配置文件

package com.liu.bootquick.config;

import com.liu.bootquick.service.HellwordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 *
 * @Configuration 指明当前类是一个配置类,就是来代替之前的spring的配置文件
 * @Bean 配置文件中来添加组件
 * *
 */
@Configuration
@Slf4j
public class MyConfig {
//    该方法的返回值就是添加到容器中的组件,
//     该方法的名称为该组件在容器中的默认的id
//    springboot推荐使用该方式进行初始化组件
    @Bean
    public HellwordService helloService(){
        log.info("向springboot 容器中添加helloService 组件");
        return  new HellwordService();
    }
}

4 占位符

随机数

${random.init}配置文件中可以用占位符

${random.uuid}配置文件可以用占位符

占位符获取之前配置的值,如果没有可以用:指定默认值

${person.hello:hello} 如果获取的值为空,则表达式取值为hello

5 profile

5.1 多profile文件

我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties

默认使用的是application.properties的配置

5.2 yml 支持多文档块方式
spring:
    activemq:
      broker-url: tcp://192.168.0.143:61616
      in-memory: true
      pool:
        enabled: false
      user: admin
      password: admin
    profiles:
      active: dev

---

#开发环境
spring:
  profiles: dev 


---
#生成环境
spring:
  profiles: prod
5.3 激活指定profile

方法一:

spring.profiles.active= dev

方法二 :

在打成jar后 使用java -jar xxxx.jar --spring.profiles.active=dev

[外链图片转存失败(img-5MX9v65L-1565936411968)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1537422576002.png)]

方法三 :

虚拟机参数设定: -Dspring.profiles.active=dev

[外链图片转存失败(img-gWJ8JRhw-1565936411968)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1537422855028.png)]

6 配置文件的加载位置:

在配置文件的存放位置是有优先级的,

1、file/config

2、file

3、classpath/config

4、classpath

以上是按照优先级从高到低的顺序,所有的文件的文件都会被加载,***高优先级配置***内容会***覆盖低优先级配置***内容。

低优先级的配置可以和高优先级的配置文件形成互补配置,这样就可以使用合集来配置springboot

在项目已经打包的情况下,我们可以使用命令的方式给项目指定配置文件来启动项目,如:

注意:这里的配置文件会和原有的配置文件形成互补配置,默认优先级最高

java -jar xxx.jar --spring.config.location=g:\application.properties

7 外部配置加载顺序

总结:

1、由jar包外向jar包内进行寻找,优先加载带profile的,再来加载不带profile

2、命令行的参数 优先级最高

8 自动配置原理

配置文件配置的属性参考

自动配置原理

1)springboot启动的时候加载了主配置类,开启了自动配置功能

精髓:

1) springboot启动时候会加载大量的自动配置类

2)我们看到我们需要功能有没有springboot默认写好的自动配置类

3)我们再来看这个自动配置类到底配置了哪些组件

4)给容器中自动配置类的时候,会自动从properties中获取某些属性,我们就可以在配置文件中指定这些属性。

自动配置类在一定条件下才能生效

开启springboot debug 模式,来让控制台打印自动配置报告,这样我们就可以很方便指定哪些自动配置类生效

debug =true 

============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:(自动配置匹配)
-----------------

   ActiveMQAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
     


Negative matches:(自动配置未匹配)
-----------------

   ActiveMQConnectionFactoryConfiguration.PooledConnectionFactoryConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.apache.activemq.pool.PooledConnectionFactory' (OnClassCondition)


三、springboot日志

1、日志框架

日志门面:SLF4J

日志实现: logback

springboot:底层是spring框架,spring框架默认是用jcl

springboot 选用SLF4j 和logback

2 、slf4j使用

2.1 如何在系统中使用SLF4J

以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,二是电泳日志抽象层里面的方法

给系统里面导入slf4j的jar和logback的实现jar


package com.liu.bootquick.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Hello {

    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(Hello.class);
        logger.info("slf4j");
    }
}




可以通过下图可以很方便的来配置日志:

[外链图片转存失败(img-8RJmmJRC-1565936411969)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1537489807553.png)]

每一个日志实现框架都有自己的配置文件,使用slf4j以后,配置文件还是做成日志是想框架自己本身的配置文件

2.2 日志遗留问题

slf4j +logback : spring(commons-logging) 、hibernate(jboss-logging)。。。。

在依赖其他框架的时候,其他框架 底层可能依赖于其他的日志框架。通过下图可以解决日志的统一的方案;

统一日志记录,及时使用别的框架和我一起统一使用

[外链图片转存失败(img-13bkJr9q-1565936411970)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1537489748744.png)]

如何用系统中的日志都统一到SLF4J

1、将系统中的其他日志框架先排除出去;

2、用中间包来替换换原来的日志框架

3、我们到如slf4j其他的实现

#springboot 处理日志的依赖关系  ,将其他几种日志的转换成slf4j 日志框架 并提供实现
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
      <version>2.0.4.RELEASE</version>
      <scope>compile</scope>
    </dependency>

[外链图片转存失败(img-jtoe9Egq-1565936411971)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1537491900569.png)]

总结:

springboot底层也是使用slf4j+logback的凡是进行日志记录;

springboot 也吧其他的日志替换成了slf4j;

在使用替换包的时候,虽然是名称相同, 但是在底层实现的时候,已经被改成了 slf4j 的工厂

//JUL

    public static void install() {
        LogManager.getLogManager().getLogger("")
                          .addHandler(new SLF4JBridgeHandler());
    }
//log4j

public class SLF4JLoggerContextFactory implements LoggerContextFactory {
    private static final StatusLogger LOGGER = StatusLogger.getLogger();


          

排除commons-logging

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

springboot 能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他的框架的时候,只需要把这个日志框架的日志框架排除掉。

4 日志使用:

4.1 日志的配置
#指定日志级别
logging.level.com.liu=debug 
#不指定全路径,则表示在当前工程路劲下,如果指定则 就在指定的目录
logging.file=boot.log 
  
  #在当前磁盘路径下创建spring/logs日志目录,使用spring.log 作为默认的文件名
logging.path=/spring/logs
#控制台的日志格式
logging.pattern.console=
#文件的日志格式输出
logging.pattern.file=  
  

日志文件格式化的参数详解:

%m输出代码中指定的消息
%p输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r输出自应用启动到输出该log信息耗费的毫秒数
%c输出所属的类目,通常就是所在类的全名
%t输出产生该日志事件的线程名
%n输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
%d输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%l输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
4.2 指定日志文件

不同的日志系统:使用的默认配置文件

Logging SystemCustomization
Logbacklogback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging)logging.properties

logback.xml: 会直接被日志框架识别,会跳过spring

logback-spring.xml : 会先被springboot 来识别并配置,可以使用高级特性,可以使用boot的标签,来使用

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev, staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

5 切换日志

可以按照slf4j 的日志是配图,进行相关的切换.可以右键进行排除jar包,然后倒入新的jar包就可以了

具体可以参照上面的日志图,来切换日志;

starter-log4j2 就可以完成日志的切换

四 、springboot 与web开发

1、使用springboot

1)创建springboot应用,选中我们需要的模块;

2)springboot已经默认帮我们将这些场景配置好了;我们只需要再配置文件中指定少量的配置文件,就可以运行起来了。

2、springboot对静态资源的映射

  • /** 访问当项目的任何资源,都去静态资源文件夹找映射

    classpath:/META-INF/resources/

    classpath:/resources/

    classpath:/static/

    classpath:/public/

  • 欢迎页面;静态资源文件夹下面所有的index.html 页面;被/**映射

  • 所有的**/favicon.ico 都是在静态资源文件下找;

3 模板引擎

jsp、velocity、freemark、thymeleaf

[外链图片转存失败(img-dSpuyZy1-1565936411971)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1537503836331.png)]

springboot 推荐使用Thymeleaf

3.1 thymeleaf 的引入
	
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

六 springboot 与数据访问

1、jdbc

springboot 基础jar包 来支持 jdbc操作


	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>




yml 配置

spring:
  datasource:
    username: root
    password: Root123
    url: jdbc:mysql://127.0.0.1:3306/springboot
    driver-class-name: com.mysql.jdbc.Driver
    
  	<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>druid</artifactId>
		    <version>1.1.8</version>
</dependency>
  配置阿里的数据源
   spring:
      datasource:
        username: root
        password: Root123
        url: jdbc:mysql://127.0.0.1:3306/springboot
        driver-class-name: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值