JSTL - JSP标准标签库

一,JSP标准标签库 JSTL

 * 用于编写和开发jsp页面的一组标准标签。目的在于简化JSP页面的设计。
 * 组成:
  core核心标签库:http://java.sun.com/jsp/jstl/core  前缀c
  I18N国际化与格式化标签库:http://java.sun.com/jsp/jstl/fmt 前缀fmt
  SQL标签库:http://java.sun.com/jsp/jstl/sql 前缀sql
  XML标签库:http://java.sun.com/jsp/jstl/xml 前缀x
  Funcions :http://java.sun.com/jsp/jstl/Funcions  前缀fn
 * 二种版本
  EL版本和请求时表达式版本

二,配置JSTL

 * 下载JSEL安装包,解压后有2个jar包jstl.jar和standart.jar;
 jstl.jar中包含JSTL规范中定义的接口和相关的类;
 standart.jar中包含Jakarta小组对JSTL的实现和JSTL中5个标签库的TLD文件;
 放入WEB-INF/lib目录下。
 
 * 在JSP页面中导入要使用的标签库的URL。和使用自定义标签一样。

 * 可以在web.xml中使用<tablib-url>元素来修改标签库的URL引用。

 
 
三,核心标签库Core :用于操作JSP页面创建的范围变量;
 1,组成:
  通用标签:设置,删除和显示在JSP页面内创建的变量值。
  条件标签:
  迭代标签

  * 动态值指属性的值可以是jsp表达式,EL表达式,或通过<jsp:attribute>标签设置的值。
  EL 提供了一种简化语言,用于在 JSP 应用程序中访问和操作数据并使该数据可被 JSTL 定制标记用作动态属性值。

 2,通用标签:

  <c:set>:设置范围变量或bean属性的值;
   * 设置范围变量使用var,value,scope;
     设置bean属性使用value,target(bean对象), property(属性名)

   * var和scope属性不能接受动态值,其他标签也一样。

   * tld中<body-content>设置为JSP;

  <c:remove>:移除范围变量;
   * 不指定scope按PageContext.removeAttribute(name)来移除。
     指定scope按PageContext.removeAttribute(name,scope)来移除。
   
  <c:out>:将表达式结果输出到当前的JspWriter对象中;
   * 类似JSP表达式或EL ${表达式};
   * tld中<body-content>设置为JSP;
 3,条件标签:

  <c:if>:if的实现
   * var 为存储条件结果的变量为boolean类型.
   * tld中<body-content>设置为JSP;
   * 如果指定了scope就必须指定var属性。scope默认page。
   * 执行结果被输出到当前JspWriter对象中.

  <c:choose>:if/else的实现,
   * 判断<c:when>标签的测试条件的值是否为true。如果没有满足的条件<c:ohterwise>被执行。
   * tld中<body-content>设置为JSP;
   * <c:choose>为<c:when>和<c:ohterwise>的父标签,<c:choose>只能含有这2个标签.
   
  <c:when>:一个可选条件;
   * tld中<body-content>设置为JSP;
   * 必须在<c:choose>标签下使用<c:ohterwise>之前出现.

  <c:ohterwise>:最后的选择;

  <c:catch>:允许在 JSP 页面内进行初级的异常处理,使得能够在页面自身内部进行定制错误处理。


 4,迭代标签
  <c:forEach>:主要用于访存和显示数据集,通常是以列表或表中的一系列行的形式显示

   * 对整数范围上的迭代(类似 Java 语言的 for 语句)
    <c:forEach var="name" varStatus="name" begin="expression" end="expression" step="expression">
     body content
    </c:forEach>
    begin 和 end 属性要么是静态整数值,要么是可以得出整数值的表达式。它们分别指定迭代索引的初始值以及迭代索引的终止值。
    出现 step 时,它也必须是整数值。它指定每次迭代后索引的增量。省略了 step 属性,那么步长缺省为 1。
    如果指定了 var 属性,那么将会创建一个带有指定名称的并限定了作用域的变量,并将每次迭代的当前索引值赋给该变量。只可以在 <c:forEach> 标记体内对其进行访问。
   
   * 对集合上的迭代
    <c:forEach var="name" items="expression" varStatus="name" begin="expression" end="expression" step="expression">
       body content
    </c:forEach>

    items 属性是唯一必需的属性。 items 属性的值应该是一个集合,对该集合的成员进行迭代,通常使用 EL 表达式指定值。
    如果items是通过 <c:forEach> 标记的 item 属性指定的,那么对于每次迭代该已命名变量都将被绑定到集合后续元素上。
    
    <c:forEach> 标记的 items 属性所支持的集合
       items 的值                        所产生的 item 值 
    java.util.Collection              调用 iterator() 所获得的元素 
    java.util.Map                     java.util.Map.Entry 的实例 
    java.util.Iterator                     迭代器元素
    java.util.Enumeration                  枚举元素
    Object 实例数组                         数组元素
    基本类型值数组                    经过包装的数组元素
    用逗号定界的 String                    子字符串
    javax.servlet.jsp.jstl.sql.Result   SQL 查询所获得的行

   * 不论是对整数还是对集合进行迭代, <c:forEach> 剩余的属性 varStatus 所起的作用相同。
   和 var 属性一样, varStatus 用于创建限定了作用域的变量。
   不过,由 varStatus 属性命名的变量并不存储当前索引值或当前元素,
   而是赋予 javax.servlet.jsp.jstl.core.LoopTagStatus 类的实例。
   该类定义了一组特性,它们描述了迭代的当前状态,

   LoopTagStatus 对象的特性

   特性        Getter           描述 
   current getCurrent()   当前这次迭代的(集合中的)项
   index  getIndex()   当前这次迭代从 0 开始的迭代索引
   count  getCount()   当前这次迭代从 1 开始的迭代计数
   first  isFirst()   用来表明当前这轮迭代是否为第一次迭代的标志
   last  isLast()   用来表明当前这轮迭代是否为最后一次迭代的标志
   begin  getBegin()   begin 属性值 
   end  getEnd()   end 属性值 
   step  getStep()   step 属性值 

   * 对String的迭代:按特定的分隔字符为间隔迭代。

  <c:forTokens>:迭代字符串中有分隔符分隔的成员。

   * 通过java.util.StringTokenizer类实例完成字符串的分隔。delims和items属性为其构造参数。

   * 通过 delims 属性提供用于生成标记的一组定界符.其它属性都相同。

   * 对于标记之间为空或为空格则不输出。

 5,URL相关的标签:
  <c:import>:导入一个基于URL的资源。
   * 不仅可以导入同一web应用下的资源,还可以导入不同web应用或网站中的资源。
   * tld中<body-content>设置为JSP;

  <c:url> :使用正确的URL重写规则构造一个URL

   * 在前面附加当前 servlet 上下文的名称
   * 和<c:param>一起使用将请求参数名称和值的 URL 编码
   * 为会话管理重写 URL 。

   * value 属性用来指定基本 URL,然后在必要时标记对其进行转换。
   如果这个基本 URL 以一个斜杠开始,那么会在它前面加上 servlet 的上下文名称。可以使用 context 属性提供显式的上下文名称。
   如果省略该属性,那么就使用当前 servlet 上下文的名称。
   这一点特别有用,因为 servlet 上下文名称是在部署期间而不是开发期间决定的。
   (如果这个基本 URL 不是以斜杠开始的,那么就认为它是一个相对 URL,这时就不必添加上下文名称。)

   * 如果为 var 属性提供了一个值(还可以同时为 scope 属性提供一个相应的值,这是可选的),
   那么将生成的 URL 赋值给这个限定了作用域的指定变量。
   否则,将使用当前的 JspWriter 输出生成的 URL。这种直接输出其结果的能力允许 <c:url> 标记作为值出现,

   *

  <c:redirect>:重定位到另外的资源。

   * 用于向用户的浏览器发送 HTTP 重定向响应

   * 通过请求分派器进行转发是在服务器端实现的,而重定向却是由浏览器来执行的。
   从开发人员的角度来讲,转发比重定向更有效率。

  <c:import>:将输出结果导入JSP页面
   * core 库的 <c:import> 操作是更通用、功能更强大的 <jsp:include> 版本

   * 和 <jsp:include> 一样, <c:import> 也是一种请求时操作,它的基本任务就是将其它一些 Web 资源的内容插入 JSP 页面中。

   * 通过 url 属性指定将要导入内容的 URL,这个属性是 <c:import> 的唯一一个必选属性。
   如果 url 属性的值以斜杠开始,那么它就被解释成本地 JSP 容器内的绝对 URL。

   * 如果没有为 context 属性指定值,那么就认为这样的绝对 URL 引用当前 servlet 上下文内的资源。

   * 也可以将包含协议和主机名的完整 URI 指定为 url 属性的值。可以使用 java.net.URL 类所支持的任何协议。

   * var 属性会导致从指定 URL 获取的内容(作为 String 值)被存储在一个限定了作用域的变量中,而不是包含在当前 JSP 页面中。
 

