Spring MVC中的@ModelAttribute是什么?


372

@ModelAttributeSpring MVC 的目的和用途是什么?



40
我认为这是一个有用的问题,因为它可以使读者获得比Spring官方文档所提供的更多的信息(包括示例)。
anton1980

Answers:


399

@ModelAttribute指的是Model对象的属性(MVC中的M;),所以我们假设有一个带有表单支持对象的表单,该表单称为“ Person”。然后,您可以让Spring MVC通过使用@ModelAttribute批注将此对象提供给Controller方法:

public String processForm(@ModelAttribute("person") Person person){
    person.getStuff();
}

另一方面,注释用于定义应作为模型一部分的对象。因此,如果要在模型中引用Person对象,可以使用以下方法:

@ModelAttribute("person")
public Person getPerson(){
    return new Person();
}

这个带注释的方法将允许您访问View中的Person对象,因为它是由Spring自动添加到模型中的。

请参见“使用@ModelAttribute”


8
@fasseg @ModelAttribute第一种情况下实际上不需要。
尼尔·麦圭根

@Neil何时需要@ModelAttribute在方法属性中使用?
Ryan


1
您应该包括如何填充Person以及如何调用此方法。
菲利普·雷戈

134

我知道这是一条旧的线,但是我想我把帽子戴在戒指上,看看我是否还能再弄点水了:)

我发现我最初难以理解的@ModelAttribute是Spring决定将多个注释合并为一个注释的结果。一旦将其拆分为几个较小的注释,它将变得更加清晰:

对于参数注释,可以将其@ModelAttribute视为等效项,@Autowired + @Qualifier即它尝试从Spring托管模型中检索具有给定名称的bean。如果未找到命名的bean null,则它不会隐式地承担以下角色,@Bean即使用默认构造函数创建新实例并将该bean添加到模型中,而不是引发错误或return 。

对于方法注释,可以将其@ModelAttribute视为与的等效项@Bean + @Before,即它将由用户代码构造的bean放入模型中,并且始终在请求处理方法之前调用它。

形象地,我看到@ModelAttribute以下内容(请不要按字面意思!):

@Bean("person")
@Before
public Person createPerson(){
  return new Person();
}

@RequestMapping(...)
public xxx handlePersonRequest( (@Autowired @Qualifier("person") | @Bean("person")) Person person, xxx){
  ...
}

如您所见,Spring做出了正确的决定以做出@ModelAttribute一个无所不包的注释。没有人愿意看到一个注释。


2
嗯,@ Bean默认为单例。我不确定在这里是否适用相同的概念。
僵尸

10
绝对不。我只是使用更简单的注释来解释这个复杂的注释。请从概念上而不是从字面上理解我的解释。
Christopher Yang

4
@Zombies @Scope("request")然后添加:)
OrangeDog

28

对于我的样式,我总是使用@ModelAttribute从spring表单jsp中捕获对象。例如,我在jsp页面上设计表单,该表单存在commandName

<form:form commandName="Book" action="" methon="post">
      <form:input type="text" path="title"></form:input>
</form:form>

我用以下代码在控制器上捕获对象

public String controllerPost(@ModelAttribute("Book") Book book)

并且书的每个字段名称都必须与表单子元素中的路径匹配


4
catch动词准确地描述了@ModelAttribute已完成的工作。真好
涡流

3
年度最佳答案。
木星Cls

4
但是有必要吗?在不使用@ModelAttribute批注的情况下仍然可以正常工作。

23

因此,我将尝试以更简单的方式进行解释。让我们:

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }
}

如Spring MVC文档中所述,@ ModelAttribute批注可以在方法方法参数上使用。当然,我们可以在一个控制器中同时使用两者。

1.方法注释

@ModelAttribute(“cities”)
 public List<String> checkOptions(){
 return new Arrays.asList(new[]{“Sofia”,”Pleven","Ruse”});//and so on
}

这种方法的目的是在模型中添加属性。因此,在我们的示例中,city键将列表new Arras.asList(new[]{“Sofia”,”Pleven","Ruse”})作为模型中的值(您可以将Model视为map(key:value))。 在同一控制器内,控制器中的@ModelAttribute方法在@RequestMapping方法之前被调用。

