struts总结

struts2基本知识点

MVC模式介

struts2基本知识点

MVC模式介绍

struts2环境搭建

struts2配置

OGNL表达式

struts2标签

struts2拦截器

struts2类型转换

struts 2输入校验

struts2文件上传

struts2国际化

Action中属性值注入

el表达式为什么可以取出值栈里的内容

struts2工作流程

MVC模式介绍

1) model1架构模式:

核心是JSP文件,用户提交信息给JSP页面,JSP页面接受用户提交的值,并通过JavaBean连接数据库和操作数据库,然后将结果返回给用户。项目中包含大量的JSP文件及少量JavaBean,不方便维护。

2) model2架构模式:

核心是JSPServlet,也称为MVC模式。M为模型,一般采用JavaBean来实现;V为视图,一般采用JSP来实现,C为控制器,一般采用Servlet来实现。

struts2环境搭建

1) 下载struts2框架,以struts-2.3.15.1为例

2) 下载eclipsemyeclipse(以后均已eclipse为例),打开eclipse,配置好JDKTomcat

3) 新建web工程struts2

4) 打开下载好的struts2框架,进入app,解压struts2-blank,

5) 复制WEB-INF/lib下的的jar包到工程的lib目录下

6) 打开struts2-blank下的web.xml,复制filterfilter-mapping到工程的web.xml

7) 复制struts2-blank\WEB-INF\classes下的struts.xml到工程的src

8) 打开struts.xml,注释掉里面所有的内容,照着样例新建package节点

9) 新建hello.jsp,浏览器里输入http://127.0.0.1:8080/struts2/hello

常量struts.devMode,设置为true即为开发者模式,修改配置文件以后立即生效,可以显示更加详细的错误信息。

添加struts2源码支持:右键struts2-core-2.3.15.1.jar,添加源码的位置

struts2配置

1) constant:定义struts常量值

2) package

3) namespace:定义action的访问路径

4) action

a) 默认执行ActionSupport

b) 也可以自定义action,有三种方法

i. 自定义一个action,写一个execute方法

ii. 自定义一个action,实现Action接口,重写execute方法

iii. 自定义一个action,继承ActionSupport,重写execute方法(推荐使用)

5) result:定义要转向的视图,与action的方法的返回值相对应

a) 常用四种类型

i. dispatcher(默认)

ii. redirect

iii. chain

iv. redirectAction

v. freemarker

vi. httpreader

vii. stream

viii. velocity

ix. xslt

x. plaintext

xi. tiles

b) global-results:全局结果对象

c) 动态结果集

i. 在action中保存一个属性,存储具体结果的location

6) action动态方法调用

a) 指定method属性

b) 通配符*{通配符的序号,从1开始}

7) action接受参数

a) action的属性接受参数

b) DomainModel接受参数

c) ModelDriven接受参数,需要实现ModelDriven接口,重写getModel方法

OGNL表达式

1) OGNLObject-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL

2) ognl表达式取值设值(上下文与root

3) value stack值栈

a) 是多个对象的一个集合,相对于OGNL来说是一个单一的对象

b) 作为ognlroot

c) Struts2框架把OGNL Context设置为我们的ActionContext

1. application

2. session

3. value stack(root)

4. action (the current action)

5. request

6. parameters

7. attr (searches page, request, session, then application scopes)

d) action的实例将会被入值栈中,值栈又作为OGNL表达式的root,所以当取action中的属性值时,不需要加#

4) 通过struts标签取值

a) 取值栈里的值

b) 去ActionContext其他对象的值,需要加#

struts2标签(非重点)

1) property:输出指定值

2) if/elseif/else:条件逻辑控制

3) iterator:遍历集合,有三个属性id,status,value

a) id:遍历取得的每一个元素都保存在id变量中

b) status:IteratorStatus实例对象

c) value:OGNL表达式

4) include:包含另一个页面

5) fielderror:一般用于输入校验

6) action:允许在JSP中直接访问并调用Action

7) bean:允许在JSP页面中创建JavaBean实例

8) debug:可以用来输出服务器端对象中的信息

9) date:格式化输出的的日期