四,国际化和格式化标签库

 1,HTTP 协议通过 Accept-Language 请求头将本地化信息从浏览器传递至服务器。许多 Web 浏览器允许用户定制他们的语言首选项,
 那些没有为一种或多种首选语言环境提供显式设置的浏览器会询问操作系统以确定在 Accept-Language 头中发送哪个值(或哪些值)。
 servlet 规范通过 javax.servlet.ServletRequest 类的 getLocale() 和 getLocales() 方法自动地利用 HTTP 协议的这一功能。
 JSTL fmt 库中的定制标记又会利用这些方法来自动地确定用户的语言环境,从而相应地调整它们的输出。
 但不存在将用户的时区从浏览器传输到服务器的标准 HTTP 请求头。
 
 2,组成:
  本地化上下文标记:设置本地化上下文,其它标记将在其中进行操作。
  日期标记:标记分别支持对日期和数字进行格式化和解析。
  消息标记:侧重于对文本消息进行本地化。


 3,本地化上下文标记
  <fmt:setLocale> : 覆盖用户语言环境,JSP 容器处理完该 JSP 代码段之后,将忽略用户浏览器设置中所指定的语言首选项。 
 
   * value 属性。该属性的值应当是命名该语言环境的一个字符串或者是 java.util.Locale 类的一个实例。
   语言环境名称是这样组成的:小写的两字母 ISO 语言代码,可选地,后面可以跟下划线或连字符以及大写的两字母 ISO 国家或地区代码。
   
   * 可选属性 scope 用来指定语言环境的作用域。
   page 作用域指出这项设置只适用于当前页.
   request 作用域将它应用于请求期间访问的所有 JSP 页面。
   session ,那么指定的语言环境被用于用户会话期间访问的所有 JSP 页面。
   application 指出该语言环境适用于该 Web 应用程序所有 JSP 页面的全部请求和该应用程序所有用户的全部请求。

   * variant 属性(也是可选的)允许您进一步针对特定的 Web 浏览器平台或供应商定制语言环境。例如, MAC 和 WIN
    
  <fmt:setTimeZone> :设置其它 fmt 定制标记所使用的缺省时区值。
   *  value 属性是必需的,但是在本例中它应当是时区名或 java.util.TimeZone 类的实例。
   * 通过调用 java.util.TimeZone 类的 getAvailableIDs() 静态方法来检索有效的时区名列表。 
   * 使用可选的 scope 属性来指出时区设置的作用域。

   * 可以使用 var 属性,将 TimeZone 实例的值存储在限定了作用域的变量中。

  <fmt:timeZone>:使用该标记来指定将由其它 JSTL 标记使用的时区。但是, <fmt:timeZone> 操作的作用域仅限于其标记体内容。

 4,日期标记
  <fmt:formatDate> :用来格式化和显示日期和时间(数据 输出)

   * value 属性才是必需的。其值应当是 java.util.Date 类的实例,指定要进行格式化和显示的日期和/或时间数据。
   * 可选的 timeZone 属性指出将要显示哪个时区的日期和/或时间。
   * type 属性指出要显示指定的 Date 实例的哪些字段,应当是 time 、 date 或 both 。该属性的缺省值是 date 。
   * dateStyle 和 timeStyle 属性分别指出应当如何格式化日期和时间信息。有效的样式有 default 、 short 、 medium 、 long 和 full 。
   *  pattern 属性来指定定制样式,而不必依赖于内置样式。
   * 如果指定了 var 属性,那就把包含格式化日期的 String 值指派给指定的变量。

  <fmt:parseDate>: 用来解析日期和时间值(数据 输入)
   * type 、 dateStyle 、 timeStyle 、 pattern 和 timeZone 属性对 <fmt:parseDate> 和对 <fmt:formatDate> 起一样的作用,
   不同之处仅在于对于前者,它们控制日期值的解析而非显示。

   * parseLocale 属性用来指定一种语言环境,将根据这种语言环境来解析该标记的值,它应当是语言环境的名称或 Locale 类的实例。
   
   * 对于生产代码,文本输入的验证和转换最好由后端代码(比如 servlet)来处理,而不是通过 JSP 定制标记来处理。
 
 5,数字标记
  <fmt:formatNumber> :用来以特定于语言环境的方式显示数字数据,包括货币和百分数。操作由语言环境确定,

   * value 属性才是必需的。它用来指定将被格式化的数值。

   * type 属性的值应当是 number 、 currency 或 percentage ,并指明要对哪种类型的数值进行格式化。
   当 type 属性的值为 currency 时, currencyCode 属性可以用来显式地指定所显示的数值的货币单位。

   * pattern 属性优先于 type 属性,允许对遵循 java.text.DecimalFormat 类模式约定的数值进行更精确的格式化。

   * maxIntegerDigits 、 minIntegerDigits 、 maxFractionDigits 和 minFractionDigits 属性用来控制小数点前后所显示的有效数字的个数。
   这些属性要求是整数值。
   * groupingUsed 属性带有布尔值并控制是否要对小数点前面的数字分组。

  
  <fmt:parseDate> :
   * integerOnly 属性指出是否应当只解析所给值的整数部分。如果该属性的值为 true ,那么就忽略要被解析的字符串中跟在小数点后面的任何数字。该属性的缺省值为 false 。

   * 解析数据并不是一项非常适合于表示层的任务。如果解析和验证数据作为应用程序业务逻辑的一部分实现,那么软件维护将会得到简化。

 6,消息标记
  <fmt:message> :实现文本的本地化。

   * 该操作利用 java.text.MessageFormat 类所提供的功能,所以可以将参数化的值替换进这样的文本消息,以便动态地定制本地化内容。
   
   * 只有 key 属性才是必需的。 key 属性的值用来确定要显示在资源束中定义的哪些消息。
   * var 属性,那么将由该标记所生成的文本消息赋给指定的变量,而不是写到 JSP 页面。
   * <fmt:param> 标记的 value 属性来提供文本消息的参数化值。

  <fmt:setBundle> : 操作设置了一个缺省资源束,供 <fmt:message> 标记在特定作用域内使用,
   
   *  basename 属性是必需的,它标识了设为缺省值的资源束。
   * basename 属性的值不应当包含任何本地化后缀或文件扩展名。
   * 可选的 scope 属性指明缺省资源束设置所应用的 JSP 作用域。如果没有显式地指定该属性,就假定为 page 作用域。
   
   * 如果指定了可选的 var 属性,那么将把由 basename 属性所标识的资源束赋给该属性值所命名的变量。
   在这种情况下, scope 属性指定变量的作用域;没有将缺省资源束赋给相应的 JSP 作用域。


  <fmt:bundle> : 指定了为嵌套在其标记体内容中的全部和任意 <fmt:message> 操作所用的资源束。
   * 只有 basename 属性才是必需的。您可以使用可选的 prefix 属性来为任何嵌套的 <fmt:message> 操作的 key 值指定缺省前缀。

  

 7,使用JDK工具native2asci.exe,它在JDK/BIN 目录下,进行编码的转换:

  * 用于存储特定于语言环境消息的资源束采用类或特性文件的形式,这些类或特性文件符合标准命名约定,在这种命名约定中基名和语言环境名组合在一起。

  native2ascii [-reverse] [-encoding encoding] [inputfile [outputfile]]
 
  正转:To:Unicode
  native2ascii -encoding gb2312 source.properties target.properties

  反转:Reverse Unicode To 指定码
  native2ascii -reverse -encoding Big5 source22.properties target2.properties

  例如:native2ascii -encoding gb2312 E:/apache/zh_CN.txt E:/zh_CN.txt
  