在这里,我们要向模型添加通用信息,这些通用信息将以表格的形式显示给用户。例如,它可以用于填充HTML选择:

在此处输入图片说明

2.方法参数

public String findPerson(@ModelAttriute(value="person") Person person) {
    //..Some logic with person
    return "person.jsp";
}

方法参数上的@ModelAttribute指示应从模型中检索参数。因此,在这种情况下,我们希望在Model person对象中将其作为键,并希望获取其值并将其放入方法参数Person person中。如果不存在或(有时您拼写错误(值=“ persson”)),则Spring将在模型中找不到它,并将使用其默认值创建空的Person对象。然后将使用请求参数,并尝试使用它们的名称将数据绑定到Person对象中。

name="Dmitrij"&countries=Lesoto&sponsor.organization="SilkRoad"&authorizedFunds=&authorizedHours=&

因此,我们有了名称,它将使用setName(String name)绑定到Person.name。所以在

//..Some logic with person

我们可以使用值“ Dimitrij”访问该填充名称。

当然,Spring可以绑定更复杂的对象,例如“列表”,“地图”,“地图集列表”等,但是在幕后它使数据绑定变得神奇。

  1. 我们可以同时在参数中带有@ModelAttribute的模型注释方法和请求方法处理程序。然后,我们必须统一规则。

  2. 当然,我们有很多不同的情况-@ModelAttribute方法也可以在@ControllerAdvice中定义,依此类推...


13

我知道我参加晚会很晚,但是我会像他们所说的那样引用:“迟到总比不到好”。因此,让我们开始吧,每个人都有他们自己的方式来解释事物,让我尝试用一​​个示例通过几个步骤对其进行总结和简化;假设您有一个简单的表单form.jsp

<form:form action="processForm" modelAttribute="student">
First Name : <form:input path="firstName" /> 
<br><br>
Last Name : <form:input path="lastName" />
<br><br>
<input type="submit" value="submit"/>
</form:form>

path =“ firstName” path =“ lastName”当调用表单时,这些是StudentClass中的字段/属性,但调用了它们的getter,但一旦提交,便调用了它们的setter,并在modelAttribute =表单标签中的“学生”。

我们的StudentController包含以下方法;

@RequestMapping("/showForm")
public String showForm(Model theModel){ //Model is used to pass data between 
//controllers and views
    theModel.addAttribute("student", new Student()); //attribute name, value
return "form";
}

@RequestMapping("/processForm")
public String processForm(@ModelAttribute("student") Student theStudent){
    System.out.println("theStudent :"+ theStudent.getLastName());
return "form-details";
}

//@ModelAttribute("student") Student theStudent
//Spring automatically populates the object data with form data all behind the 
//scenes 

现在终于有了一个form-details.jsp

<b>Student Information</b>
${student.firstName}
${student.lastName}

回到问题,Spring MVC中的@ModelAttribute是什么?从源为您的样品定义, http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation@ModelAttribute是一个注释结合的方法参数或方法返回值来命名模型属性然后将其公开到网络视图。

实际发生的情况是,它将获取表单提交的所有值,然后将其保存以供您绑定或分配给对象。它的工作方式与@RequestParameter相同,在这里我们只获取一个参数并将值分配给某个字段。唯一的区别是@ModelAttribute保存所有表单数据,而不是单个参数。它为您创建一个Bean,其中包含供开发人员稍后使用的表单提交的数据。

概括整个事情。步骤1:发送一个请求,我们的方法showForm运行,并建立一个模型,并设置一个临时bean(其名称为Student)被转发到表单。 theModel.addAttribute(“ student”,new Student());

步骤2: 表单提交模型上的modelAttribute =“ student”更改了学生,现在它拥有表单的所有参数

步骤3: @ModelAttribute(“ student”)Student theStudent 我们获取@ModelAttribute持有的值,并将整个bean /对象分配给Student。

第4步:然后我们在出价时使用它,就像在页面上显示它一样

我希望它可以帮助您理解概念。谢谢


9

以任何Web应用程序为例,无论是Gmail还是Facebook或Instagram,还是任何其他Web应用程序,都与最终用户与应用程序或UI与后端应用程序之间的数据或信息交换有关。即使在Spring MVC世界中,也有两种交换数据的方法:

  1. 从控制器到用户界面,以及
  2. 从UI到Controller。

