JSF 2.0 Facelets 的模板技术

企业微信网页本地调试实战指南 本文为企业微信网页开发者提供了一套完整的本地调试实战指南。针对企业微信内置浏览器调试困难的核心痛点,详细讲解了如何在PC端通过修改Hosts、配置开发服务器实现高效调试,并介绍了手机端利用Charles代理工具的完整方案。指南涵盖了环境配置、常见问题排查及JS-SDK调试等进阶技巧,旨在帮助开发者快速搭建顺畅的本地调试环境,大幅提升开发效率。 阅读详情

JSF 2.0 Facelets 的模板技术

作者:Deepak Vohra

2011 年 8 月发布

下载:
下载:Oracle WebLogic Server 11g 第 1 版 (10.3.4) 安装程序

下载:Apache Jakarta Standard 1.1 Taglib

下载:Facelets.zip

简介

在 JavaServer Faces (JSF) 2.0 中,Facelets 取代 JavaServer Pages (JSP) 成为默认的视图声明语言 (VDL)。有了 Facelets,您不需要像以前在 JSF 1.2 中那样配置视图处理器。Facelets 是一种以 JSF 为中心的视图技术。

Facelets 以组合为基础。一个组合定义一个 Facelets 页中的 JSF UIComponent 结构。Facelets 应用程序可以包含多个组合,这些组合在不同的 Facelets 页中定义、作为一个应用程序运行。

Facelets 是一种类似 Tiles 的模板化框架。与 Tiles 相比,Facelets 的优势在于它预先集成了 JSF UIComponent,并且不需要 Facelets 配置文件,而 Tiles 需要 Tiles 配置文件。

在 Facelets 中可以添加 JSF 验证器和转换器。Facelets 全面支持表达式语言 (EL) 和 JavaServer Pages Standard Tag Library (JSTL)。在 Web 应用程序中使用 Facelets 的部分好处包括模板化、重用和易于开发。

在本文中,我们将在 Oracle Enterprise Pack for Eclipse 11g 中开发一个 Facelets Web 应用程序,然后将该应用程序部署到 Oracle WebLogic Server 11g。在该 Facelets 应用程序中,将一个输入文本 UIComponent 添加到输入 Facelets 页。借助 JSF 导航,将该输入 Facelets 页导航到另一 Facelets 页,这个 Facelets 页显示由输入 Facelets 页指定的 SQL 查询生成的 JSF 数据表。我们将使用 Oracle Database 11g 快捷版作为数据源。通过在输入和输出的页眉和页脚中包含图形来展示模板功能;只需在模板中指定图形一次。

注:本文中开发的 Facelets Web 应用程序的源代码可以从这里下载。

Facelets 技术概述

在开发应用程序之前,我们先回顾一下 Facelets 技术。Facelets 标记与 JSF Core 和 JSF HTML 标记库结合使用,开发 JSF Facelets 应用程序。表 1 讨论了一些 Facelets 标记。

表 1. Facelets 标记

Facelets 标记

说明

属性

ui:composition

定义 UIComponent 组合。一个组合可以由多个 UIComponent 组成。Facelets 页中仅编译 ui:composition 标记内的文本。

template:可选属性,指定用于在组合内添加 UIComponent 的模板。

ui:define

用于在 Facelets 页中使用模板添加内容。

name:必需的属性;与 ui:insert 中的 name 属性相匹配。

ui:decorate

类似于 ui:composition,只不过 ui:decorate 标记中不包括的文本也会编译到 Facelets 页中。

template:必需的属性,指定 ui:decorate 标记中用于添加 UIComponent 的模板。

ui:component

类似于 ui:composition,只不过在 UIComponent 结构中添加一个新的 UIComponent 作为根组件。

id:如果未指定,则 Facelets 分配一个 ID。

binding:将 UIComponent 与 JavaBean 的一个属性绑定。

ui:fragment

ui:component 对应的非修整标记,类似于 ui:composition 对应的 ui:decorate 标记。

id:如果未指定,则 Facelets 分配一个 ID。

binding:将 UIComponent 与 JavaBean 的一个属性绑定。

ui:include

包括一个 Facelets 页,该页定义 Facelets 页或模板页中的一个组合或组件。

src:必需的属性,通过 EL 表达式或字符串文字指定要包括的目标 Facelets 页。

ui:insert

用于模板中为使用该模板定义 UIComponent 的 Facelets 页面定义布局。模板客户端使用相应的 ui:define 标记将 UIComponent 添加到 Facelets 页。如果一个 Facelets 页指定了一个模板但没有指定与 ui:insert 标记对应的 ui:define 标记,Facelets 页中将使用默认的 ui:insert 标记。

name:在 Facelets 页的 ui:define 标记中拥有相应 name 属性的属性,用于将模板与 Facelets 页匹配。

ui:param

当模板或 Facelets 页中包括一个 Facelets 页时指定一个变量。

name:必需的属性,指定变量名称。

value:必需的属性,指定变量值为 EL 表达式或文字。

默认情况下,Facelets 页为 XHTML 页。Facelets 应用程序由以下配置文件和模板文件组成。

  • 一个 Facelet 模板文件,这是一个 XHTML 页
  • Facelet 页眉和 Facelet 页脚 XHTML 页
  • 一个 JSF 配置文件 faces-config.xml
  • Facelet 组合页,也是一个 XHTML 页

模板文件定义 Facelets 中的布局,包含 <ui:insert/> 标记,用于指定使用模板定义 UIComponent 的 Facelets 组合的结构。

JSF 配置文件是唯一需要的配置文件;不需要 Facelets 配置文件。一个 Facelets 页是一个 XHTML 页,包括 Facelets 命名空间中定义的标记。

