Contents

Spring MVC @ModelAttribute注释

1.概述

最重要的Spring MVC 注解之一是@ModelAttribute 注释。 @ModelAttribute是一个注解,它将方法参数或方法返回值绑定到命名模型属性,然后将其公开给 Web 视图。 在本教程中,我们将通过一个通用概念(公司员工提交的表单)来演示此注释的可用性和功能。

2. 深入了解*@ModelAttribute*

正如介绍性段落所揭示的,我们可以将*@ModelAttribute*用作方法参数或在方法级别使用。

2.1. 在方法级别

当我们在方法级别使用注解时,它表明方法的目的是添加一个或多个模型属性。此类方法支持与@RequestMapping 方法相同的参数类型,但它们不能直接映射到请求。

让我们看一个简单的例子来了解它是如何工作的:

@ModelAttribute
public void addAttributes(Model model) {
    model.addAttribute("msg", "Welcome to the Netherlands!");
}

在上面的例子中,我们看到了一个方法,它为控制器类中定义的所有模型添加了一个名为msg的属性。

当然,我们将在本文后面看到这一点。

一般来说,Spring MVC 在调用任何请求处理程序方法之前总是会首先调用该方法。*基本上,@ModelAttribute方法在调用带有@RequestMapping*注释的控制器方法之前被调用。**这是因为必须在控制器方法内部开始任何处理之前创建模型对象。

将相应的类注释为@ControllerAdvice 也很重要。因此,我们可以在Model中添加将被标识为全局的值。这实际上意味着对于每个请求,响应中的每个方法都存在一个默认值。

2.2. 作为方法参数

当我们使用注解作为方法参数时,它表示从模型中检索参数。当注释不存在时,它应该首先被实例化,然后添加到模型中。一旦出现在模型中,参数字段应该从具有匹配名称的所有请求参数中填充。

在以下代码片段中,我们将使用提交到addEmployee端点的表单中的数据填充*employee *模型属性。Spring MVC 在调用提交方法之前在后台执行此操作:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@ModelAttribute("employee") Employee employee) {
    // Code that uses the employee object
    return "employeeView";
}

在本文后面,我们将看到一个完整的示例,说明如何使用员工对象来填充employeeView模板。

它将表单数据与 bean 绑定。使用@RequestMapping注释的控制器可以具有使用@ModelAttribute*注释的自定义类参数。*

在 Spring MVC 中,我们将其称为数据绑定,这是一种通用机制,可以让我们不必单独解析每个表单字段。

3. 表单示例

在本节中,我们将查看概述部分中概述的示例,这是一个非常基本的表单,提示用户(特别是公司员工)输入一些个人信息(特别是name 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()方法中,我们有一个绑定到ViewEmployee对象。我们可以像这样简单地将表单字段映射到对象模型。在该方法中,我们从表单中获取值并将它们设置为ModelMap

最后,我们返回employeeView,这意味着我们将各自的 JSP 文件称为View代表。

此外,还有一个addAttributes()方法。其目的是在模型中添加将被全局识别的值。也就是说,对每个控制器方法的每个请求都将返回一个默认值作为响应。我们还必须将特定类注释为*@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()都运行之后,我们可以在从Controller类返回的View中引用它们,方法是在$的花括号中提及它们的给定名称,例如*${name}*。

3.5. 结果视图

现在让我们打印我们从表单中收到的内容:

<h3>${msg}</h3>
Name : ${name}
ID : ${id}