我是Spring MVC的新手。请帮我解开文档。
文档
Spring MVC Documentation州(强调我的):
@ModelAttribute
表示应该从模型中检索参数。如果模型中不存在,则应首先实例化参数,然后将其添加到模型中。一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。 WebDataBinder类将请求参数名称(包括查询字符串参数和表单字段)与名称模型属性字段进行匹配。@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
类中的字段)。完成控制器后,这些变量将被丢弃,除非它们已被送入模型。@ModelAttribute
填充类的字段,然后填充要传递回视图的模型的属性它是否正确?
@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-> value查找来从请求对象获取值。返回的值是Object类型。如果您没有在Web应用程序中使用Spring,那么这就是您要输入的内容。
当你开始使用@ModelAttribute
时,Spring会将这种抽象更进一步。该注释采用数据绑定的概念。数据绑定的目标是控制器中的代码不必为每个表单元素调用request.getParameter("foo1")
。想象一下,你有一个包含5个字段的Web表单。如果没有数据绑定,程序员必须手动检索并验证每个字段。程序员必须确保请求包含属性,属性的值存在,以及属性的值是每个字段的预期类型。使用@ModelAttribute
告诉Spring为你做这项工作。
如果使用@ModelAttribute("fooBar") FooBar fooBar
在控制器中注释方法FooBar
的实例将始终由Spring构造,并提供给您的方法。数据绑定发挥作用的地方,就是在Method的参数中使用此注释时; Spring查看HttpServletRequest
的实例,并查看它是否可以将请求中的数据与FooBar
实例上的右属性匹配。这是基于java属性约定,其中有一个字段,如foo
和公共getter和setter,名为getFoo
和setFoo
。这可能看起来很神奇但是如果你打破常规,你的Spring数据绑定将停止工作,因为它无法知道从HttpServletRequest
绑定数据的位置你仍然会得到FooBar
的实例,但是属性不会被设置为请求中的任何值。
@ModelAttribute
:绑定整个Java对象(如Employee)。支持多个请求参数
@RequestParam
:绑定单个请求参数(如firstName)
一般来说,
@RequestParam
最适合阅读少数参数。
当您拥有包含大量字段的表单时,将使用@ModelAttribute
。
和
@ModelAttribute
为您提供其他功能,如数据绑定,验证和表格预填充。
@ModelAttribute
注释参数由注册的ServletModelAttributeMethodProcessor
(或ModelAttributeMethodProcessor
)处理,@RequestParam
注释参数由注册的RequestParamMethodArgumentResolver
或RequestParamMapMethodArgumentResolver
处理,具体取决于参数类型。
以下是Spring如何使用这些HandlerMethodArgumentResolvers
来解析处理程序方法的参数的解释:
在两种情况下,@ModelAttribute
和@RequestParam
,要绑定的值都是从ServletRequest
parameters中检索到的。
您可以查看上面提到的类型的源代码,但这里有简单的细节。
对于@ModelAttribute
,Spring将创建参数类型的实例。它将检查该实例的字段,并尝试根据由@ModelAttribute
名称和字段名称组成的命名/别名策略将参数值绑定到它们。它通常使用一组Converter
实例从String
(参数值始终是String
值)转换为目标字段类型Integer
,Date
等。您还可以注册自己的Converter
类型进行自定义转换。您还可以嵌套POJO类型。
对于@RequestParam
,Spring将使用相同的Converter
实例将参数值直接转换为带注释的参数类型。
请注意,参数值不会被“丢弃”。它们在容器的请求处理周期的持续时间内存储在HttpServletRequest
中。您可以随时通过appropriate methods访问它们。
@ModelAttribute
(参数)从@SessionAttributes
或@ModelAttribute
(方法)加载模型属性。
您不需要它只是绑定请求中的值,但它会在从@SessionAttributes
加载后执行此操作。
@RequestParam
将请求参数绑定到对象。
在方法级别使用注释时,它指示该方法的目的是添加一个或多个模型属性。这些方法支持与@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中通常所说的数据绑定,这是一种常见的机制,可以使您不必单独解析每个表单字段。