JavaWEB(十八)--JSTL表达式

JSTL1.1简介

  • JavaServer Pages Standard Tag Library (1.1 ),它的中文名称为 JSP 标准标签函数库。JSTL是一个标准的已制定好的标签库,可以应用于各种领域,如:基本输入输出、流程控制、循环、XML文件剖析、数据库查询及国际化和文字格式标准化的应用等。从表 7-1 可以知道,JSTL 所提供的标签函数库主要分为五大类:

(1)核心标签库 (Core tag library)
(2)I18N 格式标签库 (I18N-capable formatting tag library)
(3)SQL 标签库 (SQL tag library)
(4)XML 标签库 (XML tag library)
(5)函数标签库 (Functions tag library)
这里写图片描述
- 另外,JSTL 也支持 EL(Expression Language)语法,例如:在一个标准的 JSP 页面中可能会使用到如下的写法:

<%= userList.getUser().getPhoneNumber() %>
使用 JSTL 搭配传统写法会变成这样:
<c_rt:out value="<%= userList.getUser( ).getPhoneNumber( ) %>" />
使用 JSTL 搭配 EL,则可以改写成如下的形式:
<c:out value="${userList.user.phoneNumber}" />

核心标签库 (Core tag library)

  • 核心标签库(Core)主要有:基本输入输出、流程控制、迭代操作和 URL 操作
    这里写图片描述

  • 在 JSP 中要使用 JSTL 中的核心标签库时,必须使用<%@ taglib %>指令,并且设定 prefix 和uri 的值,通常设定如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

表达式操作

  • 表达式操作分类中包含四个标签:、、和。接下来将依序介绍这四个标签的用法。

<c:out>
<c:out>主要用来显示数据的内容,就像是 <%= scripting-language %> 一样,例如:
Hello ! <c:out value="${username}" />
语法
语法 1:没有本体(body)内容
<c:out value="value" [escapeXml="{true|false}"] [default="defaultValue"] />
语法 2:有本体内容
<c:out value="value" [escapeXml="{true|false}"]>
default value
</c:out>

属性:

这里写图片描述

Null 和 错误处理:

  • · 假若 value 为 null,会显示 default 的值;假若没有设定 default 的值,则会显示一个空
    的字符串。说明一般来说,默认会将 <、>、’、” 和 & 转换为 <、>、'、" 和 &。假若不想转换时,只需要设定的 escapeXml 属性为 fasle 就可以了
    这里写图片描述
  • 范例
<c:out value="Hello JSP 2.0 !! " />
<c:out value="${ 3 + 5 }" />
<c:out value="${ param.data }" default="No Data" />
<c:out value="<p>有特殊字符</p>" />
<c:out value="<p>有特殊字符</p>" escapeXml="false" />

1.在网页上显示 Hello JSP 2.0 !! ;
2.在网页上显示 83.在网页上显示由窗体传送过来的 dat
null 时,则网页上会显示 No Data;
4.在网页上显示“<p>有特殊字符</p>
5.在网页上显示“有特殊字符”。

<c:set>
<c:set>主要用来将变量储存至 JSP 范围中或是 JavaBean 的属性中。
语法
语法 1:将 value 的值储存至范围为 scope 的 varName 变量之中
<c:set value="value" var="varName" [scope="{ page|request|session|application }"]/>
语法 2:将本体内容的数据储存至范围为 scope 的 varName 变量之中
<c:set var="varName" [scope="{ page|request|session|application }"]>
… 本体内容
</c:set>
语法3:
将 value 的值储存至 target 对象的属性中
< c:set value="value" target="target" property="propertyName" />
语法 4:
将本体内容的数据储存至 target 对象的属性中
<c:set target="target" property="propertyName">
… 本体内容
</c:set>

  • 属性:
    这里写图片描述

