Struts2框架学习总结(从入门到精通)

一、Struts2入门

struts2概述

  1. javaee三层中的web层
  2. 在struts1和webwork基础上的全新的框架
  3. 解决一些问题
    ①当功能很多,会创建很多的servlet,那么维护起来不方便,在javaweb阶段我们是通过BaseServlet的的底层反射来实现的
    在这里插入图片描述
  4. struts2版本
    在这里插入图片描述
    目前比较稳定的版本
  5. web层框架
    ①struts2
    ②springMVC

struts2入门案例

  1. 从lib目录中导入jar包,但是里面可能上百个jar包,你可以从app目录(里面是一些案例,最好从blank案例中拿)中找到里面的web-inf->lib下的jar包进行copy
    在这里插入图片描述
    在这里插入图片描述
    关于jar包详情可参考:https://blog.csdn.net/For_ZZHacker/article/details/85675995
  2. 创建action(这里的action就相当于javaweb学的servlet)

① 每次访问servlet的时候都会默认执行service方法(写一个servlet:写一个类的时候需要继承httpservlet类,然后重写里面的方法(例如doget,dopost),然后再web.xml中配置访问servlet的路径)
② 每次访问action的时候都会默认执行execute方法(同样需要配置action的访问路径,见下一步)

在这里插入图片描述

  1. 配置action类的访问路径
    ① 创建struts2的核心配置文件,该配置文件的名称和位置是固定的,跟hibernate的配置文件一样。位置在src下面,文件名称叫struts.xml
    ② 引入dtd的约束
    在这里插入图片描述
    在这里插入图片描述
    访问路径为:http://127.0.0.1:8080/项目名/hello.action
    (action可加可不加,常用浏览器例如火狐,谷歌,IE没问题,杂牌浏览器还是加上后面的action有可能会出错)
    注意:此时访问会出现404问题,一个可能是服务器启动报异常了,另一个就是没有配置过滤器!!!
  2. 配置struts2的过滤器(在web.xml中配置)
    (struts2已经帮我们封装好了过滤器,我们只需要配置一下即可)
    在这里插入图片描述
    在这里插入图片描述
    此时再去访问就会访问成功!!!
  3. 小总结:通过一个案例我们知道了使用框架我们可以少些很多的代码,他给我们封装了许多代码,但是我们需要去配置运用这些封装好了的类。
    另外:struts.xml里面有许多的action,web.xml就定义了一个过滤器

struts2底层执行过程

  1. 几个概念
    过滤器是在启动服务器的时候创建的,servlet默认是在第一次访问的时候创建的
    框架的学习反射是重点!!!!
    在这里插入图片描述

  2. 查看过滤器源代码

    在这里插入图片描述
    里面有init方法,doFilter方法,destroy方法
    ①过滤器在服务器启动的时候就会执行,创建过滤器时候执行init方法

  • init方法中加载struts2自带的配置文件和自己创建的配置文件(struts.xml,web.xml)
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 现在再来看一下第二个加载的配置文件是什么在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述

小总结:我们开发的时候只需要关心struts.xml,web.xml这两个需要自己配的配置文件即可

struts2相关配置

struts2的核心配置文件struts.xml

在这里插入图片描述
在这里插入图片描述
最大的标签是<struts> 里面有3个常用标签从大到小<package><action><results>,以及里面的属性.
① package标签

  • 类似一个代码包,区别不同的action,要配置action,必须首先写package标签,在package标签中才能配置action
  • package标签属性
    - name属性:用来区分不同的package,随便起名
    - extends属性:就是个继承的意思在这里插入图片描述
    - namespace属性:不写默认也是“/”,最好写上。
    在这里插入图片描述

② action标签

  • action标签主要配置action的访问路径
  • action的标签属性
    - name属性:区分不同的action;package标签中的namespace属性和这里的name属性构成了访问路径
    - class属性:全路径=包名+类名,通过反射的原理去执行该类的
    - method属性:在这里插入图片描述

③ result标签

  • 根据你的action中的方法返回值,将页面定位到指定的页面或action上
  • result标签的属性
    - name属性:和你方法的返回值要一样
    在这里插入图片描述
    里面的“/”代表的是当前项目的根目录
    - type属性
    在这里插入图片描述
    有4个值:dispatcher(默认),redirect,chain,redirectAction
    dispatcher(默认)和redirect:result标签中“/”代表的是项目根路径,不写就代表当前路径下
    chain和redirectAction:result标签中“/”没有任何意义,不需要写,写了就是多余,也就是只能从当前路径去指定页面!!!
    chain:只能转发到同一命名空间下的Action
    redirect:可以重定向到action中去,也可以重定向到显示页面中去

