Struts 2.5.20全套开发资源与JSON插件详解

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Struts 2是一个遵循MVC设计模式的Java Web框架,由Apache基金会维护,能够方便地构建动态Web应用。该资源包"struts-2.5.20-all"包含Struts 2框架的完整实现及 struts2-json-plugin.jar ,该插件优化了JSON数据处理能力。本文详细介绍了Struts 2的核心概念如Action、ActionMapping、Result、Interceptor、ValueStack和OGNL,以及如何通过Struts 2 JSON插件自动序列化数据、配置JSON结果类型、控制JSON数据格式化选项和实现Ajax支持,旨在提升开发效率和用户体验。 struts-2.5.20-all(含struts2-json-plugin.jar)jar资源

1. Struts 2框架概述

Struts 2框架简介

Struts 2是一个经典且功能强大的Java EE Web应用框架,它采用MVC(Model-View-Controller)设计模式,将应用的业务逻辑、数据与展示层分离。该框架简化了基于Java EE技术的Web应用开发,提高了开发效率和系统的可维护性。Struts 2通过拦截器实现和注解支持,为开发者提供了一个灵活且易于扩展的编程模型。

Struts 2的发展与优势

自从从Struts 1版本演化而来,Struts 2经过多次更新优化,为开发者带来了许多新特性和改进。它集成了对AJAX的支持,支持RESTful风格的URL设计,引入了拦截器机制,以及与多种验证框架的无缝集成。由于其高度可定制性和成熟的社区支持,Struts 2在企业级应用开发中仍然占有一定的市场份额。

Struts 2的应用场景

Struts 2框架广泛应用于需要快速开发企业级Web应用的场景中,尤其是在那些使用Spring和Hibernate作为基础技术栈的项目中。框架的轻量级特性和对多种插件的支持,使其可以作为大型企业应用的一部分,同时也能适应敏捷开发和微服务架构的需求。

接下来的章节将深入探讨Struts 2的核心组件,以及如何在实际开发中使用Struts 2构建Web应用。

2. Struts 2核心组件解析

2.1 Struts 2的Action组件

2.1.1 Action接口的实现与生命周期

在Struts 2框架中,Action组件是最核心的部分,它代表了一个特定的业务逻辑。Action组件需要实现 com.opensymphony.xwork2.Action 接口或者继承 com.opensymphony.xwork2.ActionSupport 类,后者提供了默认的实现,方便开发者编写Action。

实现Action接口时,通常需要重写 execute 方法,该方法是Action的业务逻辑处理的入口点。在请求处理的过程中,Struts 2框架负责Action实例的创建和销毁。

Action组件的生命周期:

  1. 初始化: 当请求被提交到服务器时,Struts 2框架会通过 ActionMapper 来确定哪个Action来处理这个请求。
  2. 实例化: 如果找到对应的Action类,Struts 2会调用其无参构造函数来创建一个Action实例。
  3. 调用execute方法: Struts 2框架创建一个 ActionContext 对象,它包含了Action所需的所有环境信息,然后调用Action的 execute 方法。 execute 方法返回一个字符串,指示接下来的流程(例如: "success" "input" "error" 等)。
  4. 销毁: 请求处理完成后,Action实例会被销毁,释放资源。
public class MyAction extends ActionSupport {
    public String execute() {
        // 业务逻辑代码
        return SUCCESS;
    }
}
2.1.2 ActionContext与会话管理

ActionContext 是Action与Struts 2框架通信的上下文环境。它包含了如请求参数、会话信息等数据。

  • 会话管理: 在Struts 2中,会话级别的数据通常是通过ActionContext或值栈(ValueStack)进行管理的。 ActionContext 提供了一个 Session 的Map对象,开发者可以通过它来存取会话级别数据。
public class MyAction extends ActionSupport {
    public String execute() {
        ActionContext ctx = ActionContext.getContext();
        // 会话管理
        Map<String, Object> session = (Map<String, Object>) ctx.getSession();
        session.put("myKey", "myValue");
        return SUCCESS;
    }
}