在下文中,我们将在 Oracle Enterprise Pack for Eclipse 11g、Oracle WebLogic Server 11g 和 Oracle Database 11g 快捷版中创建一个 Facelets 应用程序。

先决条件

必须具备以下先决条件:

搭建环境

首先,我们需要在 Oracle Database 快捷版中创建一个数据库表。

  1. 安装 Oracle Database 11g 快捷版。
  2. 使用以下 SQL 脚本创建用户 OE 和一个表。
CREATE USER OE IDENTIFIED BY OE;
 GRANT CONNECT, RESOURCE to OE;
CREATE TABLE OE.Catalog(CatalogId INTEGER 
   PRIMARY KEY, Journal VARCHAR(25), Publisher VARCHAR(25),
    Edition VARCHAR(25), Title Varchar(45), Author Varchar(25));
   INSERT INTO OE.Catalog VALUES('1', 'Oracle Magazine',  
    'Oracle Publishing', 'Nov-Dec 2004', 'Database Resource  
   Manager', 'Kimberly Floss');
   INSERT INTO OE.Catalog VALUES('2', 'Oracle Magazine',   
    'Oracle Publishing', 'Nov-Dec 2004', 'From ADF UIX to JSF',  
   'Jonas Jacobi');
   INSERT INTO OE.Catalog VALUES('3', 'Oracle Magazine',   
    'Oracle Publishing', 'March-April 2005', 'Starting with  
   Oracle ADF ', 'Steve Muench');
  1. 将 Standard 1.1 Taglib filesstandard.jar 和 jstl.jar 添加到 domain/bin/startWebLogic 批处理脚本中以设置 CLASSPATH 变量。
C:\JSTL\jakarta-taglibs-standard-1.1.2\lib\standard.jar;C:\JSTL\jakarta-taglibs-standard-1.1.2\lib\jstl.jar

在 Oracle WebLogic Server 中配置 JSF 2.0 支持

默认情况下,Oracle WebLogic Server 11g 中没有配置 JSF 2.0 支持。要配置 JSF 2.0 支持,请执行以下步骤:

  1. 启动 Oracle WebLogic Server 及其 Administration Console。
  2. 在 wls_base_domain 节点中选择 Deployments 节点。
  3. 在 Deployment 表中,单击 Install 按钮。

    facelet 1
  4. 选择 jsf-2.02.war 并单击 Next。

    facelet 2
  5. 在 Choose 目标样式中,选择 Install this deployment as a library。单击 Next。
  6. 选择默认的 Optional Settings,然后单击 Next。
  7. 单击 Finish 完成 JSF 2.0 部署。
  8. 在配置屏幕,单击 Save 保存配置。


在 Deployments 中添加了一个 JSF 2.0 部署配置。
facelet 4

在配置文件 C:\Oracle\Middleware\user_projects\domains\wls_base_domain\config\config.xml 中配置了 JSF 2.0 库。

<library>
       <name>jsf#2.0@1.0.0.0_2-0-2</name>
       <target>AdminServer</target>
       <module-type>war</module-type>
       <source-path>C:\Oracle\Middleware\wlserver_10.3\common\deployable-libraries\jsf-2.0.2.war</source-path>
       <deployment-order>100</deployment-order>
       <security-dd-model>DDOnly</security-dd-model>
</library>

在 Oracle Enterprise Pack for Eclipse 中创建一个 Facelets 项目


执行以下步骤创建一个 Facelets 项目:

  1. 在 Oracle Enterprise Pack for Eclipse 11g 中通过 File>New>Dynamic Web Project 创建一个项目。
  2. 在 Dynamic Web Project Configuration 中,指定项目名称(如 Facelets)并使用 New Runtime 创建一个新的目标运行时。
  3. 在 New Server Runtime Environment Configuration 中,选择 Oracle WebLogic Server 11g R1 PatchSet 3,选择 Create a new local server,然后单击 Next。
  4. 指定 Oracle WebLogic Server 主目录。Java 主目录配置为 JDK 1.6。单击 Next。
  5. 对于服务器配置,选择 Local 作为 Server Type,然后选择 wls_base_domain 目录作为 Domain Directory。单击 Finish。
  6. 选择 2.5 作为 Dynamic web module version。
  7. 对于 Facelets 支持,我们需要添加 JSF 2.0 配置。单击 Configuration 部分的 Modify 按钮。
  8. 在 Project Facets 中,选择 JavaServer Faces,然后对 Version 选择 2.0。单击 OK。

    facelet 5
  9. 确保将 Configuration 设置为 <custom>,如下图所示。单击 Next。

    facelet 6
  10. 对于 Java 配置,默认的输出文件夹设置为 build/classes。单击 Next。
  11. 对于 Web Module 配置,选择 Facelets 作为 Context root,选择 WebContent 作为 Content directory。选择 Generate web.xml deployment descriptor,然后单击 Next。
  12. 要配置 JSF 实现库,选择 User Library 作为 Type,然后单击 Download 按钮。
  13. 对于 Download Library,选择 JSF 2.0 (Mojarra 2.0.3-FCS) 库,然后单击 Next。

    facelet 7
  14. 接受库许可并单击 Finish。JSF 实现库配置完成。
  15. 单击 Finish。

    facelet 8

    Facelets 项目创建完毕。

    facelet 9
  16. 在 JSF 2.0 中,不需要 javax.faces.VIEW_MAPPINGS context-param,Facelets 页的默认后缀为 .xhtml。将以下 context-param 添加到 web.xml。
         
         <context-param>
                     <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                     <param-value>.xhtml</param-value>
         </context-param>
       

    当选择 JSF 项目 facet 时,会默认配置 Faces Servlet。下图显示了 web.xml 文件:

    facelet 10


  17. 将 JSF 2.0 库的库配置添加到 weblogic.xml。
<wls:library-ref>
               <wls:library-name>jsf</wls:library-name>
               <wls:specification-version>2.0</wls:specification-version>
               <wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version>
               <wls:exact-match>true</wls:exact-match>
</wls:library-ref> 

创建托管 Bean

执行以下步骤创建一个托管 bean:

  1. 要为 Facelets 应用程序创建一个托管 bean,右键单击 
    WebContent/WEB-INF/faces-config.xml 并选择 Open With>Faces Config Editor。
    facelet 11

  2. 单击 Add 添加托管 bean。
    facelet 12 

  3. 在 New Managed Bean 向导中,选择 Create a new Java class 并单击 Next。
  4. 为 Source 文件夹选择 Facelets/src,为 Package 选择 catalog.backing,为 Catalog 选择 Java 类名。单击 Next。
  5. 输入 catalog 作为托管 bean 的名称,为 Scope 选择 session。然后单击 Next。
  6. 单击 Finish。于是添加了一个托管 bean。

facelet 13

 

创建 Facelets 模板

执行以下步骤创建一个 Facelets 模板:

  1. 首先,在 WEB-INF 目录中创建 templates 目录。
  2. 接下来,将用于 Facelets 模板文件的 XHTML 页添加到 templates 目录。
  3. 右键单击 WebContent 文件夹,然后选择 New>XHTML Page。
    facelet 14 

  4. 在 New XHTML File 向导中,将 File 名称域设为 BasicTemplate,然后单击 Next。
    facelet 15

  5. 选择 New Facelet Template 并单击 Finish。

    facelet 16

    包含页眉、内容和页脚的 BasicTemplate.xhtml 添加到了 templates 目录。

    facelets 17

    模板的根元素是 html,包括针对 Facelets 命名空间的命名空间声明。

  6. 在模板中,为 Facelets 组合的不同部分添加包含在 <div/> 标记中的 ui:insert 标记:标题、页眉、内容部分以及页脚。
  7. 使用 ui:include 标记指定 header.xhtml 和 footer.xhtml Facelets 页的相对路径。下面列出了 BasicTemplate.xhtml。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<title><ui:insert name="title">JSF Facelets</ui:insert></title>
</head>
<body>
<div id="header">
        <ui:insert name="header">
           <ui:include src="/WEB-INF/templates/header.xhtml" />
        </ui:insert>
</div>
<div id="content">
       <ui:insert name="content">
      <!--  include your content file or uncomment the include below and create content.xhtml in this directory -->
         <!-- <div> -->
         <!-- <ui:include src="content.xhtml"/> -->
         <!-- </div> -->
       </ui:insert>
</div>
<div id="footer">
      <ui:insert name="footer">
         <ui:include src="/WEB-INF/templates/footer.xhtml" />
      </ui:insert>
</div>
</body>
</html> 

创建 Facelets 页

执行以下步骤创建 Facelets 页:

  1. 类似于 BasicTemplate.xhtml 的创建步骤,为 header.xhtml 和 footer.xhtml 以及输入 Facelets 页 (input.xhtml) 和输出 Facelets 页 (output.xhtml) 分别添加 XHTML 页。
  2. 对于 header.xhtml,选择 New Facelet Header 模板。
  3. 对于 footer.xhtml,选择 New Facelet Footer 模板。
  4. 对于 input.xhtml 和 output.xhtml,选择 New Facelet Composition Page 模板。
  5. 将 Facelet 组合页添加到 WebContent 目录。
    Facelets 应用程序中显示出基于不同类型模板的 XHTML 页。


    facelet 18

  6. 在 header.xhtml 页中,使用 h:graphicImage 标记为页眉指定一个 .jpg 文件。下面列出了 header.xhtml 页。
       
       <?xml version="1.0" encoding="ISO-8859-1" ?>
       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
       <html xmlns="http://www.w3.org/1999/xhtml"
           xmlns:ui="http://java.sun.com/jsf/facelets"
           xmlns:h="http://java.sun.com/jsf/html"
           xmlns:f="http://java.sun.com/jsf/core">
       <f:view>
       <h:form>
                   <h:panelGrid columns="1">
                         <h:graphicImage value="FaceletsHeader.jpg" />
                   </h:panelGrid>
             </h:form>
       </f:view>
       </html>   
    
    
  7. 在 footer.xhtml 页,使用包含在 h:panelGrid 标记中的 h:graphicImage 标记为页脚指定一个 .jpg 文件。下面列出了footer.xhtml 页。
       
       <?xml version="1.0" encoding="ISO-8859-1" ?>
       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
       <html xmlns="http://www.w3.org/1999/xhtml"
           xmlns:ui="http://java.sun.com/jsf/facelets"
           xmlns:h="http://java.sun.com/jsf/html"
           xmlns:f="http://java.sun.com/jsf/core">   
       <f:view>
       <h:form>
                   <h:panelGrid columns="1">
                         <h:graphicImage value="FaceletsFooter.jpg" />
                   </h:panelGrid>
             </h:form>
       </f:view>
       </html>   
  8. 将页眉和页脚 .jpg 文件复制到 WebContent 目录,也就是组合页 input.xhtml 和 output.xhtml 所使用的目录。
    注:源代码 {PRODUCTION:在此插入到 Facelets.zip 的链接。} 文件中包括了示例 FaceletsHeader.jpg 和 FaceletsFooter.jpg 文件,不过您可以使用任何 .jpg 文件。

  9. 接下来,定义 input.xhtml Facelet 组合页,该页在内容部分有一个用于输入文本的输入域(h:inputText 组件)和一个用于提交输入的 h:commandButton。

h:commandButton 将其绑定指定为托管 bean catalog 中的 commandButton1 组件。在托管 bean 中,该命令按钮的 action 属性设置为 catalog.commandButton1_action 方法。

Facelets 页 input.xhtml 中包含一个 ui:composition 标记,用于定义 Facelets 页的组合,ui:composition 标记中的 ui:define 标记用于定义 Facelets 组合、页眉、内容和页脚的不同部分的 UIComponent。

在 ui:composition 标记的 template 属性中指定模板名称。ui:define 标记对应于模板中的 ui:insert 标记。如果没有为相应的 ui:insert 标记指定 ui:define 标记,则在 Facelet 组合页中使用 BasicTemplate.xhtml 页中默认的 ui:insert 标记。在 input.xhtml 页中只定义了内容的 ui:define 标记;页眉和页脚部分使用的是在 header.xhtml 和 footer.xhtml 中指定并且通过 ui:insert 和 ui:include 包括在 BasicTemplate.xhtml 中的页眉和页脚 .jpg 文件。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
       <ui:define name="content">
<h:form>
               <h:panelGrid columns="2">
                     <h:outputLabel binding="#{catalog.outputLabel1}" value="SQL Query:" />
                     <h:inputText binding="#{catalog.inputText1}" />
                     <h:commandButton value="Submit" binding="#{catalog.commandButton1}"
                     action="#{catalog.commandButton1_action}" />
               </h:panelGrid>
         </h:form>
       </ui:define>
</ui:composition>
</html>

output.xhtml Facelets 组合页的内容部分包含一个 h:dataTable UI 组件,用于输出 input.xhtml Facelet Composition 页中 SQL 查询到的 JSF 数据表。内容的 ui:define 标记定义 Facelets 页的组合。h:dataTable 绑定到托管 bean 中的 dataTable1 属性,h:column 组件分别绑定到托管 bean 中的 column1、olumn2…column6 属性。下面列出了 Facelet 组合页的 output.xhtml 文件。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
       <ui:define name="content">
           <h:form>
               <h:dataTable  binding="#{catalog.dataTable1}" border="1" rows="5">
                     <h:column binding="#{catalog.column1}"></h:column>
                     <h:column binding="#{catalog.column2}"></h:column>
                     <h:column binding="#{catalog.column3}"></h:column>
                     <h:column binding="#{catalog.column4}"></h:column>
                     <h:column binding="#{catalog.column5}"></h:column>
                     <h:column binding="#{catalog.column6}"></h:column>
               </h:dataTable>
         </h:form>
       </ui:define>
</ui:composition>
</html>

 

为 Facelets 应用程序指定导航

下面我们在 faces-config.xml 中添加导航规则,以便在 Facelets 应用程序中添加导航功能。

  1. 添加 Facelet 组合页 error.xhtml 以便在出现错误时进行导航。
  2. 打开 faces-config.xml,选择 Navigation Rule 选项卡。
  3. 将 input.xhtml 和 output.xhtml Facelet 组合页以及 error.xhtml 页拖到 Navigation Rule 中。
  4. 要在两个 Facelets 页之间创建导航规则,如在 input.xhtml 和 output.xhtml 之间,选择组件模板中的 Link。            

    facelet 19
  5. 要在两个 Facelets 页之间添加导航实例,使用组件模板中的 Select 选择一个链接。 

    facelet 20
  6. 要定义链接属性,右键单击一个链接并选择 Show View>Properties。 

    facelet 21
  7. 在 Link>From Outcome 域中指定所需的导航。为从 input.xhtml 到 output.xhtml 的链接指定“success”,这样,如果来自 input.xhtml 的输出结果是“success”,则导航到 output.xhtml。为从 input.xhtml 到 error.xhtml 的链接指定“failure”,这样,如果结果是“failure”,则导航到 error.xhtml。

    facelet 22

    下面列出了包含托管 bean 和导航规则的 faces-config.xml 配置文件。
    <?xml version="1.0" encoding="UTF-8"?>

    <faces-config
           xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
           version="2.0">
             <application>
                   <message-bundle>resources.application</message-bundle>
                   <locale-config>
                         <default-locale>en</default-locale>
                   </locale-config>
             </application>
             <managed-bean>
                   <managed-bean-name>catalog</managed-bean-name>
                   <managed-bean-class>catalog.backing.Catalog</managed-bean-class>
                   <managed-bean-scope>session</managed-bean-scope>
             </managed-bean>
             <navigation-rule>
                   <display-name>input.xhtml</display-name>
                   <from-view-id>/input.xhtml</from-view-id>
                   <navigation-case>
                         <from-outcome>success</from-outcome>
                         <to-view-id>/output.xhtml</to-view-id>
                   </navigation-case>
             </navigation-rule>
             <navigation-rule>
                   <display-name>input.xhtml</display-name>
                   <from-view-id>/input.xhtml</from-view-id>
                   <navigation-case>
                         <from-outcome>failure</from-outcome>
                         <to-view-id>/error.xhtml</to-view-id>
                   </navigation-case>
             </navigation-rule>
    </faces-config> 
    
    
  8. 在 Catalog.java 中,即托管 bean 的 Java 类,为 HTML 和 UI 组件添加所需的导入语句。为数据表添加一个 HtmlDataTable 变量,为数据表列添加一些 UIColumn 组件变量。另外,为表单添加一些 HTML 组件变量,输入文本以指定一个 SQL 查询,添加一个用于提交 SQL 查询的命令按钮

    我们在构建 XHTML 页时,将 HTML 和 UI 组件变量绑定到了 Facelets 组合 XHTML 页的 JSF 组件。
    private HtmlDataTable dataTable1;
             private UIColumn column1;
             private UIColumn column2;
             private UIColumn column3;
             private UIColumn column4;
             private UIColumn column5;
             private UIColumn column6; 
        
  9. 为 HTML 和 UI 组件添加访问器方法。添加一个在单击 Submit 按钮时调用的方法。 
    public String commandButton1_action() { }
  10. 在 Submit 按钮 action 方法中,检索 JSF 输入文本域中的 SQL 查询输入并运行 SQL 查询以生成结果集。 
    rs = stmt.executeQuery((String) inputText1.getValue());
  11. 设置数据表的边界和单元格填充形式。还要设置代表数据表中一行数据的变量。
    dataTable1.setBorder(5);
       dataTable1.setCellpadding("1");
       dataTable1.setVar("catalog");
  12. 设置数据表中各列的标题值。数据表中各列与数据库表中的各列相对应。

    通过创建 HtmlOutputText 标题组件并利用 setHeader 方法在 UIColumn 组件上设置标题来添加列标题。使用 setValue 方法设置 HtmlOutputText 值。例如,下面的代码添加 CatalogId 列的列标题: 
       HtmlOutputText headerComponent = new HtmlOutputText();
       headerComponent.setValue("CatalogId");
       column1.setHeader(headerComponent); 
  13. 为数据表中的每列创建一个 HtmlOutputText 组件,为 HtmlOutputText 组件指定一个值表达式,并将组件添加到列中。

    这就创建了一个 ValueExpression 对象,具体创建过程:首先创建一个 FacesContext 对象,然后从 FacesContext 创建一个 ELContext 对象和一个 ExpressionFactory 对象,最后从 ExpressionFactory 对象和 ELContext 对象创建一个 ValueExpression 对象。使用 setValueExpression 方法设置 HtmlOutputText 组件的值表达式。
    通过调用 getChildren 方法然后调用 add 方法,将 HtmlOutputText 组件添加到 UIColumn 组件。例如,为 CatalogId 列添加了 HtmlOutputText 组件,如下所示。 
    HtmlOutputText column1Text = new HtmlOutputText();
       FacesContext fCtx = FacesContext.getCurrentInstance();
       ELContext elCtx = fCtx.getELContext();
       ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
       ValueExpression ve = ef.createValueExpression(elCtx,
                                     "#{catalog.catalogid}", String.class);
       column1Text.setValueExpression("value", ve);
       column1.getChildren().add(column1Text); 
  14. 创建一个 ResultSetDataModel 对象。使用 ResultSetDatModel 对象来封装 ResultSet 对象,ResultSet 对象必须可以滚动。用 setWrappedData 方法将由 SQL 查询检索到的 ResultSet 设置为用于 ResultSetDataModel 的数据。 
    ResultSetDataModel dataModel=new ResultSetDataModel();
       dataModel.setWrappedData(rs); 
  15. 使用 setValue 方法将数据表与 ResultSetDataModel 对象绑定。
dataTable1.setValue(dataModel);

下面列出了托管 bean Java 类 Catalog.java。

package catalog.backing;
import javax.faces.component.html.HtmlCommandButton;
   import javax.faces.component.html.HtmlDataTable;
   import javax.faces.component.html.HtmlForm;
   import javax.faces.component.html.HtmlInputText;
   import javax.faces.component.html.HtmlOutputLabel;
   import javax.faces.component.UIColumn;
   import javax.faces.component.html.HtmlOutputText;
   import javax.faces.context.FacesContext;
   import javax.el.*;
   import javax.faces.model.ResultSetDataModel;
   import java.sql.*;
public class Catalog {
         private HtmlForm form1;
         private HtmlInputText inputText1;
         private HtmlOutputLabel outputLabel1;
         private HtmlCommandButton commandButton1;
         private HtmlDataTable dataTable1;
         private UIColumn column1;
         private UIColumn column2;
         private UIColumn column3;
         private UIColumn column4;
         private UIColumn column5;
         private UIColumn column6;
         private Statement stmt;
         private Connection connection;
         private ResultSet rs;
      public void setForm1(HtmlForm form1) {
               this.form1 = form1;
         }
      public HtmlForm getForm1() {
               return form1;
         }
      public void setInputText1(HtmlInputText inputText1) {
               this.inputText1 = inputText1;
         }
      public HtmlInputText getInputText1() {
               return inputText1;
         }
      public void setOutputLabel1(HtmlOutputLabel outputLabel1) {
               this.outputLabel1 = outputLabel1;
         }
      public HtmlOutputLabel getOutputLabel1() {
               return outputLabel1;
         }
      public void setCommandButton1(HtmlCommandButton commandButton1) {
               this.commandButton1 = commandButton1;
         }
      public HtmlCommandButton getCommandButton1() {
               return commandButton1;
         }
      public void setDataTable1(HtmlDataTable dataTable1) {
               this.dataTable1 = dataTable1;
         }
      public HtmlDataTable getDataTable1() {
               return dataTable1;
         }
      public void setColumn1(UIColumn column1) {
               this.column1 = column1;
         }
      public UIColumn getColumn1() {
               return column1;
         }
      public void setColumn2(UIColumn column2) {
               this.column2 = column2;
         }
      public UIColumn getColumn2() {
               return column2;
         }
      public void setColumn3(UIColumn column3) {
               this.column3 = column3;
         }
      public UIColumn getColumn3() {
               return column3;
         }
      public void setColumn4(UIColumn column4) {
               this.column4 = column4;
         }
      public UIColumn getColumn4() {
               return column4;
         }
      public void setColumn5(UIColumn column5) {
               this.column5 = column5;
         }
      public UIColumn getColumn5() {
               return column5;
         }
      public void setColumn6(UIColumn column6) {
               this.column6 = column6;
         }
      public UIColumn getColumn6() {
               return column6;
         }
      public String commandButton1_action() {
               // Add event code here...
            try {
                  Class.forName("oracle.jdbc.OracleDriver");
                  String url = "jdbc:oracle:thin:@localhost:1521:XE";
                  connection = DriverManager.getConnection(url, "OE", "OE");
                  stmt = connection.createStatement(
                                 ResultSet.TYPE_SCROLL_INSENSITIVE,
                                 ResultSet.CONCUR_READ_ONLY);
                  rs = stmt.executeQuery((String) inputText1.getValue());
                  HtmlDataTable dataTable1 = new HtmlDataTable();
                     dataTable1.setBorder(5);
                     dataTable1.setCellpadding("1");
                     dataTable1.setVar("journalcatalog");
                     ResultSetDataModel dataModel = new ResultSetDataModel();
                  dataModel.setWrappedData(rs);
                  this.setDataTable1(dataTable1);
                  UIColumn column1 = new UIColumn();
                     UIColumn column2 = new UIColumn();
                     UIColumn column3 = new UIColumn();
                     UIColumn column4 = new UIColumn();
                     UIColumn column5 = new UIColumn();
                     UIColumn column6 = new UIColumn();
                  this.setColumn1(column1);
                     this.setColumn2(column2);
                     this.setColumn3(column3);
                     this.setColumn4(column4);
                     this.setColumn5(column5);
                     this.setColumn6(column6);
                  HtmlOutputText headerComponent = new HtmlOutputText();
                     headerComponent.setValue("CatalogId");
                     column1.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Journal");
                     column2.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Publisher");
                     column3.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Edition");
                     column4.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Title");
                     column5.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Author");
                     column6.setHeader(headerComponent);
                  HtmlOutputText column1Text = new HtmlOutputText();
                  FacesContext fCtx = FacesContext.getCurrentInstance();
                     ELContext elCtx = fCtx.getELContext();
                     ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
                     ValueExpression ve = ef.createValueExpression(elCtx,
                                 "#{journalcatalog.catalogid}", String.class);
                  column1Text.setValueExpression("value", ve);
                  column1.getChildren().add(column1Text);
                  HtmlOutputText column2Text = new HtmlOutputText();
                  fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.journal}",
                                 String.class);
                     column2Text.setValueExpression("value", ve);
                  column2.getChildren().add(column2Text);
                     HtmlOutputText column3Text = new HtmlOutputText();
                  fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.publisher}",
                                 String.class);
                     column3Text.setValueExpression("value", ve);
                  column3.getChildren().add(column3Text);
                     HtmlOutputText column4Text = new HtmlOutputText();
                     fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.edition}",
                                 String.class);
                     column4Text.setValueExpression("value", ve);
                  column4.getChildren().add(column4Text);
                     HtmlOutputText column5Text = new HtmlOutputText();
                     fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.title}",
                                 String.class);
                     column5Text.setValueExpression("value", ve);
                  column5.getChildren().add(column5Text);
                     HtmlOutputText column6Text = new HtmlOutputText();
                     fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.author}",
                                 String.class);
                     column6Text.setValueExpression("value", ve);
                  column6.getChildren().add(column6Text);
                  dataTable1.setValue(dataModel);
            } catch (SQLException e) {
                     System.out.println(e.getMessage());
                     return "failure";
            } catch (ClassNotFoundException e) {
                     System.out.println(e.getMessage());
                     return "failure";
               } finally {
            }
               return "success";
         }
   }

