【推荐】Spring Boot 程序初始化实战: CommandLineRunner 和 ApplicationRunner

Spring Boot 启动后置任务:ApplicationRunner 实战与进阶 本文深入探讨了Spring Boot中ApplicationRunner的实战应用与进阶技巧,包括核心用法、执行顺序控制、高级应用场景及性能优化建议。通过实际案例展示了如何利用ApplicationRunner进行缓存预热、命令行参数解析等操作,显著提升应用启动效率。 阅读详情

我们在开发过程中会有这样的场景:需要在容器启动的时候执行一些内容,比如:读取配置文件信息,数据库连接,删除临时文件,清除缓存信息。在Spring Boot中给我们提供了两个接口来帮助我们实现这样的需求。这两个接口就是我们今天要讲的

  1. CommandLineRunner
  2. ApplicationRunner,

他们的执行时机为容器启动完成的时候。使用起来非常简单。只需要实现CommandLineRunner或者ApplicationRunner接口。

如果是Spring 环境下,则可以参看本博的下面的文章讲如何在Spring环境做初始化操作的。

https://blog.youkuaiyun.com/bigtree_3721/article/details/103735767。

如果在SpringBoot应用启动的时候需要执行特定的动作,可以利用CommandLineRunner或者ApplicationRunner。实现了CommandLineRunner或者ApplicationRunner接口的Component会在 所有Spring Beans都初始化之后,SpringApplication.run()之前执行,非常适合在应用程序启动之初进行一些数据初始化的工作。

共同点:

其一 执行时机都是在容器启动完成的时候进行执行;其二 这两个接口中都有一个run()方法;

如果程序里既有ApplicationRunner ,也有CommandLineRunner代码 ,

则ApplicationRunner 先运行,而CommandLineRunner 后运行。

不同点:

ApplicationRunner中run方法的参数为ApplicationArguments,

而CommandLineRunner接口中run方法的参数为String数组。

问题提出: 如果有多个实现类,而我们需要按照一定的顺序执行的话,那么应该怎么办呢?

解决方案:

方法1)可以在实现类上加上@Order注解指定执行的顺序;

方法2)可以在实现类上实现Ordered接口来标识。

需要注意:数字越小,优先级越高,也就是@Order(1)注解的类会在@Order(2)注解的类之前执行。

 

下面展示了如何在程序中使用CommandLineRunner和ApplicationRunner。

Maven配置

pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.concretepage</groupId>
    <artifactId>spring-boot-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>spring-demo</name>
    <description>Spring Boot Demo Project</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies> 
    <build>
        <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        </plugins>
    </build>
</project> 

CommandLineRunner

CommandLineRunner是个接口,有一个run()方法。为了使用CommandLineRunner我们需要创建一个类实现该接口并覆盖run()方法。使用@Component注解实现类。当SpringApplication.run()启动spring boot程序时,启动完成之前,CommandLineRunner.run()会被执行。CommandLineRunner的run()方法接收启动服务时传过来的参数。

run(String... args)

参数为String数组。

CommandLineRunnerBean.java

package com.concretepage.bean;

import java.util.Arrays;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class CommandLineRunnerBean implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(CommandLineRunnerBean.class);  
    public void run(String... args) {
        String strArgs = Arrays.stream(args).collect(Collectors.joining("|"));
        logger.info("Application started with arguments:" + strArgs);
    }
} 

MyApplication.java

package com.concretepage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.concretepage.service.HelloService;

@SpringBootApplication
public class MyApplication {
    private static final Logger logger = LoggerFactory.getLogger(MyApplication.class);
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
        HelloService service =  context.getBean(HelloService.class);
        logger.info(service.getMessage());
        }       
} 

我们也可以创建一个service。一旦Spring boot启动完成service就会执行。

这意味着SpringApplication.run()执行完成后service的方法就会执行。
HelloService.java

package com.concretepage.service;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String getMessage(){
        return "Hello World!";
    }
}

现在使用带有参数的可执行jar运行程序。spring-boot-demo-0.0.1-SNAPSHOT.jar为生成的jar文件。执行命令如下:

java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar data1 data2 data3 

输出结果为:

