@ModelAttribute

@ModelAttribute 方法引數註解將表單資料、查詢引數、URI 路徑變數和請求頭繫結到模型物件。例如

  • Java

  • Kotlin

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { } (1)
1 繫結到 Pet 例項。
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute pet: Pet): String { } (1)
1 繫結到 Pet 例項。

表單資料和查詢引數優先於 URI 變數和請求頭,URI 變數和請求頭僅在不覆蓋同名請求引數時才包含在內。請求頭名稱中的短橫線將被去除。

Pet 例項可能是

  • 從模型中獲取,它可能已被 Model 新增。

  • 如果模型屬性在類級別的 @SessionAttributes 中列出,則從 HTTP 會話中獲取。

  • 透過預設建構函式例項化。

  • 透過具有與 Servlet 請求引數匹配的引數的“主建構函式”例項化。引數名稱透過位元組碼中執行時保留的引數名稱確定。

預設情況下,建構函式和屬性 資料繫結 都適用。然而,模型物件設計需要仔細考慮,出於安全原因,建議使用專門用於 Web 繫結的物件,或僅應用建構函式繫結。如果仍必須使用屬性繫結,則應設定 allowedFields 模式以限制可以設定的屬性。有關此內容和示例配置的更多詳細資訊,請參閱 模型設計

使用建構函式繫結時,您可以透過 @BindParam 註解自定義請求引數名稱。例如

  • Java

  • Kotlin

class Account {

	private final String firstName;

	public Account(@BindParam("first-name") String firstName) {
		this.firstName = firstName;
	}
}
class Account(@BindParam("first-name") val firstName: String)
@BindParam 也可以放置在對應於建構函式引數的欄位上。雖然 @BindParam 開箱即用,您也可以透過在 DataBinder 上設定 DataBinder.NameResolver 來使用不同的註解。

建構函式繫結支援 ListMap 和陣列引數,這些引數可以從單個字串轉換而來,例如,逗號分隔列表,或者基於索引鍵,例如 accounts[2].nameaccount[KEY].name

WebFlux 與 Spring MVC 不同,它支援模型中的響應式型別,例如 Mono<Account>。您可以宣告帶有或不帶有響應式型別包裝器的 @ModelAttribute 引數,它將相應地解析為實際值。

如果資料繫結導致錯誤,預設情況下會丟擲 WebExchangeBindException,但您也可以在 @ModelAttribute 旁邊立即新增 BindingResult 引數,以便在控制器方法中處理此類錯誤。例如

  • Java

  • Kotlin

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

要使用 BindingResult 引數,您必須在它之前宣告 @ModelAttribute 引數,且不帶響應式型別包裝器。如果您想使用響應式型別,可以直接透過它處理錯誤。例如

  • Java

  • Kotlin

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public Mono<String> processSubmit(@Valid @ModelAttribute("pet") Mono<Pet> petMono) {
	return petMono
		.flatMap(pet -> {
			// ...
		})
		.onErrorResume(ex -> {
			// ...
		});
}
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") petMono: Mono<Pet>): Mono<String> {
	return petMono
			.flatMap { pet ->
				// ...
			}
			.onErrorResume{ ex ->
				// ...
			}
}

您可以透過新增 jakarta.validation.Valid 註解或 Spring 的 @Validated 註解(請參閱 Bean 驗證Spring 驗證)在資料繫結後自動應用驗證。例如

  • Java

  • Kotlin

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { (1)
	if (result.hasErrors()) {
		return "petForm";
	}
	// ...
}
1 在模型屬性引數上使用 @Valid
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
	if (result.hasErrors()) {
		return "petForm"
	}
	// ...
}
1 在模型屬性引數上使用 @Valid

如果由於其他引數具有 @Constraint 註解而應用了方法驗證,則會丟擲 HandlerMethodValidationException。請參閱控制器方法 驗證 部分。

使用 @ModelAttribute 是可選的。預設情況下,任何非簡單值型別(由 BeanUtils#isSimpleProperty 確定)未被任何其他引數解析器解析的引數都被視為隱式的 @ModelAttribute
當使用 GraalVM 編譯為原生映象時,上述隱式 @ModelAttribute 支援不允許對相關資料繫結反射提示進行適當的提前推斷。因此,建議在使用 GraalVM 原生映象時,顯式地使用 @ModelAttribute 註解方法引數。
© . This site is unofficial and not affiliated with VMware.