运行 Facelets 应用程序

接下来,在运行应用程序之前,我们需要为 Facelets 应用程序指定一些 factory 类。

  1. 添加 WEB-INF/classes/META-INF/services 目录。
  2. 在 services 目录中,利用在 factory 文件中指定的相应 factory 实现类创建以下 factory 文件。
  • 文件名:javax.faces.application.ApplicationFactory

类名:com.sun.faces.application.ApplicationFactoryImpl

  • 文件名:javax.faces.context.FacesContextFactory

类名:com.sun.faces.context.FacesContextFactoryImpl

  • 文件名:javax.faces.lifecycle.LifecycleFactory

类名:com.sun.faces.lifecycle.LifecycleFactoryImpl

  • 文件名:javax.faces.render.RenderKitFactory

类名:com.sun.faces.renderkit.RenderKitFactoryImpl

下图显示了 Facelets 应用程序的目录结构。

facelet 23

  1. 如果 Oracle WebLogic Server 没有运行,请启动它。
  2. 要运行 Facelets 应用程序,右键单击 input.xhtml 并选择 Run As>Run on Server。

facelet 24

  1. 选择运行该应用程序的服务器。
  2. 单击 Next。
  3. 选择默认设置并单击 Next。
  4. 单击 Finish。

创建一个 EAR 应用程序并将其部署到 Oracle WebLogic Server。

