文章目錄
- form标簽
-
- 為什麼使用form标簽?
- form标簽主要應用場景?
- from标簽的使用
-
- 元素屬性
- 使用
-
- 輸入框 input
- 單選按鈕 radiobutton
- 複選框 checkbox、checkboxes
- 選擇框 select
- 選項清單 options
- 多行輸入 testarea
- errors
- fn标簽(這裡主要是擷取集合或者數組的長度)
-
- 為什麼使用fn标簽
- 使用
- c标簽(相當于for循環)
-
- 為什麼要使用c标簽
- c标簽的使用
- 伺服器表單校驗
-
- JSR 303
-
- 内置限制
- Hibernate Validator(驗證器)
-
- 内置限制
- 使用
form标簽
為什麼使用form标簽?
- 他會把ModelMap傳過來的值,自動綁定到目前form對應的實體對象
- 它直接支援DELETE、PUT(UPDATE)送出
form标簽主要應用場景?
form标簽主要應用于編輯更新,一進來就要展示,在展示上面進行修改或者删除
注意:使用form之前一定要保證有對應的bean,沒有對應的bean時, 會自動以command為key到request域中查詢,當找不到的時候, 會報異常
from标簽的使用
元素屬性
- acceptCharset:定義伺服器接收的字元編碼清單
- commandName:暴露表單對象的模型屬性名稱,預設為command
- cssClass:定義應用到form元素的CSS類
- cssStyle:定義應用到form元素的CSS樣式
- htmlEscape:true或false,表示是否進行HTML轉義
- modelAttribute:和commandName功能基本一緻
使用
使用時需要添加 <%@ taglib prefix="from" uri="http://www.springframework.org/tags/form" %>
- from全局使用modelAttribute和bean綁定
- 元件使用path與屬性綁定,這樣就相當于bean.attribute
<form:form modelAttribute="customer">
<from:input path="cust_id"/><br>
<form:input path="cust_name"/><br>
<form:input path="cust_profession"/><br>
//單選按鈕使用
<form:radiobutton path="cust_priority" label="會員" value="1"/>
<form:radiobutton path="cust_priority" label="普通" value="0"/><br>
<form:checkboxes path="hobby" items="${hobbys}"/><br>//cheackboxes使用
//cheakbox使用
<form:checkbox path="hobby" value="籃球" label="籃球"/>
<form:checkbox path="hobby" value="遊泳" label="遊泳"/>
<form:checkbox path="hobby" value="乒乓球" label="乒乓球"/>
<form:checkbox path="hobby" value="羽毛球" label="羽毛球"/>
//選擇框使用
<form:select path="orders" items="${orderList}" itemValue="order_id" itemLabel="order_name" />
//fn标簽的使用
${fn:length(orders)}<br>
//c标簽的使用
<c:forEach var="order" items="${orders}" begin="0" end="${fn:length(customer.orders)}" >
${order.cust_id}
</c:forEach>
</form:form>
輸入框 input
輸入框就不必多說,隻需要設定好path就可以了
單選按鈕 radiobutton
如果多個選項在一個單選按鈕租裡面,path一緻,相當于這個path值就是單選按鈕租。在按鈕組裡面需要給定每個按鈕的值,我們的做法是用value來接收,這個value不是這個單選按鈕顯示的值,這個value裡面存儲的值是你發送請求時,傳去伺服器的值。label才是這個單選按鈕顯示到頁面我們看到的值。
複選框 checkbox、checkboxes
- 複選框裡面有兩個東西,先說checkboxes,使用必須指定兩個屬性。path不用說,接收數組或者list對象。然後我們必須配置一個items,這個items裡面存放的是一個按鈕組,管理的是一堆複選框按鈕,每一個複選框按鈕的label和value都相同。那麼這個複選框按鈕的值從哪裡來呢?值是在發送請求到這個接收頁面的時候,控制器方法裡面把值提前寫好了通過選項數組或者集合發送過來。展示的時候它會自動做一個周遊,把我們背景輸入的選項組裡面的内容展示過來。當發現value值和你綁定的path值一緻的時候,這個複選框按鈕就會被選中。在使用的時候注意,items裡面用${}取值
- 會用了checkboxes,在使用checkbox就非常簡單了,跟單選按鈕使用是一樣的,綁定好path,給label顯示值和value用來傳回的值就行了。可能在這一點概念了解有點問題,就是單選按鈕接收的隻是一個按鈕啊,一個屬性和value值對比一緻就把該元件設定為選中狀态,而我checkbox裡面path接收的可是一個數組,他是怎麼跟我的value值裡面比對的呢?因為是在數組中進行了一個周遊,找到一個值和我checkbox按鈕的value值一緻,然後把按鈕标記為選中狀态。
選擇框 select
這個就是做一個下拉清單,比如一個遊戲,你遊戲裡面提供幾種寵物,比如貓、狗等等(注意前提系統中已經提供好了,自己不得随意修改,也不能重複)。就這樣通過path來擷取bean中的寵物對象,items同複選框,輸出的是我背景已經定義好了下拉清單組。itemsvalue就是用來跟我bean中寵物判斷是否一緻,一緻就被選中。itemslabel就是在頁面上顯示的值。
選項清單 options
生成一個select标簽的選項清單,是以需要和select标簽一同使用
<form:select path=“xxx”>
<form:options items=“xxx”/>
</form:select>
多行輸入 testarea
與input用法完全一緻
errors
文法<from:errors path="*">: *表示顯示所有錯誤消息
fn标簽(這裡主要是擷取集合或者數組的長度)
為什麼使用fn标簽
如果我們的bean中有一個關聯對象,現在要擷取關聯對象的長度來做循環。因為在html界面是不能直接使用list.size()或者array.length來擷取長度的,但是我們又要使用這個長度,就必須要用到fn标簽。
使用
使用時需要添加:直接
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
${fn:length(orders)}
就可以使用了
但是我在使用過程中發現我擷取不到orders的長度,顯示為0,然後我看了背景傳入的參數,對象裡面orders屬性裡面是有内容的。當我們在調用對象裡面的屬性的時候(假設不是私有屬性),我們會這麼寫customer.orders(html頁面不分私有都這麼寫,因為它會自動調用get、set方法)。為什麼這裡我不這麼寫呢,因為我把fn看成了form的一個元件,當成path裡面的寫法了,fn是不能看成form元件的,它是單獨提供的一個函數包。是以擷取關聯對象的長度方式為:
${fn:length(customer.orders)}
c标簽(相當于for循環)
為什麼要使用c标簽
當你遊覽一個頁面的時候,擷取背景全部的資料需要循環輸出,就會用到for标簽
當你的一個對象裡面有關聯對象的時候,需要用到form标簽
c标簽的使用
- items裡面寫list或者數組的名稱
- begin就相當于for循環裡面的開始位置
- end就相當于截止位置,意思是當值等于end的時候截止。這裡需要注意一下,我們在使用循環的時候是這樣
for(int i=0;i<orders.length;i++){
}
如果從0開始begin=0,到截止元素${fn:length(orders)}(我這裡是三個訂單),也就是從0運作到3,結果顯示能夠成功的輸出三個訂單,也就是說在運作的時候隻運作到end-1就結束了。
c循環内部可以再對關聯對象做資料捆綁嗎?
//直接擷取關聯對象
<form:form modelAttribute="orders">
</form:form>
//從bean中擷取關聯對象
<form:form modelAttribute="customer.orders">
</form:form>
- 不能這麼用,因為modelAttribute是跟bean綁定,如果沒有這個bean就找不到。
-
也不能從bean中通過’.'的方式來擷取關聯對象,隻能綁定現有的bean
不額外添加一個form還能繼續使用form元件來展示orders裡面屬性嗎?
<c:forEach var="order" items="${customer.orders}" begin="0" end="${fn:length(customer.orders)}" >
方式一:
<form:input path="order.order_id"/>
方式二:
<form:input path="orders.order_id"/>
</c:forEach>
- 不能用存放周遊元素的order來擷取屬性,因為path也是綁定的bean找查找屬性,沒有這個order
-
也不能從屬性中orders.order_id,orders是一個集合嘛。
不是用資料捆綁,直接輸出就可以了
<c:forEach var="order" items="${customer.orders}" begin="0" end="${fn:length (customer.orders)}" >
訂單id :<input value="${order.order_id}"><br>
訂單編号:<input value="${order.order_num}"><br>
訂單名稱: <input value="${order.order_name}"><br>
</c:forEach>
*這是正确的做法,注意在value裡面取值要用連接配接符${}
伺服器表單校驗
前端校驗了為什麼還要伺服器端校驗?
因為隻使用前端校驗的話,如果把遊覽器把js禁用就完犢子啦。
mvc:annotation-driven/
JSR 303
- JSR 303是Java為Bean資料合法性校驗提供的标準架構,它已經包含在JavaEE 6.0中。
- JSR 303 通過在 Bean 屬性上标注類似于 @NotNull、@Max 等标準的注解
- 指定校驗規則,并通過标準的驗證接口對 Bean 進行驗證
内置限制
- @Null 被注釋的元素必須為 null
- @NotNull 被注釋的元素必須不為 null
- @AssertTrue 被注釋的元素必須為 true
- @AssertFalse 被注釋的元素必須為 false
- @Min(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
- @Max(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
- @DecimalMin(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
- @DecimalMax(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
- @Size(max=, min=) 被注釋的元素的大小必須在指定的範圍内
- @Digits (integer, fraction) 被注釋的元素必須是一個數字,其值必須在可接受的範圍内
- @Past 被注釋的元素必須是一個過去的日期
- @Future 被注釋的元素必須是一個将來的日期
- @Pattern(regex=,flag=) 被注釋的元素必須符合指定的正規表達式
Hibernate Validator(驗證器)
是JSR 303的一個參考實作,除支援所有标準的校驗注解外,它還支援擴充注解
内置限制
- @NotBlank(message =) 驗證字元串非null,且長度必須大于0
- @Email 被注釋的元素必須是電子郵箱位址
- @Length(min=,max=) 被注釋的字元串的大小必須在指定的範圍内
- @NotEmpty 被注釋的字元串的必須非空
- @Range(min=,max=,message=) 被注釋的元素必須在合适的範圍内
使用
- 在項目中使用JSR303 驗證表單,@Valid是開啟表單驗證的注解
//Customer類添加限制
@[email protected]
public class Customer {
@NotNull(message = "id不能為空")
private Integer cust_id;
@NotBlank(message = "姓名不能為空")
private String cust_name;
@NotBlank(message = "職業不能為空")
private String cust_profession;
@NotBlank(message = "電話不能為空")
private String cust_phone;
private Boolean cust_priority;
private List<Order> orders=new ArrayList<>();
}
//控制器裡添加@Valid
@RequestMapping(value = "/customer",method = RequestMethod.PUT)
public String updateCustomer(@Valid Customer customer,BindingResult bindingResult){
System.out.println("*********"+customer.toString());
customerMapper.updateByPrimaryKey(customer);
return "redirect:firstto/"+customer.getCust_id();
}
此處遇到的問題:我添加的驗證器回報400錯誤,但是隻要在參數裡面加入Errors errors就不會報錯了
特别說明:如果一個方法中有參數被 @Valid 标注了,但該參數後面沒有緊跟一個 BindingResult或者Errors 類型的參數,那麼送出到該方法時,将傳回 400 錯誤。
2. 擷取傳回的錯誤資訊。(沒有經過重定向,直接轉發到目标頁面)
//擷取傳回的錯誤資訊
if (bindingResult.getErrorCount()!=0){
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
modelAndView.addObject(fieldError.getField(),fieldError.getDefaultMessage());
}
}