转发后页面变了,但是地址栏并没变,本质来讲转发就是同一个请求,重定向是又一次新的请求(相当于2次请求)

struts2常量配置

  1. struts2框架,帮我们实现一部分功能,struts2里面有常量,在常量里面封装一部分功能。
  2. struts2默认的常量位置(记住)
    在这里插入图片描述
  3. 修改struts2默认常量值
    ① 常用方法
    在这里插入图片描述
    该标签写<struts>下面,和<package>标签同级
    ② 还有2种方式(了解)
    在这里插入图片描述
  4. 常用常量
    在这里插入图片描述
    在这里插入图片描述

分模块开发

  1. 每个人自己的模块配置文件单独开发,最后合并引入到核心配置文件中就行,这样就不会将我们的核心配置文件给弄乱了。在这里插入图片描述

在这里插入图片描述

struts2的action创建

action的编写方式

  1. action编写的3种方式在这里插入图片描述
  2. 创建类,实现Action接口方式(将一些常用的返回值定义为常量例如SUCCESS=“success”),不常用在这里插入图片描述在这里插入图片描述
  3. 创建类,继承类ActionSupport,常用
    在这里插入图片描述
    当然也可以用那些常量,因为也实现了interface Action
    在这里插入图片描述

struts2的action方法访问(重点)

  1. 一共三种方式实现
    第一种:使用action标签的method属性,在这个属性里面写执行的action的方法,不写默认执行execute()方法
    在这里插入图片描述
    第二种:使用通配符的方式实现
    在这里插入图片描述
    第三种:动态访问实现(不用)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 一个错误演示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. 一个action访问不同方法的例子
  • 普通方式在这里插入图片描述
  • 使用通配符的方式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  1. 又是一个struts2应用的案例
    在这里插入图片描述
    在这里插入图片描述

二、Struts2数据操作

结果页面的配置

  1. 全局结果页面
    使用global-results标签将result标签写这里面,global-results标签位于package标签里面,此时action标签默认就有global-results标签中包含的result标签
    在这里插入图片描述
  2. 局部结果页面
    在这里插入图片描述
  3. result标签type属性
    在这里插入图片描述
    在这里插入图片描述

在action获取表单提交的数据

  1. 使用ActionContext类获取
    在这里插入图片描述
    在这里插入图片描述
  • 一个例子来演示
  • 创建表单,提交表单到action里面在这里插入图片描述
  • 在这里插入图片描述
  1. 使用ServletActionContext类获取
    在这里插入图片描述
    在这里插入图片描述
  2. 使用接口注入方式获取(实现不同的接口,例如ServletRequestAware接口里面有个方法可以设置出request对象)

让action实现接口,为了得到request对象,需要新建一个成员变量来进行赋值的,然后在execute方法中才能使用
ware:器皿,物品—》容器
在这里插入图片描述

在这里插入图片描述
request用的多,session经典案例是用在登录的时候,context用的少

struts2提供获取表单数据方式(减少了代码,替代了上面的方式例如:ServletActionContext)

原始的写法获取表单数据并封装到实体类中(麻烦费劲,但是有效稳定)
在这里插入图片描述

  1. 属性封装(会用即可)
    在这里插入图片描述
    在这里插入图片描述
  2. 模型驱动封装(重点)
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  1. 表达式封装(也可以认为是属性封装的特例,因为写法原理一样)
    在这里插入图片描述
    在这里插入图片描述

struts2获取数据封装到集合中

  1. 封装到list集合
    在这里插入图片描述
  2. 封装到map集合
    在这里插入图片描述

扩展-表达式封装和模型驱动比较

相同点:都封装到实体类中
不同点:模型驱动只能封装到同一个实体类对象中,表达式封装可以封装到不同实体类中
在这里插入图片描述
在这里插入图片描述

案例-添加客户功能

在这里插入图片描述
在这里插入图片描述

三、Struts2值栈

OGNL概述

  1. web阶段用EL表达式在jsp页面中来获取域对象里面的值
  2. ognl表达式比EL表达式功能更强大
    在这里插入图片描述

(1)在struts2里面操作值栈数据
(2)一般把ognl在struts2操作:和struts2标签一起使用操作值栈