2017-03-19 13:38:38.909  INFO 1036 --- [main] c.c.bean.CommandLineRunnerBean  : Application started with arguments:data1|data2|data3
2017-03-19 13:38:38.914  INFO 1036 --- [main] com.concretepage.MyApplication  : Started MyApplication in 1.398 seconds (JVM running for 1.82)
2017-03-19 13:38:38.915  INFO 1036 --- [main] com.concretepage.MyApplication  : Hello World! 

ApplicationRunner

ApplicationRunner和CommandLineRunner的作用相同。在SpringApplication.run()完成spring boot启动之前,ApplicationRunner的run()方法会被执行。

run(ApplicationArguments args) 

可以看到,CommandLineRunner.run()接收String数组作为参数,而ApplicationRunner.run()接收ApplicationArguments作为参数。这些参数是启动spring boot程序时传给main()方法的。

ApplicationRunnerBean.java

package com.concretepage.bean;

import java.util.Arrays;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class ApplicationRunnerBean implements ApplicationRunner {
    private static final Logger logger = LoggerFactory.getLogger(ApplicationRunnerBean.class);  
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
            String strArgs = Arrays.stream(arg0.getSourceArgs()).collect(Collectors.joining("|"));
            logger.info("Application started with arguments:" + strArgs);
    }
} 

创建可执行jar包并使用如下参数运行:

java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar data1 data2 data3 

输出结果为:

2017-03-19 16:26:06.952  INFO 5004 --- [           main] c.c.bean.ApplicationRunnerBean           : Application started with arguments:data1|data2|data3
2017-03-19 16:26:06.956  INFO 5004 --- [           main] com.concretepage.MyApplication           : Started MyApplication in 1.334 seconds (JVM running for 1.797)
2017-03-19 16:26:06.957  INFO 5004 --- [           main] com.concretepage.MyApplication           : Hello World! 

CommandLineRunner和ApplicationRunner的执行顺序

在spring boot程序中,我们可以使用不止一个实现CommandLineRunner和ApplicationRunner的bean。为了有序执行这些bean的run()方法,可以使用@Order注解或Ordered接口。例子中我们创建了两个实现CommandLineRunner接口的bean和两个实现ApplicationRunner接口的bean。我们使用@Order注解按顺序执行这四个bean。

CommandLineRunnerBean1.java

@Component
@Order(1)
public class CommandLineRunnerBean1 implements CommandLineRunner {
    public void run(String... args) {
        System.out.println("CommandLineRunnerBean 1");
    }
}

ApplicationRunnerBean1.java

@Component
@Order(2)
public class ApplicationRunnerBean1 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("ApplicationRunnerBean 1");
    }
}

CommandLineRunnerBean2.java

@Component
@Order(3)
public class CommandLineRunnerBean2 implements CommandLineRunner {
    public void run(String... args) {
        System.out.println("CommandLineRunnerBean 2");
    }
}

ApplicationRunnerBean2.java

@Component
@Order(4)
public class ApplicationRunnerBean2 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("ApplicationRunnerBean 2");
    }
} 

输出结果为:

CommandLineRunnerBean 1
ApplicationRunnerBean 1
CommandLineRunnerBean 2
ApplicationRunnerBean 2 

 

 

Spring Boot 框架整体启动流程详解 作者其他文章:Spring Boot 3.x系列文章Spring Boot 2.7.8 中文参考指南(一)Spring Boot 2.7.8 中文参考指南(二)-WebSpring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Prometheus 系列文章Prometheus 的介绍和安装直观感受PromQL及其数据类型PromQL之选择器和运算符PromQL之函数Prometheus 告警机制介绍及命令解读Prometheus 告警模块配置深度解析。 阅读详情

相关推荐

知识图谱初步学习(一)——本体+Protege新手学习

文章目录前言(本体详解)1.本体概念2.本体分类3.本体组成4.本体构建方法一、protege简介二、软件使用步骤1.安装2.使用三、问题解决方案汇总 前言(本体详解) 在开始学习知识图谱的过程中,首先就是要了解什么是本体(ontology)。 1.本体概念 本体的概念最初源自于哲学领域,在哲学中的定义为“对世界上客观事物的系统描述,即存在论”。哲学中的本体关心的是客观现实的抽象本质。而在计算机领域,本体是可以在语义的层次上来对知识进行描述,可以看做是某一个领域知识的通用模型。 本体是从客观世界中抽象出来

qq_43654669的博客 3万+

深入理解 Spring Boot 的 CommandLineRunner 原理及使用