2.2 Struts 2的ActionMapping组件

2.2.1 ActionMapping的作用与配置

ActionMapping 是一个配置对象,它定义了与Action相关的信息,如URL模式、输入视图、结果类型等。

  • 配置: struts.xml 配置文件中,可以为每个Action配置一个ActionMapping实例。
<action name="exampleAction" class="com.example.MyAction">
    <result name="success">/exampleSuccess.jsp</result>
</action>

在上面的例子中, exampleAction 是Action的名称, class 属性指定了对应的Action类。

2.2.2 Action映射与URL模式匹配

Struts 2通过 ActionMapper 接口来解析请求URI,并找到对应的Action。默认的 DefaultActionMapper 实现了基础的映射机制,但开发者也可以通过实现这个接口来自定义映射逻辑。

2.3 Struts 2的Result组件

2.3.1 Result类型与视图返回机制

Struts 2的Action执行后,需要返回一个结果(Result)给客户端,这通常是一个JSP或其他类型的视图。Struts 2预定义了几种结果类型,例如 dispatcher chain redirect 等。

  • 视图返回机制: Struts 2内部使用拦截器栈处理请求和响应,并通过Result处理器返回视图。
<result name="success" type="dispatcher">/somePage.jsp</result>

在上述配置中,如果Action返回"success",Struts 2将使用 dispatcher 结果类型来返回 somePage.jsp 页面。

2.3.2 自定义Result实现

开发者可以自定义Result类型以实现特定的返回机制。例如,可以创建一个返回JSON数据的Result,以支持Web服务。

public class JsonResult extends AbstractResult {

    public void execute(...) {
        // 实现JSON输出逻辑
    }
}

2.4 Struts 2的Interceptor组件

2.4.1 拦截器的作用与生命周期

Struts 2框架通过拦截器(Interceptor)实现AOP(面向切面编程)功能。拦截器可以在Action执行前或执行后插入特定的逻辑,如验证、日志记录等。

  • 生命周期: 一个请求会通过拦截器链,每个拦截器可以在Action执行前后执行自己的逻辑。
<interceptor name="myInterceptor" class="com.example.MyInterceptor"/>
<action name="..." class="...">
    <interceptor-ref name="myInterceptor"/>
    ...
</action>
2.4.2 拦截器链与动态拦截机制

拦截器链是拦截器的有序集合,这些拦截器按照在 struts.xml 中配置的顺序执行。动态拦截机制允许在运行时动态地为Action添加拦截器。

public class MyInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        // 在Action执行前的逻辑
        String result = invocation.invoke();
        // 在Action执行后的逻辑
        return result;
    }
}

2.5 Struts 2的ValueStack组件

2.5.1 ValueStack的概念与工作机制

ValueStack是Struts 2中用于存储Action的属性值的栈结构,它为Action提供了灵活的数据存取方式。ValueStack允许拦截器和结果类型通过OGNL(对象图导航语言)访问Action的属性。

  • 工作机制: ValueStack与Action的属性绑定,开发者可以通过OGNL表达式直接访问Action的属性。
2.5.2 OGNL在ValueStack中的应用

OGNL是Struts 2的核心技术之一,用于在ValueStack中存取数据。OGNL表达式可以访问Action的属性、方法和静态数据。

// OGNL访问Action属性
String name = (String) ActionContext.getContext().getValueStack().findValue("name");

使用OGNL,开发者可以方便地操作ValueStack中的数据,实现数据的获取和设置。

通过本章节的解析,可以了解Struts 2的核心组件及其实现细节,为深入理解和应用Struts 2框架打下坚实基础。

3. Struts 2 JSON插件功能介绍

在当前的Web开发中,前后端分离已成为一种趋势,前端通过HTTP请求获取JSON格式的数据已成为标准做法。Struts 2框架的JSON插件正是应这一需求而生,其提供了方便的机制来处理JSON数据,并能够与Struts 2的动作和值栈无缝集成。本章节我们将深入探讨Struts 2 JSON插件的功能。

3.1 Struts 2 JSON插件的基本功能