EL表达式,OGNL表达式(从表单获取数据三种方式中的表达式方式(隶属于属性封装方式))
html标签,jstl标签,struts2标签

  1. OGNL不是struts2的一部分,单独的项目,经常和struts2一起使用
    (1)使用ognl时候首先导入jar包,struts2提供了ognl的jar包

OGNL入门案例

在这里插入图片描述

什么是值栈

在这里插入图片描述
在这里插入图片描述

获取值栈对象

在这里插入图片描述
在这里插入图片描述

值栈内部结构

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

下图中root部分是个栈,栈里面有2个元素,因为没有操作值栈,所以栈顶元素是当前值栈所在action的一个引用(为了方便操作的),当你往栈里面放东西就会放到栈顶的位置上。
在这里插入图片描述

向值栈放数据

1 向值栈放数据多种方式
第一种 获取值栈对象,调用值栈对象里面的 set 方法

在这里插入图片描述
在这里插入图片描述
第二种 获取值栈对象,调用值栈对象里面的 push方法

在这里插入图片描述
在这里插入图片描述

第三种 在action定义变量,生成变量的get方法(好处是减少空间的分配了)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

向值栈放对象

在这里插入图片描述

向值栈放list集合

在这里插入图片描述
在这里插入图片描述

从值栈获取数据

1 使用struts2的标签+ognl表达式获取值栈数据
(1)<s:property value=”ognl表达式”/>

获取字符串

1 向值栈放字符串
在这里插入图片描述
2 在jsp使用struts2标签+ognl表达式获取
在这里插入图片描述

获取对象

在这里插入图片描述

获取list集合

在这里插入图片描述
在这里插入图片描述
第三种方式使用struts2的iterator标签类似于jstl的foreach标签
在这里插入图片描述
在这里插入图片描述
想使用context里面的数据需要加个“#”,将数据放到context这样的操作目的是为了方便取值,不占用root部分,提高效率
在这里插入图片描述
这里注意一下application,其实就是ServletContext对象,记得这个applicatIon域中是共享的

foreach+EL表达式的方式(需要jstl.jar包和standard.jar,并且在开头引入c标签taglib uri是jstl/core)
在这里插入图片描述

其他操作

在这里插入图片描述
ognl的数组获取值的写法先写下标,再写数组名,中间有点号,值栈的栈顶就是0号位置,依次向下排,所有的都会放到这个top数组,不是只有push这种没有key的。
注意:很多种写法都用<s:property value="ognl表达式">来获取,实质上这个标签是从栈顶先来寻找符合的值,找到就直接显示,不管后面符合该表达式的值了。

EL表达式获取值栈数据(为什么能取到)

如果数据在值栈中虽然能取到,但是性能很低,因为有多余操作,例如先去域对象中找等等。
先看例子:能够取到值栈中的数据
在这里插入图片描述
在这里插入图片描述
先解释一个词wrap:包起来,穿外衣,缠绕—》本质就是增强的意思
源码里面会有这个词,以及wrapper可以理解为包装器和增强器
EL表达式中就是对request进行了增强,本质就是对getAttubute进行了增强
看源码首先从struts2的过滤器中开始看-----》找到里面有个doFilter方法—》再看到这个doFilter方法中的request被增强了使用wrapRequest(oldRequest)方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后这个选中的ActionContext.put,又将标志值(看好了不是attribute,只是一个标志而已)放到了值栈的第二部分context中去了,其实这个context中包含request对象的引用,Httpsession对象的引用,servletContext对象的引用等等(也因此可以用ognl表达式获取到域对象中的数据),此时put进去就和这些域对象平起平坐了。

ActionContext.getContext.put(String,Object)是把对象放到了StackContext中,这个对象跟request,session等一样,它们平起平坐,但这些都不是root对象(这些是context对象),所以要通过#访问。

request.setAttribute(String,Object)就是把值放到request范围,而StackConext里含有request对象,所以可以通过#request.*来访问。

OGNL的#、%使用

#使用

在这里插入图片描述

%使用

在这里插入图片描述
注意是表单标签
上面这个图就相当于html中的input标签,所以一般不用ognl的表单标签,因为性能低,不如直接用html的表单标签
在这里插入图片描述

案例-显示所有信息列表(用值栈来存数据,以前用的域对象)

首先想到3种方式set,put,直接定义成员变量方式,第三种最常用
在这里插入图片描述

四、Struts2拦截器(interceptor)