Null 和 错误处理
语法 3 和语法 4 会产生异常错误,有以下两种情况:
☆ target 为 null
☆ target 不是 java.util.Map 或 JavaBean 对象
假若 value 为 null 时:将由储存变量改为移除变量
☆ 语法 1:由 var 和 scope 所定义的变量,将被移除
□ 若 scope 已指定时,则 PageContext.removeAttribute(varName, scope)
□ 若 scope 未指定时,则 PageContext.removeAttribute(varName)
☆ 语法 3:
□ 假若 target 为 Map 时,则 Map.remove(property)
□ 假若 target 为 JavaBean 时,property 指定的属性为 null

  • 使用时,var 主要用来存放表达式的结果;scope 则是用来设定储存的范围,例如:假若 scope=”session”,则将会把数据储存在 session 中。如果中没有指定 scope 时,则它会默认存在 Page 范围里。
    这里写图片描述
  • 考虑下列的写法:
<c:set var="number" scope="session" value="${1 + 1}"/>
  • 把 1+1 的结果 2 储存到 number 变量中。如果c:set没有 value 属性,此时 value 之值在c:set和/c:set之间,本体内容看下面的范例
<c:set var="number" scope="session">
<c:out value="${1+1}" />
</c:set>

上面的 <c:out value="${1+1}" /> 部分可以改写成 2 或是 <%=1+1%> ,结果都会一样,也就
是说,<c:set>是把本体(body)运算后的结果来当做 value 的值。另外,<c:set>会把 body 中最开头
和结尾的空白部分去掉。如:
<c:set var="number" scope="session">
_____________1 + 1
</c:set>
则 number 中储存的值为 1 + 1 而不是 1 + 1。
范例
<c:set var="number" scope="request" value="${1 + 1}" />
<c:set var="number" scope="session" />
${3 + 5}
</c:set>
<c:set var="number" scope="request" value="${ param.number }" />
<c:set target="User" property="name" value="${ param.Username}" />
1.将 2 存入 Request 范围的 number 变量中;
2.将 8 存入 Session 范围的 number 变量中;
3.假若 ${param.number}为 null 时,则移除 Request 范围的 number 变量;若${param.number}
不为 null 时,则将 ${param.number}的值存入 Request 范围的 number 变量中;
4.假若 ${param.Username}为 null 时,则设定 User(JavaBean)的 name 属性为 null;若不为
null 时,则将 ${param.Username}的值存入 User(JavaBean)的 name 属性(setter 机制)。
● <c:remove>
<c:remove>主要用来移除变量。
语法
<c:remove var="varName" [scope="{ page|request|session|application }"] />

  • 属性:
    这里写图片描述

说明
<c:remove>必须要有 var 属性,即要被移除的属性名称,scope 则可有可无,例如:
<c:remove var="number" scope="session" />
将 number 变量从 Session 范围中移除。若我们不设定 scope,则<c:remove>将会从 Page、
Request、Session 及 Application 中顺序寻找是否存在名称为 number 的数据,若能找到时,
则将它移除掉,反之则不会做任何的事情。


流程控制

流程控制分类中包含四个标签:<c:if>、<c:choose>、<c:when>和<c:otherwise>,
● <c:if>
<c:if>的用途就和我们一般在程序中用的 if 一样。
语法
语法 1:没有本体内容(body)
<c:if test="testCondition" var="varName"
[scope="{page|request|session|application}"]/>
语法 2:有本体内容
<c:if test="testCondition" [var="varName"]
[scope="{page|request|session|application}"]>
具体内容
</c:if>

  • 属性
    这里写图片描述
  • 说明

<c:if> 标签必须要有 test 属性,当 test 中的表达式结果为 true 时,则会执行本体内容;如
果为 false,则不会执行。例如:${param.username = = 'admin'},如果 param.username 等于 admin
时,结果为 true;若它的内容不等于 admin 时,则为 false。
接下来看下列的范例:
<c:if test="${param.username = = 'admin' }">
ADMIN 您好!! //body 部分
</c:if>
如果名称等于 admin,则会显示"ADMIN 您好!! "的动作,如果相反,则不会执行<c:if>的 body
部分,所以不会显示"ADMIN 您好!! //body 部分"。另外<c:if>的本体内容除了能放纯文字,还可以
放任何 JSP 程序代码(Scriptlet)、JSP 标签或者 HTML 码。
除了 test 属性之外,<c:if>还有另外两个属性 var 和 scope。当我们执行<c:if>的时候,可以
将这次判断后的结果存放到属性 var 里;scope 则是设定 var 的属性范围。哪些情况才会用到 var
和 scope 这两个属性呢?例如:当表达式过长时,我们会希望拆开处理,或是之后还须使用此结果
时,也可以用它先将结果暂时保留,以便日后使用。
● <c:choose>
<c:choose>本身只当做 <c:when> 和 <c:otherwise> 的父标签。
语法
<c:choose>
本体内容( <when> 和 <otherwise> )
</c:choose>
属性

