java面试题(二)

Java Web

1. jsp 和 servlet 有什么区别?

     1.  jsp的本质是Servlet,(jsp编译后就成了Servlet,JVM只能识别java的类,不能识别jsp的代码,Web容器将jsp的代码编译成JVM能识别的java类)。

     2. jsp侧重于页面展示,Servlet侧重于业务逻辑。

     3. jsp从Java代码和html分离出来,有自己的内置对象。Servlet中没有内置对象。

     4. Jsp是Servlet的一种简化,使用Jsp只需要完成程序员要输出到客户端的内容,Jsp中的java脚本如何嵌套到一个类中,由Jsp容器完成。而Servlet是个完整的java类,这个类的service方法用于生成对客户端的响应。

2.jsp 有哪些内置对象?作用分别是什么?

   JSP有9个内置对象:

        request:封装客户端的请求,其中包含来自GET或POST请求的参数。

        response:封装服务器对客户端的响应。

        pageContext:通过该对象可以获取其他对象。

        session:封装用户会话的对象。

        application:封装服务器运行环境的对象。

        out:输出服务器响应的输出流对象。

        config:Web应用的配置对象。

        page:JSP页面本身(相当于Java程序中的this)

        exception:封装页面抛出异常的对象。

3.说一下 jsp 的 4 种作用域?

       request:代表依次请求

       page:作用于当前页面

       session:代表一次会话

      application:代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

4.session 和 cookie 有什么区别?

cookie存储在客户端,数据大小有局限性,相对不安全,客户端可以清除cookie,如果不进行cookie的持久化设置,cookie默认存储在内存中,浏览器关闭,cookie消毁。如果进行cookie的持久化设置,它将被永久的保存在内存中。

session存储与服务端,它依赖于cookie。相对安全但会增加服务器的压力。当浏览器第一次访问服务器时,会创建session对象,以cookie的形式向客户端浏览器存储一个唯一的标识sessionID, 在以后的访问中,都会携带上jsessionId,找到对应的session对象。

5.说一下 session 的工作原理?

     session是一个存在服务器上的类似于一个散列表格的文件。里面存有我们需要的信息,在我们需要用的时候可以从里面取出来。类似于一个大号的map吧,里面的键存储的是用户的sessionid,用户向服务器发送请求的时候会带上这个sessionid。这时就可以从中取出对应的值了。

6.如果客户端禁止 cookie 能实现 session 还能用吗?

    客户端禁用cookie之后将不能得到session了,因为session是用sessionId来确定当前会话所对应的服务器session,而sessionId是通过cookie来传递的,禁用cookie相当于失去了sessionId,也就得不到session了。

7.springMVC 和 struts 的区别是什么?

    1.Struts2的核心基于Filter即StrutsPreparedAndExcuteFilter

      SpringMVC的核心基于Servlet 即DispatcherServlet

      运行速度:servlet比过滤器快

    2.Struts2是多例的(类开发),参数传递是通过类的属性传递(属性驱动和模型驱动)

     SpringMVC建议是单例的,基于类中的方法开发的,一个url对应一个方法,传递参数是传到方法的形参上面,

   3.Struts2采用的是值栈存储请求以及相应数据,ognl存取数值

    SpringMVC采用请求来解析请求内容,然后由内部的getParameter给方法中的形参赋值,再把后台处理过的数据通过          ModelAndView对象存储,存储数据,查看返回的页面,在把对象通过请求传输到页面。

8.如何避免 sql 注入?

       1. PreparedStatement(简单又有效的方法)

       2. 使用正则表达式过滤传入的参数

       3. 字符串过滤

       4. JSP中调用该函数检查是否包函非法字符

9.什么是 XSS 攻击,如何避免?

     XSS攻击又称CSS,全称Cross Site Script  (跨站脚本攻击),其原理是攻击者向有XSS漏洞的网站中输入恶意的 HTML 代码,当用户浏览该网站时,这段 HTML 代码会自动执行,从而达到攻击的目的。XSS 攻击类似于 SQL 注入攻击,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息。 XSS是 Web 程序中常见的漏洞,XSS 属于被动式且用于客户端的攻击方式。

