數據庫 Orders表中的每一行存儲一個單獨的訂單,其中的信息包括聯系人姓名、送貨地址以及信用卡細目。Orders表有6列:OrderId(定單標識), ContactName(聯系人姓名), DeliveryAddress(送貨地址), CCName(信用卡所屬人姓名), CCNumber(信用卡號碼)和 CCExpiryDate(信用卡有效期限)。 用于在一個Oracle數據庫中創建所需的表的腳本文件pizzaria-oracle.sql存放在pizzaria.zip文件中。 業務對象 以下是在該應用程序中使用的業務對象: ProductBean用于封裝一個產品信息。它具有如下屬性:id(標識)、name(名稱)、description(說明)和price(價格)。每次details.asp頁被訪問的時候,JSF實現(implementation)就會自動創建一個ProductBean實例。該JSF實現調用ProductBean的無參數構造器,從數據庫中獲取相關的數據,并且將其填入相應的字列中。 ProductSummary。ProductSummary(產品概要)用于表示產品的概要。該類包含2個屬性:id(標識)和name(名稱)。 ShoppingItemBean。ShoppingItemBean用于表示購物項目。該類包含4個屬性:productId(產品標識), productName(產品名稱), price(價格)以及 quantity(數量)。 ShoppingCartBean。ShoppingCartBean用于表示一個存儲在對話(session)對象中的購物車。該類允許用戶添加購物項目(使用addShopping方法),獲取包含所有購物項目的列表(使用getShoppingItems方法),獲得所購貨物的總價值(使用getTotal方法)。 OrderBean。OrderBean表示一個訂單。該類具有如下5個屬性:contactName, deliveryAddress, creditCardName, creditCardNumber以及 creditCardExpiryDate。 MenuBean。MenuBean使用getMenu方法顯示可供產品的目錄。該方法返回一個包含到產品細節的鏈接的HTML表。
應用程序上下文監聽器 應用程序上下文監聽器(AppContextListener類)從web.xml文件讀出用于訪問數據庫的初始參數,然后將其寫入ServletContext對象。用到的初始參數如下:jdbcDriver, dbUrl, dbUserName和 dbPassword。在你的web.xml文件中編輯這些值,以便反應你數據庫的真實值。 JSF應用程序配置 JSF允許編程人員僅僅通過應用程序配置文件就可以輕松配置應用程序。該文件如果存在的話,則它應該被命名為faces-config.xml,并且應該位于你應用程序下的WEB-INF 目錄。 可以在faces-config.xmlz文件中對該應用程序的多個方面進行配置,包括bean管理、頁面導航、定制UI(用戶界面)組件、定制驗證程序和消息資源。在 PizzaRia 應用程序中,我將該faces-config.xml用于bean管理和頁面導航的配置。 <!ELEMENT managed-bean (description*, display-name*, icon*, managed-bean name, managed-bean-class, managed-bean-scope, (managed-property* | map-entries | list-entries))> 每個managed-bean元件都必須包含一個managed-bean-name元件,一個managed-bean-class元件,以及一個managed-bean-scope元件,并且可選擇性地包含一些描述、顯示名、圖標和managed-property/map-entries/list-entries元件。 managed-bean-name指定了被用來在整個應用程序中引用該JavaBean的名稱。managed-bean-class元件包含該JavaBean的完全限度的類名。managed-bean-scope元件定義該JavaBean的作用域。該元件可能的值是:application、session、request或者none。如果managed-bean-scope元件是none以外的其他值,那么,所創建的該JavaBean元件將會被存儲在相應的對象中。比如說,如果值是"session",那么,該JavaBean就會被存儲在一個給定用戶的session對象中。 在PizzaRia應用程序中,我注冊了如代碼清單1所示的4個JavaBeans。 頁面導航:頁面導航決定了Web應用程序的控制流。本節演示如何在JSF中創立一個頁面導航。 JSF使用navigation-rule元件來為頁面導航定義規則。其定義如下: <!ELEMENT navigation-rule (description*, display-name*, icon*, from-view-id?, navigation-case*)> from-view-id元件是首頁(起始頁)的標識符。為了說明被稱之為index.jsp的JSP頁面的導航規則,下面給出子元件from-view-id的值: <from-view-id>/index.jsp</from-view-id> navigation-case元件表示一個可能的目標頁面。navigation-rule一個元件可以有零個或者數個navigation-case子元件。 每個navigation-case元件都指定from-view-id的特定處理結果的目標頁面。結果可以來自from-view-id元件中 UICommand組件的行動(action)屬性。 navigation-case元件由如下所示的代碼描述: <!ELEMENT navigation-case (description*, display-name*, icon*, from-action?, from-outcome?, to-view-id, redirect?)> to-view-id元件指定目標頁面。from-outcome值是處理from-view-id的結果。該值來自于在from-view-id中觸發了ActionEvent的 UICommand組件的行動屬性。 from-action元件也表示處理from-view-id的結果。但其值來自于引發了ActionEvent的UICommand組件的行動屬性的運算值。 代碼清單2展示了在PizzaRia應用程序中使用的navigation-rule元件。 在JSP頁面中使用UI組件 JSF提供兩個定制標記庫來幫助用戶快速編寫Web應用程序:HTML和Core。HTML定制標記庫定義了用來表示UI組件的標記。Core定制標記庫使用具有組件的驗證器(validators)定義了注冊事件處理器的核心行動,以及其他一些行動。你可以在自己的JSF應用程序的JSP頁面中使用這兩個庫的標記。 為了在JSP頁面中使用HTML和Core定制標記庫,必須在頁面中包含如下所示的taglib指令: <%@ taglib uri="http://java.sun.com /jsf/html/" prefix="h" %> <%@ taglib uri="http://java.sun.com/ jsf/core/" prefix="f" %> Prefix的屬性值可以是任意值。但是,根據慣例,最好是使用"h"和"f"。 在JSF應用程序中編寫JSP頁面是每一個頁面制作者的責任。除了布置組件之外,他們的責任還包括把組件綁定到模型對象數據并且把Core標記(諸如事件監聽器和驗證器)添加到組件標記中。 在HTML定制標記庫中有25個標記。每個組件都呈現為一個HTML元件,而多個標記被呈現為同一個HTML元件。表1列出了HTML定制標記庫中的標記。
使用驗證器 驗證器是一個實現類(implementation class),它可以驗證輸入值,如果是非法輸入,就會發出一個錯誤信息。可以通過將一個驗證器嵌入一個其輸入需要驗證的輸入組件中來使用它。如果該驗證器判斷出用戶的輸入是非法的,那么JSF servlet就會重新顯示剛才提交了表單的那個JSP頁面,而不會將本地值復制給綁定到該輸入組件上的JavaBean實例。
另外,HTML定制標記庫中的input_text和input_textarea標記有必填的屬性。如果將該屬性標賦值為真,那么用戶在繼續進行操作之前,就必須對文本輸入框元件或者文本輸入區域進行填寫。 JSP應用程序是事件驅動型的程序。在JSF中處理事件令人驚奇的簡單。以下是處理步驟:
在JSF中的事件對象。JSF中的所有事件對象必須提供javax.faces .event.FacesEvent類,以便這些事件被請求處理生命周期支持。FacesEvent類是java.util.EventObject的子類,并添加了getComponent方法,該方法返回引發該事件的UIComponent組件。 FacesEvent類有兩個子類:ActionEvent和 ValueChangeEvent。ActionEvent類激活諸如UICommand組件之類的UI組件。 為捕獲一個JSF事件,需要使用一個事件監聽器。JSF程序中的所有監聽器都必須實現javax.faces.event.FacesListener接口。該接口提供java.util.EventListener接口,后者是必須由所有Java事件監聽器實現的接口。 public void processAction(ActionEvent event) throws AbortProcessingException ValueChangeListener接口是為了捕獲ValueChangeEvent而實現的接口。該接口添加了一個方法:processValueChange。當ValueChangeEvent動作被其監聽者監聽到時,就會調用processValueChange方法。processValueChange方法的代碼如下: public void processValueChange(ValueChangeEvent event) throws AbortProcessingException
AppActionListener類使用兩個非常有用的方法:getValueBinding 和getDatabaseUtil。getValueBinding接受指定對象名的字符串,并返回一個可以向下轉換類型為對象類型的ValueBinding對象。比如說,為獲得用戶的在應用程序配置文件中被注冊成shoppingCartBean 的ShoppingCartBean實例,開發人員需要通過傳遞"shoppingCartBean"來調用getValueBinding。 ShoppingCartBean cart = (ShoppingCartBean) getValueBinding("#{shoppingCartBean}").getValue(facesContext); getValueBinding方法如下: private ValueBinding getValueBinding(String valueRef) { ApplicationFactory factory = (ApplicationFactory)FactoryFinder .getFactory(FactoryFinder .APPLICATION_FACTORY); Application application = factory.getApplication(); return application.createValueBinding (valueRef); } getDatabaseUtil方法返回一個對ServletContext中的DatabaseUtil實例的引用: private DatabaseUtil getDatabaseUtil() { FacesContext facesContext = FacesContext.getCurrentInstance(); ServletContext servletContext = (ServletContext) facesContext.getExternalContext() .getContext(); return (DatabaseUtil) servletContext .getAttribute("DATABASE_UTIL"); } 運行該應用程序 JSF開發實戰(二) bromon原創 請尊重版權 JSF開發實戰的第一篇(jsf開發實戰一)演示了如何建立一個最簡單的JSF應用,從那個例子中我們可以觀察到JSF的頁面組件是如何與后臺的javabean綁定的,也看到了JSF標簽的最基本使用。在本文中我們會演示一個更加復雜的應用,它包含了更豐富的JSF標簽。 要開發的例子是一個用戶管理程序,管理員輸入帳號與密碼登陸,然后它可以看到所有用戶的列表,并且可以修改或者刪除其中的一些數據。利用myeclipse所帶的jsf-config.xml設計器,頁面流程如下: ![]() 可以看出,這個應用設計到的業務邏輯有: 用戶登陸、修改用戶信息、增加新用戶、刪除用戶 我們在后臺的數據庫操作中使用hibernate框架來輔助開發,相關的技術細節請自行查閱文檔。 首先建立pojo文件:User.java,它包含幾個基本屬性: private int id; private String name; private String password; private int power; 請自行完成set/get方法,并且編寫對應的hbm.xml文件。 我們的主要工作之一,是要建立好供jsf頁面組件使用的javabean,把它命名為UMDelegater.java。它會調用UserManager來完成業務邏輯,這里是一個代理模式。UserManager的內容只是簡單的增/刪/查/改的操作,這里不再具體列出。UMDelegater的內容是: package org.bromon.jsf.control; import java.util.List; import javax.faces.model.DataModel; import javax.faces.model.ListDataModel; import org.bromon.jsf.model.UserManager;//自行建立的工具類,負責所有的hibernate操作 import org.bromon.jsf.model.pojo.User;//pojo對象 public class UMDeletager { private UserManager um=new UserManager();//所有具體的方法都由它來實現 private User user=new User(); private DataModel allUsers=new ListDataModel();//JSF的內置對象,用來封裝html中table的數據 //----------set/get方法--------------------- public DataModel getAllUsers() { return allUsers; } public void setAllUsers(List list) { allUsers.setWrappedData(list); } public UserManager getUm() { return um; } public void setUm(UserManager um) { this.um = um; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } //-----功能方法--------- public String login() { String s=um.login(this.getUser()); if(s.equals("ok")) { this.setAllUsers(um.loadAll());//如果登陸成功,就取出所有的用戶信息 return "login:ok"; }else { swapper.setLoginFailInfo(s); return "login:fail"; } } public String edit() { this.user=(User)allUsers.getRowData();//頁面中的table自動返回含有id的user對象 this.user=um.loadById(user.getId()); if(user!=null) { return "edit"; }else { return "error"; } } public String update() { um.update(this.getUser()); this.setAllUsers(um.loadAll());//重新取一次數據,目的是更新緩存 return "update:ok"; } public String addNew() { this.setUser(new User());//生成一個新的user對象,不含任何數據,它會被自動映射成一個沒有數據的form return "add"; } public String add() { um.add(this.getUser()); this.setAllUsers(um.loadAll());//重新取一次數據,目的是更新緩存 return "add:ok"; } } 在jsf-config.xml中聲明這個bean: <managed-bean> <managed-bean-name>UMDelegater</managed-bean-name> <managed-bean-class>org.bromon.jsf.control.UMDeletager</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> 業務邏輯就設計完成了,下面可以開始編寫jsf文件,首先是index.jsp: 首先引入標簽庫,并且聲明page屬性: <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 然后是構建頁面: <body> <f:view> <h:form> <h:panelGrid columns="3"> <h:outputLabel for="name" value="帳號:"/> <h:inputText id="name" value="#{UMDelegater.user.name}" required="true"/> <h:message for="name"/> <h:outputLabel for="password" value="密碼:"/> <h:inputSecret id="password" value="#{UMDelegater.user.password}" required="true" /> <h:message for="password"/> </h:panelGrid> <h:panelGroup> <h:commandButton value="登陸" action="#{UMDelegater.login}"/> </h:panelGroup> </h:form> </f:view> </body> 頁面中聲明了兩個文本框,分別映射UMDelegater對象中user對象的name屬性,和UMDelegater對象中user對象的password屬性。一旦這個表單被提交,這兩個文本框的值就會被自動賦給user對象,我們只需要從user中取數據就行了,不用再去執行麻煩的request.getParameter(“”),更改編碼,轉換數據類型等操作。 我們同時還聲明了一個button,它與UMDelegater對象的login方法綁定,點擊該按鈕,系統會執行UMDelegater.login方法,該方法從user對象中取出name和password,和數據庫中的記錄進行比較。如果合法,那么就取出所有的數據,放到一個DataModel對象中,具體代碼是: List userList=UserManager.getAllUser();//取得所有用戶數據,放到一個List中 DataModel allUser=new ListDataModel ();//DataModel是一個接口,ListDataModel是它的一個實現 allUsers.setWrappedData(userList);//將數據填充進去備用 使用DataModel意義何在呢?JSF中,我們可以把一個html頁面上的table和一個DataModel綁定起來,這些數據會自動填充到table中,我們不必再自己去寫循環,生成若干的<tr>、<td>來生成一個table。在list.jsp中我們會看到如何使用DataModel。 放好數據之后,登陸成功的操作就完成了,返回一個login:ok,就可以重定向到list.jsp。如果用戶登陸失敗,那么會返回login:fail,重定向到error.jsp,它的內容就不敘說了。下面我們看看list.jsp里面有什么,下面是它的<body>代碼: <body> <f:view> <h:form> <h:dataTable id="users" value="#{UMDelegater.allUsers}" var="u" border="1" width="80%" > <h:column> <f:facet name="header"> <h:outputText value="id"/> </f:facet> <h:outputText value="#{u.id}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="帳號"/> </f:facet> <h:commandLink action="#{UMDelegater.edit}"> <h:outputText value="#{u.name}"/> </h:commandLink> </h:column> <h:column> <f:facet name="header"> <h:outputText value="密碼"/> </f:facet> <h:outputText value="#{u.password}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="權限代碼"/> </f:facet> <h:outputText value="#{u.power}"/> </h:column> </h:dataTable> <p> <h:commandLink action="#{UMDelegater.addNew}" value="增加用戶" /> </p> </h:form> </f:view> </body> 我們使用了一個h:dataTable標簽,它是JSF獨有的東西,它會被翻譯為一個html的table,通過指定h:dataTable的value="#{UMDelegater.allUsers}"屬性,它就與我們剛才生成的DataModel對象關聯起來,數據會被自動填充。我們只需要聲明dataTable中的每一列的表頭,數據來自哪個字段就可以了,如下: <h:column> <f:facet name="header"> <h:outputText value="id"/> </f:facet> <h:outputText value="#{u.id}"/> </h:column> 表格最后還有一個“增加用戶”的按鈕,它與UMDelegater.addNew綁定,它會把我們重定向到add.jsp。 需要注意的是,每個用戶名都是個超鏈接,點擊之后可以重定向到edit.jsp,這個頁面可以修改用戶資料。這是通過如下代碼實現的: <h:commandLink action="#{UMDelegater.edit}"> <h:outputText value="#{u.name}"/> </h:commandLink> 可以看出,實際上系統調用了UMDelegater.edit方法,該方法的功能是根據頁面傳過來的用戶id查詢數據庫,找到相關記錄后返回一個User對象,然后重定向到edit.jsp,由于我們后面編寫edit.jsp的時候會把form元素與User對象綁定,所以該User對象所含有的數據會自動顯示到各個form元素上。 list.jsp的顯示效果如下: ![]() 看到這里你也許會問,那么我如何來美化這個表格?實際上這正式JSF這類框架面臨的最大問題,它大量的使用了標簽庫,目前流行的網頁制作工具(如deamweaver)又沒有提供足夠的支持,所以只能依靠挖掘dataTable標簽的各個屬性,并且大量依賴css才能實現頁面的美化。如果java世界能有一個強大的JSF IDE,能夠提供vs.net一樣的能力,那么JSF也許會更容易流行。 下面我們來看看edit.jsp的內容,如下: <body> <f:view> <h:form> <h:inputHidden id="id" value="#{UMDelegater.user.id}"/> <h:panelGrid columns="3"> <h:outputLabel for="name" value="帳號"/> <h:inputText id="name" value="#{UMDelegater.user.name}" required="true"/> <h:message for="name"/> <h:outputLabel for="power" value="權限"/> <h:inputText id="power" value="#{UMDelegater.user.power}" required="true"/> <h:message for="power"/> </h:panelGrid> <h:panelGroup> <h:commandButton value="保存" action="#{UMDelegater.update}"/> </h:panelGroup> </h:form> </f:view> </body> 可以看出,edit.jsp并沒有什么特別需要留意的,只是一個最簡單的form與bean的綁定,“保存”按鈕與UMDelegater.update方法綁定,它的功能是把修改后的form數據寫入數據庫,然后重新取一次數據,以免緩存做怪,看不到修改的效果。 Add.jsp也和edit.jsp很類似,它的內容如下: <body> <f:view> <h:form> <h:panelGrid columns="3"> <h:outputLabel for="name" value="帳號:" /> <h:inputText id="name" value="#{UMDelegater.user.name}" required="true"/> <h:message for="name"/> <h:outputLabel for="password" value="密碼:"/> <h:inputText id="password" value="#{UMDelegater.user.password}" required="true"/> <h:message for="password"/> <h:outputLabel for="power" value="權限"/> <h:inputText id="power" value="#{UMDelegater.user.power}" required="true"/> <h:message for="power"/> </h:panelGrid> <h:panelGroup> <h:commandButton value="保存" action="#{UMDelegater.add}"/> </h:panelGroup> </h:form> </f:view> </body> JSF開發實戰(一) bromon原創 請尊重版權 JSF將是J2EE5.0中所包含的web開發框架,這應該是第一個成為jcp標準,并且隨j2eesdk一起發布的web框架,可以看出sun對它的期望很高。JSF最大的競爭對手是tapestry,是apache的產品,但是apache又弄出了個myfaces,是對jsf標準的一個實現。也許你也和我一樣,在jsf和tapestry之間猶豫很久,將來從apache的態度上應該可以看出二者的走向。在tss上有一篇比較jsf 1.0與tapestry 3.0的文章,內容很扎實到位:http://www.theserverside.com/articles/article.tss?l=JSFTapestry JSF的競爭對手不是struts/webwork之流,它們基本上已經是不同階段上的東西了,放在一起比較意義不大。 JSF的開發流程和asp.net中所倡導的code behind方式很相似,核心是事件驅動,組件和標簽的封裝程度非常高,很多典型應用已經不需要開發者去處理http。頁面操作會被自動映射到對應的java bean中,后臺邏輯只需要同java bean發生交互。整個過程是通過“依賴注入(DI)”來實現的,看來這是目前解偶合的最佳途徑啊,spring的影響真是深遠。不過正式因為jsf采用了這樣的方式,導致開發工作和以前的jsp/struts等都有非常大的不同,需要一定的時間去學習。學習之前建議先對依賴注入有比較清楚的認識,可以參考我的learn Spring in spring系列的第一篇。 本系列將以兩個例子來講解jsf的基本開發,第一個例子當然是hello world。目前可用的jsf ide不多,ibm要到06年才能放出支持jsf的wtp版本。所以我們的例子基本以手寫為主,這樣也能讓我們有更清楚的認識,同時推薦目前最好的jsf開發工具:myeclipse 4.0 GA。后面的例子將會有jsf和hibernate的內容,它都能給予很好的支持。由于myeclipse并不免費,所以我們除了講解在ide中如何操作外,還會敘述手動操作的具體內容,以免過于依賴開發工具。用什么服務器都可以,這里采用了jboss 4.0.2。如果你的服務器是高版本的tomcat(5.5+),那么必須要刪除它自帶的一些包才能很好的支持jsf,具體細節請查看它的文檔。 請自行下載jsf ri和JSTL 1.1。 廢話少說,開始了。 在myeclipse 4.0GA中新建一個web項目,命名為hello,為項目增加對JSTL的支持: ![]() 在JSTL的版本中選擇1.1。 該操作實際上是把jstl.jar和standard.jar加到工程中。 采用類似的操作為項目添加對jsf的支持:myeclipse?add jsf capabilities 如圖: ![]() 其中的jsf implementation是選擇使用哪中JSF實現,我們采用的是sun的jsf ri JSF config path是配置文件的位置,保持不變 URL pattern是jsf servlet的映射方式,有兩種選擇,具體細節后面說明。 以上操作上是為項目加入了jsf需要的jar和tld文件,并且創建了一個faces-config.xml的配置文件。涉及到的jar有:commons-beanutils.jar commons-collections.jar commons-digester.jar commons-logging.jar jsf-api.jar jsf-impl.jar 涉及到了jsf中所有的tld文件。 當前的faces-config.xml文件的內容是: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config> </faces-config> 環境已經建立好了,現在我們要建立一個程序,它的功能是讓用戶在表單中輸入名字,提交后系統會返回一個問候。使用jsf的以后好處是,開發人員會很自然的把mvc各層分開,不會像使用strtus那樣別扭,這一點在后面的開發中感覺得到。 首先開發model層,它是個很簡單的bean: package org.bromon.jsf.model.hello; public class SayHello { public String say(String name) { return "你好,"+name; } } 在model層中你可以隨意的實現業務的數據邏輯,不需要與web層有任何的關系。 下面開發控制層,它負責存取web層的數據,并且調用model層的邏輯: /** * jsf的控制層方法 * @author bromon */ package org.bromon.jsf.control.hello; import org.bromon.jsf.model.hello.*; public class HelloDelegater { //------屬性--------- private String name;//表單中的文本框數據會傳到這里 private String result;//web頁會從這里取得運行結果 private SayHello sayHello;//model層的對象,并不事例化,由系統注入 //-----set/get-------- public String getName() { return name; } public void setName(String name) { this.name = name; } public SayHello getSayHello() { return sayHello; } public void setSayHello(SayHello sayHello) { this.sayHello = sayHello; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } //-----邏輯方法--------- public String say() { this.setResult(sayHello.say(this.getName())); return "ok"; } } 需要注意的是,屬性的名字、set/get方法的名字必須嚴格按照java bean規范編寫,因為它們要被注入依賴時使用。sayHello對象并沒有被實例化,它會在運行時由系統注入。 這兩個bean當然要在系統中申明,否則無法實現DI。在faces-config.xml文件中添加內容: <managed-bean> <managed-bean-name>SayHello</managed-bean-name> <managed-bean-class> org.bromon.jsf.model.hello.SayHello </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>HelloDelegater</managed-bean-name> <managed-bean-class> org.bromon.jsf.control.hello.HelloDelegater </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>sayHello</property-name> <value>#{SayHello}</value> </managed-property> </managed-bean> 在后一個bean中,它的sayHello屬性被指定要在運行時注入一個org.bromon.jsf.model.hello.SayHello的實例。 下面要編寫表示層的頁面,只有一個index.jsp: 需要引入兩個標簽庫: <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> 下面是構造jsf標簽: <body> <f:view> <h:form> <h:panelGrid columns="3"> <h:outputLabel for="name" value="姓名:"/> <h:inputText id="name" value="#{HelloDelegater.name}" required="true"/> <h:message for="name"/> <h:outputLabel value="#{HelloDelegater.result}"/> </h:panelGrid> <h:panelGroup> <h:commandButton action="#{HelloDelegater.say}" value="提交"/> </h:panelGroup> </h:form> </f:view> </body> 頁面中包含了一個文本框和一個label,他們分別被綁定到了HelloDelegater類的兩個屬性上,具體的綁定工作有系統通過翻轉控制的方式調用對應的set/get方式實現。提交按鈕被綁定到了HelloDelegater.say方法,該方法會把計算結果賦給result屬性,它會在頁面中顯示出來。 因為我們在url pattern中選擇了*.faces,所以我們應該訪問如下地址來查看程序: http://localhost:8080/hello/index.faces 相應的,如果你選擇了/faces/*,那么就應該是: http://localhost:8080/hello/faces/index.jsp 程序執行結果如下: ![]() 下一篇文章中,將介紹一個更加復雜的用戶管理程序,可以更清楚的看到jsf的特征,還會涉及到jsf的model對象一些組件的使用。 |
|