拦截器的概述

  1. 拦截器是struts2里面的概念
  2. struts2框架封装的功能都是在拦截器里面
  3. 在没有自定义拦截器的情况下,每次执行action,默认只会执行默认的拦截器
    下图是常量的位置:
    在这里插入图片描述
    下图是struts2里面默认拦截器的位置:
    在这里插入图片描述
    这个文件结构跟自己定义的struts.xml结构差不多
    其中的package标签名字就是struts-default,还定义了result-type,默认是dispatcher
    在这里插入图片描述
    这里还指定了默认的拦截器栈
    在这里插入图片描述

在这个文件中<interceptors>里面定义了大量的<interceptor>这些就是定义的拦截器,还有一些拦截器栈
在这里插入图片描述
下图这些只是引用<interceptor-ref>,真正的定义拦截器是在上面定义的
在这里插入图片描述
4. 拦截器的执行时间:
在action创建之后,执行action中的方法之前 ,执行的拦截器,可以通过在默认的随便一个拦截器上打个断点来验证,会发现先到拦截器中的断点,再到action中的具体方法中的断点上

追踪一个拦截器看一下(就拿这个模型驱动的拦截器来演示一下):
这里是xml文件,用ctrl+鼠标左键不能连接到,先选中用ctrl+shift+t来找到该类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

百度解释拦截器:
一、概述:
java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。
二、原理:
大部分时候,拦截器方法都是通过代理的方式来调用的。Struts 2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。Struts2拦截器是可插拔的,拦截器是AOP的一种实现。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
三、定义一个拦截器
自定义一个拦截器需要三步:
1 .自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。
2 .在struts.xml中注册上一步中定义的拦截器。
3 .在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。
四、与过滤器的区别:
过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西;拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。
1.拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2.拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。
3.拦截器只对action起作用,而过滤器几乎可以对所有请求起作用。
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
5.在action的生命周期里,拦截器可以多起调用,而过滤器只能在容器初始化时调用一次。

拦截器底层原理

1 拦截器底层使用两个原理
第一个 aop思想(aop的底层是动态代理)
(0)后面在spring里面把aop做更深层次分析
(1)文字描述:
Aop是面向切面(方面)编程:有个基本功能,需要扩展功能,不通过修改源代码方式扩展功能。
(2)画图分析:
在这里插入图片描述
第二个 责任链模式
(1)在java中有很多的设计模式,责任链模式是其中的一种
(2)责任链模式和过滤链很相似的
责任链模式:
要执行多个操作,有添加、修改、删除三个操作。
首先执行添加操作,添加操作执行之后 做类似于放行操作,执行修改操作,修改操作执行之后做类似于放行操作,执行删除操作
过滤链:一个请求可有多个过滤器进行过滤,每个过滤器只有做放行才能到下一个过滤器
在这里插入图片描述
2 aop思想和责任链模式如何应用到拦截器里面?

(1)文字描述:

  • 拦截器在action对象创建之后,action的方法执行之前执行

  • 在action方法执行之前执行默认拦截器,执行过程使用aop思想,在action没有直接调用拦截器的方法,使用配置文件方式进行操作

  • 在执行拦截器时候,执行很多的拦截器,这个过程使用责任链模式
    – 假如执行三个拦截器,执行拦截器1,执行拦截器1之后做放行操作,执行拦截器2,执行拦截器2之后做放行,执行拦截器3,执行拦截器3之后放行,执行action的方法

(2)画图分析
在这里插入图片描述

3 查看源代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
源码主要步骤:
在这里插入图片描述

重要概念

1 过滤器和拦截器区别
(1)过滤器:服务器启动时创建,过滤器理论上可以任意内容,比如html、jsp、servlet、图片路径
(2)拦截器:拦截器只可以拦截action

2 Servlet和action区别
(1)servlet默认第一次访问时候创建,创建一次,单实例对象
(2)action每次访问时候创建,创建多次,多实例对象

自定义拦截器

在这里插入图片描述

自定义登录拦截器

1 需求:在项目中,有很多的action的超链接,实现只有是登录的状态,才可以点击action的超链接实现功能,如果不是登录状态,点击action超链接返回到登录页面

2 登录的状态:使用session域对象实现
(1)登录成功之后,把数据放到session里面
(2)判断session是否有值,可以知道是否是登录状态

3 实现登录的基本功能
(1)查询数据库判断用户名和密码
在这里插入图片描述
此时可以在jsp页面用EL表达式来获取到session域中的信息
在这里插入图片描述