五,XML库
 
 1,在企业级应用越来越依赖XML的今天,XML格式的数据被作为信息交换的优先选择。
 XML processing标签库为程序设计者提供了基本的对XML格式文件的操作。在该标签库中的标签一共有10个,被分为了三类,分别是:
     XML核心标签:<x:parse>、<x:out>、<x:set>。
      XML流控制标签:<x:if>、<x:choose>、<x:when>、<x:otherwise>、<x:forEach>。
      XML转换标签:<x:transform>、<x:param>。

 2,<x:parse> : 标签是该组标签库的核心,用于解析XML文件.

  <x:parse>标签属性和说明
  属性    描述
  doc    源XML的内容,该属性的内容应该为String类型或者java.io.Reader的实例,可以用xml属性来替代,但是不被推荐
  var    将解析后的XML保存在该属性所指定的变量中,之后XML processing标签库中的其他标签若要取XML中的内容就可以从该变量中得到(可选)
  scope    变量的作用范围(可选)
  varDom    指定保存的变量为org.w3c.dom.Document接口类型(可选)
  scopeDom    org.w3c.dom.Document的接口类型变量作用范围(可选)
  systemId    定义一个URI,该URI将被使用到XML文件中以接入其他资源文件(可选)
  filter    该属性必须为org.xml.sax.XMLFilter类的一个实例,可以使用EL表达式传入,将对XML文件做过滤得到自身需要的部分(可选)

  其中,var、scope和varDom、scopeDom不应该同时出现,而应该被视为两个版本来使用,二者的变量都可以被XML processing标签库的其他标签来使用。
  <x:parse>标签单独使用的情况很少,一般会结合XML processing标签库中的其他标签来一起工作。下面看一个示例。
  首先给出一个简单的XML文件,将对该XML文件做解析,该XML文件名为SampleXml.xml。
  <?xml version="1.0" encoding="UTF-8"?>
  <xml-body>
       <name>RW</name>
       <passWord>123456</passWord>
       <age>28</age>
       <books>
           <book>book1</book>
           <book>book2</book>
           <book>book3</book>
       </books>
  </xml-body>

  标签库的工作:
  <c:import var="xmlFile" url="http://localhost:8080/booksamplejstl/SampleXml.xml"/>
  <x:parse var="xmlFileValue" doc="${xmlFile}"/>
  该示例读取XML文件得到了<c:import>标签的帮助,<c:import>标签将源XML文件的内容保存在“xmlFile”变量中,<x:parse>标签根据“xmlFile”变量的值解析“SampleXml.xml”。

 3,<x:out>:用于显示XML内容的
  <x:out>标签从<x:parse>标签解析后保存的变量中取得需要的XML文件内容,并显示在页面上。该标签是通过XPath技术(定位XML元素的一种技术)来实现的。要使用<x:out>标签必须将xalan-j的jar包保存在“WEB-INF/lib”下。它的属性和描述如表9.13所示:
 
  <x:out>标签属性和说明
  属性    描述
  select    XPath表达式
  escape    当特殊字符如:“<,>,&,’,””出现在取得的结果字符串中时,将以转义字符来替换

  <x:out>标签需要与<x:parse>标签协同工作,下面看一个示例。
  <c:import var="xmlFile" url="http://localhost:8080/booksamplejstl/SampleXml.xml"/>
  <x:parse var="xmlFileValue" doc="${xmlFile}"/>
  name:<x:out select="$xmlFileValue/xml-body/name"/><br>
  passWord:<x:out select="$xmlFileValue/xml-body/passWord"/><br>
  age:<x:out select="$xmlFileValue/xml-body/age"/><br>

  读取XML文件并解析后的变量xmlFileValue将加上“$”作为XPath表达式的开头,select中的表达式将从xml-body根元素下的各个子元素中取得实体内容。
 
  根据“SampleXml.xml”文件的内容,将显示。
  name:RW
  passWord:123456
  age:28

 4,<x:set>:用于保存XML内容。

  <x:set>标签允许将某个源XML中元素的实体内容或属性,保存到一个变量中去,它的实现也依靠XPath技术。
 
  <x:set>标签属性和说明
  属性    描述
  select    XPath表达式
  var    保存结果的变量名
  scope    变量的作用范围(可选)

  <x:set>标签的var保存的变量由XPath的结果决定该变量的类型,下面看一个示例。
  <c:import var="xmlFile" url="http://localhost:8080/booksamplejstl/SampleXml.xml"/>
  <x:parse var="xmlFileValue" doc="${xmlFile}"/>
  <x:set select="$xmlFileValue/xml-body/name" var="thisName"/>
  这里将保存XML的name元素内容到变量“thisName”中。

 5,<x:if>:用于判断

  <x:if>标签允许由XPath的boolean()函数得到的判断结果,来判断是否显示其标签所包含的内容。
  <x:if>标签的属性与<x:set>标签相同,但是var的结果只能是boolean类型。

 6,<x:choose>、<x:when>、<x:otherwise>:用于复杂判断。

  这组标签将一起使用,来提供“if elseif”语句的功能。
  <x:choose>标签没有属性,可以被认为是父标签,<x:when>、<x:otherwise>将作为其子标签来使用。
  <x:when>标签等价于“if”语句,它包含一个select属性,该属性为XPath判断表达式。
  <x:otherwise>标签没有属性,它等价于“else”语句。

 7,<x:forEach>:用于对XML元素循环。

  <x:forEach>为对XML文件中同一名称元素的循环控制标签。

  <x:set>标签属性和说明
  属性    描述
  select    XPath表达式,结果是一个集合,将对该集合进行循环(可选)
  begin    开始条件(可选)
  end    结束条件(可选)
  step    循环的步长,默认为1(可选)
  var    做循环的对象变量名,表示XPath表达式结果集合中的一个对象(可选)
  varStatus    显示循环状态的变量(可选)

  下面看一个示例。
  <x:forEach select="$xmlFileValue/xml-body/books/book" var="book">
  ${book}
  </x:forEach>

  该示例将使用循环读取XML中多个同存于books元素下的book子元素。

 8,<x:transform>:格式化XML显示数据。
  <x:transform>标签允许使用XSLT(转换XML格式的语言)为页面的显示数据做格式化的处理。

  <x:transform>标签属性和说明
  属性    描述
  doc    源XML的内容,该属性的内容应该为String、java.io.Reader、javax.xml.transform.Source、org.w3c.dom.Document的实例,或者从<x:parse>、<x:set>两个标签得到。可以用xml属性来替代,但是不被推荐(可选)
  xslt    源XSLT的内容,该属性的内容应该为String、java.io.Reader、javax.xml.transform.Source的实例(可选)
  docSystemId    定义一个URI,该URI将被使用到XML文件中以接入其他资源文件。可以用xml SystemId属性来替代,但是不被推荐(可选)
  xsltSystemId    定义一个URI,该URI将被使用到XSLT文件中以接入其他资源文件(可选)
  var    将格式化后的XML文件保存在该属性所指定的变量中,保存的变量为org.w3c.dom.Document接口类型(可选)
  scope    变量的作用范围(可选)
  result    保存转化结果的变量,保存的变量为javax.xml.transform.Result类型的实例(可选)

  下面看一个示例:
   <c:import var="xmlFile" url="http://localhost:8080/booksamplejstl/SampleXml.xml" />
   <c:set var="xsltdoc">
       <?xml version="1.0"?>
       <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
           <xsl:template match="/">
               <xsl:apply-templates />
           </xsl:template>
          <xsl:template match="xml-body">
               <html>
                   <head></head>
                   <body marginheight="0" marginwidth="0" topmargin="0" leftmargin="0">
                       <h2>
                           UserName:
                           <xsl:value-of select="name" />
                       </h2>
                       <h2>
                           PassWord:
                           <xsl:value-of select="passWord" />
                      </h2>
                       <h2>
                           age:
                           <xsl:value-of select="age" />
                       </h2>
                   </body>
               </html>
           </xsl:template>
       </xsl:stylesheet>
   </c:set>
   <x:transform xslt="${xsltdoc}" doc="${xmlFile}" />

  这个示例将XML文件保存的数据信息利用<c:import>保存在“xmlFile”中,然后使用<c:set>标签保存一个XSLT的源到“xsltdoc”,最后通过<x:transform>格式化XML文件的数据显示在页面上。

 9,用于参数传递的<x:param>标签
  <x:param>标签用于在格式化XML时传递所需要的参数。它的属性和描述与<c:param>标签相同。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值