10) ui:参考文档:Tag Developers Guide > Struts Tags > Tag Reference > UI Tag Reference

struts2拦截器

1) 什么是拦截器

a) 电梯开关门

b) 动态代理

 

2) 如何定义一个拦截器

a) 实现Interceptor接口

b) 继承AbstractInterceptor

3) 配置拦截器

a) 在struts.xml中添加interceptors节点

b) 在action节点中引入拦截器

struts2类型转换(非重点)

1) 类型转化的意义

a) WEB应用程序交互都是建立在HTTP协议之上的,互相传递的都是字符串。

b) WEB应用程序中,使用了多种数据类型,譬如int,float,date等等。

2) 内置类型转换器

a) boolean/Boolean、char/Character、int/Integer、folat/Float、long/Long、double/Double

b) date

c) Collection

d) Set

e) 数组类型

3) 自定义类型转换器

    自定义类型转换器要实现TypeConverter接口,可直接继承DefaultTypeConverter

    可使用Struts 2提供的StrutsTypeConverter

a) 局部类型转换器

定义一个转换器类,新建属性文件[ActionName]-conversion.properties, 文件里的内容是propertyName=ConvertName

b) 全局类型转换器

            定义一个转换器类,新建属性文件xwork-conversion.properties,文件里的内容是ClassName=ConvertName。

            对于转换器转换的数据模型,一定要用<s:property>取出。

 

4) 类型转换中的错误处理

a) 原因:如果不按照指定的格式进行输入就会产生错误

b) 处理步骤:在struts.xml文件中配置失败后跳转的页面,name=input

     用<s:fielderror name="">输出

c) 如何输出指定的错误信息?

<constant name=“struts.custom.i18.resources” value="messageResource">

     新建资源文件messageResource_zh_CN.properties,代码如下:

     xwork.default.invalid.fieldvalue={0}字段类型转换失败

d) 如何为每个字段输出指定的错误信息?

i. 只能使用局部类型转换器

ii. ActionName.properties

iii. invalid.fieldvalue.属性名=错误提示信息

struts 2输入校验(非重点)

1) 通过实现validate方法

a) this.addActionError

b) 配置input跳转页面

2) 如何保存用户上次输入的表单信息

a) 通过s标签

b) 通过el表达式从值栈里去

c) 通过ognl表达式总parameters里取

i. 如果取得是普通字段#parameters.username

ii. 如果取的是对象里的某个字段#parameters[‘user.username’]

3) this.addFieldError  

<s:fielderror><s:param>username

4) 使用内建的校验器

a) com.opensymphony.xwork2.validator.validators.default.xml

b) 编写校验文件

i. 文件名:ActionName-validation.xml

ii. 存放在Action的同目录下

iii. 字段校验器配置风格<fieldname=”username”><field-validator type=”required”><message>请输入用户名

iv. 非字段校验器配置风格<validator type=”required”><param name=”fieldname”>username</param><message>请输入用户名</message>

struts2文件上传

1) 注意enctype="multipart/form-data"

2) Action中设置三个属性

a) [FileName]:表单文件域中的参数名

b) [FileName]ContentType

c) [FileName]FileName

3) 注意设置文件上传的路径String uploadPath = ServletActionContext.getServletContext().getRealPath("/upload");

4) 动态设置文件上传目录

a) 在struts.xml中对应的action部分添加<param name=”savePth”>E:/xxx</param>

b) 在action中添加savePath属性的get/set方法

5) 限制文件上传大小和类型

a) 文件上传拦截器fileUpload

b) 参数allowedTypes设置允许上传文件的类型,参考服务器web.xml

c) 参数maximumSize设置允许上传文件的大小,例如61400

d) 在struts.xml文件中设置文件上传拦截器,注意拦截器的覆盖,要添加默认拦截器<interceptor-ref name="defaultStack"></interceptor-ref>

6) 自定义上传错误提示信息

a) 配置input,为上传失败的页面

b) 添加<s:filederror/>输出错误信息

7) 国际化错误信息

a) 指定资源文件[fileUploadError]_zh_CN.properties

b) 文件太大的key:struts.messages.error.file.too.large

