天天看點

Spring MVC資料綁定form标簽fn标簽(這裡主要是擷取集合或者數組的長度)c标簽(相當于for循環)伺服器表單校驗

文章目錄

  • form标簽
    • 為什麼使用form标簽?
    • form标簽主要應用場景?
    • from标簽的使用
      • 元素屬性
      • 使用
        • 輸入框 input
        • 單選按鈕 radiobutton
        • 複選框 checkbox、checkboxes
        • 選擇框 select
        • 選項清單 options
        • 多行輸入 testarea
        • errors
  • fn标簽(這裡主要是擷取集合或者數組的長度)
    • 為什麼使用fn标簽
    • 使用
  • c标簽(相當于for循環)
    • 為什麼要使用c标簽
    • c标簽的使用
  • 伺服器表單校驗
    • JSR 303
      • 内置限制
    • Hibernate Validator(驗證器)
      • 内置限制
    • 使用

form标簽

為什麼使用form标簽?

  1. 他會把ModelMap傳過來的值,自動綁定到目前form對應的實體對象
  2. 它直接支援DELETE、PUT(UPDATE)送出

form标簽主要應用場景?

form标簽主要應用于編輯更新,一進來就要展示,在展示上面進行修改或者删除

注意:使用form之前一定要保證有對應的bean,沒有對應的bean時, 會自動以command為key到request域中查詢,當找不到的時候, 會報異常

from标簽的使用

元素屬性

  1. acceptCharset:定義伺服器接收的字元編碼清單
  2. commandName:暴露表單對象的模型屬性名稱,預設為command
  3. cssClass:定義應用到form元素的CSS類
  4. cssStyle:定義應用到form元素的CSS樣式
  5. htmlEscape:true或false,表示是否進行HTML轉義
  6. modelAttribute:和commandName功能基本一緻

使用

使用時需要添加

<%@ taglib prefix="from" uri="http://www.springframework.org/tags/form" %>

  1. from全局使用modelAttribute和bean綁定
  2. 元件使用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

  1. 複選框裡面有兩個東西,先說checkboxes,使用必須指定兩個屬性。path不用說,接收數組或者list對象。然後我們必須配置一個items,這個items裡面存放的是一個按鈕組,管理的是一堆複選框按鈕,每一個複選框按鈕的label和value都相同。那麼這個複選框按鈕的值從哪裡來呢?值是在發送請求到這個接收頁面的時候,控制器方法裡面把值提前寫好了通過選項數組或者集合發送過來。展示的時候它會自動做一個周遊,把我們背景輸入的選項組裡面的内容展示過來。當發現value值和你綁定的path值一緻的時候,這個複選框按鈕就會被選中。在使用的時候注意,items裡面用${}取值
  2. 會用了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标簽的使用

  1. items裡面寫list或者數組的名稱
  2. begin就相當于for循環裡面的開始位置
  3. 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>
           
  1. 不能這麼用,因為modelAttribute是跟bean綁定,如果沒有這個bean就找不到。
  2. 也不能從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>
           
  1. 不能用存放周遊元素的order來擷取屬性,因為path也是綁定的bean找查找屬性,沒有這個order
  2. 也不能從屬性中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

  1. JSR 303是Java為Bean資料合法性校驗提供的标準架構,它已經包含在JavaEE 6.0中。
  2. JSR 303 通過在 Bean 屬性上标注類似于 @NotNull、@Max 等标準的注解
  3. 指定校驗規則,并通過标準的驗證接口對 Bean 進行驗證

内置限制

  1. @Null 被注釋的元素必須為 null
  2. @NotNull 被注釋的元素必須不為 null
  3. @AssertTrue 被注釋的元素必須為 true
  4. @AssertFalse 被注釋的元素必須為 false
  5. @Min(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
  6. @Max(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
  7. @DecimalMin(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
  8. @DecimalMax(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
  9. @Size(max=, min=) 被注釋的元素的大小必須在指定的範圍内
  10. @Digits (integer, fraction) 被注釋的元素必須是一個數字,其值必須在可接受的範圍内
  11. @Past 被注釋的元素必須是一個過去的日期
  12. @Future 被注釋的元素必須是一個将來的日期
  13. @Pattern(regex=,flag=) 被注釋的元素必須符合指定的正規表達式

Hibernate Validator(驗證器)

是JSR 303的一個參考實作,除支援所有标準的校驗注解外,它還支援擴充注解

内置限制

  1. @NotBlank(message =) 驗證字元串非null,且長度必須大于0
  2. @Email 被注釋的元素必須是電子郵箱位址
  3. @Length(min=,max=) 被注釋的字元串的大小必須在指定的範圍内
  4. @NotEmpty 被注釋的字元串的必須非空
  5. @Range(min=,max=,message=) 被注釋的元素必須在合适的範圍内

使用

  1. 在項目中使用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());
           }
       }
           

繼續閱讀