官术网_书友最值得收藏!

6.3 使用HTML標簽

與通用標簽不同,HTML標簽不過多提供控制結構或邏輯。而是著重于如何使用action類、value stack或者Data Tags中的數據,并且在HTML中呈現出來。如果說普通標簽只是簡單地做些輸出結果(如果有內容),HTML標簽的輸出則是因模板(template)而異,它們常常組合在一起作為一個主題(theme),做實際的渲染輸出HTML的工作。關于模板和主題將在以后的章節詳細介紹。

Struts2竭力支持開發者所偏愛的技術,這也是Struts2沒有綁定于某一種特定的模板語言的原因。Struts2支持幾乎所有應用廣泛的模板語言甚至還為新語言提供了接口。默認情況下,幾乎每一個標簽都支持JSP、Velocity和FreeMarker。

注意

Struts2中默認的模板語言是FreeMarker,而不像其前身WebWork中默認的是Velocity。關于兩者的優劣有很多評論,一般的說法是FreeMarker提供的錯誤信息更多,更加容易調試。

6.3.1 模板和主題

Struts提供的html標簽的核心是主題(theme)和模板(template)。首先明確一下3個概念:

1)tag(標簽):小段代碼,在JSP、FreeMarker或者Velocity里執行。

2)template(模板):一個文件,通常使用JSP或者FreeMarker編寫,能被特定的標簽(HTML tags)輸出。

3)theme(主題):一系列templates打包在一起,提供通用的功能。

Struts2提供了4種主題可以選擇:

1)simple主題:一個最小的主題,包含了最少的輔助功能。使用simple主題的缺點就是它不支持其他主題那么多的屬性。例如label屬性在simple主題里沒有任何用處。類似地,simple主題提供的功能也遠遠少于xhtml和ajax主題,自動顯示錯誤信息就不被支持。

2)xhtml主題:使用了通用的HTML實踐的默認主題。

3)css_xhtml主題:使用嚴格的CSS布局對xhtml主題重新實現。

4)ajax主題:一個基于xhtml主題的主題,提供了高級AJAX特性。

關于主題有兩項配置,它們定義在struts.properties文件中,如表6.18所示。

表6.18 主題的配置

注意

使用simple主題的缺點就是它不支持其他主題那么多的屬性。例如,label屬性在simple主題里沒有任何用處。類似地,simple主題提供的功能也遠遠少于xhtml和ajax主題提供的:自動顯示錯誤信息就不被支持。

6.3.2 通用屬性

每個UI標簽都有一些共有的通用屬性。除了那些處理label的屬性,其他屬性都可以在simple和xhtml主題上使用。表6.19列出了UI標簽所有的通用屬性。

表6.19 UI標簽所有的通用屬性

如果沒有設定ID屬性,那么Struts2表單標簽會自動設置一個ID。form標簽的ID就是其action的名字,如“updatePerson”。對于Form內的表單元素ID被設定為所在form的ID+"_"+元素的name屬性,如“updatePerson_username”。

除了表6.19中的通用屬性之外,所有的UI標簽也支持通常設置的JavaScript事件。這允許簡單的JavaScript集成并讓表單更具有交互性,見表6.20。

表6.20 UI標簽支持的JavaScript事件

所有的UI標簽還有一項特性很有趣,也很有用,那就是“name-value聯動”。通常在構建一個表單時輸入數據的字段也是從它獲取數據的字段,并會把它顯示在表單中(通過value屬性賦值)。常見的就是在修改屬性的表單中,如下代碼:

<s:form action="updateUser">
<s:textfield name="user.firstName" value="%{user.firstName}"/>
</s:form>

Struts2提供一個簡單的方式,可以自動設置value的值,無須以顯式的方式給value賦值了。如下代碼所示:

<s:form action="updateUser">
<s:textfield name="user.firstName“/>
</s:form>

當然,有時不需要默認的值在表單中作為這個字段的值,可以給value屬性賦其他值。

6.3.3 表單標簽介紹

在HTML中的表單元素在Struts2中都提供了對應的標簽來支持,見表6.21所示。

表6.21 表單標簽成員列表

表單標簽成員眾多,但使用方法都比較類似。本書只介紹幾種典型的標簽。

1. form標簽

form標簽是所有UI標簽中獨一無二的,因為它擔當了容器的角色。它有一個起點(<s:form>)和一個終點(</s:form>)。在simple主題里,它只輸出html的form元素,而在xhtml主題中,它除了form元素之外還輸出周圍的表格。form標簽的屬性如表6.22所示。