c) 类型不允许的key:struts.messages.error.content.type.not.allowed

struts2国际化(非重点)

1) Internationalization(i18n)

2) 加载全局资源文件完成国际化

a) 在struts.xml中添加<constant name=” struts.custom.i18n.resources”value=”messageResources”>,用来配置全局资源文件。

b) 新建全局资源文件messageResources_zh_CN.properties,内容为welcomeMessage=

c) 新建全局资源文件messageResources_en_US.properties,内容为welcomeMessage=Hello,everyone!

3) 临时指定资源文件完成国际化

a) <s:i18n name="messageResource">

4) 为资源文件传递参数

a) 可以在text标签中添加param标签向资源文件传递参数

b) 资源文件通过占位符接受参数

5) 资源文件加载顺序

a) 如果使用了i18标签指定临时资源文件,则从临时资源文件找

b) 如果在临时资源文件中没有找到,则查找全局资源文件

c) 如果在全局资源文件中任然没有找到,则直接输出key

d) 如果没有使用i18标签指定临时资源文件,则从全局寻找,若没有直接输出key值

6) Action国际化

a) 加载全局资源文件完成国际化

i. 在action中定义输出变量

ii. 通过getText方法给变量赋值

b) 加载包范围资源文件完成国际化

i. 命名规则:package_zh_CN.properties

ii. 位置:包下,只能被包中的action访问

c) 加载Action范围资源文件完成国际化

i. 命名规则:ActionName_language_country.properties

ii. 位置:保存在action的同目录下,只能被对应的action访问

d) 加载顺序

Action中属性值注入

1) ParametersInterceptor

a) doIntercept;

b) setParameters(action, stack, parameters);

c) for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {

d) newStack.setParameter(name, value);

el表达式为什么可以取出值栈里的内容

1) StrutsPrepareAndExecuteFilter

2) request = prepare.wrapRequest(request);

3) StrutsRequestWrapper.getAttribute()

4) public Object getAttribute(String key) {

5) Object attribute = super.getAttribute(key);

6) ValueStack stack = ctx.getValueStack();

 

 

 

 

需求1:

之前我们的视图跳转都是以dispacher转发到jsp这种形式,现在我要扩展一个新的result type,专门用来处理json数据, 同时,我要保留原来的jsp视图。现在,就需要我们扩展一个新的result type,专门用来处理json数据格式的跳转。

(客户端向服务端请求json数据,服务端只能通过out的方法向客户端写入)

 自定义result步骤:

 (1)新建一个result类,实现result接口,给出execute方法的具体实现

 (2)execute()方法,通过拿到response向页面写入json数据

 (3)怎样拿到action中的数据模型并转为json数据

      arg0.getStack().findValue(property)),需要提供模型的get/set方法

 (4)新建struts-plugin.xml,具体参考官方demo

 (5)修改struts.xml,在result中加入要转为json格式的属性值得名称

(会出现java.lang.NoSuchFieldException: DEFAULT_PARAM异常,但不影响运行结果,暂时还没找到解决方法。可以去掉log4j.properties来消除异常信息)

需求2:

(1)需求:我们现在自己做了一套界面,现在第三方公司向要获取我们公司的数据,但是又不想用我们的界面,界面是由第三方公司自行设计的,

             并且是由json数据格式进行展示的。

(2)自定义拦截器:

      拦截第三放公司的请求,把他们需要获取的数据转换为json数据.为了实现上述目的,拦截器就需要更改action中的return值

arg0.getInvocationContext().getValueStack().setValue("success", "json");

Map<String,Object> params = arg0.getInvocationContext().getParameters();

arg0.getInvocationContext().setParameters(params);

(3)自定义拦截器加载问题

struts2工作流程

1) 客户端发送请求

2) 请求经过一系列的过滤器(StrutsPrepareAndExecuteFilter)

3) StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action

4) 如果ActionMapper决定需要调用某个ActionStrutsPrepareAndExecuteFilter则把请求交给ActionProxy

5) ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action

6) ActionProxy创建一个ActionInvocation的实例

7) 在调用Action前后涉及到相关拦截器的调用