我们感兴趣的是如何将数据从UI传递到Controller。这也可以通过两种方式完成:

  1. 使用HTML表单
  2. 使用查询参数。

使用HTML表单:考虑以下情况,

表格提交代表

当我们从Web浏览器提交表单数据时,我们可以在Controller类中作为对象访问该数据。当我们提交HTML表单时,Spring容器会做四件事。它会,

  1. 首先使用request.getParameter方法读取请求中提交的所有数据。
  2. 读取它们之后,它将使用integer.parseIntdouble.parseDouble以及基于数据的数据类型可用的所有其他解析方法将它们转换为适当的Java类型。
  3. 一旦解析,它将创建我们创建的模型类的对象。例如,在这种情况下,正在提交的是用户信息,我们创建了一个名为User的类,Container将为其创建一个对象,并将设置自动输入该对象的所有值。
  4. 然后它将通过将值设置为控制器来移交该对象。

为了使整个工作正常进行,我们必须遵循某些步骤。

内部工作

我们首先需要定义一个模型类,例如User,其中的字段数应与HTML表单中的字段数完全匹配。同样,我们在HTML表单中使用的名称应与我们在Java类中使用的名称匹配。这两个非常重要。名称应匹配,表单中的字段数应与我们创建的类中的字段数相匹配。完成后,容器将自动读取传入的数据,创建此模型的对象,设置值并将其交给控制器。要在Controller内部读取这些值,我们使用@ModelAttribute方法参数上的注释。当我们在Controller中创建方法时,我们将使用@ModelAttribute并向其添加一个参数,该参数将自动使Container提供该对象。

这是用于注册用户的示例代码:

@RequestMapping(value = "registerUser", method = RequestMethod.POST)
public String registerUser(@ModelAttribute("user") User user, ModelMap model) {
    model.addAttribute("user", user);
    return "regResult";
}

希望这个图解说明有所帮助!


4

这用于Spring中的数据绑定MVC。让您拥有一个包含表单元素的jsp,例如

JSP

<form:form action="test-example" method="POST" commandName="testModelAttribute"> </form:form>

(Spring Form方法,也可以使用Simple form元素)

在控制器端

@RequestMapping(value = "/test-example", method = RequestMethod.POST)
public ModelAndView testExample(@ModelAttribute("testModelAttribute") TestModel testModel, Map<String, Object> map,...) {

}

现在,当您提交表单时,表单字段值将可供您使用。


4

将方法参数或方法返回值绑定到已公开的Web视图的命名模型属性的注释。

public String add(@ModelAttribute("specified") Model model) {
    ...
}


1

@ModelAttribute(@ModelAttribute("Testing") Test test) as Testing 在给定示例中使用您指定的名称创建一个属性,Test是bean的测试,是bean的引用,并且Testing将在模型中可用,因此您可以在jsp页面上进一步使用它来检索存储的值在你里面ModelAttribute


1

@ModelAttribute只是将jsp字段中的值绑定到Pojo calss,以在控制器类中执行我们的逻辑。如果您熟悉struts,则就像在提交时填充formbean对象一样。


0

ModelAttribute批注用作Spring MVC Web应用程序的一部分,并且可以在两种情况下使用。

首先,它可以用于将数据注入到JSP之前的负载模型中。这对于确保需要JSP才能显示所有数据本身特别有用。通过将一种方法连接到模型来获得进样。

其次,它可用于从现有模型中读取数据并将其分配给教练方法的参数。

刷新https://dzone.com/articles/using-spring-mvc%E2%80%99s


0

在方法级别

1.在方法级别使用注释时,表明该方法的目的是添加一个或多个模型属性

@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("india", "india");
}

在方法自变量1.在用作方法自变量时,它指示应从模型中检索自变量。如果不存在,则应首先实例化,然后将其添加到模型中,并且一旦存在于模型中,则应从具有匹配名称的所有请求参数中填充arguments字段,以便将表单数据与Bean绑定。

 @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
  public String submit(@ModelAttribute("employee") Employee employee) {
  return "employeeView";
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.