Struts 2 JSON插件的核心在于帮助开发者简化将Java对象转换成JSON格式数据的过程,并将JSON数据作为HTTP响应返回给前端。下面,我们将详细探讨JSON插件的安装与配置,以及JSON转换与响应。

3.1.1 JSON插件的安装与配置

要使用Struts 2 JSON插件,首先需要将相关的库文件添加到项目的类路径中。通常,JSON插件作为一个额外的jar包提供,可以在Struts 2的官方下载页面找到。下载完成后,将jar包复制到项目的 WEB-INF/lib 目录下。

接下来,需要在Struts 2的配置文件 struts.xml 中声明JSON插件,以确保Struts 2能够加载并使用它。添加如下配置:

<package name="jsonPackage" extends="struts-default">
    <action name="jsonExample" class="com.example动作类">
        <result name="success" type="json">
            <param name="root">jsonRoot</param> <!-- 自定义根元素 -->
        </result>
    </action>
</package>

在这个配置中,我们定义了一个名为 jsonExample 的动作,并指定了当动作执行成功时,返回类型为JSON。

3.1.2 JSON转换与响应

在Struts 2中,JSON插件默认集成了多种对象到JSON的转换机制。例如,当返回的属性是普通类型时,可以直接转换为JSON中的字符串。如果属性是集合或映射类型,则会转换为JSON数组或对象。

开发者可以通过 @JSON 注解来控制特定属性的序列化方式。例如,对于不需要转换为JSON的属性,可以通过 @JSON Exclude 注解来排除。

3.2 Struts 2 JSON插件的高级特性

除了基本的数据转换功能,Struts 2 JSON插件还支持高级特性,如数据过滤和复杂对象序列化,进一步增强了数据处理能力。

3.2.1 高级数据处理与过滤

在处理复杂的业务逻辑时,开发者可能不希望将所有数据一次性返回给前端,而是进行适当的过滤。Struts 2 JSON插件支持通过过滤器来控制哪些数据需要被包含在响应中。

在动作类中,可以使用 @JSON Filter 注解来指定过滤条件。例如:

@JSON Filter(name = "ageFilter", value = "age")
public class UserAction extends ActionSupport {
    private int age;
    private String name;
    // 省略getter和setter方法
}

上面的代码将只包含属性 age 在JSON输出中,而忽略了 name

3.2.2 复杂对象的序列化与反序列化

复杂对象的序列化与反序列化是Struts 2 JSON插件的另一个亮点。当需要序列化自定义对象或包含有特殊要求的复杂结构时,插件可以提供额外的配置支持。

对于自定义对象,可以通过实现 JsonSerializer 接口来进行定制序列化逻辑。例如:

public class CustomObjectSerializer implements JsonSerializer<CustomObject> {
    public String serialize(CustomObject obj, Serializer serializer) {
        // 自定义序列化逻辑
    }
}

这样,当 CustomObject 类型的对象需要被序列化时,将会使用上面定义的 serialize 方法来生成JSON字符串。

小结

在本章中,我们了解了Struts 2 JSON插件的基本和高级功能。通过安装与配置,以及对数据的转换和处理,使得开发者能够更加灵活地处理JSON数据。在下一章,我们将探索如何将这些功能应用到实际的开发项目中,构建RESTful服务,实现前后端分离,以及与Ajax技术的结合。

4. Struts 2 JSON插件在实际开发中的应用

4.1 构建RESTful服务

RESTful设计原则与实践

RESTful 架构是一种软件架构风格,它以简单、可扩展的方式实现了 Web 应用和互联网服务的架构设计。在 RESTful 设计中,服务器和客户端之间通过标准的HTTP方法进行通信,如 GET、POST、PUT、DELETE 等,每个方法对应不同的动作,而数据交换格式则常使用 JSON 或 XML。

在构建 RESTful 服务时,需要考虑资源的定义和表示。资源通常表示为名词,如 users orders 等,可以通过 URI 指定。状态的转移(State Transfer)意味着客户端和服务器之间的交互通过改变资源的状态来实现。为了遵循无状态的设计原则,每个请求都应该包含服务执行所需的全部信息。