限制
<c:choose>的本体内容只能有:
·空白
·1 或多个 <c:when>
·0 或多个 <c:otherwise>
说明
若使用<c:when>和<c:otherwise>来做流程控制时,两者都必须为<c:choose>的子标签,即:
<c:choose>

<c:when>
</c:when>:
<c:otherwise>
</c:otherwise>

</c:choose>
● <c:when>
<c:when> 的用途就和我们一般在程序中用的 when 一样。
语法
<c:when test="testCondition" >
本体内容
</c:when>

  • 属性
    这里写图片描述
  • 限制

☆ <c:when>必须在<c:choose>和</c:choose>之间
☆ 在同一个<c:choose>中时,<c:when>必须在<c:otherwise>之前
说明
<c:when>必须有 test 属性,当 test 中的表达式结果为 true 时,则会执行本体内容;如果为
false 时,则不会执行。
● <c:otherwise>
在同一个 <c:choose> 中,当所有 <c:when> 的条件都没有成立时,则执行 <c:otherwise> 的
本体内容。
语法
<c:otherwise>
本体内容
</c:otherwise>
属性

限制
·<c:otherwise> 必须在 <c:choose> 和 </c:choose>之间
·在同一个 <c:choose> 中时,<c:otherwise> 必须为最后一个标签
说明
在同一个 <c:choose> 中,假若所有 <c:when> 的 test 属性都不为 true 时,则执行
<c:otherwise> 的本体内容。

  • 范例
<c:choose>
<c:when test="${condition1}">
condition1 为 true
</c:when>
<c:when test="${ condition2}">
condition2 为 true
</c:when>
<c:otherwise>
condition1 和 condition2 都为 false
</c:otherwise>
</c:choose>

范例说明:当 condition1 为 true 时,会显示“condition1 为 true”;当 condition1 为 false
且 condition2 为 true 时,会显示“condition2 为 true”,如果两者都为 false,则会显示“condition1
和 condition2 都为 false”

这里写图片描述


迭代操作

迭代(Iterate)操作主要包含两个标签:<c:forEach>和<c:forTokens>,笔者依此顺序依次说明这两个标签的使用。
● <c:forEach>
<c:forEach> 为循环控制,它可以将集合(Collection)中的成员循序浏览一遍。运作方式为当
条件符合时,就会持续重复执行<c:forEach>的本体内容。
语法
语法 1:迭代一集合对象之所有成员
<c:forEach [var="varName"] items="collection" [varStatus="varStatusName"] [begin="begin"]
[end="end"] [step="step"]>
本体内容
< /c:forEach>
语法 2:迭代指定的次数
<c:forEach [var="varName"] [varStatus="varStatusName"] begin="begin" end="end"
[step="step"]>
本体内容
</c:forEach>

  • 属性
    这里写图片描述
  • 限制

·假若有 begin 属性时,begin 必须大于等于 0
·假若有 end 属性时,必须大于 begin
·假若有 step 属性时,step 必须大于等于 0
Null 和 错误处理
·假若 items 为 null 时,则表示为一空的集合对象
·假若 begin 大于或等于 items 时,则迭代不运算
说明
如果要循序浏览一个集合对象,并将它的内容显示出来,就必须有 items 属性。
范例
下面的范例 Core_forEach.jsp 是将数组中的成员一个个显示出来的:
■ Core_forEach.jsp

<%@ page contentType="text/html;charset=GB2312 " %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>CH7 - Core_forEach.jsp</title>
</head>
<body>
<h2><c:out value="<c:forEach> 的用法" /></h2>
<%
String atts[] = new String [5];
atts[0]="hello";
atts[1]="this";
atts[2]="is";
atts[3]="a";
atts[4]="pen";
request.setAttribute("atts", atts);
%>
<c:forEach items="${atts}" var="item" >
${item}</br
</c:forEach
</body>
</html>