8) Action执行完毕,ActionInvocation根据struts.xml中的配置找到对应的返回结果

struts2环境搭建

struts2配置

OGNL表达式

struts2标签

struts2拦截器

struts2类型转换

struts 2输入校验

struts2文件上传

struts2国际化

Action中属性值注入

el表达式为什么可以取出值栈里的内容

struts2工作流程

MVC模式介绍

1) model1架构模式:

核心是JSP文件,用户提交信息给JSP页面,JSP页面接受用户提交的值,并通过JavaBean连接数据库和操作数据库,然后将结果返回给用户。项目中包含大量的JSP文件及少量JavaBean,不方便维护。

2) model2架构模式:

核心是JSPServlet,也称为MVC模式。M为模型,一般采用JavaBean来实现;V为视图,一般采用JSP来实现,C为控制器,一般采用Servlet来实现。

struts2环境搭建

1) 下载struts2框架,以struts-2.3.15.1为例

2) 下载eclipsemyeclipse(以后均已eclipse为例),打开eclipse,配置好JDKTomcat

3) 新建web工程struts2

4) 打开下载好的struts2框架,进入app,解压struts2-blank,

5) 复制WEB-INF/lib下的的jar包到工程的lib目录下

6) 打开struts2-blank下的web.xml,复制filterfilter-mapping到工程的web.xml

7) 复制struts2-blank\WEB-INF\classes下的struts.xml到工程的src

8) 打开struts.xml,注释掉里面所有的内容,照着样例新建package节点

9) 新建hello.jsp,浏览器里输入http://127.0.0.1:8080/struts2/hello

常量struts.devMode,设置为true即为开发者模式,修改配置文件以后立即生效,可以显示更加详细的错误信息。

添加struts2源码支持:右键struts2-core-2.3.15.1.jar,添加源码的位置

struts2配置

1) constant:定义struts常量值

2) package

3) namespace:定义action的访问路径

4) action

a) 默认执行ActionSupport

b) 也可以自定义action,有三种方法

i. 自定义一个action,写一个execute方法

ii. 自定义一个action,实现Action接口,重写execute方法

iii. 自定义一个action,继承ActionSupport,重写execute方法(推荐使用)

5) result:定义要转向的视图,与action的方法的返回值相对应

a) 常用四种类型

i. dispatcher(默认)

ii. redirect

iii. chain

iv. redirectAction

v. freemarker

vi. httpreader

vii. stream

viii. velocity

ix. xslt

x. plaintext

xi. tiles

b) global-results:全局结果对象

c) 动态结果集

i. 在action中保存一个属性,存储具体结果的location

6) action动态方法调用

a) 指定method属性

b) 通配符*{通配符的序号,从1开始}

7) action接受参数

a) action的属性接受参数

b) DomainModel接受参数

c) ModelDriven接受参数,需要实现ModelDriven接口,重写getModel方法

OGNL表达式

1) OGNLObject-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL

2) ognl表达式取值设值(上下文与root

3) value stack值栈

a) 是多个对象的一个集合,相对于OGNL来说是一个单一的对象

b) 作为ognlroot

c) Struts2框架把OGNL Context设置为我们的ActionContext

1. application

2. session

3. value stack(root)

4. action (the current action)

5. request

6. parameters

7. attr (searches page, request, session, then application scopes)

d) action的实例将会被入值栈中,值栈又作为OGNL表达式的root,所以当取action中的属性值时,不需要加#

4) 通过struts标签取值

a) 取值栈里的值

b) 去ActionContext其他对象的值,需要加#

struts2标签(非重点)

1) property:输出指定值

2) if/elseif/else:条件逻辑控制

3) iterator:遍历集合,有三个属性id,status,value

a) id:遍历取得的每一个元素都保存在id变量中

b) status:IteratorStatus实例对象

c) value:OGNL表达式

4) include:包含另一个页面

5) fielderror:一般用于输入校验

6) action:允许在JSP中直接访问并调用Action

7) bean:允许在JSP页面中创建JavaBean实例

8) debug:可以用来输出服务器端对象中的信息

9) date:格式化输出的的日期

10) ui:参考文档:Tag Developers Guide > Struts Tags > Tag Reference > UI Tag Reference