run方法:该方法在应用程序启动后被调用。:命令行参数数组。:允许抛出任何异常。是 Spring Boot 提供的一个非常有用的接口,可以帮助你在应用程序启动后执行初始化任务。通过实现run方法,你可以轻松地执行各种初始化操作,并且可以通过命令行参数传递必要的配置信息。本文通过多个示例详细介绍了如何在实际项目中使用,希望对你有所帮助。

weixin_43841461的博客 4398

TypeScript领域建模实战:基于斯坦福本体论七步法构建健壮数据模型

在软件工程中,领域建模是连接业务需求与技术实现的关键桥梁,其核心在于对业务概念、属性及其关系的显式定义与规范。通过系统化的建模方法,开发者能够将模糊的领域知识转化为清晰、可扩展且类型安全的数据结构,从而在编译时捕获潜在错误,提升代码质量与可维护性。这一过程的技术价值在于实现了从业务逻辑到类型系统的无损映射,确保了设计的一致性。在实践中,结合TypeScript的静态类型检查与Zod的运行时验证,可以构建起从概念到代码再到数据库的三层一致性约束。本文以电商、博客等常见应用场景为例,深入解析如何运用源自斯坦福知

weixin_42551967的博客 383

CommandLineRunner接口介绍

文章目录CommandLineRunner接口介绍1. CommandLineRunner接口使用2. ApplicationRunner与CommandLineRunner3. ApplicationArguments 源码分析 CommandLineRunner接口介绍   CommandLineRunner接口是在容器启动成功后的最后一步回调(类似开机自启动)。 1. CommandLine...

Chavaer 5508

傻白入门芯片设计,芯片键合(Die Bonding)(四)

傻白入门芯片设计,芯片键合(Die Bonding)(四) 引线键合、倒装芯片键合、管脚贴合技术

qq_46675545的博客 3万+

泛微Ecology流程数据表结构解析:workflow_requestbase和workflow_currentoperator到底怎么关联查询?

本文深入解析泛微Ecology系统中workflow_requestbase和workflow_currentoperator表的结构与关联机制,提供SQL查询语句示例,帮助开发者高效查询流程数据。涵盖待办事项、已办事项、办结事项和流程监控等典型场景,并分享性能优化技巧和常见问题排查指南。

weixin_33738555的博客 808

Spring boot CommandLineRunner接口使用例子

前言 Spring boot的CommandLineRunner接口主要用于实现在应用初始化后,去执行一段代码块逻辑,这段初始化代码在整个应用生命周期内只会执行一次。 如何使用CommandLineRunner接口 我们可以用以下三种方式去使用CommandLineRunner接口: 1)和@Component注解一起使用 这种使用方式相当简便,如下所示: @Component public cl...

weixin_34380296的博客 258

11.Labview实现用户界面切换的几种方式---通过VI间相互调用

本文介绍了界面切换的几种方式,分别是重入和引用①重入方式可以通过调用子VI的方式打开被调用的界面,往往应用于弹窗等的设置程序。②引用方式分两种,一种是打开引用,一种是静态引用。区别在于打开引用需要设置被打开VI的目标地址,静态引用仅需在引用时绑定VI的位置即可。③推荐使用静态引用的方式切换界面。④使用引用打开界面时,需通过属性节点和调用节点来设置程序的状态。更多内容欢迎大家补充和留言讨论~本文介绍了GUI界面设计相关的程序,更多相关文章后续持续更新,请关注作者不迷路~本期就到这里,再见~

关注我,更多技术问题欢迎私聊~ 9547

CommandLineRunner接口中run方法的执行时机