XSS防范的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码。

框架

10.为什么要使用 spring?

     就是让说spring的优点呗!spring是一个轻量级的开源的控制反转和面向切面的容器框架。可以自行扩展。此处省略。

11.解释一下什么是 aop?什么是 ioc?

    aop是面向切面编程,是对oop的扩展,将那些与业务逻辑无关的部分进行抽取形成可以复用的模块,减少代码的冗余,提高开发效率。。。具体参考博客:https://blog.csdn.net/duan196_118/article/details/104133176

12.spring 有哪些主要模块?

     spring框架集成了很多模块,主要模块有:SpringCore 、SpringContext、SpringORM、SpringDao、SpringAOP、SpringMVC、SpringWeb等。

13.spring 常用的注入方式有哪些?

    构造注入、setter注入、基于注解注入

14.spring 中的 bean 是线程安全的吗?

     spring容器中的bean是否线程安全,容器本身并没有提供bean的线程安全 策略,因此spring容器中的bean本身不具备线程安全的特性,要结合scope的bean进行分析。

15.spring 支持几种 bean 的作用域?

      spring支持的bean的作用域有五种:

      1. singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
      2. prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
      3. request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
      4. session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
      5. globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portletcontext的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效

  spring默认使用singleton作用域

16.spring 自动装配 bean 有哪些方式?

   基于注解的配置,xml配置,基于java的配置

17.spring 事务实现方式有哪些?

    1. 基于@Transactional的声明式事务管理

    2. 基于Aspectj AOP配置事务

    3. 基于TransactionProxyFactoryBean的声明式事务管理

    编程式事务管理需要使用beginTransaction()开启事务、commit进行提交、rollback进行回滚等事务管理相关的方法、

18.说一下 spring 的事务隔离?

    spring的事务支持也相当于对它底层使用数据库的事务的支持,它封装了功能的实现,提高开发效率。具体参考博客:https://blog.csdn.net/duan196_118/article/details/104814284

19.说一下 spring mvc 运行流程?

   Spring运行流程描述:

  1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;

  2. 核心控制器Dispatcher Servlet接收到请求,通过系统自定义的映射器配置找到对应的处理程序,并将URL映射的控制器返回给核心控制器。

  3.  通过核心控制器找到系统或默认的适配器

  4.  由找到的适配器,调用实现对应接口的处理器,并将结果返回给适配器,结果中包含数据模型和视图对象,再由适配器返回给核心控制器

  5.  核心控制器将获取的数据和视图结合的对象传递给视图解析器,获取解析得到的结果,并由视图解析器响应给核心控制器

  6.  核心控制器将结果返回给客户端。

20. spring mvc 有哪些组件?

springMVC的一个中心,三大组件。

    前端处理器:DispatcherServlet(不需要程序员开发)

           作用:接受请求,响应结果,相当于转发器,中央处理器。

                     减少了其他组件之间的耦合度。

    处理器映射器:Handler Mapping(不需要程序员开发)

           作用:根据请求到url查找Handler

    处理器适配器: HandlerAdapter

           作用:按照特定的规则去执行Handler

     视图器解析器:ViewResolver (不需要程序员开发)

           作用:进行视图解析,根据逻辑视图名解析成真正的视图。

21.@RequestMapping 的作用是什么?

    RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

RequestMapping注解有六个属性:

    value, method:

       value:指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
       method:指定请求的method类型, GET、POST、PUT、DELETE等;

   consumes,produces

         consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
         produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

    params,headers

         params: 指定request中必须包含某些参数值是,才让该方法处理。
         headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。

22.@Autowired 的作用是什么?

    @Autowired 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。
    @Autowired 默认是按照类型去匹配,配合 @Qualifier 指定按照名称去装配 bean。

23.什么是 spring boot?

      springboot就是Spring开源框架下的子项目,是Spring的一站式解决方案,主要是简化了spring的使用难度,降低了对配置文件的要求,使得开发人员能够更容易得上手。

