SpringBoot——配置文件

1.配置文件

SpringBoot使用一个全局的配置文件,配置文件名是固定的:

  • application.properties
  • application.yml

配置文件的作用是修改SpringBoot自动配置的默认值,这些值SpringBoot都在底层帮我们设置好。

那什么是yml文件?

YAML( YAML Ain't Markup Language) :

  • YAML A Markup Language 是一个标记语言
  • YAML isn't  Markup Language 不是一个标记语言。

以前的配置文件,大多是使用xxx.xml文件。YAML是以数据为中心,比json,xml文件。配置例子如下:

server:
  prot:8081

2.YAML语法

2.1 基本语法

k:(空格)v:表示一对键值对(空格必须有)。以空格的缩进来控制层级关系;只要左对齐的一列数据,都是同一层级的。

属性和值的大小写敏感

2.2 值的写法

2.2.1 字面量:普通的值(数字,字符串,布尔)

字符串默认不用加上单引号或者双引号。

"":双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思。

'':单引号,会转义特殊字符,特殊字符最终只是一个普通的字符串数据。

2.2.2 对象,Map(属性和值)(键值对)

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

对象还是k: v的方式

friends:
         lastname:zhangsan 
         age:20

比较专业的写法:

friend:{lastname:张三,age:18}

2.2.3 数组(List,Set)

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

pets:
  -cat
  -dog
  -pig

比较专业的写法

pets:[cat,dog,pig]

三.配置文件值注入

3.1 例子

配置文件:

person:
  lastName: hello
  age: 18
  boss: false
  maps: {k1: v1,k2: 12}
  lists:
    -lisi
    -zhaoliu

JavaBean:

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:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
    prefix="person" :配置文件中的哪个的所有属性进行一一映射

    只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties的功能
 */

@Component
@ConfigurationProperties(prefix = "person")
public class Person {

    private String lastName;
    private Integer age;
    private Boolean boss;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
}

导入配置文件处理器,配置文件进行绑定就会有提示:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

测试类(在test包下):一定要注意这个@Test注解是Junit下的,然后将类名和方法名加public。

import com.test.demo.bean.Person;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/*
SpringBoot的单元测试
可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

    @Autowired(required = false)
   Person person;
    @Test
   public void contextLoads() {
        System.out.println(person);
    }

}

输出如下:

如果使用的是SpringBoot 2.2.6版本的,要将pom文件中的exclusion配置去掉。

3.2 properties配置文件在idea中默认utf-8可能会乱码,调整如下

3.3 注释

3.3.1 @Value获取值和@ConfigurationProperties获取值进行比较

@Value的使用:

@Component
public class Person {

    @Value("${person.last-name")
    private String lastName;
    @Value("#{11*2}")
    private Integer age;
    ...
}

区别:

 @ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散绑定(驼峰式,下划线,横短线)支持不支持
SpEL不支持支持
JSR303数据校验(@Validate)支持不支持
复杂类型绑定支持不支持

配置文件yml还是properties都能获得到值。

如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value。

如果说,专门写了一个JavaBean来和配置文件进行映射,就直接使用@ConfigurationProperties。

3.3.2 @PropertySource  

@PropertySource:加载指定的配置文件

@PropertySource(value = "{classpath:person.properties}")
@Component
@ConfigurationProperties(prefix = "person")

public class Person {
...
}

3.3.3 @ImportResource

@ImportResource:导入Spring的配置文件,让配置文件里面的文件生效。Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别。想让Spring的配置文件生效,加载进来,将@ImportResource标注在一个配置类上。

Spring的配置文件:

<?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.test.demo.service.HelloService"></bean>

</beans>

注解的使用:

@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class DemoApplication {
...
}

3.3.4 @Bean

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

(1)配置类@Configuration---》Spring的配置文件

(2)使用@Bean给容器中添加组件

import com.test.demo.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
@Configuration:指定当前类是一个配置类,就是来替代之前的Spring配置文件
                在配置文件使用<bean></bean>标签添加组件
 */
@Configuration
public class MyConfig {

    @Bean
    public HelloService helloService(){
        System.out.println("配置类@Bean给容器中添加了组件....");
        return new HelloService();
    }

}

3.4 配置文件占位符

3.4.1 随机数

${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}

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

person.last‐name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15

3.5 Profile

3.5.1 多profile文件

我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml。默认使用application.properties的配置。

3.5.2 yml支持多文档块方式

server:
   port: 8081
spring:
   profiles:
         active: prod


‐‐‐
server:
   port: 8083
spring:
   profiles: dev


‐‐‐
server:
   port: 8084
spring:
   profiles: prod #指定属于哪个环境

3.5.3 激活指定profile

(1)在配置文件中指定spring.profiles.active=dev

(2)命令行:可以直接在测试的时候,配置传入命令行参数

java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

(3)虚拟机参数 :-Dspring.profiles.active=dev

3.6 配置文件加载位置

Spring boot启动会扫描以下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件。

-file:/config/
-file:./
-classpatg:/config/
-classpath:/

优先级由高到低,高优先级的配置会覆盖低优先级的配置。SpringBoot会从这四个位置全部加载主配置文件。注意是互补配置。还可以通过spring.config.location来改变默认的配置文件位置。

项目打包好以后,可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置,指定配置文件和默认加载的这些配置文件共同作用形成互补配置。

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config=G:/application.properties

3.7 外部配置加载顺序

Spring Boot也可以从以下位置记载配置:优先级从高到低,高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置。

(1)命令行参数:所有的配置都在命令行上进行指定,多个配置用空格分来:--配置项=值

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

(2)来自java:comp/env的INDI属性

(3)Java系统属性(System.getProperties)

(4)操作系统的 环境变量

(5)RandomValuePropertySource配置的random.*属性值

由jar包外向jar包内进行寻找,优先加载带profile

(6)jar包外部的application-{profifile}.propertiesapplication.yml(spring.profifile)配置文件 jar包外部的application-{profifile}.propertiesapplication.yml(spring.profifile)配置文件

(7)jar包内部的application-{profifile}.propertiesapplication.yml(spring.profifile)配置文件

再来加载不带profile

(8)jar包外部的application.propertiesapplication.yml(不带spring.profifile)配置文件

(9)jar包内部的application.propertiesapplication.yml(不带spring.profifile)配置文件

(10)@Configuration注解类上的@PropertySource

(11)通过SpringApplication。setDefaultProperties指定的默认属性

所有支持的配置加载来源。

四.自动配置原理

4.1 自动配置原理

在之前的入门文章中,我们了解了@SpringBootApplication注解中的注解,其中的一个注解就是在SpringBoot启动的时候加载主配置类,开启自动配置功能,这个注解就是@EnableAutoConfiguration。

(1)@EnableAutoConfiguration的作用:

  • 利用EnableAutoConfigurationImportSelector给容器中导入组件(这个追溯的步骤可以查看之前的入门文章)

  • 先查看selectImports方法:

 AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
  • 点击getAutoConfigurationEntry中,有 这样的代码:
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
  • 点击getCondidateConfigurations方法:
 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());

