我是Spring MVC的新手。请帮我解开文档。
文档
Spring MVC Documentation州(强调我的):
@ModelAttribute
表示应该从模型中检索参数。如果模型中不存在,则应首先实例化参数,然后将其添加到模型中。一旦出现在模型中,参数的字段应该从所有具有匹配名称的请求参数中填充。 WebDataBinder类将请求参数名称(包括查询字符串参数和表单字段)与名称模型属性字段进行匹配。
@RequestParam
将请求参数绑定到控制器中的方法参数。
免责声明/澄清者
我知道@ModelAttribute
和@RequestParam
不是一回事,互不排斥,不执行相同的角色,可以同时使用,如this question - 确实,@RequestParam
可用于填充@ModelAttribute
的字段。我的问题更多地针对其内部运作之间的差异。
问题:
@ModelAttribute
(用于方法参数,而不是方法)和@RequestParam
之间有什么区别?具体做法是:
@RequestParam
和@ModelAttribute
具有相同的来源
信息/人口,即URL中的请求参数,可能是作为POST
的表单/模型的元素提供的? @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
类中的字段)。完成控制器后,这些变量将被丢弃,除非它们已被送入模型。
@ModelAttribute
填充类的字段,然后填充要传递回视图的模型的属性
这是对的吗?
答案 0 :(得分:35)
@RequestParam
只填充独立变量(当然可能是@ModelAttribute
类中的字段)。完成控制器后,这些变量将被丢弃,除非它们已被送入模型。
不要混淆"模型"与会话。 http对话通常为:HTTP.GET
,服务器响应,然后是HTTP.POST
。当你使用@ModelAttribute
注释时,你总是在构建一个你注释过的任何实例,这就是让你认为向模型提供东西的原因。可能会让变量四处游走。这是不正确的,一旦HttpServletRequest
完成,这些变量就不应再成为浏览器/服务器对话的一部分,除非它们已保存在会话中。
@ModelAttribute
填充类的字段,然后填充要传递回视图的模型的属性
是的!为了正确,@ModelAttribute
告诉Spring使用其默认的Web数据绑定器来填充来自HttpServletRequest
的数据的实例。选择将此数据传递回视图取决于程序员。当您使用@ModelAttribute
注释的方法时,每次代码命中该servlet时都会调用它。当您使用@ModelAttribute
作为方法参数之一时,我们正在讨论传入的Http表单数据绑定。
拨打@RequestParam
是说出request.getParameter("foo")
的捷径;在引擎盖下,Java HttpServletRequest
允许您通过执行key->值查找来从请求对象获取值。返回的值是Object类型。如果您没有在Web应用程序中使用Spring,那么这就是您要输入的内容。
当您开始使用@ModelAttribute
时,Spring会将此抽象更进一步。该注释采用数据绑定的概念。数据绑定的目标是控制器中的代码不必为每个表单元素调用request.getParameter("foo1")
。想象一下,你有一个包含5个字段的Web表单。如果没有数据绑定,程序员必须手动检索并验证每个字段。程序员必须确保请求包含属性,属性的值存在,以及属性的值是每个字段的预期类型。使用@ModelAttribute
告诉Spring为您完成这项工作。
如果使用@ModelAttribute("fooBar") FooBar fooBar
在控制器中注释方法,则FooBar
的实例将总是由Spring构造,并提供给您的方法。数据绑定发挥作用的地方是在Method的参数中使用此注释时; Spring查看HttpServletRequest
的实例,并查看它是否可以将请求中的数据与FooBar
的实例上的右属性相匹配。这基于java属性约定,其中包含foo
字段和名为getFoo
和setFoo
的公共getter和setter。这可能看起来很神奇,但是如果你违反惯例,你的Spring数据绑定将停止工作,因为它无法知道 where 绑定来自HttpServletRequest
你的数据仍会获得FooBar
的实例,但不会将属性设置为请求中的任何值。
答案 1 :(得分:3)
@ModelAttribute
:绑定整个Java对象(如Employee)。支持多个请求参数
@RequestParam
:绑定单个请求参数(如firstName)
一般来说,
@RequestParam
最适合阅读少数参数。
@ModelAttribute
。
和
@ModelAttribute
为您提供其他功能,例如数据绑定,验证和表单预填充。
答案 2 :(得分:2)
@ModelAttribute
带注释的参数由注册的ServletModelAttributeMethodProcessor
(或ModelAttributeMethodProcessor
)处理,@RequestParam
带注释的参数由注册的RequestParamMethodArgumentResolver
或{{1}处理取决于参数类型。
以下解释了Spring如何使用这些RequestParamMapMethodArgumentResolver
来解析处理程序方法的参数:
在HandlerMethodArgumentResolvers
和@ModelAttribute
这两种情况下,要绑定的值都是从ServletRequest
parameters中检索的。
您可以查看上述类型的源代码,但这里有简单的细节。
对于@RequestParam
,Spring将创建参数类型的实例。它将检查该实例的字段,并尝试根据由@ModelAttribute
名称和字段名称组成的命名/别名策略将参数值绑定到它们。它通常使用一组@ModelAttribute
个实例从Converter
(参数值始终为String
值)转换为目标字段类型String
,Integer
,您也可以注册自己的Date
类型进行自定义转换。您也可以嵌套POJO类型。
对于Converter
,Spring将使用相同的@RequestParam
实例将参数值直接转换为带注释的参数类型。
请注意,参数值不会被“丢弃”。它们在容器请求处理周期的持续时间内存储在Converter
中。您始终可以通过appropriate methods。
答案 3 :(得分:0)
@ModelAttribute
(参数)从@SessionAttributes
或@ModelAttribute
(方法)加载模型属性。
您不仅需要绑定请求中的值,而且从@SessionAttributes
加载后也会这样做。
@RequestParam
将请求参数绑定到对象。
答案 4 :(得分:0)
在方法级别使用注释时,它表示该方法的目的是添加一个或多个模型属性。此类方法支持与@RequestMapping
方法相同的参数类型,但不能直接映射到请求。
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
将名为msg的属性添加到控制器类中定义的所有模型的方法。
在调用任何请求处理程序方法之前,Spring-MVC将始终首先调用该方法。 也就是说,在调用使用@RequestMapping注释的控制器方法之前调用@ModelAttribute方法。序列背后的逻辑是,必须在控制器方法内部任何处理开始之前创建模型对象。
将相应的类注释为@ControllerAdvice也很重要。因此,您可以在Model中添加将被标识为全局的值。这实际上意味着对于每个请求,对于响应部分中的每个方法都存在默认值。
当用作方法参数时,它表示应从模型中检索参数。如果不存在,则应首先将其实例化,然后添加到模型中,并且一旦出现在模型中,就应从所有具有匹配名称的请求参数中填充参数字段。
在随后的代码段中,用提交到addUser端点的表单中的数据填充用户模型属性。 Spring MVC在调用submit方法之前在幕后执行此操作:
**@RequestMapping**(value = "/addUser", method = RequestMethod.POST)
public String submit(@ModelAttribute("user") User user) {
return "userView";
}
因此,它将表单数据与bean绑定。使用@RequestMapping注释的控制器可以使用@ModelAttribute注释自定义类参数。
这就是Spring-MVC中通常所说的数据绑定,这是一种常见的机制,可以使您不必单独解析每个表单字段。