Spring MVC中@ModelAttribute的目的和用法是什么?


当前回答

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

从控制器到UI,以及 从UI到控制器。

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

使用HTML表单 使用查询参数。

使用HTML表单: 考虑下面的场景,

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

first read all the data that is submitted that comes in the request using the request.getParameter method. once it reads them, it will convert them into the appropriate Java type using integer.parseInt, double.parseDouble and all the other parse methods that are available based on the data type of the data. once parsed, it will create a object of the model class that we created. For example, in this scenario, it is the user information that is being submitted and we create a class called User, which the Container will create an object of and it will set all the values that come in automatically into that object. it will then handover that object by setting the values to the Controller.

为了让整个计划顺利进行,我们必须遵循一定的步骤。

We first need to define a model class, like User, in which the number of fields should exactly match the number of fields in the HTML form. Also, the names that we use in the HTML form should match the names that we have in the Java class. These two are very important. Names should match, the number of fields in the form should match the number of fields in the class that we create. Once we do that, the Container will automatically read the data that comes in, creates an object of this model, sets the values and it hands it over to the Controller. To read those values inside the Controller, we use the @ModelAttribute annotation on the method parameters. When we create methods in the Controller, we are going to use the @ModelAttribute and add a parameter to it which will automatically have this object given by the Container.

下面是一个注册用户的示例代码:

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

希望这个图解解释对你有帮助!

其他回答

这用于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,...) {

}

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

所以我会试着用更简单的方式来解释。让我们有:

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
}

这种方法的目的是在模型中添加属性。因此,在我们的案例中,cities key将拥有列表new Arrays.asList(new[]{"Sofia","Pleven","Ruse"})作为模型中的值(您可以将模型看作map(key:value))。在同一个控制器中,在@RequestMapping方法之前调用控制器中的@ModelAttribute方法。

在这里,我们希望向Model添加将在表单中用于显示给用户的公共信息。例如,它可以用来填充HTML选择:

2.方法参数

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

An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. So in this case we expect that we have in the Model person object as key and we want to get its value and put it to the method argument Person person. If such does not exists or (sometimes you misspell the (value="persson")) then Spring will not find it in the Model and will create empty Person object using its defaults. Then will take the request parameters and try to data bind them in the Person object using their names.

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

我们有了name,它会使用setName(String name)绑定到person。name。因此,在

//..Some logic with person

我们可以访问这个值为“Dimitrij”的填充名称。

当然,Spring可以绑定更复杂的对象,比如List、map、List Of Sets Of Maps等等,但在幕后,它实现了数据绑定的魔力。

我们可以同时拥有带模型注释的方法和参数中带有@ModelAttribute的请求方法处理程序。那我们就得统一规则。 当然,我们有很多不同的情况——@ModelAttribute方法也可以在@ControllerAdvice中定义,等等……

我知道这是一个老帖子,但我想我把我的帽子扔在戒指里,看看我是否能把水弄浑一点:)

我发现我最初难以理解@ModelAttribute是因为Spring决定将几个注释合并为一个注释。当我把它分成几个更小的注释时,它变得更清晰了:

对于参数注释,可以将@ModelAttribute看作是@Autowired + @Qualifier的等量物,即它试图从Spring托管模型中检索具有给定名称的bean。如果没有找到命名bean,它不会抛出错误或返回null,而是隐式地扮演@Bean的角色,即使用默认构造函数创建一个新实例,并将bean添加到模型中。

对于方法注释,可以认为@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成为一个包罗万象的注释;没有人想看到注释的大杂烩。

对于我的风格,我总是使用@ModelAttribute从spring form 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)

book的每个字段名必须与form子元素中的path匹配

将方法参数或方法返回值绑定到已命名模型属性的注释,暴露在web视图中。

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