点击loadFactoryNames方法进行追溯:

Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");

这里的getSpringFactoriesLoadFactoryClass方法:

  protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

SpringFatoriesLoader.loadFactoryNames()扫描所有jar包类路径下,META-INF/spring.factories,把扫描的这些文件的内容包装成properties对象。从properties对象中获得EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加到容器中。

将类路径下META-INF/spring.factories里面配置的EnableAutoConfiguration的值加入到容器中。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,
\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration
,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration
,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfi
guration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,
\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中,用它们来做自动配置。

4.2 举例

每一个自动配置类进行自动配置功能,以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理。

//表示这是一个配置类,可以给容器中添加组件
@Configuration(proxyBeanMethods = false)


//启动指定类的ConfigurationProperties功能,将配置文件中对应的值和ServerProperties绑定起来,并把ServerProperties加入IOc容器中
@EnableConfigurationProperties(ServerProperties.class)


//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类的配置就是生效,判断当前应用是否是Web应用,如果是,当前配置生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)

//判断当前项目有没有这个类CharacterEncodingFilter,SpringMVC中进行乱码解决的过滤器
@ConditionalOnClass(CharacterEncodingFilter.class)

//判断配置文件中是否存在某个配置,如果不存在,判断也是成立
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    //他已经和SpringBoot配置文件映射
	private final Encoding properties;

    //只有一个有参构造器的情况下,参数的值就会从容器中拿
	public HttpEncodingAutoConfiguration(ServerProperties properties) {
		this.properties = properties.getServlet().getEncoding();
	}

    //给容器中添加一个组件,这个组件的某些值需要从properties中
	@Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
		return filter;
	}
...
}

根据当前的不同条件判断,决定这个配置类是否生效?一旦这个配置类生效,这个配置类就会给容器中添加各个组件,这些组件的属性值是从对应的properties中获取的(这些类里面的每一个属性是和配置文件绑定的)。

@EnableConfigurationProperties(ServerProperties.class)

所有配置文件能配置的属性都是在xxxProperties类中封装的,配置文件能配置什么就可以参照某个功能对应的属性类。

4.3 细节

上面有提到一个注解是@Conditionala派生注解(Spring注解版原生的@Conditional作用),这个的作用是必须是@Conditional指定的条件成立,才能给容器中添加组件,配置里面的内容才会生效。

@Conditional扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava系统的Java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean
@ConditionalOnMissingBean 容器中不存在指定的Bean
@ConditionalExpression满足SpEL表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate系统中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty系统指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionalOnWebApplication当前是Web环境
@ConditionalOnNotWebApplictaion当前不是Web环境
@ConditionalOnJndiJNDI存在指定项

自动配置类必须在一定的条件下才能生效。那么如何知道哪些自动配置类生效?可以通过启用debug=true属性,来让控制台打印自动配置报告。

4.4 总结

(1)SpringBoot启动时会自动加载大量的自动配置类

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

(3)再来看这个自动配置类到底配置了哪些组件(只要我们用的组件有,就不需要再配置)

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

(5)xxxAutoCofiguration自动配置类,给容器中添加组件

(6)xxxProperties封装配置文件中的相关属性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值