SpringMVC框架简介

SpringMVC

1.导包

    spring-aop-4.0.9.RELEASE.jar

    spring-beans-4.0.9.RELEASE.jar

    spring-context-4.0.9.RELEASE.jar

    spring-core-4.0.9.RELEASE.jar

    spring-expression-4.0.9.RELEASE.jar

    spring-web-4.0.9.RELEASE.jar

    spring-webmvc-4.0.9.RELEASE.jar

2.SpringMVC配置文件 SpringMVC.xml

    选中命名空间:beans aop context mvc

3.普通的servlet流程:

请求 -> url -> pattern -> 交给对应的servlet去处理

*SpringMVC工作原理|工作流程|执行原理:

请求 -> 前端控制器 (DispatchServlet) -> handlerMapping -> handlerAdapter(适配器|处理器|控制器) -> service&dao ->ModelAndView -> viewResolver -> jsp

 

 

如果现在想用SpringMVC,而不是普通的servlet需要配置一个SpringMVC自带的servle

通过以下配置,拦截所有请求

 

web项目的web.xml中配置SpringMVC拦截器:

        <servlet>

            <servlet-name>springDispatcherServlet</servlet-name>

            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

            <!-- 告诉服务器MVC配置文件在哪里 contextConfigLocationsDispatcherServlet中的一个属性-->

            <init-param>

                 <param-name>contextConfigLocation<param-name>

                 <param-value>classpath:SpringMVC.xml</param-value>

            </init-param>

            <!-- 设置启动服务器时自动生效 -->

            <load-on-startup>1</load-on-startup>

        </servlet>

        <servlet-mapping>

            <!-- 拦截所有"/"请求交给springDispatcherServlet -->

            <servlet-name>springDispatcherServlet</servlet-name>

            <url-pattern>/</url-pattern>

        </servlet-mapping>

 

4.创建servlet层

    1.创建普通类 org.***.serlvet | org.***.controller | org.***.handler | org.***.action 包下

    2.在类上加 @Controller注解

    3.有注解必须将注解所在的包扫描到配置文件中

        在SpringMVC.xml中配置扫描器

    <!-- 扫描org.***.handler -->

        <context:component-scan base-package="org.***.handler"/>

 

 

    4.配置视图解析器InternalResourceViewResolver

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

            <!-- 给所有的响应地址加前缀(文件夹名) -->

            <property name="prefix" value="views"/>

            <!-- 给所有的响应地址加后缀(文件格式) -->

            <property name="suffix" value=".jsp"/>

        </bean>

 

    5.在方法上加拦截注解 @RequestMapping("url")

        请求的路径是什么 注解中的url就是什么

总结:

    <url-pattern>/</url-pattern>中的 ” / ”

    映射是去匹配 @RequestMapping("url")注解,可以和方法名、类名不一致

    设置POST|GET请求接收方式

@RequestMapping(value="url",method=RequestMethod.POST,params={"name","age!=23",....})

value属性:设置请求路径,如果没有其他参数可以不设置,直接写路径即可

method属性:设置接收方式RequestMethod.POST | GET | DELETE | PUT

params属性:设置接接收参数,可以是一个,也可以用{}中加入多个参数,也可以加入表达式

    其本质是约束比如 age!=23 ,那么age如果为23则不接收其请求,

    如果参数设置了"name" 那么请求中必须携带name参数 否则不接收,

    如果参数设置了"name=zs"那么请求中必须携带name而且其值为zs否则不接收等等类Java的表达式.

    headers属性:这是请求头的约束

    SpringMVC默认为单例;设置SpringMVC为多例:类上加@scope="prototype";

 

5.ant风格请求路径:

?

任意单字符

*

任意字符 0个或多个

**

任意目录

 

1.浏览器get传值通过@PathVariable动态获取参数