为了实践 RESTful 架构,Struts 2 JSON 插件提供了多种支持: - 使用 @Action 注解,开发者可以轻松地为每个动作指定HTTP方法。 - 提供了简单的方式将业务对象转换为 JSON 格式,通过注解或者配置文件可以轻松地控制 JSON 的序列化。 - 支持跨域请求(CORS),这对于实现 RESTful API 非常重要。

Struts 2 JSON插件与RESTful集成

为了集成 Struts 2 JSON 插件与 RESTful API,开发者需要进行以下步骤:

  1. struts.xml 中配置 Action,指定请求类型和对应的处理方法。 xml <action name="user" class="com.example.UserAction" method="getUser"> <result name="success" type="json"> <param name="root">user</param> </result> </action> 在上面的配置中, getUser 方法将处理一个名为 user 的 GET 请求,并将返回的 user 对象序列化为 JSON。

  2. 在 Action 类中定义业务逻辑。 ```java public class UserAction extends ActionSupport { private User user;

    public String getUser() { // Assume 'userService' is a bean that fetches user information. user = userService.getUserByID(1); return SUCCESS; }

    public User getUser() { return user; }

    public void setUser(User user) { this.user = user; } } `` 在这个例子中, getUser 方法被一个 GET 请求调用,它通过 userService 获取用户信息,并将其存储在 user` 对象中。

  3. 使用拦截器栈 defaultStack ,它是 JSON 插件默认提供的,用于处理 JSON 数据的序列化和反序列化。

通过以上步骤,开发者可以有效地将 Struts 2 JSON 插件与 RESTful 服务集成,利用 Struts 2 框架强大的功能来提供轻量级、可维护的 Web 服务。

5. Struts 2与JSON数据交互的优化策略

5.1 性能优化技巧

5.1.1 数据传输的压缩与缓存

随着Web应用的快速发展,前端页面逐渐丰富,大量数据需要在客户端和服务器之间传输。这种数据传输如果未经优化,不仅会耗费更多的带宽,还会因为数据量大而导致加载速度慢,影响用户体验。使用数据压缩和缓存技术是提升Web应用性能的有效手段。

数据压缩

在Web应用中,常用的压缩格式有gzip、deflate和brotli等。服务器在发送响应时,可以通过压缩内容来减小数据大小,客户端在接收到响应后,会自动解压缩内容。这种压缩方式可以显著减少传输的数据量,提升网络传输效率。

在Struts 2中,可以通过修改web.xml配置文件,设置过滤器来启用HTTP压缩功能,如示例代码所示:

<filter>
    <filter-name>compressionFilter</filter-name>
    <filter-class>org.apache.catalina.filters.DeflaterFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>compressionFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

数据缓存

数据缓存是指服务器端或客户端保存一份数据副本,当下次请求相同数据时,可以直接使用缓存数据,从而减少服务器的计算负担和网络传输。

在Struts 2中,可以通过Action的生命周期方法如 init destroy 来手动管理缓存资源。例如,在 init 方法中初始化数据缓存,在 destroy 方法中清理缓存资源。

5.1.2 并发处理与异步处理机制

Web应用的并发处理和异步处理是提高应用性能和扩展性的关键。在Struts 2中,可以使用异步执行机制来处理耗时任务,避免阻塞主线程,从而提升应用的响应能力和吞吐量。

异步执行

Struts 2支持异步方法执行,这意味着可以在不等待操作完成的情况下继续处理请求。这在处理如文件上传、邮件发送等耗时操作时尤其有用。

要启用异步执行,可以在Action类中使用 @Async 注解,并确保项目中已经配置了相应的异步执行支持。示例如下:

@Action(async = true)
public class AsyncAction extends ActionSupport {
    private Future<String> futureResult;

    public String execute() throws Exception {
        futureResult = asyncService.processData();
        return SUCCESS;
    }

    public Future<String> getFutureResult() {
        return futureResult;
    }
}

并发处理