表6.22 form標簽屬性表

要注意最重要的兩個屬性是action和namespace。它們組合起來,用來把form鏈接到一個特殊的action。例如,如下代碼會被提交到/secure/updateProfile.action:

<s:form action="updateProfile" namespace="/secure">

2. textfield標簽

textfield標簽是最常用的一個UI標簽,輸出一個text類型的HTML input元素,在前面的章節中已經多次使用。textfield標簽的屬性如表6.23所示。

表6.23 textfield標簽屬性表

3. textarea標簽

textarea標簽用來填寫比textfield標簽更大數量的文本(包括換行符),不像textfield和password標簽那樣輸出HTML<input>標記,這個標簽輸出HTML<textarea>標記。textarea標簽的參數如表6.24所示。

表6.24 textarea標簽參數表

4. checkbox標簽

不像其他標簽,checkbox標簽不把字段的value當成字符串類型。也就是說,復選框必須有一個字段為布爾量來求值或者能被轉化為布爾類型。

<s:checkbox label=" BOX" name=user.address.poBox fieldValue="true'>

注意

復選框和其他的標簽有點不同。HTML的規范方式要求只有當復選框被選中的時候才會提交對應的值。如果復選框沒有被選中,那么提交的參數中就根本不包含這個項目。因此接受參數的model設計時,應該將默認值定為false,很可能是model此字段沒有被賦值。這樣做可以保證表單提交時不論復選框狀態為何,都會得到期望的值。

5. select標簽

創建一個HTML Select列表組件。select標簽的參數如表6.25所示。

表6.25 select標簽參數表

最重要的屬性是list,它告訴標簽要選擇的選項從哪里來。在最簡單的表單里,列表呈現給用戶,選擇的值會被提交到表單并被映射到指定的字段,也是與名字對應的屬性。如果一個值被預先設置,那么列表里這個字段具有相同值的選項就會自動被選中。

<s:select label="State" name="user.address.state" list="{'江西','湖北'}">

在這個例子中,表達式user.address.state的值會被設置為江西或者湖北。如果填入的值是這兩個值中的一個,select標簽就會設置表單。輸出的HTML可能是

<select>
<option>'江西'<option>
<option>'湖北'<option>
</select>

很多時候可能會希望option的顯示值和實際值是不同的。比如:

<select>
<option value=1>'江西'<option>
<option value=2>'湖北'<option>
</select>

這需要給select標簽設置listKey和listValue屬性就可以。listKey和listValue特性是通過迭代這個列表并在循環中把對象放到stack頂部的方式進行的。這也是iterator標簽使用的相同的方式。如果使用的是一個map作為select標簽進行迭代的列表,對象會通過Map.Entry進行迭代,就像iterator標簽一樣。因為Map.Entry提供了getKey()和getValue()方法,這些通常被用來作為listKey和listValue的值。使用基于Map的方法來重新編寫state下拉框:

<s:select label="State" name="user.address.state" list="#{1:'江西', 2:'湖北'}">

6.3.4 非表單標簽

非表單標簽與表單標簽相反,是為輸出一些表單以外的HTML元素設計的,主要用于顯示而非提交參數。它們也會帶來很多方便,如table自動排序等。非表單標簽成員如表6.26所示。

表6.26 非表單標簽成員列表

需要解釋一下的是component標簽,使用特定的模板輸出一個自定義的UI widget(組件)。附加的對象可以通過param標簽傳遞給模板,設置的對象可以在模板里面通過 $parameters.paramname獲取。如在component(組件)內部,它們可以通過$parameters.get('key1') 和 $parameters.get('key2') 的方式被訪問,也允許通過$parameters.key1和$parameters.key2來引用它們。

component標簽提供了一種建立自定義UI標簽的方式。例如,假設想要一個包含3項的復選框來表示on/off/none,可以使用HTML來編寫一個,用JavaScript和一些定制的圖像來代表3個狀態。

6.3.5 標簽實例

首先看一下需要表現的頁面,是一個用戶信息修改提交頁面,如圖6.11所示。

圖6.11 標簽舉例界面圖

如果用普通JSP表現,如實例6-14所示,在firstname字段后面有關于錯誤信息的處理,如果有錯誤信息,就在這個字段后面打印錯誤日志。

【實例6-14】標簽實例:updateProfile.jsp

01    <%@ page
02    import="org.hibernate.auction.model.User,org.hibernate.auction.model.Address,
      java.util.Map,java.util.Collections"%>