facelet 25

  1. 在 Oracle WebLogic Server 上,运行我们早前利用 URL http://localhost:7001/Facelets/faces/input.xhtml 为 JSF 2.0 配置的 input.xhtml Facelet 组合页。

输入 Facelets 页的三个部分分别为页眉、内容和页脚。Facelet 组合页的不同部分对应 input.xhtml Facelet 组合页的不同 ui:define 标记。来自 BasicTemplate.xhtml 模板的 header.xhtml 和 footer.xhtml 文件包含在组合中。

  1. 指定 SQL 查询 SELECT * FROM OE.CATALOG,单击 Submit。

facelet 26

显示 output.xhtml Facelet 组合页,其中包括 SQL 查询生成的 JSF 数据表。

组合页中包含相同的 header.xhtml 和 footer.xhtml,这展示了模板功能。显示相同的页眉和页脚 .jpg 文件。

facelet 27

另请参见

关于作者

Deepak Vohra 是一名 Sun 认证的程序员、Sun 认证的 Web 组件开发人员以及 Oracle 认证的初级人员。

Facelets在JSF框架中的视图构建指南 本文还有配套的精品资源,点击获取 简介:Facelets是JavaServer Faces (JSF)框架的视图构建技术,用于创建企业级Web应用的组件化用户界面。它利用XML基础、可重用组件、模板结构和与JSF的集成,简化了页面布局和组件管理。博客提供了一个Facelets入门和高级特性的全面指南,包括布局文件解析、组件化、模板使用、EL表达式支持以及与JSF的交互细节。... 阅读详情

