3.十、在方法參數上使用@ModelAttribute註解

  這一部分實例見這個項目的 mvc 分支下的 ModelAttrArgsController.javahtml


  上節說過,@ModelAttribute能夠用在方法或方法參數上。本節解釋它用在參數上的情形。java

  一個用在方法參數上的@ModelAttribute註解指示了參數應該從模型(這裏所說的「模型」指 Model)中獲取。若是模型中不存在,參數會首先被實例化,而後添加到模型中。一旦模型中存在,這個參數的字段會被全部的名字匹配的請求參數所填充。這在 Spring MVC 中叫作數據綁定,它可以把你從要對每個字段進行類型轉換的繁重體力勞動中解救出來,是很是有用的機制。git

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) 
{ 
    // ...
}

  上面給出的例子的 Pet 實例來自哪裏?這裏有一個可選項:web

  • 它可能已經存在與模型中了,由於使用了@SessionAttributes — 見「使用@SessionAttributes存儲模型屬性到 HTTP 會話中」一節.spring

  • 它可能已經存在於模型中了,由於同一個控制器中的@ModelAttribute方法,就像上一節中解釋的那樣。數據庫

  • 它多是從URI模板變量和類型轉換器中獲取的(下面會詳細解釋)。session

  • 它多是使用默認構造器初始化的。mvc

@ModelAttribute方法是一種經常使用的從數據庫中獲取屬性的方式,能夠經過使用@SessionAttributes註解把這種屬性在各個請求之間共享。在一些狀況下,能夠很方便的經過使用URI模板變量和類型轉換器來獲取這些屬性。下面是一個例子:app

@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) 
{
    // ...
}

  在這個例子中,模型屬性名(「account」)匹配URI模板變量名。若是你註冊的一個Converter<String, Account>能夠把字符串 account 值轉換爲一個 Account,那麼上面的例子即便不須要@ModelAttribute也能夠正常工做。.net

  下一步是數據綁定。WebDataBinder類匹配請求參數名稱——包括請求字符串參數和表單字段——到屬性字段名。在必須的類型轉換(從字符串到目標類型字段)以後,匹配的字段收集好了。數據綁定和校驗見官方文檔第五章-檢驗、數據綁定和類型轉換。爲控制器自定義數據綁定過程見 「自定義WebDataBinder初始化」一節。

  在數據綁定以後,可能會出現一些錯誤,好比缺乏必須字段或者類型轉換錯誤。爲了檢查這些錯誤,你能夠緊跟在@ModelAttribute參數後面添加一個BindingResult參數:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) 
{
    if (result.hasErrors()) { return "petForm"; }
    // ...
}

  有了BindingResult以後,你就能夠檢查在提交同一個表單時有沒有發現錯誤,這些錯誤能夠經過 Spring 的<errors>表單標籤來顯示。

  注意到在一些狀況下,在 model 中不使用數據綁定來訪問一個屬性是頗有用的。這種狀況下,你能夠把Model注入到控制器中,或者在註解上使用綁定標記:

@ModelAttribute
public AccountForm setUpForm() { return new AccountForm(); }

@ModelAttribute
public Account findAccount(@PathVariable String accountId) 
{ 
    return accountRepository.findOne(accountId); 
}

@PostMapping("update")
public String update(
        @Valid AccountUpdateForm form, BindingResult result,
        @ModelAttribute(binding=false) Account account) 
{ /* omitted */ }

  除了數據綁定,你也可使用你本身定義的、用來傳遞BindingResult(用於記錄數據綁定錯誤)的校驗器調用校驗這容許數據綁定和驗證的錯誤積累在一個地方,隨後報告給用戶:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) 
{
    new PetValidator().validate(pet, result);
    if (result.hasErrors()) return "petForm";

    // ...
}

  或者你能夠自動調用校驗,經過添加 JSR-303 的 @Valid 註解:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) 
{
    if (result.hasErrors()) return "petForm";

    // ...
}

  關於如何配置和使用校驗器,詳見官方文檔的5.8節「Spring校驗」和第五章 校驗、數據綁定和類型轉換

相關文章
相關標籤/搜索