03    <%
04      User user = (User) request.getAttribute("user");
05      Map fieldErrors = (Map) request.getAttribute("fieldErrors");
06      if (fieldErrors == null) {
07         fieldErrors = Collections.EMPTY_MAP;
08      }
09    %>
10 <html>
11        <head>
12             <title><s:text name="title" />UpdateProfile</title>
13        </head>
14        <body>
15             <form action="updateProfile.action" method="post">
16                  <table>
17                        <% if (fieldErrors.containsKey("user.firstname")) {%>
18                        <tr>
19                             <td align="center" valign="top" colspan="2">
2 0                                  <span class="errorMessage"> <%= fieldErrors.get("user.firstname")%>
21                                  </span>
22                             </td>
23                        </tr>
24                        <% }%>
25                        <tr>
26                             <td align="right">
27                                  <label>
28                                      First name£o
29                                  </label>
30                             </td>
31                             <td>
32                                  <input type="text" name="user.firstname"
33                                        value="<%= user.getFirstname() %>" />
34                             </td>
35                        </tr>
36                        <tr>
37                             <td align="right">
38                                  <label>
39                                      Last name£o
40                                  </label>
41                             </td>
42                             <td>
43                                  <input type="text" name="user.lastname"
44                                        value="<%= user.getLastname() %>" />
45                             </td>
46                        </tr>
47                        <tr>
48                             <td align="right">
49                                  <label>
50                                      Email£o
51                                  </label>
52                             </td>
53                             <td>
54                                  <input type="text" name="user.email"
55                                        value="<%= user.getEmail() %>" />
56                             </td>
57                        </tr>
58                        <tr>
59                             <td align="right">
60                                  <label>
61                                      Gender£o
62                                  </label>
63                             </td>
64                             <td>
6 5                                  <input type="radio" name="user.gender" value="0" id="user.gender0"
6 6                                        <% if (user.getGender() == 0) { %> checked="checked" <% } %> />
67                                  <label for="user.gender0">
68                                        Male
69                                  </label>
7 0                                  <input type="radio" name="user.gender" value="1" id="user.gender1"
7 1                                        <% if (user.getGender() == 1) { %> checked="checked" <% } %> />
72                                  <label for="user.gender1">
73                                        Female
74                                  </label>
75                             </td>
76                        </tr>
77                        <%
78     Address address = user.getAddress();
79     boolean nullAddress = address == null;
80 %>
81                        <tr>
82                             <td align="right">
83                                  <label>
84                                        Street Address:
85                                  </label>
86                             </td>
87                             <td>
88                                  <input type="text" name="user.address.street"
89                                      value="<%= !nullAddress ? address.getStreet() £o ""%>" />
90                             </td>
91                        </tr>
92                        <tr>
93                             <td align="right">
94                                  <label>
95                                      Zip Code£o
96                                  </label>
97                             </td>
98                             <td>
99                                  <input type="text" name="user.address.zipcode"
100                                     value="<%= !nullAddress ?address.getZipcode() £o ""%>" />
101                            </td>
102                      </tr>
103                      <tr>
104                            <td align="right">
105                                 <label>
106                                     City£o
107                                 </label>
108                            </td>
109                            <td>
110                                 <input type="text" name="user.address.city"
111                                     value="<%= !nullAddress ?address.getCity() £o ""%>" />
112                            </td>
113                      </tr>
114                      <tr>
115                            <td align="right">
116                                 <label>
117                                     State£o
118                                 </label>
119                            </td>
120                            <td>
121                                 <select name="user.address.state">
122                                      <option value="Californa"
123                                            <% if (!nullAddress &&
124                        "California".equals(address.getState())) { %>
125                                            selected="selected" <% } %>>
126                                            Californa
127                                      </option>
128                                      <option value="Oregon"
129                                            <% if (!nullAddress &&
130                        "Oregon".equals(address.getState())) { %>
131                                            selected="selected" <% } %>>
132                                            Oregon
133                                      </option>
134                                 </select>
135                            </td>
136                      </tr>
137                      <tr>
138                            <td align="right">
139                                 <label>
140                                     Country£o
141                                 </label>
142                            </td>
143                            <td>
144                                 <select name="user.address.country">
145                                      <option value="USA"
146                                            <% if (!nullAddress && "USA".equals(address.getCountry())) { %>
147                                            selected="selected" <% } %>>
148                                            USA
149                                      </option>
150                                      <option value="Canada"
151                                            <% if (!nullAddress &&"Canada".equals(address.getCountry())) { %>
152                                            selected="selected" <% } %>>
153                                            Canada
154                                      </option>
155                                      <option value="Mexico"
156                                            <% if (!nullAddress &&"Mexico".equals(address.getCountry())) { %>
157                                            selected="selected" <% } %>>
158                                            Mexico
159                                      </option>
160                                      <option value="Other"
161                                            <% if (!nullAddress &&"Other".equals(address.getCountry())) { %>
162                                            selected="selected" <% } %>>
163                                            Other
164                                      </option>
165                                 </select>
166                            </td>
167                      </tr>
168                      <tr>
169                            <td colspan="2">
170                                 <table>
171                                      <tr>
172                                            <td valign="middle">
173                                                 <input type="checkbox" name="user.address.poBox" value="true"
174                                                      <% if (!nullAddress && address.isPoBox()) { %>
175                                                      checked="checked" <% } %> />
176                                            </td>
177                                            <td valign="middle" style="width:100%">
178                                                 <label class="checkboxLabel">
179                                                      P.O. Box
180                                                 </label>
181                                            </td>
182                                      </tr>
183                                 </table>
184                            </td>
185                      </tr>
186                      <tr>
187                            <td colspan="2">
188                                 <div align="'right'">
189                                      <input value="Update Profile" type="submit" />
190                                 </div>
191                            </td>
192                      </tr>
193                 </table>
194            </form>
195      </body>
196 </html>

