1. 概述
Spring MVC中最重要的註解之一是 @Spring MVC 註解。
@ModelAttribute 是一個將方法參數或方法返回值綁定到名為模型屬性的註解,並將其暴露給 Web 視圖的註解。
在本教程中,我們將通過一個常見的概念——來自公司員工提交的表單——來演示該註解的可用性和功能。
2. @ModelAttribute 深入解析
正如引言中所述,我們可以使用 @ModelAttribute 既作為方法參數,也可以在方法級別使用。
2.1. 在方法級別
當我們在方法級別使用註解時,它表明該方法旨在添加一個或多個模型屬性。 這樣的方法支持與 @RequestMapping 方法相同的參數類型,但不能直接映射到請求。
以下是一個快速示例,説明其工作原理:
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
在上例中,我們看到一個方法,它會將名為 msg 屬性添加到控制類中定義的每個 model。
當然,我們稍後會在文章中看到它的實際應用。
一般來説,Spring MVC 始終會在調用任何請求處理方法之前,首先調用該方法。基本上,@ModelAttribute 方法在調用帶有 @RequestMapping 標註的控制器方法之前被調用。這是因為模型對象必須在控制器方法內部的任何處理開始之前創建。
此外,我們也需要將相應類標註為 @ControllerAdvice。 這樣,我們就可以在 Model 中添加值,這些值將被識別為全局值。 這實際上意味着對於每個響應方法,都會存在默認值。
2.2. 作為方法參數使用
當我們將標註作為方法參數使用時,表示從模型中檢索該參數。如果標註不存在,則首先需要實例化它,然後再將其添加到模型中。一旦在模型中存在,則應從所有具有匹配名稱的請求參數中填充參數字段。
在下面的代碼片段中,我們將填充 employee 模型屬性,該屬性的數據來自向 addEmployee 端點提交的表單。Spring MVC 在調用 submit 方法之前,在幕後執行此操作:
@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@ModelAttribute("employee") Employee employee) {
// Code that uses the employee object
return "employeeView";
}稍後,本文檔中我們會看到如何使用 employee 對象填充 employeeView 模板的完整示例。
它將表單數據與 Bean 綁定。 帶有 @RequestMapping 註解的控制器可以具有自定義類參數(或)帶有 @ModelAttribute 註解的類參數。
在 Spring MVC 中,我們稱之為數據綁定,這是一種常見的機制,可以避免我們必須單獨解析每個表單字段。
3. 表單示例
本節將介紹概述部分中提到的示例,一個非常基礎的表單,它會提示用户(具體是公司員工)輸入一些個人信息(具體是姓名和ID)。提交完成後,在沒有任何錯誤的情況下,用户期望看到之前提交的數據顯示在另一個屏幕上。
3.1. 視圖
讓我們首先創建一個包含 id 和 name 字段的簡單表單:
<form:form method="POST" action="/spring-mvc-basics/addEmployee"
modelAttribute="employee">
<form:label path="name">Name</form:label>
<form:input path="name" />
<form:label path="id">Id</form:label>
<form:input path="id" />
<input type="submit" value="Submit" />
</form:form>
3.2. 控制器
以下是控制器類,其中我們將實現上述視圖的邏輯:
@Controller
@ControllerAdvice
public class EmployeeController {
private Map<Long, Employee> employeeMap = new HashMap<>();
@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(
@ModelAttribute("employee") Employee employee,
BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
model.addAttribute("name", employee.getName());
model.addAttribute("id", employee.getId());
employeeMap.put(employee.getId(), employee);
return "employeeView";
}
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
}在 submit() 方法中,我們有一個 Employee 對象綁定到我們的 View 上。 我們可以像這樣將表單字段映射到對象模型。 在該方法中,我們從表單中獲取值並將它們設置為 ModelMap。
最終,我們返回 employeeView,這意味着我們以 View 的代表身份調用相應的 JSP 文件。
此外,還有一個 addAttributes() 方法。 它的目的是在 Model 中添加全局識別的值。 也就是説,每個請求到每個控制器方法都會返回一個默認值作為響應。 我們還需要對特定的類進行標註為 @ControllerAdvice。
3.3. 模型
正如之前提到的,Model 對象非常簡單,包含了“前端”屬性所需要的所有信息。下面我們來看一個例子:
@XmlRootElement
public class Employee {
private long id;
private String name;
public Employee(long id, String name) {
this.id = id;
this.name = name;
}
// standard getters and setters removed
}3.4. 總結
<@ControllerAdvice> 輔助控制器,特別是應用於所有 <@RequestMapping> 方法的 <@ModelAttribute> 方法。當然,我們的 <addAttributes()> 方法將首先運行,在其他 <@RequestMapping> 方法之前。
考慮到這一點,並在 <submit()> 和 <addAttributes()> 運行之後,我們可以通過在美元符號和花括號內的美元符號化雙元組中提及它們的名稱(例如,${name})來在從 <Controller> 類返回的 <View> 中引用它們。
3.5. 結果視圖
現在讓我們打印從表單中接收到的內容:
<h3>${msg}</h3>
Name : ${name}
ID : ${id}
4. 結論
本文研究了在方法參數和方法級別使用場景中,使用 @ModelAttribute 註解的用法。