24.spring boot 核心配置文件是什么?有哪几种类型?它们有什么区别?

     Spring Boot 有两种类型的配置文件,application 和 bootstrap 文件

     Spring Boot会自动加载classpath目前下的这两个文件,文件格式为 properties 或 yml 格式

     *.properties 文件是 key=value 的形式

     *.yml 是 key: value 的形式

     *.yml 加载的属性是有顺序的,但不支持 @PropertySource 注解来导入配置,一般推荐用yml文件,看下来更加形象

     bootstrap 配置文件是系统级别的,用来加载外部配置,如配置中心的配置信息,也可以用来定义系统不会变化的属性.bootstatp 文件的加载先于application文件

     application 配置文件是应用级别的,是当前应用的配置文件

25.为什么要用 spring boot?

    SpringBoot有很多的优点,挑选自己熟知的进行阐述即可。

  • 简化了Spring配置文件,
  • 没有代码和XML文件的生成
  • 内置TomCat
  • 能够独立运行
  • 简化监控

26.spring boot 有哪些方式可以实现热部署?

  第一种:依赖spring-boot-devtools实现,将以下代码放到dependencies中:

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

 第二种:在maven项目下,在pox.xml文件中的build中添加spring-loaded依赖,如图:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>springloaded</artifactId>
    <version>1.2.8.RELEASE</version>
</dependency>

然后以CMD命令切换到项目文件目录下,以maven的方式运行项目,命令:mvn spring-boot:run

第三种:

   第三种和第二种采用相同的方式,不过需要将spring-loaded下载下来,

27.什么是 ORM 框架?

      对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单来说,将程序中的兑现自动持久化到关系数据库中。那么,到底如何实现持久化呢?一种简单的反感是采用硬编码的方式(jdbc操作sql方式),为每一种可能的数据库访问操作提供单独的方法。这种方法存在很多缺陷,所有使用ORM框架(为了解决面向对象与关系数据库存在的互不匹配的现象的框架)来解决。

28.hibernate 中如何在控制台查看打印的 sql 语句?

  在hibernate.cfg.xml中进行配置:

29.hibernate 有几种查询方式?

  可以参考博客:https://blog.csdn.net/duan196_118/article/details/104124649

30.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?

   getCurrrentSession();该方法获取的是与当前线程绑定的session,获取的是同一个session,需要在主配置中添加配置,而且不需要手动关闭session。

<property name="hibernate.current_session_context_class">thread</property>

   openSession();每次获取的都是不同的session 

31.hibernate 是如何工作的?

   可以参考博客:https://blog.csdn.net/duan196_118/article/details/104121617

32.get()和 load()的区别?

    把get和load放到一起进行对比是Hibernate面试时最常问到的问题,这是因为只有正确理解get()和load()这二者后才有可能高效地使用Hibernate。get和load的最大区别是,如果在缓存中没有找到相应的对象,get将会直接访问数据库并返回一个完全初始化好的对象,而这个过程有可能会涉及到多个数据库调用;而load方法在缓存中没有发现对象的情况下,只会返回一个代理对象,只有在对象getId()之外的其它方法被调用时才会真正去访问数据库,这样就能在某些情况下大幅度提高性能。

33.在 hibernate 中使用 Integer 和 int 做映射有什么区别?

     hibernate的Pojo类中 经常会用到int 型得变量 这个时候如果使用基本类型的变量(int ) 如果数据库中对应的存储数据是 null 时使用Pojo类进行获取数据会出现类型转换异常 如果使用的是对象类型(Integer)这个时候则不会报错。

34.hibernate 实体类可以被定义为 final 吗?

      是的,你可以将Hibernate的实体类定义为final类,但这种做法并不好。因为Hibernate会使用代理模式在延迟关联的情况下提高性能,如果你把实体类定义成final类之后,因为Java不允许对final类进行扩展,所以Hibernate就无法再使用代理了,如此一来就限制了使用可以提升性能的手段。
      不过,如果你的持久化类实现了一个接口而且在该接口中声明了所有定义于实体类中的所有public的方法的话,你就能够避免出现前面所说的不利后果。

