Spring MVC中的@ModelAttribute是什么?

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

431721 次浏览

@ModelAttribute引用Model对象的属性(MVC中的M;) 假设我们有一个表单,它有一个名为Person的表单支持对象 然后你可以让Spring MVC通过使用@ModelAttribute注释将这个对象提供给Controller方法:

public String processForm(@ModelAttribute("person") Person person){
person.getStuff();
}
另一方面,注释用于定义应该是Model的一部分的对象。 因此,如果你想在Model中引用Person对象,你可以使用以下方法:

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

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

看到“使用@ModelAttribute”

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

我发现我最初难以理解@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可以用作方法参数/参数,也可以用于方法声明之前。 该注释的主要目的是将请求参数或表单字段绑定到模型对象

Ref。http://www.javabeat.net/modelattribute-spring-mvc/

对于我的风格,我总是使用@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匹配

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

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

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

这用于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
}

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

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

enter image description here

2.方法参数

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

方法参数上的@ModelAttribute表示应该从模型检索该参数。因此,在本例中,我们期望Model中有对象作为键,我们希望获取它的值并将其放到方法参数人的人中。如果这样的对象不存在或(有时你拼写错了(value="persson")),那么Spring将不会在Model中找到它,并将使用其默认值创建空的Person对象。然后将获取请求参数,并尝试使用它们的名称在Person对象中对它们进行数据绑定。

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等等,但在幕后,它实现了数据绑定的魔力。

  1. 我们可以同时拥有带模型注释的方法和参数中带有@ModelAttribute的请求方法处理程序。那我们就得统一规则。

  2. 当然,我们有很多不同的情况——@ModelAttribute方法也可以在@ControllerAdvice中定义,等等……

我知道我迟到了,但我要引用他们说的话, “迟到总比不到好”。让我们开始吧, 每个人都有自己解释事情的方式,让我试着总结一下,用一个例子用几个步骤为你简单解释一下; 假设你有一个简单的形式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>

这些是Student类中的字段/属性。当表单被调用/初始化时,它们的getter被调用。在表单提交时,它们的setter被调用,它们的值在表单标记中用modelAttribute="student"指示的bean中传输。

我们有StudentController,它包括以下方法:

@RequestMapping("/showForm")
// `Model` is used to pass data between controllers and views
public String showForm(Model theModel) {
// attribute name, value
theModel.addAttribute("student", new Student());
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是一个注释,它将一个方法参数或方法返回值绑定到一个命名的模型属性,然后将它公开给web视图 实际发生的是,它获取表单中提交的所有值,然后保存它们供你绑定或赋值给对象。它的工作方式类似于@RequestParameter,在@RequestParameter中,我们只获得一个形参并将值赋给某个方法参数。 区别在于@ModelAttribute保存所有表单数据,而不是单个参数。它为您创建一个bean,其中包含表单中提交的数据

概括一下整件事:

< p >步骤1:
请求被发送,我们的方法showForm()运行,一个模型,一个临时bean,被设置为student并被转发到表单:
theModel.addAttribute("student", new Student()); < / p > < p >步骤2:
表单属性modelAttribute="student"定义了在表单提交时,模型将更新学生并保存表单的所有参数 < p >步骤3:
在表单提交时,使用参数@ModelAttribute("student") Student theStudent调用processForm()方法:在带有modelAttribute="student"的表单中保存的值被提取并分配给Student对象中的字段 < p >步骤4:
然后我们使用它作为我们出价,就像在页面上显示它等,就像我做的

我希望它能帮助你理解这个概念。谢谢

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

ModelAttribute注释被用作Spring MVC Web应用程序的一部分,可以在两种场景中使用。

首先,它可以用于将数据注入到预jsp加载模型中。这在确保需要JSP来显示所有数据本身时特别有用。注入是通过将一个方法连接到模型来获得的。

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

具有一定https://dzone.com/articles/using-spring-mvc%E2%80%99s

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

  1. 从控制器到UI,以及
  2. 从UI到控制器。

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

  1. 使用HTML表单
  2. 使用查询参数。
使用HTML表单: 考虑下面的场景,

Form Submission Representation .

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

  1. 首先使用request.getParameter方法读取请求中提交的所有数据。
  2. 一旦读取它们,它将使用integer.parseIntdouble.parseDouble和所有其他基于数据的数据类型可用的解析方法将它们转换为适当的Java类型。
  3. 一旦解析,它将创建我们创建的模型类的对象。例如,在这个场景中,提交的是用户信息,我们创建了一个名为user的类,容器将创建一个对象,并将自动进入该对象的所有值设置为user。
  4. 然后它将通过将值设置为Controller来切换该对象。

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

内部工作

我们首先需要定义一个模型类,如User,其中的字段数量应该与HTML表单中的字段数量完全匹配。此外,我们在HTML表单中使用的名称应该与Java类中的名称相匹配。这两点非常重要。名称应该匹配,表单中的字段数量应该与我们创建的类中的字段数量匹配。一旦我们这样做了,容器将自动读取进来的数据,创建这个模型的对象,设置值并将其交给控制器。为了在控制器内部读取这些值,我们在方法参数上使用@ModelAttribute注释。当我们在控制器中创建方法时,我们将使用@ModelAttribute并向其添加一个参数,该参数将自动具有容器给出的对象。

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

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

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

在方法层面

< p > 1。当注释在方法级别上使用时,它表明了它的目的 方法是添加一个或多个模型属性

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

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

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

首先,模型在MVC Spring (MVC =模型,视图,控制器)中使用。这就是说,模型与“视图”一起使用;

这些观点是什么?视图可以被认为是“html页面”,这是由我们的后端框架(在我们的例子中是Spring)生成的,在html页面的某些部分有一些可变数据

所以我们有了模型,它是一个实体,包含了要被“注入”的数据;进入视图。

有几个“观点”;可以与Spring一起工作的库:其中包括JSP、Thymeleaf、Mustache等。

例如,让我们假设我们正在使用Thymeleaf(它们都是相似的。更重要的是,除了JSP, Spring甚至不知道他正在使用哪些视图库。所有模型都是通过Spring的Servlet提供服务的。这意味着对于所有这些视图库,Spring代码都是相同的。你唯一需要改变的是这些html页面的语法,它们位于resources/static/templates中)

resources/static/templates   //All our view web pages are here

控制器负责路由。例如,我们的站点托管在localhost:8080上。我们需要一个显示学生的路径(URL)。让我们假设这在localhost:8080/students上可用。做这个的控制器是StudentController:

@Controller  //Not @RestController
public class StudentController {


@GetMapping(/students)
public String getStudentView() {
return "student";
}
}

这段代码的作用是说,如果我们要

localhost: 8080 /学生

然后调用getStudentView()方法。但是注意它应该返回一个字符串。然而,当使用视图库时,控制器被@Controller(而不是@RestController)注释,spring所做的是寻找一个带有方法返回的String名称的html视图页面,在我们的例子中,它将在

/ /静态/模板/ student.html资源

这对于没有数据的静态页面来说已经足够好了。然而,如果我们需要一个带有一些数据的动态页面,Spring提供了另一个很大的优势:getStudentView()上面的方法,也会在底层传递一个模型给我们的视图“student.html”。我们的模型将包含可以在文件"student.html"中访问的数据;使用视图库中的特定语法。例如,用百里香叶:

<div th:text="${attribute1}"> </div>
这将访问属性"attribute1"我们的模型。 我们可以通过模型传递不同的数据。这是通过给它分配各种属性来实现的。有不同的方式分配属性,使用@ModelAttribute:

@Controller  //Not @RestController
public class StudentController {


@ModelAttribute(name = "attribute1")
public int assignAttribute1() {
return 123454321
}   // Think it as "model.attribute1 = 123454321"


@GetMapping(/students)
public String getStudentView() {
return "student";
}
}

上面的代码将为模型(在底层创建的)分配一个名称为“attribute1”的属性;(认为它是一个键),值为12354321。类似“model”之类的。Attribute1 = 123454321"。

最后,当我们访问url时,模型被传递给视图

localhost: 8080 /学生

注意:所有用@ModelAttribute标注的方法都是在视图返回之前调用的。一旦创建了所有属性,模型就会传递给我们的视图。简单地说,在getStudentView()方法被调用之后,所有带有@ModelAttribute的方法都被调用。

也就是说,上面写的html代码将从浏览器中被视为:

<div> 123454321 </div> // th:text is a command of
//THymeleaf, and says to substitute the text
// between the tags with the attribute "attribute1"
// of our model passed to this view.

这是@ModelAttribute的基本用法。

还有另一个重要的用例:

模型可能需要在相反的方向:即,从视图到控制器。在上面描述的情况下,模型从控制器传递到视图。但是,假设用户从我们的html页面发回一些数据。我们可以用模型属性@ModelAttribute捕获它。这已经被其他人描述过了