:

    jsp发送一个请求  userServlet?name=zs -> userServlet/zs

    MVC接收请求和参数

    @RequestMapping(value="userServlet/{name}")

    public String welccome(@PathVariable("name")String name){

    }

 

REST风格: 一种软件编程风格

GET

POST

DELETE

PUT

 

    普通浏览器只支持GET | POST 并不支持其他 这种情况可以使用过滤器进行拦截改变请求方式

    原本的servlet过滤器是需要手写的,在使用MVC框架以后,框架提供了过滤器HiddenHttpMethodFilter

 

    实现方法:

        在WEB-INF目录下的web.xml中

            <!--映射MVC过滤器-->

            <filter>

                <filter-name>HiddenHttpMethodFilter</filter-name>

                <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>

            </filter>

            <filter>

                <filter-name>HiddenHttpMethodFilter</filter-name>

                <!--拦截所有请求-->

                <url-pattern>/*</url-pattern>

            </filter>

 

在表单中如果要发送PUT|DELETE请求而浏览器不支持就可以增加一个隐藏域

from中的method请求方式必须是post

<input type="hidden" name="_method" value="PUT|DELETE">

 

 

2.表单get提交传值

    在方法参数中定义@RequestParam("result")默认参数是必须接收的,如果前端没有传过来此参数,则会报错.在参数中加入required=false属性解决此问题

    也可以给参数加上默认值defaultValue="default" 若前端未传此参数,则使用默认参数

:

     public String getName(@RequestParam("name")String name)

 

3.获取请求头信息 @RequestHeader

:public String getName(@RequestHeader("Accept-Language")String Language)

4.获取Cookie信息 @CookieValue

    :public String getSessionId(@CookieValue("JSESSIONID")String jSessionId)

 

小结:

 SpringMVC处理各种参数的流程/逻辑

 请求: 前端发送请求a -> @RequestMapping("a")获取参数

6.使用实体类接收参数

 form表单中的input-> name值 必须与实体类中的属性值一样,级联查询使用属性对象.对象中的属性名

例:

    <form>

        <input type="text" name="name">

        <input type="text" name="age">

        <input type="text" name="book.bookName">

    </form>

    public String addStudent(Student student){}

 

 

 

在SpringMVC中使用原生态的Servlet API 比如HttoServletRequest 就直接将servletAPI中的类或接口等 直接写在参数中即可使用 对象直接交给SpringMVC管理

:

    @RequestMapping(value="testServletAPI")  

    public String testServletAPI(HttpServletRequst request,HttpServletResponse response){ }

7.响应参数

响应参数放入Request : RequestAttribute

1.返回ModelAndView

public ModelAndView testModelAndView(){

    ModelAndView modelAndView = new ModelAndView(ShowStudent.jsp);

    //构造函数参数->响应页面

    Student stu = new Student("张三",19);

    modelAndView.addObjecg(stu);//addObject方法将响应的数据放入request域中

        return modelAndView;

}

jsp页面接收响应用EL表达式${requestScope.stu.name}

 

 

2.返回ModelMap

public String testModelMap(ModelMap modelMap){

    Student stu = new Student("张三",19);

    modelMap.put("Student",stu);//键值对形式将响应数据放入request域中

    return ShowStudent;//转发请求形式响应视图

}

jsp页面接收响应用EL表达式${requestScope.stu.name}

 

 

3.返回Map

public String testModelMap(Map<"String",Object> map){

    Student stu = new Student("张三",19);

    map.put("Student",stu);//键值对形式将响应数据放入request域中

    return ShowStudent;//转发请求形式响应视图

}

jsp页面接收响应用EL表达式${requestScope.stu.name}

 

         

4.返回Model

public String testModelMap(Model model){

    Student stu = new Student("张三",19);

    model.addAttribute("Student",stu);//键值对形式将响应数据放入request域中

    return ShowStudent;//转发请求形式响应视图

}

jsp页面接收响应用EL表达式${requestScope.stu.name}

 

5.响应参数放入session域 :

@SessionAttributes("")放在类名上

    1.单个对象@SessionAttributes(value="student")放入对象名

        1.2.放入多个参数@SessionAttributes(value={"student","book"})

    2.放一个类型的对象@SessionAttributes(types=Student.class)

        2.2.放入多个对象@SessionAttributes(types={Student.class,Book.class})

           

6.更新请求:     

@ModleAttrribute此注解标注的方法在所有方法前执行

:

    @ModleAttribute

    public void getStudent(@RequestParam("stuId")Integer stuId,Map map){

        Student student = StudentServiceImpl.getStudent(stuId);//调用三层获取Student对象

        //假设 studentid=12,name=zhangsan,age=19,

        map.put("student",student);

        //通过map放入request域中 放入的就是key值就是对象自动映射首字母大写,如果想改名,

        //那么调用处也要用@modelAttribute()来标注 比如map.put("stu",student)那么

        //调用处fu(@ModelAttribute("stu")Student student);

    }

 

    @RequestMapping("updateStudent")

    public String queryStudentById(@RequestParam("stuName")String stuName,Student student,Map map){

        //request域中的student自动映射参数中的Student(映射的是类型与形参无关)

            student.setName(stuName);

            map.put("student",student);

            return "index";

        }

常用场景:

    1.经常使用在更新之前

    2.想要不修改本身代码 再增加功能

注意事项:

    本身controller的设计理念是一个controller处理一个请求,所以加@ModelAttribute非常合理

    但是因为SpringMVC本身太强大灵活,所以经常将各种方法写在一个类(controller)里,

    所以使用@ModelAttribute时需要慎重,因为执行每一个请求前都要执行一遍,会使程序执行效率降低或产生干扰

 

8. 视图解析器

1.视图解析器处理流程:

Controller返回值 ->

ModelAndView ->

视图解析器  ->

视图

String(ssucess)

无论返回什么

ViewResolver

View

View(ssucess)

都会返回

 

jsp/HTML/PDF/Excel

ModelAndView

ModelAndView

 

 

 

 

 

2.常见的视图解析器:

    InternalresourceView、InternalResourceViewResolver

    Public clas  JstlView extends InternalResourceView 可以解析jstl/实现国际(i18n/internationalization/base)化操作

    SpringGMVC解析jsp时 会默认使用InternalResourceView,如果发现jsp中包含了jstl语言,则自动转为jstlView

 

3.实现国际化的步骤:

1.创建资源文件 -> 基名_语言_地区.properties | 基名_语言properties

2.参数就是k/v对

    例:你好=hello

3.具体实现国际化步骤

    a.创建资源文件

    b.配置springmvc.xml加载资源文件

<bean id="messageSource" class="prg.springframework.context.support.ResourceBundleMessageSource">

    <property name="basename" value="i18n"/>

</bean>

ResourceBundleMessageSource会再SpringMVC响应时介入(解析国际化资源文件)

    c.通过JSTL使用国际化

      jstl.jar  standar.jar

      springmvc在启动时.会自动查找一个id="messageSource"的bean.如果有则自动加载

9.pringMVC视图解析器常见功能

1.实现jsp直接访问jsp

SpringMVC:index.jsp -> succes.jsp :

       

<mvc:view-controller path="index" view-name="success"/>

 

    此时客户端的一切请求会将Controller(@RequestMapping())的一切请求屏蔽掉.都在<mvc:-controller>中查找

    加入<mvc:annotation-driven></mvc:annotation-driven>(此标签是SpringMVC的基础配置,很多功能都需要通过该注解来协调)实现两种方式的共存

2.请求转发 改成 重定向

        转发:forward:   重定向:redirect

:

public void goIndexfun(){ return index; } ->

public void goIndexfun(){

    return forward:/WEB-INF/jsp/index.jsp;

}

public void goIndexfun(){

    return redirect:/WEB-INF/jsp/index.jsp;

}

注意:如果使用此请求方法,则请求地址不会被视图解析器加上前缀和后缀,就需要自己加前缀和后缀,否则请求访问404

3.处理静态资源:

(静态资源:html css js 图片 视频等)

可以与用户交互的资源为动态资源(如百度搜索:天气)

在SpringMVC中如果直接访问静态资源,结果会是404原因如下:

之前所有的请求,通过通配符/拦截,进而交给SpringMVC的入口DispatcherServlet去处理;找该请求映射对应的@RequestMapping

    例:http://localhost:8080/SpringMVCProject/img.png

        @RequestMapping("img.png") return sucess; 所以找不到

    解决:如果是需要mvc处理的,交给@RequestMapping去处理,如果不需要SpringMVC处理则使用tomcat默认的servlet去处理.

    例:如果有对应的请求拦截:<url-pattern>*.png</url-pattern>则被拦截交servlet处理,如果没有就直接访问.

    兼容两种方式值需要增加一个配置:

springMVC中加入标签<mvc:default-servlet-handler></mvc:default-servlet-handler>

此标签就可以让没有对应的@RequestMapping直接访问

注意:要在加入了<mvc:annotation-driven></mvc:annotation-driven>的基础上使用,两个标签都需要

4.类型转换

    a.Spring内置有一些常见的类型转换器

    b.也可以自定义类型转换器

        i.编写自定义类型转换器的类

            约定:实现Converter接口

        ii.将自己编写的转换器加入到SpringMVC配置中

  1. 将自定义转换器纳入SpringIOC中

               

<bean id="myConverter" class="org.langiao.converter.Myconverter"></bean>

 

  1. 将myConverter再纳入SpringMVC提供的转换器Bean中,所有的转换器都需要再spring工厂中注册,所以将自定义的转换器set进去就可以了

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">

        <property name="converters">

            <set>

                <ref bean="myConverter"/>

            </set>

        </property>

</bean>

  1. 将conversionService注册到annotation-driven中来协调一下

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

10.数据格式化

:SimpleDateForamt date= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

 

   

SpringMVC提供了很多注解,方便我们数据格式化:

  1. 在SpringMVC配置文件中加入配置数据格式化所以来的注解所需要的bean

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">

</bean>

 

  1. 通过注解来使用//将前端传过来的数据进行格式约定方便映射接收

   

例:在pojo类中

            @DateTimeFormmat(pattern="yyyy-MM-dd")

            private Date birthday

        3.fu(Student stu,BinndingResult result); 

        //如果格式化出错(传参出错) 会将错误信息放入BindingResult中 此为约定参数

        其中有一个方法getErrorCont()返回错误信息数组,getDefaultMessage()方法返回单个错误信息

         本身具有容错性 如果使用 控制台是可以输出错误信息 但是前段页面是不会报错的,解决此类问题:

            将错误信息放入request域中, 在前端页面拿出展示即可

            例:map.put("errors",result.getFieldErrors())返回错误信息集合

        4.将类型转换的bean myConverter 放入格式化中 就能实现既格式化 又类型转换

         注:BindingResult是一个约定参数,必须放在要接收的错误参数的下一个 暨:fu(Student stu,BindingResult result,Map map);否则不会生效

11. 校验

1.准备校验时使用的JAR

validation-api-1.0.0.GA.jar:JDK的接口;

hibernate-validator-4.2.0.Final.jar是对上述接口的实现;如果版本较高可能与aip冲突

jobss-jogging.jar

classmate.jar

hibernate-validator-annotation-processor.jar

log4j、slf4j、slf4j-log4j

2.需要<mvc:annotation-driven></mvc:annotation-driven>支持 要实现各种校验,必须实现一个接口:ValidatorFactory

org.springframework.validation.beanvalidation.LocalValidatorFactoryBean 是一个SpringMVC实现校验的标准接口实现类

而annotation-driven会自动加载LocalValidatorFactoryBean这个类.

3.在需要的类中的属性前加入jsr注解,在conctroller需要校验的方法参数前加@Valid注解

            例:

                @Past

                private Date birthday

                fn(@Valid Student stu)

          JSR 303 基本的校验

            空检查

            @Null 验证对象是否为null

            @NotNull 验证对象是否不为null, 无法查检长度为0的字符串

            @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

            @NotEmpty 检查约束元素是否为NULL或者是EMPTY.

           

            Boolean检查

            @AssertTrue 验证 Boolean 对象是否为 true

            @AssertFalse 验证 Boolean 对象是否为 false

           

            长度检查

            @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内

            @Length(min=, max=) Validates that the annotated string is between min and max included.

           

            日期检查

            @Past 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期

            @Future 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期

            @Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式 flags: 指定 Pattern.Flag 的数组,表示正则表达式的相关选项。

           

            数值检查

            建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null

            @Min 验证 Number 和 String 对象是否大等于指定的值

            @Max 验证 Number 和 String 对象是否小等于指定的值

            @DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

            @DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

            @Digits 验证 Number 和 String 的构成是否合法

            @Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字, Integer指定整数精度,fraction指定小数精度。

            @Range(min=, max=) 被指定的元素必须在合适的范围内

            @Range(min=10000,max=50000,message=”range.bean.wage”)

            @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)

            @CreditCardNumber信用卡验证

            @Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。

            @ScriptAssert(lang= ,script=, alias=)

            @URL(protocol=,host=, port=,regexp=, flags=) 

12.SpringMVC通过Ajax处理json数据@Response

    1.导入jar包 - 最好是同一版本 否则容易出冲突

        jackson-annotations.jar

        jackson-core.jar

        jackson-databind.jar

  1. Ajax请求SpringMVC.并且返回json格式的数据

       

请求Ajax

:

    $(document).reday(function(){

        $(“#testAjaxJson”).click(function(){

            //通过ajax请求springMVC

            $.post(

                “handler/testAjaxJson”,//服务器地址

                {“name”:”zs”}

                function(){//服务端处理完毕后的回调函数}

            )

        })

    })

 

 

如何在ajax中获取回调函数:在contrller的方法中加入@ResponseBody注解之后就可以在ajax中调json对象了

:

//告诉springMVC此时的返回不是一个view页面,而是一个ajax返回值以json格式

@ResponseBody

fu(){}

13.SpringMVC实现文件上传                        

与servlet本质一样 都是通过组件实现的

commons-io.jar

commons-fileupload.jar

SpringMVC可以简化文件上传的代码.但是必须满足条件:实现MultipartreSolver接口

SpringMVC实现文件上传                  

与servlet本质一样 都是通过组件实现的

commons-io.jar

commons-fileupload.jar

SpringMVC可以简化文件上传的代码.但是必须满足条件:实现MultipartreSolver接口

  1. 配置XML文件

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

  <property name="defaultEncoding" value="UTF-8" /><!--编码格式-->

  <property name="maxUploadSize" value="-1" />    <!--上传单个文件的最大值,单位byte 如果配-1表示无限制-->

</bean>

 

   

  1. 编写前端代码

<form action="handler/testUpload" Method="post" enctype="multipart/form-data">

    <input type="file" name="fileUpload"/>

    <button type="submit">提交</button>

</form>

  1. 编写controller

    //文件上传处理方法

@RequestMapping("handler")

public class TestUpload {

    @RequestMapping("testUpload")

    public String testUpload(@RequestParam("fileUpload")MultipartFile file , HttpServletRequest request){

        //获取项目路跟目录路径

        String path = request.getSession().getServletContext().getRealPath("upload/");

        System.out.println(path);

        try {

            InputStream input = file.getInputStream();

            //拿到流 抛异常

            String fileName = file.getOriginalFilename();//获取上传文件名

            OutputStream out = new FileOutputStream(path+fileName);

            byte[] bs = new byte[1024];

            int len= -1;

            while((len=input.read(bs)) != -1){

                out.write(bs,0,len);

            }

            out.close();

            input.close();

        } catch (IOException e) {

            // TODO Auto-generated catch block

            System.out.println("进入异常");

        }

            return "/hello";

        }

}

 

14.SpringMVC拦截器

    a.编写拦截器 public class MyInterceptor implements HandlerInterceptor

        重写方法:

            prehandle();拦截请求

            postHandle();拦截响应

            afterCompletion();渲染完毕触发

    b.配置:将自己写的拦截器配置到springmvc中 默认拦截全部请求

//如果默认拦截全部 不配置<mvc:interceptor>则放在<mvc:interceptors>中

<mvc:interceptors>

    <!--配置具体的拦截路径-->

  <mvc:interceptor>

    <!--指定拦截的路径,基于ant风格-->

    <mvc:mapping path="/**">

    <!--指定不拦截的路径二者取交集-->  

    <mvc:exclude-mapping path=""/>

    <bean class"MyInterceptor的全名"></bean>

    </mvc:interceptor>

</mvc:interceptors>

 

    c:拦截器链  

    拦截器1 -> 拦截器2 -> 执行方法 -> 拦截器2 -> 拦截器1 -> 渲染展示 ->

    最终渲染只会用一次 谁排最后就用谁

15.异常处理:

    SpringMVC:必须实现HandlerExceptionResolver接口,该接口的实现类 都是异常的各种处理方式   

  1. ExceptionHandlerExceptionResolver,主要提供了@ExceptionHandler注解,并且通过该注解处理异常

//该方法就可以捕获本类中抛出的ArithmeticException异常

@ExceptionHandler({ArithmeticException.class})

 //参数中只能有一个异常参数,有其他参数此方法就不会捕获异常了 

public ModelAndView handlerArithmeticException(ArithmeticException e){

    ModelAndView mv = new ModelAndView("error");

    System.out,println(e);

    mv.addObject("er",e);

    return mv

}

 

 

           

 

异常处理路径:最短优先

    如果有方法抛出一个ArithmeticException异常,而该类中 有2个对应的异常处理方法则按照就近原则     

    @Exception默认只能捕获当前类中的异常方法

如果发生异常的方法,和处理异常的方法不在同一个类中: 加一个注解@ControllerAdvice即可

例子:

@ControllerAdvice

public class MyExceptiongHandler(){//用于处理异常的类

    fun();

}

总结:如果一个 方法用于处理异常,并且只处理当前类的异常:则只在类中加一个

 

@ExceptiongHandler修饰的方法   

    如果一方法用于处理异常,并且处理所有类中的异常:新建一个@ControllerAdvice修饰的类,在类中加一个处理异常的@ExceptiongHandler修饰的方法  

        b.ResponseStatusExceptionResolver:自定义异常显示页面@ResponseStatus(value="HttpStatus.FORBIDDEN",reason="数组越界")

//value错误信息码,枚举类型,reason错误信息提示

            继承Exception编程自定义异常类

    :@ResponseStatus(value="HttpStatus.FORBIDDEN",reason="数组越界")

        public class MyArrayIndexOutOfBoundsExcption extends Exception(){}

自定义异常类,该注解也可以直接放到方法前

 

通过过配置方式处理异常

            <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

                <!--如果发生异常 相当于将错误信息e放入request域中-->

                <!--如果不写下面这个声明 就会将异常变量放入默认值Exception-->

                <property name ="exceptionAttribute" value="e" >

                </property>

                <property name="exceptionMappings">

                   <props>

                       <!--相当于catch (NullPointerException e){跳转:error}-->

                       <prop key="java.lang.NullPointerException">

                           error

                       </prop>

                   </props>

                </property>

            </bean>

 

                  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值