Spring MVC:请解释@RequestParam 和@ModelAttribute 之间的区别
Spring MVC: please explain difference between @RequestParam and @ModelAttribute
我是 Spring MVC 的新手。请帮我解压文档。
文档
Spring MVC Documentation 状态(强调我的):
方法参数上的 @ModelAttribute
指示应从模型中检索参数。如果模型中不存在参数,则应首先实例化参数,然后将其添加到模型中。一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。 WebDataBinder class 匹配请求参数名⟩——⟩包括查询字符串参数和表单字段⟩—⟩按名称匹配模型属性字段。
@RequestParam
将请求参数绑定到控制器中的方法参数。
免责声明/澄清
我知道@ModelAttribute
和@RequestParam
不是一回事,不互斥,作用不同,可以同时使用,如this question - 事实上,@RequestParam
可用于填充 @ModelAttribute
的字段。我的问题更倾向于他们内部运作方式的不同。
问题:
@ModelAttribute
(用于方法参数,而不是方法)和@RequestParam
有什么区别?具体来说:
- 来源:
@RequestParam
和 @ModelAttribute
的来源是否相同
信息/人口,即 URL 中的请求参数,它们可能作为 POST
ed 的表单/模型的元素提供?
- 用法: 用
@RequestParam
检索的变量被丢弃是否正确(除非传递到模型中),而用 @ModelAttribute
检索的变量是正确的自动送入要返回的模型?
或者在非常基本的编码示例中,这两个示例之间真正的工作区别是什么?
示例 1:@RequestParam
:
// foo and bar are thrown away, and are just used (e.g.) to control flow?
@RequestMapping(method = RequestMethod.POST)
public String testFooBar(@RequestParam("foo") String foo,
@RequestParam("bar") String bar, ModelMap model) {
try {
doStuff(foo, bar);
}
// other code
}
示例 2:@ModelAttribute
:
// FOOBAR CLASS
// Fields could of course be explicitly populated from parameters by @RequestParam
public class FooBar{
private String foo;
private String bar;
// plus set() and get() methods
}
// CONTROLLER
// Foo and Bar become part of the model to be returned for the next view?
@RequestMapping(method = RequestMethod.POST)
public String setupForm(@ModelAttribute("fooBar") FooBar foobar) {
String foo = fooBar.getFoo();
String bar = fooBar.getBar();
try {
doStuff(foo, bar);
}
// other code
}
我目前的理解:
@ModelAttribute
和 @RequestParam
都查询请求参数以获取信息,但它们使用此信息的方式不同:
@RequestParam
只是填充独立变量(当然可能是 @ModelAttribute
class 中的字段)。这些变量将在 Controller 完成后被丢弃,除非它们已被输入到模型中。
@ModelAttribute
填充 class 的字段,然后填充模型的属性以传回视图
这是正确的吗?
@RequestParam
just populates stand-alone variables (which may of course be fields in a @ModelAttribute
class). These variables will be thrown away when the Controller is done, unless they have been fed into the model.
不要将 "model" 与会话混淆。 http会话一般是:HTTP.GET
,服务器响应,然后是HTTP.POST
。当您使用 @ModelAttribute
注释时,您总是在构造您注释的任何内容的实例,这就是让您认为 'feeding things to the model' 可能会使变量保留的原因。这是不正确的,一旦 HttpServletRequest
完成,这些变量不应再成为 browser/server 对话的一部分,除非它们已保存在会话中。
@ModelAttribute
populates the fields of a class, which then populates an attribute of the model to be passed back to the view
是的!正确地说,@ModelAttribute
告诉 Spring 使用其默认的 Web 数据绑定器来使用来自 HttpServletRequest
的数据填充某个实例。选择将此数据传递回视图取决于程序员。当你有一个用 @ModelAttribute
注释的方法时,每次代码命中该 servlet 时都会调用它。当您将 @ModelAttribute
作为方法的参数之一时,我们正在谈论传入的 Http 表单数据绑定。
叫@RequestParam
是说request.getParameter("foo")
的捷径;在幕后,Java 的 HttpServletRequest
允许您通过键-> 值查找从请求对象中获取值。返回的值是 Object 类型。如果您没有在 Web 应用程序中使用 Spring,这就是您经常输入的内容。
当您开始使用 @ModelAttribute
时,Spring 会将这种抽象更进一步。这个注解使用了数据绑定的概念。数据绑定的目标是控制器中的代码不必为每个表单元素调用 request.getParameter("foo1")
。假设您有一个包含 5 个字段的 Web 表单。如果没有数据绑定,程序员必须手动检索和验证每个字段。程序员必须确保请求包含 属性,属性 的值存在,并且 属性 的值是每个字段预期的类型。使用 @ModelAttribute
告诉 Spring 为您完成这项工作。
如果您在控制器中用 @ModelAttribute("fooBar") FooBar fooBar
注释一个方法 FooBar
的实例将 总是 由 Spring 构造并提供到你的方法。数据绑定发挥作用的地方是在方法的参数中使用此注释时; Spring 查看 HttpServletRequest
的实例,看看它是否可以在 FooBar
的实例上匹配到右侧 属性 请求中的数据。这是基于 java 属性约定,其中您有一个字段,例如 foo
和 public getter 和 setter,称为 getFoo
和 setFoo
。这可能看起来很神奇,但如果您要打破惯例,您的 Spring 数据绑定将停止工作,因为它无法知道 何处 来绑定来自您的 HttpServletRequest
您仍会获得 FooBar
的实例,但不会将属性设置为请求中的任何值。
@ModelAttribute
注释参数由已注册的 ServletModelAttributeMethodProcessor
(或 ModelAttributeMethodProcessor
)处理,@RequestParam
注释参数由已注册的 RequestParamMethodArgumentResolver
或 RequestParamMapMethodArgumentResolver
取决于参数类型。
这里解释了 Spring 如何使用这些 HandlerMethodArgumentResolvers
来解析处理程序方法的参数:
- Form submit in Spring MVC 3 - explanation
在这两种情况下,@ModelAttribute
和 @RequestParam
,要绑定的值是从 ServletRequest
parameters 中检索的。
你可以看看上面提到的类型的源代码,但这里是简单的细节。
对于@ModelAttribute
,Spring将创建参数类型的实例。它将检查该实例的字段并尝试根据由 @ModelAttribute
名称和字段名称组成的 naming/aliasing 策略将参数值绑定到它们。它通常使用一组 Converter
实例从 String
(参数值始终是 String
值)转换为任何目标字段类型 Integer
、Date
、等。您还可以注册自己的 Converter
类型以进行自定义转换。您还可以嵌套 POJO 类型。
对于 @RequestParam
,Spring 将使用相同的 Converter
实例将参数值直接转换为带注释的参数类型。
请注意,参数值不是 "thrown away"。在容器的请求处理周期期间,它们存储在 HttpServletRequest
中。您可以随时通过 appropriate methods.
访问它们
@ModelAttribute
(参数) 从 @SessionAttributes
或 @ModelAttribute
(方法)[= 加载模型属性23=].
您不需要它只是为了绑定来自请求的值,但它会在从 @SessionAttributes
.
加载后执行此操作
@RequestParam
将请求参数绑定到对象。
- 在方法级别
当注释用于方法级别时,表示该方法的目的是添加一个或多个模型属性。这些方法支持与 @RequestMapping
方法相同的参数类型,但不能直接映射到请求。
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
一种将名为 msg 的属性添加到控制器中定义的所有模型的方法 class。
Spring-MVC 总是先调用该方法,然后再调用任何请求处理程序方法。 也就是说,@ModelAttribute 方法在调用带有@RequestMapping 注释的控制器方法之前被调用。 该序列背后的逻辑是,模型对象必须在任何处理开始之前创建控制器方法。
将相应的 class 注释为 @ControllerAdvice 也很重要。因此,您可以在将被标识为全局的模型中添加值。这实际上意味着对于每个请求,对于响应部分中的每个方法,都存在一个默认值。
- 作为方法参数
当用作方法参数时,它表示应从模型中检索参数。如果不存在,则应首先对其进行实例化,然后将其添加到模型中,一旦出现在模型中,参数字段应从具有匹配名称的所有请求参数中填充。
在后面的代码片段中,用户模型属性填充了提交给 addUser 端点的表单中的数据。 Spring MVC 在调用提交方法之前在幕后执行此操作:
**@RequestMapping**(value = "/addUser", method = RequestMethod.POST)
public String submit(@ModelAttribute("user") User user) {
return "userView";
}
因此,它将表单数据与 bean 绑定在一起。用@RequestMapping 注释的控制器可以有自定义 class 个参数,用@ModelAttribute 注释。
这就是 Spring-MVC 中通常所说的数据绑定,这是一种通用机制,使您不必单独解析每个表单字段。
@ModelAttribute
:绑定整个 Java 对象(如 Employee)。支持多个请求参数
@RequestParam
:绑定单个请求参数(如 firstName)
一般来说,
@RequestParam
最适合读取少量参数。
@ModelAttribute
当您有一个包含大量字段的表单时使用。
和
@ModelAttribute
为您提供额外的功能,例如数据绑定、验证和表单预填充。
我是 Spring MVC 的新手。请帮我解压文档。
文档
Spring MVC Documentation 状态(强调我的):
-
方法参数上的
@ModelAttribute
指示应从模型中检索参数。如果模型中不存在参数,则应首先实例化参数,然后将其添加到模型中。一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。 WebDataBinder class 匹配请求参数名⟩——⟩包括查询字符串参数和表单字段⟩—⟩按名称匹配模型属性字段。@RequestParam
将请求参数绑定到控制器中的方法参数。
免责声明/澄清
我知道@ModelAttribute
和@RequestParam
不是一回事,不互斥,作用不同,可以同时使用,如this question - 事实上,@RequestParam
可用于填充 @ModelAttribute
的字段。我的问题更倾向于他们内部运作方式的不同。
问题:
@ModelAttribute
(用于方法参数,而不是方法)和@RequestParam
有什么区别?具体来说:
- 来源:
@RequestParam
和@ModelAttribute
的来源是否相同 信息/人口,即 URL 中的请求参数,它们可能作为POST
ed 的表单/模型的元素提供? - 用法: 用
@RequestParam
检索的变量被丢弃是否正确(除非传递到模型中),而用@ModelAttribute
检索的变量是正确的自动送入要返回的模型?
或者在非常基本的编码示例中,这两个示例之间真正的工作区别是什么?
示例 1:@RequestParam
:
// foo and bar are thrown away, and are just used (e.g.) to control flow?
@RequestMapping(method = RequestMethod.POST)
public String testFooBar(@RequestParam("foo") String foo,
@RequestParam("bar") String bar, ModelMap model) {
try {
doStuff(foo, bar);
}
// other code
}
示例 2:@ModelAttribute
:
// FOOBAR CLASS
// Fields could of course be explicitly populated from parameters by @RequestParam
public class FooBar{
private String foo;
private String bar;
// plus set() and get() methods
}
// CONTROLLER
// Foo and Bar become part of the model to be returned for the next view?
@RequestMapping(method = RequestMethod.POST)
public String setupForm(@ModelAttribute("fooBar") FooBar foobar) {
String foo = fooBar.getFoo();
String bar = fooBar.getBar();
try {
doStuff(foo, bar);
}
// other code
}
我目前的理解:
@ModelAttribute
和 @RequestParam
都查询请求参数以获取信息,但它们使用此信息的方式不同:
@RequestParam
只是填充独立变量(当然可能是@ModelAttribute
class 中的字段)。这些变量将在 Controller 完成后被丢弃,除非它们已被输入到模型中。@ModelAttribute
填充 class 的字段,然后填充模型的属性以传回视图
这是正确的吗?
@RequestParam
just populates stand-alone variables (which may of course be fields in a@ModelAttribute
class). These variables will be thrown away when the Controller is done, unless they have been fed into the model.
不要将 "model" 与会话混淆。 http会话一般是:HTTP.GET
,服务器响应,然后是HTTP.POST
。当您使用 @ModelAttribute
注释时,您总是在构造您注释的任何内容的实例,这就是让您认为 'feeding things to the model' 可能会使变量保留的原因。这是不正确的,一旦 HttpServletRequest
完成,这些变量不应再成为 browser/server 对话的一部分,除非它们已保存在会话中。
@ModelAttribute
populates the fields of a class, which then populates an attribute of the model to be passed back to the view
是的!正确地说,@ModelAttribute
告诉 Spring 使用其默认的 Web 数据绑定器来使用来自 HttpServletRequest
的数据填充某个实例。选择将此数据传递回视图取决于程序员。当你有一个用 @ModelAttribute
注释的方法时,每次代码命中该 servlet 时都会调用它。当您将 @ModelAttribute
作为方法的参数之一时,我们正在谈论传入的 Http 表单数据绑定。
叫@RequestParam
是说request.getParameter("foo")
的捷径;在幕后,Java 的 HttpServletRequest
允许您通过键-> 值查找从请求对象中获取值。返回的值是 Object 类型。如果您没有在 Web 应用程序中使用 Spring,这就是您经常输入的内容。
@ModelAttribute
时,Spring 会将这种抽象更进一步。这个注解使用了数据绑定的概念。数据绑定的目标是控制器中的代码不必为每个表单元素调用 request.getParameter("foo1")
。假设您有一个包含 5 个字段的 Web 表单。如果没有数据绑定,程序员必须手动检索和验证每个字段。程序员必须确保请求包含 属性,属性 的值存在,并且 属性 的值是每个字段预期的类型。使用 @ModelAttribute
告诉 Spring 为您完成这项工作。
如果您在控制器中用 @ModelAttribute("fooBar") FooBar fooBar
注释一个方法 FooBar
的实例将 总是 由 Spring 构造并提供到你的方法。数据绑定发挥作用的地方是在方法的参数中使用此注释时; Spring 查看 HttpServletRequest
的实例,看看它是否可以在 FooBar
的实例上匹配到右侧 属性 请求中的数据。这是基于 java 属性约定,其中您有一个字段,例如 foo
和 public getter 和 setter,称为 getFoo
和 setFoo
。这可能看起来很神奇,但如果您要打破惯例,您的 Spring 数据绑定将停止工作,因为它无法知道 何处 来绑定来自您的 HttpServletRequest
您仍会获得 FooBar
的实例,但不会将属性设置为请求中的任何值。
@ModelAttribute
注释参数由已注册的 ServletModelAttributeMethodProcessor
(或 ModelAttributeMethodProcessor
)处理,@RequestParam
注释参数由已注册的 RequestParamMethodArgumentResolver
或 RequestParamMapMethodArgumentResolver
取决于参数类型。
这里解释了 Spring 如何使用这些 HandlerMethodArgumentResolvers
来解析处理程序方法的参数:
- Form submit in Spring MVC 3 - explanation
在这两种情况下,@ModelAttribute
和 @RequestParam
,要绑定的值是从 ServletRequest
parameters 中检索的。
你可以看看上面提到的类型的源代码,但这里是简单的细节。
对于@ModelAttribute
,Spring将创建参数类型的实例。它将检查该实例的字段并尝试根据由 @ModelAttribute
名称和字段名称组成的 naming/aliasing 策略将参数值绑定到它们。它通常使用一组 Converter
实例从 String
(参数值始终是 String
值)转换为任何目标字段类型 Integer
、Date
、等。您还可以注册自己的 Converter
类型以进行自定义转换。您还可以嵌套 POJO 类型。
对于 @RequestParam
,Spring 将使用相同的 Converter
实例将参数值直接转换为带注释的参数类型。
请注意,参数值不是 "thrown away"。在容器的请求处理周期期间,它们存储在 HttpServletRequest
中。您可以随时通过 appropriate methods.
@ModelAttribute
(参数) 从 @SessionAttributes
或 @ModelAttribute
(方法)[= 加载模型属性23=].
您不需要它只是为了绑定来自请求的值,但它会在从 @SessionAttributes
.
@RequestParam
将请求参数绑定到对象。
- 在方法级别
当注释用于方法级别时,表示该方法的目的是添加一个或多个模型属性。这些方法支持与 @RequestMapping
方法相同的参数类型,但不能直接映射到请求。
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
一种将名为 msg 的属性添加到控制器中定义的所有模型的方法 class。
Spring-MVC 总是先调用该方法,然后再调用任何请求处理程序方法。 也就是说,@ModelAttribute 方法在调用带有@RequestMapping 注释的控制器方法之前被调用。 该序列背后的逻辑是,模型对象必须在任何处理开始之前创建控制器方法。
将相应的 class 注释为 @ControllerAdvice 也很重要。因此,您可以在将被标识为全局的模型中添加值。这实际上意味着对于每个请求,对于响应部分中的每个方法,都存在一个默认值。
- 作为方法参数
当用作方法参数时,它表示应从模型中检索参数。如果不存在,则应首先对其进行实例化,然后将其添加到模型中,一旦出现在模型中,参数字段应从具有匹配名称的所有请求参数中填充。
在后面的代码片段中,用户模型属性填充了提交给 addUser 端点的表单中的数据。 Spring MVC 在调用提交方法之前在幕后执行此操作:
**@RequestMapping**(value = "/addUser", method = RequestMethod.POST)
public String submit(@ModelAttribute("user") User user) {
return "userView";
}
因此,它将表单数据与 bean 绑定在一起。用@RequestMapping 注释的控制器可以有自定义 class 个参数,用@ModelAttribute 注释。
这就是 Spring-MVC 中通常所说的数据绑定,这是一种通用机制,使您不必单独解析每个表单字段。
@ModelAttribute
:绑定整个 Java 对象(如 Employee)。支持多个请求参数
@RequestParam
:绑定单个请求参数(如 firstName)
一般来说,
@RequestParam
最适合读取少量参数。
@ModelAttribute
当您有一个包含大量字段的表单时使用。
和
@ModelAttribute
为您提供额外的功能,例如数据绑定、验证和表单预填充。