相关推荐

jsf2.0andrichfaces4.0 相关包

cssparser-0.9.5.jar guava-10.0.1.jar jsf-api.jar jsf-impl.jar richfaces-components-api-4.0.0.Final.jar richfaces-components-ui-4.0.0.Final.jar richfaces-core-api-4.0.0.Final.jar richfaces-core-impl-4.0.0.Final.jar sac-1.3.jar

weblogic.xml 部署描述符元素

  weblogic.xml 部署描述符元素 本文档提供 WebLogic Server 特定的部署描述符 weblogic.xml 中的元素的完整参考。如果您的 Web 应用程序不包含 weblogic.xml 部署描述符,WebLogic Server 会自动选择部署描述符元素的默认值。要查看 weblogic.xml 的 Schema,请转至 http://www.bea.com/ns/...

352

JSF/Facelets/xhtml学习

JSF/Facelets/xhtml学习

jsf标签_JSF Facelet标签示例教程

jsf标签JSF provides a special set of tags that gives the flexibility to manage common tags/parts in one place for more than one application. These tags allow us to create a common layout that can be use...

从零开始的教程世界 949

jsf-facelets-1.1.9

Facelets 非常适合 专为 JSF 设计的视图技术

IDEA集成selenium自动化测试(Java+Selenuim+testNG+Maven)