在多用户同时操作时,需要处理并发请求,确保应用能够正确处理来自多个用户的请求,而不产生数据冲突。在Struts 2中,可以通过拦截器来管理并发会话,并通过实现 ConcurrencyInterceptor 来控制并发访问。

以下是一个简单的并发拦截器示例,用以演示如何限制同一时间只允许一定数量的用户访问特定方法:

@InterceptorRef(StandardInterceptorref.CONURRENCY)
public class ConcurrencyInterceptor extends MethodFilterInterceptor {
    private static final int MAX_CONCURRENT_USERS = 10;

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        if (concurrencyManager.reserve(MAX_CONCURRENT_USERS)) {
            try {
                return invocation.invoke();
            } finally {
                concurrencyManager.release();
            }
        } else {
            return ERROR;
        }
    }
}

5.2 安全性增强措施

5.2.1 输入验证与防止注入攻击

数据的输入验证是防止注入攻击的第一道防线。在Struts 2中,可以通过内置的拦截器如 params 拦截器来实现输入验证。 params 拦截器默认会对所有的请求参数执行输入验证,通过配置不同的属性来实现复杂的验证规则。

防止注入攻击

注入攻击通常是指SQL注入和XML注入等。通过配置合适的拦截器,可以有效地防止这类攻击。例如,可以配置 validation 拦截器来实现严格的类型转换和输入验证,从而防止恶意用户输入的字符串对应用造成破坏。

下面是一个配置示例,展示如何在struts.xml文件中设置 validation 拦截器:

<action name="exampleAction" class="ExampleAction">
    <interceptor-ref name="defaultStack"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel,errors</param>
    </interceptor-ref>
</action>

5.2.2 跨站请求伪造(CSRF)防护

跨站请求伪造(CSRF)是一种常见的Web攻击方式。攻击者通过诱导用户访问恶意网站或点击恶意链接,使得用户在不知情的情况下向受攻击的网站发送请求。在Struts 2中,可以使用CSRF拦截器来提供CSRF防护。

CSRF拦截器

CSRF拦截器会检查HTTP请求中是否包含有效的CSRF令牌。如果令牌有效,则请求可以继续执行;如果令牌无效或不存在,则拦截器会阻止请求的执行,并返回错误信息。

下面是一个配置示例,展示如何在struts.xml文件中设置 token tokenSession 拦截器来提供CSRF防护:

<action name="guardedAction" class="GuardedAction">
    <interceptor-ref name="defaultStack"/>
    <interceptor-ref name="token"/>
    <interceptor-ref name="tokenSession"/>
</action>

5.3 调试与错误处理

5.3.1 日志记录与监控工具

有效的日志记录和监控可以帮助开发者更好地理解应用的行为,及时发现和解决运行时问题。Struts 2提供了对日志记录的全面支持,并且可以集成各种日志框架。

集成日志框架

在Struts 2中,常用的日志框架包括Log4j、SLF4J等。通过配置相应的日志框架,可以实现日志的记录、格式化和输出到不同的目标,如控制台、文件或远程服务器。

下面是一个简单的配置Log4j的示例:

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

监控工具

监控工具如Nagios、New Relic等可以帮助开发者监控应用的运行状态。这些工具能够实时监控应用的性能指标,如响应时间、内存使用和处理的请求数等,并在检测到异常时发送警报。

5.3.2 错误处理机制与用户体验优化

在Web应用中,错误处理机制是十分关键的。良好的错误处理不仅可以提升用户体验,还可以减少应用的潜在风险。

错误处理机制

在Struts 2中,可以通过在Action类中定义错误信息,使用 ActionContext 来设置错误消息,并通过结果页面的错误标签来显示这些消息。这种方式可以将错误信息反馈给用户,并提供用户友好的错误提示。

下面是一个简单的示例代码,展示如何在Action中处理错误并返回:

public String execute() {
    try {
        // Business logic
    } catch(Exception e) {
        // 错误处理
        ActionContext.getContext().put("message", "发生了一个错误,请重试!");
        return ERROR;
    }
    return SUCCESS;
}