4 添加登录拦截器功能
(1)判断是否登录:判断session里面是否有名称是username的值
(2)拦截器实现过程
第一步 创建类,继承MethodFilterInterceptor类
第二步 重写MethodFilterInterceptor类里面的方法写拦截器逻辑
在这里插入图片描述
第三步 配置action和拦截器关系(注册拦截器)
(1)在要拦截的action标签所在的package标签里面声明拦截器

在这里插入图片描述

(2)在具体的action标签里面使用声明的拦截器
在这里插入图片描述
(3)struts2里面执行很多的默认拦截器,但是如果在action里面配置自定义拦截器,
问题:默认的拦截器不会执行了,如果没有到默认拦截器中的功能也可以不引用。
解决:把默认拦截器手动使用一次
在这里插入图片描述
5 配置的拦截器,会对action里面所有的方法都进行拦截
(1)在action里面有login的登录的方法,这个方法不需要拦截,如果这个方法都拦截,问题是,永远登录不进去了

(2)解决:让login方法不进行拦截
这里就是为什么要继承MethodFilterIntercepor类的原因了,如果继承的是AbstractInterceptor类需要用反射的方法才让实现让一些方法不拦截,而继承这个类直接就可以使用配置的方式来实现,如下:

  • 直接通过配置方式让action里面某些方法不进行拦截,多个方法用逗号分隔
    在这里插入图片描述
    6 如果登录状态,直接到功能页面,如果不是登录显示登陆页面
    登录之后出现小问题:
    在这里插入图片描述
    原因:
    在这里插入图片描述
    解决:设置打开的位置是在父窗口中打开,这个target在以前a标签中见过
    在这里插入图片描述

struts2的标签库

0 struts2标签使用jsp页面中

1 s:property: 和ognl表达式在jsp页面中获取值栈数据

2 s:iterator: 获取值栈list集合数据,表示list集合

3 s:debug: 查看值栈结构和数据

Struts表单标签(会用)

1 html表单标签
(1)form : action、method、enctype(上传用过)
(2)输入项

  • 大部分在input里面封装 type=”值”
  • text:普通输入项
  • password:密码输入项
  • radio:单选输入项
  • checkbox:复选输入项
  • file:文件上传项
  • hidden:隐藏项
  • button:普通按钮
  • submit:提交按钮
  • image:图片提交(点击图片,提交表单)
  • reset:重置
  • select:下拉输入项
  • textarea:文本域

2 在struts2里面对应html表单标签大部分都有

而且可以通过查看源代码的方式来看这些标签装换成html标签的样子

不能在标签的前面写该标签的名字,否则不在一行上,因为它会装换成
html标签的时候是用的table->tr->td,要用label标签写名字
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
用map的格式可以解决显示的值和value对应的值不一样的情况!!!
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

缺少两个知识点

1 struts2文件上传

2 错误处理机制

五、一些实用小细节

  1. 当你用eclipse复制一个项目的时候,不但需要修改项目的名,还需要修改项目的上下文路径,也就是你访问的时候需要输入的访问项目的名称。
    右键-》properties
    在这里插入图片描述
  2. 关于页面刷新
    我用的是chrome浏览器:
    F5:刷新网页,重新显示当前页面内容
    Ctrl+F5(Ctrl+Shift+R):重新加载当前网页而不使用缓存内容,缓存虽然加快了显示的速度,但是修改后可能不会正常显示。效果是忽略缓存,强行刷新网页(包括重载js),重新请求
    Shift+F5:用过重新载入新的js脚本,跟ctrl+F5 一样
    Ctrl+Shift+Del 清除Google浏览器缓存的快捷键

F5和Ctrl+F5原理,可参看:https://www.cnblogs.com/cxd4321/archive/2009/03/11/1408425.html
关于客户端的刷新功能,可参看:
http://www.cnblogs.com/volnet/archive/2012/11/02/2752019.html

  1. eclipse一些使用问题
    在这里插入图片描述
    直接启动tomcat也会自动运行publish(发布),但是有时项目很大会有问题,但是最保险的方式是先publish,再start.关闭的时候最好先stop,再start,虽然restart这个功能可以用。
  2. 关于注释
    在这里插入图片描述
    图中是jsp的注释,可以在jsp标签中随便注释,为所欲为。

<!-- -->是html的标签,不能注释掉里面的jstl标签和ognl标签,否则会报错!!!!

  • 51
    点赞
  • 343
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值