文章目录写在前面01 | 新建Maven项目02 | idea集成Selenium03 | 写在前面 因为软件测试的需求和博主比较经常使用Java,于是,想在Idea中集成selenuim,用Java编写测试代码,因此有了这篇文章来记录一下过程。 资源指路: java使用selenium实现模拟浏览器操作API大全 模拟登录 TestNG入门教程 感谢上面博客的大佬。 01 | 新建Maven项目 不使用骨架创建,直接点击左侧Maven,然后一路next即可。 02 | idea集成Sele

aLinxi的博客 8279

Templating with JSF 2.0 Facelets

In JavaServer Faces (JSF) 2.0, Facelets is the default view declaration language (VDL) instead of JavaServer Pages (JSP). With Facelets, you don’t need to configure a view handler as you used to do in

WebHub--Facilitating Web Development 918

Linux初级介绍之番外篇:Linux挂载windows中的共享目录

挂载windows共享目录Windows端共享权限设定解禁Guest设置共享目录权限Linux挂载端扫描共享目录挂载共享目录遇到错误的解决方案 Windows端共享权限设定 解禁Guest 右击我的电脑选择管理–>本地用户和组–>在用户项中双击Guest用户–>取消账号已禁用选项 设置共享目录权限 右击共享目录点属性–>在共享页面中点击共享选项–>下拉选择共享对象为Everyone–>点击共享按钮 3.设置本地策略 打开命令框–>输入secpol.msc–&gt