35.说一下 hibernate 的缓存机制?

 一级缓存:

Session有一个内置的缓存,其中存放了被当前工作单元加载的对象,每个session都有自己独立的缓存,且只能被当前工作单元访问。

Session的缓存有三大作用:

    1、减少访问数据库的频率。Session的缓存可以提高数据访问的性能(应用程序从缓存中读取持久化对象的速度显然比到数据中查询数据的速度快多了,)。提高速度,减少数据库压力。

    2、当缓存中的持久化对象之间存在循环关联关系时,Session会保证不出现访问对象时的死循环,以及由死循环引起的JVM堆栈溢出异常。

    3、保证数据库中的相关记录与缓存中的相应对象保持同步。

二级缓存:

SessionFactory中的数据可以被多个Session共享访问。

SessionFactory的内置缓存:存放了映射元数据,预定义的sql语句。

Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别,第二级缓存是可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件。

 

36.hibernate 对象有哪些状态?

 Hibernate中对象的状态:

  • 临时/瞬时状态
  • 持久化状态
  • 游离状态

 临时/瞬时状态

 当我们直接new出来的对象就是临时/瞬时状态的..

  • 该对象还没有被持久化【没有保存在数据库中】
  • 不受Session的管理

 持久化状态

 当保存在数据库中的对象就是持久化状态了

  • 当调用session的save/saveOrUpdate/get/load/list等方法的时候,对象就是持久化状态
  • 在数据库有对应的数据
  • 受Session的管理
  • 当对对象属性进行更改的时候,会反映到数据库中!

 游离状态

 当Session关闭了以后,持久化的对象就变成了游离状态了...

  • 不处于session的管理
  • 数据库中有对应的记录

 new出来的对象是瞬时状态->保存到数据库中(受Session管理)就是持久化状态->将session close掉就是游离状态

37.hibernate 实体类必须要有无参构造函数吗?为什么?

    实体类必须要有无参构造函数。。。

    Hibernate框架会调用这个无参构造方法来构造实例对象,即Class类的newInstance方法 ,这个方法就是通过调用无参构造方法来创建实例对象的 。

    当查询的时候返回的实体类是一个对象实例,是Hibernate动态通过反射生成的。反射的Class.forName(“className”).newInstance()需要对应的类提供一个无参构造方法,必须有个无参的构造方法将对象创建出来,单从Hibernate的角度讲 他是通过反射创建实体对象的 所以没有无参构造方法是不行的,另外Hibernate也可以通过有参的构造方法创建对象。
    如果你没有提供任何构造方法,虚拟机会自动提供默认构造方法(无参构造器),但是如果你提供了其他有参数的构造方法的话,虚拟机就不再为你提供默认构造方法,这时必须手动把无参构造器写在代码里,否则new Xxxx()是会报错的,

38.mybatis 中 #{}和 ${}的区别是什么?

  参考博客:https://blog.csdn.net/duan196_118/article/details/104269768

39.mybatis 有几种分页方式?

  参考博客:https://blog.csdn.net/duan196_118/article/details/105298291

40.RowBounds 是一次性查询全部结果吗?为什么?

 RowBounds是一次性查询全部结果

从RowBounds源码看出,RowBounds最大数据量为Integer.MAX_VALUE(2147483647),大概是20亿条。在实际开发不建议使用RowBounds。数据量达到一定程度,RowBounds所造成的内存压力比较大

41.mybatis 逻辑分页和物理分页的区别是什么?

首先介绍逻辑分页和物理分页的概念:

物理分页

物理分页依赖的是某一物理实体,这个物理实体就是数据库,比如MySQL数据库提供了limit关键字,程序员只需要编写带有limit关键字的SQL语句,数据库返回的就是分页结果。

逻辑分页(内存分页)

逻辑分页依赖的是程序员编写的代码。数据库返回的不是分页结果,而是全部数据,然后再由程序员通过代码获取分页数据,常用的操作是一次性从数据库中查询出全部数据并存储到List集合中,因为List集合有序,再根据索引获取指定范围的数据。

两者的区别:

