一、表單標簽庫 1.1、簡介 從Spring2.0起就提供了一組全面的自動數據綁定標簽來處理表單元素。生成的標簽相容HTML 4.01與XHTML 1.0。表單標簽庫中包含了可以用在JSP頁面中渲染HTML元素的標簽。表單標記庫包含在spring-webmvc.jar中,庫的描述符稱為spring- ...
一、表單標簽庫
1.1、簡介
從Spring2.0起就提供了一組全面的自動數據綁定標簽來處理表單元素。生成的標簽相容HTML 4.01與XHTML 1.0。表單標簽庫中包含了可以用在JSP頁面中渲染HTML元素的標簽。表單標記庫包含在spring-webmvc.jar中,庫的描述符稱為spring-form.tld,為了使用這些標簽必須在jsp頁面開頭處聲明這個tablib指令。
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
以下表格展示了標簽庫中的常用標簽:
標簽 |
描述 |
form |
渲染表單元素form |
input |
渲染<input type=”text”/>元素 |
password |
渲染<input type=”password”/>元素 |
hidden |
渲染<input type=”hidden”/>元素 |
textarea |
渲染textarea元素 |
checkbox |
渲染一個<input type=”checkbox”/>覆選元素 |
checkboxs |
渲染多個<input type=”checkbox”/>元素 |
radiobutton |
渲染一個<input type=”radio”/>單選元素 |
radiobuttons |
渲染多個<input type=”radio”/>元素 |
select |
渲染一個選擇元素 |
option |
渲染一個可選元素 |
options |
渲染多個可選元素列表 |
errors |
在span元素中渲染欄位錯誤 |
1.2、常用屬性
path:要綁定的屬性路徑,最重要的屬性,多個元素必填,相當於 modelAttribute.getXXX() 。
cssClass:定義要應用到被渲染元素的CSS類,類樣式。
cssStyle:定義要應用到被渲染元素的CSS樣式,行內樣式。
htmlEscape:接受true或者false,表示是否應該對被渲染的值進行HTML轉義。
cssErrorClass:定義要應用到被渲染input元素的CSS類,如果bound屬性中包含錯誤,則覆蓋cssClass屬性值。
1.3、form標簽與input標簽
這個標簽會生成HTML form標簽,同時為form內部所包含的標簽提供一個綁定路徑(binding path)。 它把命令對象(command object)存在PageContext中,這樣form內部的標簽就可以使用這個對象了。標簽庫中的其他標簽都聲明在form標簽的內部。
讓我們假設有一個叫User的領域對象,它是一個JavaBean,有著諸如 firstName和lastName這樣的屬性。我們將把它當作 一個表單支持對象(form backing object),它對應的表單控制器用 form.jsp頁面來顯示表單。
commandName:暴露表單對象的模型屬性名稱,預設為command,它定義了模型屬性的名稱,其中包含了一個backing object,其屬性將用於填充生成的表單。如果該屬性存在,則必須在返回包含該表單的視圖的請求處理方法中添加相應的模型屬性。
modelAttribute:暴露form backing object的模型屬性名稱,預設為command
commandName與modelAttribute功能基本一樣,使用modelAttribute就可以了,因為commandName已被拋棄。
如果在頁面中使用form不設置任意屬性<form:form/>,解析後的結果如下:
<form id="command" action="/SpringMVC04/bar/action11" method="post"></form>
新建一個控制器,在控制器中添加一個action,代碼如下:
package com.zhangguo.springmvc04.controllers; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.zhangguo.springmvc04.entities.Product; @Controller @RequestMapping("/bar") public class BarController { @RequestMapping("/action11") public String action11(Model model){ //向模型中添加一個名為product的對象,用於渲染視圖 model.addAttribute("product", new Product("Meizu note1", 999)); return "bar/action11"; } }
在views/bar目錄下添加action11.jsp頁面,頁面內容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bar/action11</title> </head> <body> <form:form modelAttribute="product"> <p> <label for="name">名稱:</label> <form:input path="name" /> </p> <p> <label for="price">價格:</label> <form:input path="price" /> </p> </form:form> </body> </html>
form表單與模型中名稱為product的對象進行綁定,form中的表單元素的path指的就是訪問該對象的路徑,如果沒有該對象或找不到屬性名將異常。系統將自動把指定模型中的值與頁面進行綁定,渲染後的結果如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bar/action11</title> </head> <body> <form id="product" action="/SpringMVC04/bar/action11" method="post"> <p> <label for="name">名稱:</label> <input id="name" name="name" type="text" value="Meizu note1"/> </p> <p> <label for="price">價格:</label> <input id="price" name="price" type="text" value="999.0"/> </p> </form> </body> </html>
運行結果:
模型可以為空,不是為null,中間可以沒有數據,但非字元類型會取預設值,如價格會變成0.0。model.addAttribute("product", new Product()),結果如下:
input元素可以設置其它的屬性,如前面提到的通用屬性,修改後的表單如下:
<p> <label for="name">名稱:</label> <form:input path="name" cssClass="textCss" cssStyle="color:blue" a="b" htmlEscape="false"/> </p>
修改action11方法的內容如下:
//向模型中添加一個名為product的對象,用於渲染視圖 model.addAttribute("product", new Product("Meizu note1<hr/>", 999));
渲染結果:
<p> <label for="name">名稱:</label> <input id="name" name="name" class="textCss" style="color:blue" a="b" type="text" value="Meizu note1<hr/>"/> </p>
預設從伺服器發送到客戶端的數據中是會編碼的,如示例中<hr/>,會解析成<hr>,但我們設置屬性htmlEscape="false"結果原樣輸出;我們在標簽中設置a="b"原樣解析出來,這裡給開發者留了很大的空間,如想使用原input標簽的屬性都可以直接寫。
1.4、checkbox標簽
form:checkbox元素將渲染成一個覆選框,通過該元素可以獲得3種不同類型的值,分別是boolean,數組,基本數據類型,添加一個新的實體類Person,如下所示:
package com.zhangguo.springmvc04.entities; public class Person { /* * 婚否 */ private boolean isMarried; /* * 愛好 */ private String[] hobbies; /** * 學歷 */ private String education; public boolean getIsMarried() { return isMarried; } public void setIsMarried(boolean isMarried) { this.isMarried = isMarried; } public String[] getHobbies() { return hobbies; } public void setHobbies(String[] hobbies) { this.hobbies = hobbies; } public String getEducation() { return education; } public void setEducation(String education) { this.education = education; } }
特別註意的是boolean類型的值生成的get/set屬性名稱前是不帶get與set的,這樣會引起異常,建議手動修改。
在控制器中新增2個action,代碼如下:
//checkbox @RequestMapping("/action21") public String action21(Model model){ model.addAttribute("person", new Person()); return "bar/action21"; } @RequestMapping("/action22") @ResponseBody public Person action22(HttpServletResponse response,Person person){ return person; }
在views/bar目錄下添加action21視圖,視圖腳本如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bar/action21</title> </head> <body> <form:form modelAttribute="person" action="action22"> <p> <label for="name">婚否:</label> <form:checkbox path="isMarried" /> </p> <p> <label for="name">愛好:</label> <form:checkbox path="hobbies" value="讀書"/>讀書 <form:checkbox path="hobbies" value="上網"/>上網 <form:checkbox path="hobbies" value="電影"/>電影 </p> <p> <label for="name">畢業:</label> <form:checkbox path="education" value="本科"/>大學本科 </p> <p> <button>提交</button> </p> </form:form> </body> </html>
渲染後的視圖如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bar/action21</title> </head> <body> <form id="person" action="action22" method="post"> <p> <label for="name">婚否:</label> <input id="isMarried1" name="isMarried" type="checkbox" value="true"/><input type="hidden" name="_isMarried" value="on"/> </p> <p> <label for="name">愛好:</label> <input id="hobbies1" name="hobbies" type="checkbox" value="讀書"/><input type="hidden" name="_hobbies" value="on"/>讀書 <input id="hobbies2" name="hobbies" type="checkbox" value="上網"/><input type="hidden" name="_hobbies" value="on"/>上網 <input id="hobbies3" name="hobbies" type="checkbox" value="電影"/><input type="hidden" name="_hobbies" value="on"/>電影 </p> <p> <label for="name">畢業:</label> <input id="education1" name="education" type="checkbox" value="本科"/><input type="hidden" name="_education" value="on"/>大學本科 </p> <p> <button>提交</button> </p> </form> </body> </html>
運行結果:
form:checkbox在渲染成input標簽里會變成2個表單元素,這樣可以確保用戶沒有選擇內容時也會將值帶會伺服器,預設是沒有這樣的。
小結:checkbox有三種使用方法
第一種用法:若綁定值是java.lang.Boolean類型,則值為true時,input(checkbox)標為checked(選中)。其value(值)屬性對應於setValue(Object)值屬性的解析值。
第二種用法:若綁定值是Array(數組)類型或java.util.Collection,則配置的setValue(Object)值出現在綁定的Collection中時,input(checkbox)標為checked(選中)。
第三種用法:若綁定值為其他類型,則當配置的setValue(Object)等於其綁定值時,input(checkbox)標為checked(選中)。
1.5、radiobutton標簽
這個標簽生成類型為radio的HTML input 標簽,也就是常見的單選框。這個標簽的典型用法是一次聲明多個標簽實例,所有的標簽都有相同的path屬性,但是他們的value屬性不同。
定義2個action,代碼如下:
@RequestMapping("/action31") public String action31(Model model){ model.addAttribute("person", new Person()); return "bar/action31"; } @RequestMapping("/action32") @ResponseBody public Person action32(HttpServletResponse response,Person person){ return person; }
在views/bar下定義視圖action31.jsp,腳本如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bar/action31</title> </head> <body> <form:form modelAttribute="person" action="action32"> <p> <label for="name">學歷:</label> <form:radiobutton path="education" value="專科"/>專科 <form:radiobutton path="education" value="本科"/>本科 <form:radiobutton path="education" value="研究生"/>研究生 </p> <p> <button>提交</button> </p> </form:form> </body> </html>
運行後頁面渲染結果:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>bar/action31</title> </head> <body> <form id="person" action="action32" method="post"> <p> <label for="name">學歷:</label> <input id="education1" name="education" type="radio" value="專科"/>專科 <input id="education2" name="education" type="radio" value="本科"/>本科 <input id="education3" name="education" type="radio" value="研究生"/>研究生 </p> <p> <button>提交</button> </p> </form> </body> </html>
運行結果:
1.6、password標簽
這個標簽生成類型為password的HTML input標簽,渲染後生成一個密碼框。input標簽的值和表單支持對象相應屬性的值保持一致。該標簽與input類似,但有一個特殊的屬性showPassword, 是否將對象中的值綁定到密碼框中,預設為false,也意味著密碼框中不會出現預設的掩碼。
修改action31,修改後如下所示:
@RequestMapping("/action31") public String action31(Model model){ Person person=new Person(); person.setEducation("edu"); model.addAttribute("person", person); return "bar/action31"; }
當頁面腳本如下時:
<p> <label>密碼:</label> <form:password path="education" showPassword="true"/> </p>
渲染結果:
<p> <label>密碼:</label> <input id="education" name="education" type="password" value="edu"/> </p>
當頁面腳本如下時:
<p> <label>密碼:</label> <form:password path="education" showPassword="false"/> </p>
渲染結果:
<p> <label>密碼:</label> <input id="education" name="education" type="password" value=""/> </p>
1.7、select標簽
這個標簽生成HTML select標簽,就是下拉框,多選框。在生成的HTML代碼中,被選中的選項和表單支持對象相應屬性的值保持一致。這個標簽也支持嵌套的option和options標簽。
定義兩個action,代碼如下:
//select 下拉列表 @RequestMapping("/action41") public String action41(Model model){ List<ProductType> productTypes = new ArrayList<ProductType>(); productTypes.add(new ProductType(11