m0_53497201的博客 228

JSF 2.0检验总结之:同一个JBOSS 5.1.0 jsf 2.0(for primefaces) +JSF 1.2 同时运行的总结

背景: 公司原来有个产品是基于jboss 5.1.0 +jsf 1.2+EJB来开发的,由于jboss 5.1.0默认的提供了对jsf 1.2的支持,所以很容易的进行开发和部署,最近由于产品升级,要求前台需要用primefaces来实现,primefaces是基于jsf 2.0的,同时也要求旧的产品也可以在同一个runtime下运行 问题: 由于相同产品的两个不同实现要在同一个jbo

不积跬步,无以至千里;不积小流,无以成江海! 4344

手把手教你解决Windows 10网络驱动器无法访问问题(附详细排查步骤)

本文详细指导Windows 10用户解决网络驱动器无法访问的常见问题。通过从现象快速定位到系统排查,提供了从检查网络连通性、修复凭据权限到调整高级设置的完整步骤,特别是针对“找不到网络路径”等错误,帮助用户高效恢复对共享资源的访问。

weixin_29233857的博客 517

【原创教程】西门子1500与施耐德伺服的通讯以及调试

该函数块主要描述伺服的手动,左边的引脚Forward是指伺服手动正转,Backward是指伺服手动反转,Fast是指手动的某个方向为快速运行,TipPos手册上描述为固定值,WaitTIme是指伺服手动的相应时间,VeloSlow指伺服手动正常慢速运动的速度,VeloFast指伺服手动快速运动的速度,Acceleration是指伺服手动的加速度,Decelertion是指伺服手动的减速度。该函数块用于伺服停止,左边的引脚Execute为伺服停止执行,Deceleration含义为减速,Axis为轴。

Qinmingyue13的博客 1374

JSF 2使用Facelets进行模板化的示例

在Web应用程序中,大多数页面遵循相似的Web界面布局和样式,例如,相同的页眉和页脚。 在JSF 2.0中,您可以使用Facelets标记轻松提供标准的Web界面布局,实际上,它与Apache Tiles框架看起来很相似。 在此示例中,它显示了使用4个Facelets标签来从模板构建页面: ui:insert –在模板文件中使用,它定义了将由加载模板的文件替换的内容。 内容可以替换为“...

一名可爱的技术搬运工 395

《UDS协议从入门到精通(UDS速查手册)》(完结撒花版)

专栏总目录,文中介绍了UDS协议相关的基础知识和一些术语,给出了详细介绍6大类26种服务的跳转目录。