1.数据库负担

物理分页每次都访问数据库,逻辑分页只访问一次数据库,物理分页对数据库造成的负担大。
2.服务器负担

逻辑分页一次性将数据读取到内存,占用了较大的内存空间,物理分页每次只读取一部分数据,占用内存空间较小。

3.实时性

逻辑分页一次性将数据读取到内存,数据发生改变,数据库的最新状态不能实时反映到操作中,实时性差。物理分页每次需要数据时都访问数据库,能够获取数据库的最新状态,实时性强。

4.适用场合

逻辑分页主要用于数据量不大、数据稳定的场合,物理分页主要用于数据量较大、更新频繁的场合。

MyBatis使用RowBounds实现的分页是逻辑分页,也就是先把数据记录全部查询出来,然在再根据offset和limit截断记录返回(数据量大的时候会造成内存溢出),不过可以用插件或其他方式能达到物理分页效果。

42.mybatis 是否支持延迟加载?延迟加载的原理是什么?

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

43.说一下 mybatis 的一级缓存和二级缓存?

mybatis的一级缓存是sqlsession级别的,它默认开启且不可关闭,当在同一个sqlsession中进行相同的sql语句查询时,第二次及以后的查询回去缓存中取数据,一级缓存最多缓存1024条SQL。二级缓存是指可以跨sqlsession的缓存,是mapper级别的缓存,对于mapper级别的缓存不同的sqlsession可以共享,需要我们在setting中开启二级缓存的使用,在对应的mapper.xml文件中配置cache节点,然后在对应的select节点中添加useCache=true。

44.mybatis 和 hibernate 的区别有哪些?

参考博客:https://blog.csdn.net/duan196_118/article/details/104271371

45.mybatis 有哪些执行器(Executor)?

   SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

   ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

   BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

  CachingExecutor(缓存执行器):装饰设计模式典范,先从缓存中获取查询结果,存在就返回,不存在,再委托给Executor delegate去数据库取,delegate可以是上面任一的SimpleExecutor、ReuseExecutor、BatchExecutor。

  ClosedExecutor(无用执行器):毫无用处,读者可自行查看其源码,仅作为一种标识,和Serializable标记接口作用相当。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。

46.mybatis 分页插件的实现原理是什么?

     分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

47.如何获取当前数据库版本?

     1. select version();

     2. 在cmd里面输入 mysql -V 来获取mysql版本号

48.一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?

一般情况下,我们创建的表的类型是InnoDB,如果新增一条记录(不重启mysql的情况下),这条记录的id是8;但是如果重启(文中提到的)MySQL的话,这条记录的ID是6。因为InnoDB表只把自增主键的最大ID记录到内存中,所以重启数据库或者对表OPTIMIZE操作,都会使最大ID丢失。

但是,如果我们使用表的类型是MylSAM,那么这条记录的ID就是8。因为MylSAM表会把自增主键的最大ID记录到数据文件里面,重启MYSQL后,自增主键的最大ID也不会丢失。

注:如果在这7条记录里面删除的是中间的几个记录(比如删除的是3,4两条记录),重启MySQL数据库后,insert一条记录后,ID都是8。因为内存或者数据库文件存储都是自增主键最大ID.

49. mysql 的内连接、左连接、右连接有什么区别?

     INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。

     LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。

     RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。

50. 数据库中char 和 varchar 的区别是什么?

    首先明确的是,char的长度是不可变的,而varchar的长度是可变的,也就是说,定义一个char[10]和varchar[10],如果存进去的是‘abcd’,那么char所占的长度依然为10,除了字符‘abcd’外,后面跟六个空格,而varchar就立马把长度变为4了,取数据的时候,char类型的要用trim()去掉多余的空格,而varchar是不需要的。

     尽管如此,char的存取数度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率,而varchar是以空间效率为首位的。

       再者,char的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;而varchar的存储方式是,对每个英文字符占用2个字节,汉字也占用2个字节。

       两者的存储数据都非unicode的字符数据。

简单总结至此,答案仅供参考。如有不足,欢迎留言指正。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值