struts2拦截器

1) 什么是拦截器

a) 电梯开关门

b) 动态代理

 

2) 如何定义一个拦截器

a) 实现Interceptor接口

b) 继承AbstractInterceptor

3) 配置拦截器

a) 在struts.xml中添加interceptors节点

b) 在action节点中引入拦截器

struts2类型转换(非重点)

1) 类型转化的意义

a) WEB应用程序交互都是建立在HTTP协议之上的,互相传递的都是字符串。

b) WEB应用程序中,使用了多种数据类型,譬如int,float,date等等。

2) 内置类型转换器

a) boolean/Boolean、char/Character、int/Integer、folat/Float、long/Long、double/Double

b) date

c) Collection

d) Set

e) 数组类型

3) 自定义类型转换器

    自定义类型转换器要实现TypeConverter接口,可直接继承DefaultTypeConverter

    可使用Struts 2提供的StrutsTypeConverter

a) 局部类型转换器

定义一个转换器类,新建属性文件[ActionName]-conversion.properties, 文件里的内容是propertyName=ConvertName

b) 全局类型转换器

            定义一个转换器类,新建属性文件xwork-conversion.properties,文件里的内容是ClassName=ConvertName。

            对于转换器转换的数据模型,一定要用<s:property>取出。

 

4) 类型转换中的错误处理

a) 原因:如果不按照指定的格式进行输入就会产生错误

b) 处理步骤:在struts.xml文件中配置失败后跳转的页面,name=input

     用<s:fielderror name="">输出

c) 如何输出指定的错误信息?

<constant name=“struts.custom.i18.resources” value="messageResource">

     新建资源文件messageResource_zh_CN.properties,代码如下:

     xwork.default.invalid.fieldvalue={0}字段类型转换失败

d) 如何为每个字段输出指定的错误信息?

i. 只能使用局部类型转换器

ii. ActionName.properties

iii. invalid.fieldvalue.属性名=错误提示信息

struts 2输入校验(非重点)

1) 通过实现validate方法

a) this.addActionError

b) 配置input跳转页面

2) 如何保存用户上次输入的表单信息

a) 通过s标签

b) 通过el表达式从值栈里去

c) 通过ognl表达式总parameters里取

i. 如果取得是普通字段#parameters.username

ii. 如果取的是对象里的某个字段#parameters[‘user.username’]

3) this.addFieldError  

<s:fielderror><s:param>username

4) 使用内建的校验器

a) com.opensymphony.xwork2.validator.validators.default.xml

b) 编写校验文件

i. 文件名:ActionName-validation.xml

ii. 存放在Action的同目录下

iii. 字段校验器配置风格<fieldname=”username”><field-validator type=”required”><message>请输入用户名

iv. 非字段校验器配置风格<validator type=”required”><param name=”fieldname”>username</param><message>请输入用户名</message>

struts2文件上传

1) 注意enctype="multipart/form-data"

2) Action中设置三个属性

a) [FileName]:表单文件域中的参数名

b) [FileName]ContentType

c) [FileName]FileName

3) 注意设置文件上传的路径String uploadPath = ServletActionContext.getServletContext().getRealPath("/upload");

4) 动态设置文件上传目录

a) 在struts.xml中对应的action部分添加<param name=”savePth”>E:/xxx</param>

b) 在action中添加savePath属性的get/set方法

5) 限制文件上传大小和类型

a) 文件上传拦截器fileUpload

b) 参数allowedTypes设置允许上传文件的类型,参考服务器web.xml

c) 参数maximumSize设置允许上传文件的大小,例如61400

d) 在struts.xml文件中设置文件上传拦截器,注意拦截器的覆盖,要添加默认拦截器<interceptor-ref name="defaultStack"></interceptor-ref>

6) 自定义上传错误提示信息

a) 配置input,为上传失败的页面

b) 添加<s:filederror/>输出错误信息

7) 国际化错误信息

a) 指定资源文件[fileUploadError]_zh_CN.properties

b) 文件太大的key:struts.messages.error.file.too.large

c) 类型不允许的key:struts.messages.error.content.type.not.allowed