先产生一个字符串数组,然后将此数组 atts 储存至 Request 的属性范围中,
再用<c:forEach>将它循序浏览一遍。这里 items 表示被浏览的集合对象,var 用来存放指定的集合
对象中成员,最后使用<c:out>将 item 的内容显示出来

  • c:forEach除了支持数组之外,还有标准 J2SE 的集合类型,例如:ArrayList、List、
    LinkedList、Vector、Stack 和 Set 等等;另外还包括 java.util.Map 类的对象,例如:HashMap、Hashtable、Properties、Provider 和 Attributes。

  • c:forEach还有 begin、end 和 step 这三种属性:begin 主要用来设定在集合对象中开始的位置(注意:第一个位置为 0);end 用来设定结束的位置;而 step 则是用来设定现在指到的成员和下一个将被指到成员之间的间隔。

● c:forTokens
c:forTokens 用来浏览一字符串中所有的成员,其成员是由定义符号(delimiters)所分隔的。

  • 语法
<c:forTokens items="stringOfTokens" delims="delimiters" [var="varName"]
[varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
本体内容
</c:forTokens>
  • 属性:
    这里写图片描述

这里写图片描述

  • 限制

·假若有 begin 属性时,begin 必须大于等于 0
·假若有 end 属性时,必须大于 begin
·假若有 step 属性时,step 必须大于等于 0
Null 和 错误处理
·假若 items 为 null 时,则表示为一空的集合对象
·假若 begin 大于或等于 items 的大小时,则迭代不运算
说明
<c:forTokens>的 begin、end、step、var 和 varStatus 用法都和<c:forEach>一样,因此,笔
者在这里就只介绍 items 和 delims 两个属性:items 的内容必须为字符串;而 delims 是用来分割
items 中定义的字符串之字符。
范例
下面为一个典型的<c:forTokens>的范例:
<c:forTokens items="A,B,C,D,E" delims="," var="item" >
${item}
</c:forTokens>
上面范例执行后,将会在网页中输出 ABCDE。它会把符号“,”当做分割的标记,拆成 5 个部分,
也就是执行循环 5 次,但是并没有将 A,B,C,D,E 中的“,”显示出来。items 也可以放入 EL 的表达
式,如下:

<%
String phoneNumber = "123-456-7899";
request.setAttribute("userPhone", phoneNumber);
%>
<c:forTokens items="${userPhone}" delims="-" var="item" >
${item}
</c:forTokens>

<%
String phoneNumber = "123-456-7899";
request.setAttribute("userPhone", phoneNumber);
%>
<c:forTokens items="${userPhone}" delims="-" var="item" >
${item}
</c:forTokens>
种字符来分割字符串,它还可以一次设定多个分割字符串用的字符。如下面这个范例

<c:forTokens items="A,B;C-D,E" delims=",;-" var="item" >
${item}
</c:forTokens>
  • 此范例会在网页输出 ABCDE,也就是说,delims 可以一次设定所有想当做分割字符串用的字符。其实用c:forEach也能做到分割字符串,写法如下:
<c:forEach items="A,B,C,D,E" var="item" >
${item}
</c:forEach>
  • 上述范例同样也会在网页输出 ABCDE。c:forEach并没有 delims 这个属性,因c:forEach无法设定分割字符串用的字符,而 c:forEach分割字符串用的字符只有“ ,”,这和使用c:forTokens,delims 属性设为“,”的结果相同。所以如果使用c:forTokens来分割字符串,功能和弹性上会比使用c:forEach来得较大;

URL 操作

  • JSTL 包含三个与 URL 操作有关的标签,它们分别为:c:import、c:redirect和c:url。
    它们主要的功能是:用来将其他文件的内容包含起来、网页的导向,还有 url 的产生。笔者将依序介绍这三个标签。

● <c:import>
<c:import> 可以把其他静态或动态文件包含至本身 JSP 网页。它和 JSP Action 的
<jsp:include>最大的差别在于:<jsp:include>只能包含和自己同一个 web application 下的文件;
而 <c:import>除了能包含和自己同一个 web application 的文件外,亦可以包含不同 web
application 或者是其他网站的文件。
语法
语法 1:
<c:import url="url" [context="context"] [var="varName"]
[scope="{page|request|session|application}"] [charEncoding="charEncoding"]>
本体内容
</c:import>语法 2:
<c:import url="url" [context="context"]
varReader="varReaderName" [charEncoding="charEncoding"]>
本体内容
</c:import>

这里写图片描述

Null 和 错误处理
·假若 url 为 null 或空时,会产生 JspException
说明
首先<c:import>中必须要有 url 属性,它是用来设定被包含网页的地址。它可以为绝对地址或
是相对地址,使用绝对地址的写法如下:
<c:import url="http://java.sun.com" />
<c:import>就会把 http://java.sun.com 的内容加到网页中。
另外<c:import>也支持 FTP 协议,假设现在有一个 FTP 站台,地址为 ftp.javaworld.com.tw,
它里面有一个文件 data.txt,那么可以写成如下方式将其内容显示出来:
<c:import url="ftp://ftp.cse.yzu.edu.tw/data.txt" />
如果是使用相对地址,假设存在一个文件名为 Hello.jsp,它和使用<c:import>的网页存在于
同一个 webapps 的文件夹时,<c:import>的写法如下:
<c:import url="Hello.jsp" />
如果以“/”开头,那么就表示跳到 web 站台的根目录下,以 Tomcat 为例,即 webapps 目录。
假设一个文件为 hello.txt,存在于 webapps/examples/images 里,而 context 为 examples,可以写成以下方式将 hello.txt 文件包含进我们的 JSP 页面之中:
<c:import url="images/hello.txt" />
接下来如果要包含在同一个服务器上,但并非同一个 web 站台的文件时,就必须加上 context
属性。假设此服务器上另外还有一个 web 站台,名为 others,others 站台底下有一个文件夹为 jsp,
且里面有 index.html 这个文件,那么就可以写成如下方式将此文件包含进来:
写成以下方式将 hello.txt 文件包含进我们的 JSP 页面之中:
<c:import url="images/hello.txt" />
接下来如果要包含在同一个服务器上,但并非同一个 web 站台的文件时,就必须加上 context属性。假设此服务器上另外还有一个 web 站台,名为 others,others 站台底下有一个文件夹为 jsp,且里面有 index.html 这个文件,那么就可以写成如下方式将此文件包含进来:

这里写图片描述

  • 除此之外,c:import也提供 var 和 scope 属性。当 var 属性存在时,虽然同样会把其他文件的内容包含进来,但是它并不会输出至网页上,而是以 String 的类型储存至 varName 中。scope 则是设定 varName 的范围。储存之后的数据,我们在需要用时,可以将它取出来,代码如下:
<c:import url="/images/hello.txt" var="s" scope="session" />
  • 我们可以把常重复使用的商标、欢迎语句或者是版权声明,用此方法储存起来,想输出在网页上时,再把它导入进来。假若想要改变文件内容时,可以只改变被包含的文件,不用修改其他网页。

  • 另外,可以在的本体内容中使用,它的功用主要是:可以将参数传递给被包含的文件,它有两个属性 name 和 value;

这里写图片描述

  • 这两个属性都可以使用 EL,所以我们写成如下形式:
<c:import url="http://java.sun.com" >
<c:param name="test" value="1234" />
</c:import>

范例

下 面 为 一 用 到 <c:import> 、 <c:param> 及 属 性 范 围 的 范 例 , Core_import.jsp 和
Core_imported.jsp:

<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>CH7 - Core_import.jsp</title>
</head>
<body>
<h2><c:out value="<c:import> 的用法" /></h2>
<c:set var="input1" value="使用属性范围传到 Core_imported.jsp 中" scope="request"/>包含
core_imported.jsp 中<hr/>
<c:import url="Core_imported.jsp"charEncoding="GB2312" >
<c:param name="input2" value="使用<c:param>传到 Core_imported.jsp 中"/>
</c:import><hr/>
${output1}
</body>
</html>

分别使用和来传递参数。

<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>CH7 - Core_imported.jsp</title>
</head>
<body>
<fmt:requestEncoding value="GB2312" />
<c:set var="output1" value="使用属性范围传到 Core_import.jsp 中" scope="request"/>
${input1}</br>
<c:out value="${param.input2}" escapeXml="true" />
</body>
</html>
  • Core_imported.jsp 是被包含的文件,它会把从 Core_import.jsp 传来的参数分别输出到页面上,必须注意的是 input1 参数是使用属性范围来传递的,因此可以直接用 input1input2使 i n p u t 1 来 得 到 参 数 , 而 i n p u t 2 则 必 须 使 用 {param.input2}来得到参数;

  • 使用c:set来传递值给 Core_import.jsp,这就是c:param无法做到的动作,
    c:param只能从包含端抛给被包含端,但是在属性范围中,可以让包含端也能得到被包含端传来的
    数据;

● <c:url>
<c:url>主要用来产生一个 URL。
语法
语法 1:没有本体内容
<c:url value="value" [context="context"] [var="varName"]
[scope="{page|request|session|application}"] />
语法 2:本体内容代表查询字符串(Query String)参数
<c:url value="value" [context="context"] [var="varName"]
[scope="{page|request|session|application}"] >
<c:param> 标签
</c:url>

  • 属性
    这里写图片描述
  • 说明
<c:url value="http://www.javafan.net " >
<c:param name="param" value="value"/>
</c:url>
  • 可以发现 c:url也可以搭配c:param使用,上面执行结果将会产生一个网址为
    http://www.javafan.net?param=value,我们更可以搭配 HTML 的a使用,如下:
<a href="
<c:url value="http://www.javafan.net " >
<c:param name="param" value="value"/>
</c:url>">Java 爱好者</a>

另外<c:url>还有三个属性,分别为 context、var 和 scope。context 属性和之前的<c:import>相同,可以用来产生一个其他 web 站台的网址。如果<c:url>有 var 属性时,则网址会被存到 varName中,而不会直接输出网址。
哪些状况下才会去使用<c:url>?例如:当我们须动态产生网址时,有可能传递的参数不固定,或者是需要一个网址能连至同服务器的其他 web 站台之文件,而且<c:url>更可以将产生的网址储存
起来重复使用。另外,在以前我们必须使用相对地址或是绝对地址去取得需要的图文件或文件,现
在我们可以直接利用<c:url>从 web 站台的角度来设定需要的图文件或文件的地址,如下:
<img src="<c:url value="/images/code.gif" />" />
如此就会自动产生连到 image 文件夹里的 code.gif 的地址,不再须耗费精神计算相对地址,并
且当网域名称改变时,也不用再改变绝对地址。
● <c:redirect>
<c:redirect>可以将客户端的请求从一个 JSP 网页导向到其他文件。
语法
语法 1:没有本体内容
<c:redirect url="url" [context="context"] />
语法 2:本体内容代表查询字符串(Query String)参数
<c:redirect url="url" [context="context"] > <c:param> </c:redirect >

  • 属性
    这里写图片描述
  • 说明

url 就是设定要被导向到的目标地址,它可以是相对或绝对地址。例如:我们写成如下:<c:redirect url="http://www.javafan.net" />
那么网页将会自动导向到 http://www.javafan.net。另外,我们也可以加上 context 这个属性,
用来导向至其他 web 站台上的文件,例如:导向到 /others 下的 /jsp/index.html 时,写法如下:
<c:redirect url="/jsp/index.html" context="/others" />
<c:redirect> 的功能不止可以导向网页,同样它还可以传递参数给目标文件。在这里我们同样
使用<c:param>来设定参数名称和内容。

  • 范例
<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>CH7 - Core_redirect.jsp</title>
</head>
<body>
<h2><c:out value="<c:redirect> 的用法" /></h2>
<c:redirect url="http://java.sun.com">
<c:param name="param" value="value"/>
</c:redirect>
<c:out value="不会执行喔!!!" />
</body>
</html>
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值