车载系统攻城狮 9万+

JSF2.0中Facelets将取代JSP

<br />原文: http://www.developersky.net/thread-22-1-1.html<br />迎接Facelets ,向JSP 说再见<br />JSF (Java Server Faces)是Java的UI组件框架,用来创建Web 应用程序动态页面。JSF提供了API来创建、管理、处理用于web页面的UI组件和标签库。JSF的最新版本JSF2 .0是Java EE 6 规范的一部分。JSF2.0提供了一些新的特性,能够帮助开发人员更加简单的开发JSF应用程序。<

lk617238688的专栏 1411

肺癌术后随访离散选择实验(DCE)设计与SAS实现

随着肺癌早期诊断和治疗技术的进步,肺癌患者的生存率显著提高,术后随访管理成为提升患者生活质量的关键环节。然而,如何在有限的医疗资源下设计出既符合患者需求又具有成本效益的随访方案,是临床决策面临的重要挑战。 离散选择实验(Discrete Choice Experiment, DCE)是一种定量研究方法,通过模拟真实世界的选择情境,测量患者对不同随访方案属性的偏好程度。本研究旨在通过DCE方法,系统评估肺癌术后患者对随访服务的偏好,为制定以患者为中心的随访策略提供循证依据。

huanghm88的专栏 97

ABAP Bits and Bytes 完全参考,理解内存、字节、位运算与类型解释

ABAP开发中业务代码与底层字节处理的差异:业务层关注采购订单、会计凭证等语义信息,而接口开发需处理十六进制、位运算等底层操作。文章通过整数变量示例说明同一段字节在不同类型解释下会呈现不同值,并介绍x类型、位运算及类型转换的实际应用。这些知识在文件接口、加密传输等场景中尤为重要,开发者需注意字节序、编码等问题。建议将底层协议处理与业务逻辑分离,以保持代码清晰和可维护性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 141

JSF —— Facelets 标签

最初是作为对JSF 1.x中基于JSP的视图处理程序的替代而开发的。在JSF2.0中,Facelets作为JSF的默认视图技术来替换JSP。除了是一种更好的视图处理程序外,Facelets还支持大量用于模板化和其他目的的标签。   命名空间: xmlns:ui="http://java.sun.com/jsf/facelets"   Facelet

tuxq5721 2946

LibCity:开源的交通预测算法库 | 面向小白,从0到1【SUMO十字路口仿真建模】路网搭建、车辆配置、实现仿真、仿真结果输出

LibCity:开源的交通预测算法库 | 面向小白,从0到1【SUMO十字路口仿真建模】路网搭建、车辆配置、实现仿真、仿真结果输出

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 458

如何在JSF 2.0中使用注释

问题 在JSF 2.0中,注释掉这样的JSF标记 JSF… <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitiona...

一名可爱的技术搬运工 513

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

facelets2.0_不要在facelets中重复表情

facelets2.0 您是否曾经在JSF中看到过像这样的重复EL表达式? <h:inputText value="#{oneBean.name}" rendered="#{anotherBean.showPerson}"/> <h:inputText value="#{oneBean.birthday}" rendered="#{anotherBean.showPerson...

cunfu5234的博客 106

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Simple JSF application with facelets

1. 把 jsf-facelets.jar 拷贝到 WEB-INF/lib 目录(在应用程序部署时,它最终必须放在 WEB-INF/lib 目录中)。 2. 把 Facelet 初始化参数添加到 web.xml 文件中。在web.xml里面添加以下参数:&lt;context-param&gt;  &lt;param-name&gt;javax.faces.DEFAULT_...

初学JAVA 152

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

JSF(MyFaces) + Facelets 的一些配置和开发准备

在这里想把用JSF和Facelets开发的一些基本的概念,配置和开发准备留个备忘录。目的是,在今后想用这两样技术的时候,能快速上手,关键的配置和注意点能一目了然,再做一个空的blank prj供开发用。 JSF的各种实现       刚开始一直弄明白JSF RI和Myfaces core是什么东西。 MyFaces Core同样是SUN JSF标准的实现,而JSF RI是SUN实现的JSF的...

iteye_1653的博客 295

JSF, MyFaces, RichFaces 和 Facelets的区别

初学JavaEE时很多东西都没理解,只是一股脑地往大脑里灌,现在是到明确一下的时候了。 JSF(JavaServer Faces) JSF是一套用于构造基于组件的Web应用的界面的规范。 需要着重强调的是,JSF是一套规范,即由人(JCP)规定好了这项技术应该包括哪些功能的一份说明,是抽象的概念。我们通常所讲的Web应用,指的是基于B/S架构的软件,通俗一点就是你打开浏览器看到的东西

停止更新 3364

JSF 2.0 Facelets标签之ui:include

一.先上各种对ui:include的解释说明:1.The UI Include tag is a server-side include tag for Facelets. It simply includes the document pointed to by the "src" attribute as part of the current JSF page. The included document should use a component or composition tag to tri

2515

JSF2.0

Jsf2.01.         Facelets界面组件模型在JSF  2.0 中引入了全新的界面表现模型Facelets ,可以方便的实现自有组件定制和页面模版化。Facelets是一个强大的轻量级声明语言。Facelets是用来建立JSF应用程序时的一个可供选择的表现层技术。由于Facelets 采用W3C 的XHTML规范,是一个严格的xml 规范,组件树渲染不再需要如jsp 一样编译成class 文件后再运行,可以直接渲染,而大大提升了渲染速度。2.         内置的Aja

wangyang_software的专栏 1664
上一篇: javax.faces.view.facelets.ResourceResolver
下一篇: WADL
javaPie
博客等级 码龄16年 1171粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值