在JSP页面中,可以使用Struts 2的标签库来显示错误消息:

<s:property value="message"/>

通过以上这些优化策略的实施,可以显著提升Struts 2应用在处理JSON数据交互时的性能、安全性和用户体验。这些策略不仅关注于技术层面的优化,还包括对最终用户体验的提升,为构建高效、稳定和安全的Web应用提供了坚实的基础。

6. 案例研究与总结

6.1 案例分析:构建一个使用JSON插件的应用

在本章节中,我们将通过一个具体的案例来分析如何使用Struts 2框架和其JSON插件来构建一个Web应用程序。我们将重点关注应用需求分析、设计、以及关键代码实现和问题解决。希望通过这个案例能够加深你对Struts 2框架和JSON插件实际应用的理解。

6.1.1 应用需求分析与设计

假设我们需要开发一个简易的图书管理系统,该系统需要支持基本的增删改查功能,并且前端使用Ajax来实现与用户的动态交互。我们需要通过Struts 2的JSON插件来实现后端数据的序列化和反序列化。

在需求分析阶段,我们确定了以下几个关键功能点:

  • 用户可以查看图书列表。
  • 用户可以添加新书。
  • 用户可以编辑现有图书信息。
  • 用户可以删除图书。
  • 用户在添加和编辑图书时,不需要刷新页面即可提交信息。

接下来是系统设计阶段,我们采用了MVC架构设计,将应用分为模型(Model)、视图(View)和控制器(Controller)三个部分。模型负责数据处理,视图负责展示,控制器负责调度。

6.1.2 关键代码实现与问题解决

在这一部分,我们将展示如何编写核心的Struts 2 Action以及对应的配置文件,以实现上述功能。

Model(模型)

首先,我们定义一个Book类,它将作为数据模型,用来表示图书信息。

public class Book {
    private Integer id;
    private String title;
    private String author;
    private Date publishDate;
    // getters and setters
}

Action(控制器)

然后,我们创建一个BookAction类,它继承自ActionSupport并实现了ModelDriven接口,以方便操作Model。

public class BookAction extends ActionSupport implements ModelDriven<Book> {
    private Book book = new Book();
    private List<Book> bookList = new ArrayList<>();

    public String execute() throws Exception {
        // 这里可以根据实际情况实现业务逻辑
        return SUCCESS;
    }

    // ModelDriven接口的实现,用于返回模型对象
    @Override
    public Book getModel() {
        return book;
    }

    // 省略getter和setter方法
}

配置文件

在struts.xml配置文件中,我们需要定义Action映射和结果类型。

<action name="book" class="com.example.BookAction" method="execute">
    <result name="success" type="json">
        <param name="root">bookList</param>
        <param name="enableSMD">true</param>
    </result>
</action>

其中, <result> 标签内的 <param name="root"> 指定了JSON序列化的根对象,而 <param name="enableSMD">true</param> 则启用了Struts 2的JavaScript模块定义功能,便于前端通过Ajax调用。

问题解决

在开发过程中,我们可能会遇到各种问题。例如,可能会发现JSON插件没有按照预期序列化复杂对象,这通常是因为对象内部属性的getter方法没有正确实现,或者是对象的类型不支持序列化。解决这类问题通常需要回溯检查代码,并确保所有必要条件都已满足。

在本节中,我们通过一个具体案例详细分析了如何使用Struts 2和JSON插件来构建Web应用程序的关键步骤。希望这个案例能够帮助你理解如何在实际项目中应用这些技术。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Struts 2是一个遵循MVC设计模式的Java Web框架,由Apache基金会维护,能够方便地构建动态Web应用。该资源包"struts-2.5.20-all"包含Struts 2框架的完整实现及 struts2-json-plugin.jar ,该插件优化了JSON数据处理能力。本文详细介绍了Struts 2的核心概念如Action、ActionMapping、Result、Interceptor、ValueStack和OGNL,以及如何通过Struts 2 JSON插件自动序列化数据、配置JSON结果类型、控制JSON数据格式化选项和实现Ajax支持,旨在提升开发效率和用户体验。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值