struts2国际化(非重点)

1) Internationalization(i18n)

2) 加载全局资源文件完成国际化

a) 在struts.xml中添加<constant name=” struts.custom.i18n.resources”value=”messageResources”>,用来配置全局资源文件。

b) 新建全局资源文件messageResources_zh_CN.properties,内容为welcomeMessage=

c) 新建全局资源文件messageResources_en_US.properties,内容为welcomeMessage=Hello,everyone!

3) 临时指定资源文件完成国际化

a) <s:i18n name="messageResource">

4) 为资源文件传递参数

a) 可以在text标签中添加param标签向资源文件传递参数

b) 资源文件通过占位符接受参数

5) 资源文件加载顺序

a) 如果使用了i18标签指定临时资源文件,则从临时资源文件找

b) 如果在临时资源文件中没有找到,则查找全局资源文件

c) 如果在全局资源文件中任然没有找到,则直接输出key

d) 如果没有使用i18标签指定临时资源文件,则从全局寻找,若没有直接输出key值

6) Action国际化

a) 加载全局资源文件完成国际化

i. 在action中定义输出变量

ii. 通过getText方法给变量赋值

b) 加载包范围资源文件完成国际化

i. 命名规则:package_zh_CN.properties

ii. 位置:包下,只能被包中的action访问

c) 加载Action范围资源文件完成国际化

i. 命名规则:ActionName_language_country.properties

ii. 位置:保存在action的同目录下,只能被对应的action访问

d) 加载顺序

Action中属性值注入

1) ParametersInterceptor

a) doIntercept;

b) setParameters(action, stack, parameters);

c) for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {

d) newStack.setParameter(name, value);

el表达式为什么可以取出值栈里的内容

1) StrutsPrepareAndExecuteFilter

2) request = prepare.wrapRequest(request);

3) StrutsRequestWrapper.getAttribute()

4) public Object getAttribute(String key) {

5) Object attribute = super.getAttribute(key);

6) ValueStack stack = ctx.getValueStack();

 

 

 

 

需求1:

之前我们的视图跳转都是以dispacher转发到jsp这种形式,现在我要扩展一个新的result type,专门用来处理json数据, 同时,我要保留原来的jsp视图。现在,就需要我们扩展一个新的result type,专门用来处理json数据格式的跳转。

(客户端向服务端请求json数据,服务端只能通过out的方法向客户端写入)

 自定义result步骤:

 (1)新建一个result类,实现result接口,给出execute方法的具体实现

 (2)execute()方法,通过拿到response向页面写入json数据

 (3)怎样拿到action中的数据模型并转为json数据

      arg0.getStack().findValue(property)),需要提供模型的get/set方法

 (4)新建struts-plugin.xml,具体参考官方demo

 (5)修改struts.xml,在result中加入要转为json格式的属性值得名称

(会出现java.lang.NoSuchFieldException: DEFAULT_PARAM异常,但不影响运行结果,暂时还没找到解决方法。可以去掉log4j.properties来消除异常信息)

需求2:

(1)需求:我们现在自己做了一套界面,现在第三方公司向要获取我们公司的数据,但是又不想用我们的界面,界面是由第三方公司自行设计的,

             并且是由json数据格式进行展示的。

(2)自定义拦截器:

      拦截第三放公司的请求,把他们需要获取的数据转换为json数据.为了实现上述目的,拦截器就需要更改action中的return值

arg0.getInvocationContext().getValueStack().setValue("success", "json");

Map<String,Object> params = arg0.getInvocationContext().getParameters();

arg0.getInvocationContext().setParameters(params);

(3)自定义拦截器加载问题

struts2工作流程

1) 客户端发送请求

2) 请求经过一系列的过滤器(StrutsPrepareAndExecuteFilter)

3) StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action

4) 如果ActionMapper决定需要调用某个ActionStrutsPrepareAndExecuteFilter则把请求交给ActionProxy

5) ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action

6) ActionProxy创建一个ActionInvocation的实例

7) 在调用Action前后涉及到相关拦截器的调用

8) Action执行完毕,ActionInvocation根据struts.xml中的配置找到对应的返回结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值