【代碼剖析】在上述代碼中,如果改為由Struts2的標簽實現,那么該代碼里190多行的代碼只剩下30行就可以完成,Strus2的標簽威力可見一斑。

通過使用Struts2標簽不僅輸入與Java值對象的關系是自動完成的,而且控件的布局(在xhtml主題中對form及其中的控件都使用table做了自動布局等渲染工作,在sample主題中不包含自動布局功能。請參考6.5.3節中的介紹)、錯誤信息的處理都是由標簽完成,用戶無須再干預,具體內容如實例6-15所示。

【實例6-15】標簽實例:updateProfile1.jsp

01     <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
02     <%@ page import="java.util.Map,java.util.Collections"%>
03     <%@ taglib prefix="s" uri="/struts-tags"%>
04     <html>
05          <head>
06                <title>UpdateProfile</title>
07                <s:head />
08          </head>
09          <body>
10               <!--使用標簽實現JSP-->
11                <s:form action="updateProfile" method="post">
12                     <s:textfield label="First name" name="user.firstname"
13                          cssStyle="float:left; color:red" />
14                     <s:textfield label="Last name" name="user.lastname" />
15                     <s:textfield label="Email" name="user.email" />
16                     <s:radio label="Gender" name="user.gender"
17                          list="#{0 : 'Male', 1 : 'Female'}" />
18                     <s:textfield label="Street" name="user.address.street" />
19                     <s:textfield label="Zip Code" name="user.address.zipcode" />
20                     <s:textfield label="City" name="user.address.city" />
21                     <s:select label="State" name="user.address.state"
22                          list="{'Californa', 'Oregon'}" />
23                     <s:select label="Country" name="user.address.country"
24                          list="{'USA', 'Canada', 'Mexico', 'Other'}" />
25                     <s:checkbox label="P.O. Box" name="user.address.poBox"
26                          fieldValue="true" />
27                     <s:submit value="Update Profile" />
28                </s:form>
29                <s:set name="user" value="user" scope="request" />
30                <s:set name="fieldErrors" value="fieldErrors" scope="request" />
31          </body>
32     </html>

【代碼剖析】由于Struts2會自動增加控件的樣式所有,如果想自己定義空間的樣式不能再使用class屬性,要使用Struts2單獨提供的cssClass、cssStyle屬性。這兩個屬性在通用屬性中已經有過介紹,是所有控件都具有的屬性。

圖6.12 OGNL對象范圍

主站蜘蛛池模板: 称多县| 延津县| 南阳市| 青海省| 安西县| 普定县| 浑源县| 镇宁| 远安县| 和田县| 新巴尔虎右旗| 霍林郭勒市| 太保市| 汕尾市| 丽江市| 聂荣县| 汉寿县| 亚东县| 米脂县| 天津市| 长寿区| 广州市| 齐齐哈尔市| 瑞昌市| 射阳县| 库尔勒市| 文昌市| 白银市| 三原县| 双城市| 安徽省| 沙湾县| 肇源县| 雅安市| 成都市| 扎兰屯市| 错那县| 桂阳县| 全椒县| 迁安市| 永宁县|