Struts中用動態選擇的元素創建復選框
在用戶界面設計中,復選框組不如它的同類 —— 多行選擇框那樣流行。它們基本上做的是同一件事,即選擇映射到單一 name 屬性的一組選項。當在組中使用時,復選框執行的功能實際與多行選擇框一樣,但是它們占據的屏幕空間更多。當希望用戶在選擇一個或多個選項之前能夠看到所有選項的時候,這會很有好處。
雖然在選項不多的時候,多行選擇框通常提供更好的觀感,但是當選擇框必須動態呈現而且包含預選功能時,對企業應用程序來說復選框組會是更好的選擇。幸運的是,使用 Struts 框架可以很容易地創建動態復選框組。
在這篇文章中,我將介紹一個簡單的訣竅:用 Struts 的 <html:multibox/> 和 <logic:iterate/> 標記在應用程序的視圖層呈現大量條目,在本例中是 Java Server Page(JSP)。
我先從使用復選框元素顯示簡單的 String[] 數組開始,數組中包含喜瑪拉雅山的頂峰高度。然后,我將創建另外一個 String[] 數組,包含 selectedMountains ,代表已經選中的復選框。復選框的預選情況會在兩個數組的交叉中產生。如果 selectedMountains 的初始數組為空,那么所有復選框最初都會顯示為未選中。
創建動態復選框
創建動態復選框的訣竅包含三個主要部分:
第 1 步. 創建表單 bean
我先從創建 Struts 表單 bean 開始,它包含填充復選框所需要的信息。請注意清單 1 中的 TestForm.java 包含了兩個示例 String[] 數組變量的 getter 和 setter。數組 mountains 代表示例復選框的 全部選項,數組 selectedMountains 代表預選的在瀏覽器中顯示為選中的元素。
除了代表初始選中的復選框,selectedMountains 還代表處理表單時,由用戶選中的復選框。(它只代表最終選中的元素。)當請求頁面時,會顯示復選框。當我在它們之間迭代時,與 selectedMountains 匹配的復選框元素就是選中的元素。
清單 1 顯示了 TestForm.java 的完整代碼:
清單 1. TestForm.java
第 2 步. 編寫 JSP 代碼
接下來,我要編寫頁面的 JSP 代碼,把 TestForm.java 的信息傳遞給視圖層。在編寫這個代碼時,關鍵是要把對應的 Struts 標記庫導入 JSP。清單 2 的 JSP 代碼表示的是一個簡單的表單,顯示復選框中相應的框已經選中:
清單 2. 帶有表單的 JSP
注意,我用 Struts <bean:message/> 標記表示文本,用 <html:multibox/> 表示 HTML 復選框,用 <logic:iterate/> 標記在數組中迭代并創建相應內容。我的表單在 JSP 中通過 <html:form/> 標記被實例化。
下一步是對 <logic:iterate/> 標記中的 mountains 字段進行迭代。在這么做的時候,我創建了一個變量(mountain),用它來填充復選框,并用 <bean:write/> 標記給它一個標簽。要在復選框中創建 selected 屬性,我要再次使用 <logic:iterate/> 和 <html:multibox/> 標記。<html:multibox/> 標記中的 property 屬性由 selectedMountains 字段填充。當 selectedMountains 等于 mountain 時,selectBox 就是選中的。
第 3 步. 編寫 Action 類
最后一步是編寫 Action 類。清單 3 比起其他清單,做的事并不多。我做的只是得到 selectedMountains 的 String[] 數組,并使它可以用于頁面:
清單 3. 表單的 Action
擴充 Himalayas
有了這個代碼,工作就完成了,差不多可以展示成果了!用戶現在可以提交 JSP 表單并在 Action 類引用的對應頁面中查看結果。清單 4 中的代碼段顯示了用戶在簡單 JSP 頁面的表單中選中的復選框列表:
清單 4. 復選框選擇的結果
這個訣竅的工作方式
這個訣竅的關鍵是表單 bean 中的字段被傳遞到頁面。查看相關 JSP 代碼有助于澄清這點。一旦表單 bean 被實例化:
下一步為 Java 類的 mountains 變量中的每個 mountain 創建一個復選框。要做到這一點,我必須像下面這樣在 String[] 數組中迭代:
使用 <logic:iterate> 標記,我調用了 testForm bean 中的 getMountains() 方法。它在這個數組中迭代,并把每個值作為已經命名的 pageContext() 級的 String mountain[] 數組變量返回(即 id="mountain")。
在這里可以看到 <html:multibox/> 標記的效果以及如何顯示它:
注意 property 屬性被 selectedMountains 填充,這是我選中的變量。當這個變量與 <html:multibox/> 值(即 multibox 標記中的 <bean:write/>)對應時,在呈現表單的時候它就表現為選中。如果用戶選中表單或取消選中,那么新的 selectedMountains 值就被發送給 Action 類進行處理。這個迭代中的第二個 <bean:write/> 標記創建該標記使用的標簽,后面跟著 <br/> 標記,讓視圖在一長列中顯示這些標記。
擴展這個訣竅
通過使用 Struts LabelValueBean 類代替簡單的 String[] 數組,可以對動態復選框這個訣竅進行擴展,從而為復選框創建不同的標簽。先從添加 LabelValueBeans 到 java.util.List 開始。然后對列表進行迭代,把 LabelValueBeans 標簽和值釋放到適當的位置。這個略微復雜的訣竅與動態復選框訣竅的效果相同,但是它的結果更適合實際的用戶界面設計。清單 5 顯示了擴展的動態復選框訣竅:
清單 5. 添加標簽到動態復選框
注意,這里大的變化是用 <bean:define/> 在迭代的時候創建 LabelValueBean。然后用 <bean:write/> 輸出每個 mountainbean 的屬性(即 org.apache.struts.util.LabelValueBean 類的 getLabel() 和 getValue() 方法)。
結束語
Struts 對于復選框的動態呈現和預選提供了優秀的支持。這個訣竅是我合著 Struts Recipes 的原因 —— 那時我已經發現許多與 Struts 框架相關的理論和服務器端信息,但是用戶界面編程多數被忽略了,或者被掩蓋了。在上上下下找了一圈使用 Struts 創建復選框的訣竅之后,我放棄了,并自己寫了一個。通過把不同的部分組合起來,我可以創建適合我的動態復選框系統。
您會注意到,代碼示例被設置為適合用作不同用戶界面小控件和布局想法的測試溫床。實際上,我在書中的大多數用戶界面示例中都使用了它,只需要調整 Action 類和我的模型去適合訣竅的需求而已。我還把它用在測試不同的想法上,這樣就不用在我正在處理的應用程序內部花太多時間為某些東西編碼了。
雖然在選項不多的時候,多行選擇框通常提供更好的觀感,但是當選擇框必須動態呈現而且包含預選功能時,對企業應用程序來說復選框組會是更好的選擇。幸運的是,使用 Struts 框架可以很容易地創建動態復選框組。
在這篇文章中,我將介紹一個簡單的訣竅:用 Struts 的 <html:multibox/> 和 <logic:iterate/> 標記在應用程序的視圖層呈現大量條目,在本例中是 Java Server Page(JSP)。
我先從使用復選框元素顯示簡單的 String[] 數組開始,數組中包含喜瑪拉雅山的頂峰高度。然后,我將創建另外一個 String[] 數組,包含 selectedMountains ,代表已經選中的復選框。復選框的預選情況會在兩個數組的交叉中產生。如果 selectedMountains 的初始數組為空,那么所有復選框最初都會顯示為未選中。
創建動態復選框
創建動態復選框的訣竅包含三個主要部分:
- 一個表單 bean,容納復選框的 String[] 數組和表示選中復選框的 String[] 數組。
- 一個 JSP,帶有一個表單,在需要的時候顯示復選框。
- 一個簡單的 Action 類,從表單頁面轉到顯示頁面。
第 1 步. 創建表單 bean
我先從創建 Struts 表單 bean 開始,它包含填充復選框所需要的信息。請注意清單 1 中的 TestForm.java 包含了兩個示例 String[] 數組變量的 getter 和 setter。數組 mountains 代表示例復選框的 全部選項,數組 selectedMountains 代表預選的在瀏覽器中顯示為選中的元素。
除了代表初始選中的復選框,selectedMountains 還代表處理表單時,由用戶選中的復選框。(它只代表最終選中的元素。)當請求頁面時,會顯示復選框。當我在它們之間迭代時,與 selectedMountains 匹配的復選框元素就是選中的元素。
清單 1 顯示了 TestForm.java 的完整代碼:
清單 1. TestForm.java
package com.strutsrecipes; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; public final class CheckboxTestForm extends ActionForm { // Instance Variables /*Mountains "pre-selected"...*/ private String[] selectedMountains = {"Everest","K2","Lhotse"}; /*the ten tallest Mountains to iterate through*/ private String[] mountains = {"Everest","K2","Kangchenjunga","Lhotse", "Makalu","Kangchenjunga South", "Lhotse Middle","Kangchenjunga West", "Lhotse Shar","Cho Oyu"}; /*Getter for selectedMountains*/ public String[] getSelectedMountains() { return this.selectedMountains; } /*Setter for selectedMountains*/ public void setSelectedMountains(String[] selectedMountains) { this.selectedMountains = selectedMountains; } /*Getter for the mountains*/ public String[] getMountains() { return this.mountains; } /*Setter for the mountains*/ public void setMountains(String[] mountains) { this.mountains = mountains; } } |
第 2 步. 編寫 JSP 代碼
接下來,我要編寫頁面的 JSP 代碼,把 TestForm.java 的信息傳遞給視圖層。在編寫這個代碼時,關鍵是要把對應的 Struts 標記庫導入 JSP。清單 2 的 JSP 代碼表示的是一個簡單的表單,顯示復選框中相應的框已經選中:
清單 2. 帶有表單的 JSP
<%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%> <%-- html code, etc... --> <html:form action="/FormAction" name="testForm" type="com.strutsrecipes.CheckboxTestForm"> <h4><bean:message key="testForm.instruction"/></h4> <logic:iterate name="testForm" property="mountains" id="mountain"> <%-- create the checkbox and selected attribute --> <html:multibox property="selectedMountains"> <bean:write name="mountain"/> </html:multibox> <%-- create the label, note that "br" tag will format it vertically --> <bean:write name="mountain"/><br/> </logic:iterate> <br/> <html:submit/><html:reset/> </html:form> <%-- some more html code, etc... --> |
注意,我用 Struts <bean:message/> 標記表示文本,用 <html:multibox/> 表示 HTML 復選框,用 <logic:iterate/> 標記在數組中迭代并創建相應內容。我的表單在 JSP 中通過 <html:form/> 標記被實例化。
下一步是對 <logic:iterate/> 標記中的 mountains 字段進行迭代。在這么做的時候,我創建了一個變量(mountain),用它來填充復選框,并用 <bean:write/> 標記給它一個標簽。要在復選框中創建 selected 屬性,我要再次使用 <logic:iterate/> 和 <html:multibox/> 標記。<html:multibox/> 標記中的 property 屬性由 selectedMountains 字段填充。當 selectedMountains 等于 mountain 時,selectBox 就是選中的。
第 3 步. 編寫 Action 類
最后一步是編寫 Action 類。清單 3 比起其他清單,做的事并不多。我做的只是得到 selectedMountains 的 String[] 數組,并使它可以用于頁面:
清單 3. 表單的 Action
import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * A simple Action for Checkbox test. * * @author Danilo Gurovich */ public final class CheckboxTestAction extends Action { // -------------------------- OTHER METHODS -------------------------- /** * The execute method * * @param mapping ActionMapping * @param form CheckboxTestForm * @param request HttpServletRequest * @param response HttpServletRespons * @return success to the confirmation page * @throws ServletException not thrown, but could be! * @throws Exception ditto. */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException, Exception { // Extract attributes needed String[] selectedMountains = ((CheckboxTestForm) form).getSelectedMountains() ; System.out.println("htmlString RETURNED*" + selectedMountains.toString()); //Save the htmlString in the session for later... HttpSession session = request.getSession(); session.setAttribute(CheckboxConstants.MOUNTAINS, selectedMountains); return (mapping.findForward("success")); } } |
擴充 Himalayas
有了這個代碼,工作就完成了,差不多可以展示成果了!用戶現在可以提交 JSP 表單并在 Action 類引用的對應頁面中查看結果。清單 4 中的代碼段顯示了用戶在簡單 JSP 頁面的表單中選中的復選框列表:
清單 4. 復選框選擇的結果
<%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%> <%-- html code, etc... --> <logic:iterate id="mountain" property="mountains" name="testForm"> <bean:write name="mountain"/><br/> </logic:iterate> <hr size=5 color="black"/> <%-- some more html code, etc... --> |
這個訣竅的工作方式
這個訣竅的關鍵是表單 bean 中的字段被傳遞到頁面。查看相關 JSP 代碼有助于澄清這點。一旦表單 bean 被實例化:
<html:form action="/FormAction" name="testForm" type=" com.strutsrecipes.CheckboxTestForm"> |
下一步為 Java 類的 mountains 變量中的每個 mountain 創建一個復選框。要做到這一點,我必須像下面這樣在 String[] 數組中迭代:
<logic:iterate id="mountain" property="mountains" name="testForm"> |
使用 <logic:iterate> 標記,我調用了 testForm bean 中的 getMountains() 方法。它在這個數組中迭代,并把每個值作為已經命名的 pageContext() 級的 String mountain[] 數組變量返回(即 id="mountain")。
在這里可以看到 <html:multibox/> 標記的效果以及如何顯示它:
<html:multibox property="selectedMountains"> <bean:write name="mountain"/> </html:multibox> <bean:write name="mountain"/><br/> |
注意 property 屬性被 selectedMountains 填充,這是我選中的變量。當這個變量與 <html:multibox/> 值(即 multibox 標記中的 <bean:write/>)對應時,在呈現表單的時候它就表現為選中。如果用戶選中表單或取消選中,那么新的 selectedMountains 值就被發送給 Action 類進行處理。這個迭代中的第二個 <bean:write/> 標記創建該標記使用的標簽,后面跟著 <br/> 標記,讓視圖在一長列中顯示這些標記。
擴展這個訣竅
通過使用 Struts LabelValueBean 類代替簡單的 String[] 數組,可以對動態復選框這個訣竅進行擴展,從而為復選框創建不同的標簽。先從添加 LabelValueBeans 到 java.util.List 開始。然后對列表進行迭代,把 LabelValueBeans 標簽和值釋放到適當的位置。這個略微復雜的訣竅與動態復選框訣竅的效果相同,但是它的結果更適合實際的用戶界面設計。清單 5 顯示了擴展的動態復選框訣竅:
清單 5. 添加標簽到動態復選框
<logic:iterate id="mountainlb" property="mountainslb" name="testForm"> <bean:define id="mountainbean" name="mountainlb "type="org.apache.struts.util.LabelValueBean"/> <html:multibox property="selectedMountains"> <bean:write name="mountainbean" property="value"/> </html:multibox> <bean:write name="mountainbean" property="label"/><br/> </logic:iterate> |
注意,這里大的變化是用 <bean:define/> 在迭代的時候創建 LabelValueBean。然后用 <bean:write/> 輸出每個 mountainbean 的屬性(即 org.apache.struts.util.LabelValueBean 類的 getLabel() 和 getValue() 方法)。
結束語
Struts 對于復選框的動態呈現和預選提供了優秀的支持。這個訣竅是我合著 Struts Recipes 的原因 —— 那時我已經發現許多與 Struts 框架相關的理論和服務器端信息,但是用戶界面編程多數被忽略了,或者被掩蓋了。在上上下下找了一圈使用 Struts 創建復選框的訣竅之后,我放棄了,并自己寫了一個。通過把不同的部分組合起來,我可以創建適合我的動態復選框系統。
您會注意到,代碼示例被設置為適合用作不同用戶界面小控件和布局想法的測試溫床。實際上,我在書中的大多數用戶界面示例中都使用了它,只需要調整 Action 類和我的模型去適合訣竅的需求而已。我還把它用在測試不同的想法上,這樣就不用在我正在處理的應用程序內部花太多時間為某些東西編碼了。