CommandLineRunner接口中run(): @FunctionalInterface public interface CommandLineRunner { void run(String... args) throws Exception; } 使用时我们需要实现接口并实现run()方法 @SpringBootApplication public class Application implements CommandLineRunner { @Resource priv..

Jywudiok的博客 1976

华南理工大学-大学物理实验-绪论作业

3.用公式测量某圆柱体铝的密度,测得直径=2.0420.003(cm),高=4.1260.004(cm),质量=36.4880.006(g)。计算铝的密度和测量的标准差,并以测量结果表达式表示之。(要求判别和剔除异常数据)(30分)(了解图解法的注意事项,大学物理实验众多实验数据处理采用这种方法,如PN结温度特性研究,光电效应与普朗克常数的测定,霍尔效应测磁场等等,注意规范作图)实验测得温度与对应的金属丝的长度的数据如下表所示。(了解异常数据的判断方法及具体判断过程,30分的题目n(*≧▽≦*)n)

mohen_777的博客 581

AI辅助需求分析与提示词生成

文章标题 《AI辅助需求分析与提示词生成》 关键词 人工智能 需求分析 提示词生成 深度学习 机器学习 强化学习 数学模型 系统架构

AI天才研究院 1214

java 执行commandline,CommandLineRunner是一个带有run方法的简单spring引导接口。Spring Boot启动后将自动调用实现CommandLineRunner接...

CommandLineRunner是一个带有run方法的简单spring引导接口。Spring Boot启动后将自动调用实现CommandLineRunner接口的所有bean的run方法。Command Line Runner在加载应用程序上下文之后以及Spring Application run方法完成之前执行,相当于你的应用的初始化过程,一般用来实现一些数据预先加载或预先处理。@Spring...

weixin_35990358的博客 1144

使用Verilog实现QR分解——嵌入式 [设计与代码]

通过Verilog的硬件描述语言,我们可以将QR分解算法实现为硬件电路,并在嵌入式系统中高效地运行。本文将介绍如何使用Verilog设计并实现QR分解算法,该算法用于将一个矩阵分解为正交矩阵Q和上三角矩阵R。具体而言,QR分解通过对矩阵的列进行正交化处理,得到正交矩阵Q,并将对应的正交化结果存储在上三角矩阵R中。该算法通过将矩阵分解为两个部分,正交矩阵Q和上三角矩阵R,实现了对矩阵的分解和变换。模块,该模块接收待分解矩阵A,并输出正交矩阵Q和上三角矩阵R。下面给出了使用Verilog实现QR分解的源代码。

CodeMaven的博客 620

Spring Boot 启动后执行器深度指南:CommandLineRunner vs ApplicationRunner

Spring Boot 启动后任务执行指南:CommandLineRunner vs ApplicationRunner 核心摘要 Spring Boot 提供了两种在应用启动后执行初始化任务的接口: CommandLineRunner 接收原始字符串数组参数(String[] args) 适用于简单参数处理场景 执行时机:应用上下文刷新后,服务就绪前 ApplicationRunner(推荐) 封装参数为ApplicationArguments对象,支持选项/非选项参数解析 提供更强大的参数处理能力(如-

python15397的博客 820

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Springboot 初始化操作

在使用Springboot过程中,或多或少我们会遇到在Springboot启动时要初始化类,或者加载文件之类的一些操作

做一个有思想的技术人 1316

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

SpringBoot31-ApplicationRunner 详细讲解

特性说明用途应用启动完成后执行初始化逻辑优势保证所有 Bean 初始化完成,支持依赖注入,可访问命令行参数注意事项如果抛出异常,应用启动会失败;可用 @Order 控制多个 Runner 的执行顺序替代方案。

qq_31532983的博客 921

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Spring Boot启动后,除了ApplicationRunner,你还可以用这几种方式执行初始化任务

本文深入探讨了Spring Boot启动后执行初始化任务的五种方案,包括@PostConstruct、SmartInitializingSingleton、CommandLineRunner、ApplicationRunner和@EventListener(ReadyEvent),并对比了它们的触发时机、参数获取能力和异常处理影响。通过场景化选型指南和高级控制技巧,帮助开发者在数据预热、连接池初始化等关键场景中做出精准选择,提升应用启动效率和稳定性。

weixin_33742618的博客 464

Spring Boot应用启动后初始化:四种方案对比与生产实践指南

在Java企业级应用开发中,应用启动后的初始化逻辑是确保系统稳定运行的关键环节。其核心原理在于利用框架提供的生命周期钩子,在特定阶段执行预设任务,从而完成资源准备和数据预热。这一机制的技术价值在于提升应用启动后的即时响应能力,避免首次请求的冷启动延迟,保障服务的高可用性。典型的应用场景包括缓存预热、数据库连接池初始化、配置中心数据拉取以及向注册中心上报服务实例。本文聚焦于Spring Boot框架,深入剖析其提供的@PostConstruct、CommandLineRunner、ApplicationRun

weixin_30608503的博客 410

Spring Boot应用启动自激活:缓存预热与资源初始化实践指南

在软件工程中,应用启动初始化是确保系统就绪的关键环节,其核心原理在于利用容器生命周期管理机制,在组件装配完成后自动执行预设逻辑。这一技术价值在于提升系统自治能力,避免手动调用的繁琐与遗漏,从而增强代码健壮性和可维护性。其典型应用场景包括微服务启动时的缓存预热、数据库连接池建立、外部客户端初始化以及配置加载等。本文聚焦于Spring框架下的实现,深入探讨了如何通过@PostConstruct、ApplicationRunner及事件监听等机制,结合异步执行与线程模型,构建高效可靠的自激活组件,并特别针对缓存预

weixin_30555515的博客 400

Spring Boot CommandLineRunner 详解与应用实践

CommandLineRunner 是 Spring Boot 框架中用于在应用启动后执行特定任务的关键接口,属于 Spring 应用生命周期的重要扩展点。其核心原理是通过实现 run 方法,在应用上下文初始化完成但未正式提供服务前执行自定义逻辑。这种机制为开发者提供了标准化的启动任务处理方案,在数据预加载、连接测试、环境校验等场景具有重要技术价值。通过 @Order 注解或 Ordered 接口可以精确控制多个 Runner 的执行顺序,而结合条件化执行(@Conditional)和异常处理机制则能构建更

cqwmy840702的博客 514

Spring Boot应用启动后初始化:精准时机选择与最佳实践

在Java企业级应用开发中,应用启动后的初始化是确保系统稳定运行的关键环节。其核心原理在于理解Spring框架的生命周期事件机制,通过监听特定事件在正确的时机执行代码。这一技术的价值在于避免因初始化时机不当导致的空指针异常、循环依赖等问题,从而提升应用的健壮性和启动成功率。常见的应用场景包括缓存预热、配置加载、数据库连接池初始化以及向注册中心上报服务等。本文聚焦于Spring Boot项目启动后初始化的核心需求,深入对比了@PostConstruct、ApplicationRunner与监听Applicat

weixin_30216561的博客 337

【Spring】CommandLineRunner接口

本文深入讲解 Spring Boot 的 CommandLineRunner 接口:从源码、基础使用、执行顺序到缓存预热、数据库初始化等实战场景,以及常见踩坑与最佳实践,帮你彻底掌握启动回调机制。

406

使用CommandLineRunner应该注意什么

场景最佳实践​依赖管理​使用构造器注入,避免循环依赖​异常处理​捕获所有异常,关键失败终止应用​耗时操作​使用异步执行,不阻塞主线程​资源清理​监听 ContextClosedEvent 释放资源​环境区分​使用 @Profile 控制环境特定逻辑​执行顺序​使用 @Order 明确初始化顺序​幂等设计​确保多次执行不会产生副作用​参数访问​使用 ApplicationArguments 解析复杂参数​测试策略​直接调用 run() 方法进行单元测试。

zwh1zwh的博客 788

Spring Boot启动依赖管理:利用Actuator与ApplicationRunner实现优雅健康检查

在微服务架构中,服务间的启动依赖管理是保障系统稳定性的关键。其核心原理在于通过延迟检查机制,将外部依赖验证从Spring容器初始化阶段剥离,避免因依赖服务未就绪导致应用启动失败。这一技术方案的价值在于提升系统健壮性和部署成功率,尤其适用于数据库、配置中心、下游服务等强依赖场景。通过结合Spring Boot Actuator的健康检查机制和自定义ApplicationRunner,开发者可以实现对外部服务的启动验证与延迟等待,有效解决微服务架构中常见的启动依赖问题。

weixin_33727510的博客 354

详解Spring Boot 启动时执行特定代码逻辑实现方案

书接上回,我们总结了,大致分为环境配置、IOC容器bean加载、事件通知等,具体详细总结可自行调转查看。今天我们来看看一个平时在业务开发中常见的逻辑场景。在开发 Spring Boot 应用时,我们经常需要在项目启动时执行一些初始化逻辑,比如加载缓存、连接外部系统、初始化配置信息等。Spring Boot 提供了多种实现方式,允许我们在应用启动的不同阶段插入代码逻辑。本文将结合启动过程详细介绍这些方式,并说明适用的场景及实现示例。

weixin_41821642的博客 1088
上一篇: 【推荐】mysql联合 索引(复合索引)的探讨
下一篇: springmvc在启动工程的时候就访问数据库,加载一些共同的数据
大树叶
博客等级 码龄12年 1171粉丝 664原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值