2015-03-31 517 views
36

我是Spring MVC的新手。请帮我解开文档。Spring MVC:请解释@RequestParam和@ModelAttribute之间的区别

文档

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填充一个类的字段,然后填充模型的属性将被传递回视图

这是正确的吗?

回答

27

@RequestParam只是填充独立变量(当然这可能是@ModelAttribute类中的字段)。这些变量在控制器完成时将被丢弃,除非它们已被馈入模型中。

不要混淆“模型”一词与会话。 http会话通常是:HTTP.GET,服务器响应,然后是HTTP.POST。当你使用@ModelAttribute注解时,你总是构建一个你已经注解的实例,这就是你认为“向模型提供东西”可能会使变量停滞不前。这是不正确的,一旦HttpServletRequest完成这些变量不应该再次成为浏览器/服务器对话的一部分,除非它们已经保存在会话中。

@ModelAttribute填充类,然后填充模型的属性的字段被传递回视图

是的!为了正确,@ModelAttribute告诉Spring使用其默认Web数据绑定器来填充来自HttpServletRequest的数据的某个实例。选择将这些数据传回给视图取决于程序员。当你有一个注解为@ModelAttribute的方法时,每次代码访问该servlet时都会调用它。当你有@ModelAttribute作为方法的参数之一时,我们正在讨论传入的Http表单数据绑定。

打电话@RequestParam是说request.getParameter("foo");在底层,Java的HttpServletRequest可让您通过执行键值查找来从请求对象获取值。返回的值是Object类型。如果你在你的web应用程序中没有使用Spring,那么你会输入很多东西。

然后,当您开始使用@ModelAttribute时,Spring会将此抽象更进一步。这个注释采用了数据绑定的概念。数据绑定的目标是控制器中的代码不必为每个表单元素调用request.getParameter("foo1")。想象一下你有一个5字段的网页表单。没有数据绑定,程序员必须手动检索并验证每个字段。程序员必须确保请求包含属性,属性的值存在,并且该属性的值是每个字段预期的类型。使用@ModelAttribute告诉Spring为你做这个工作。

如果注释在你的控制器的方法与@ModelAttribute("fooBar") FooBar fooBarFooBar实例将总是可以由Spring构建,并提供给您的方法。数据绑定起作用的地方是在Method的参数中使用了这个注释的时候; Spring查看HttpServletRequest的实例,并查看它是否可以将请求中的数据与FooBar的实例上的正确属性相匹配。这是基于java的属性约定,你有一个字段,如foo和公共getter和setter叫getFoosetFoo。这看起来很神奇,但如果你打破约定,你的Spring数据绑定将停止工作,因为它无法知道,其中绑定你的数据HttpServletRequest你仍然会得到一个FooBar的实例,但属性不会被设置为来自请求的任何值。

2

@ModelAttribute注释参数由注册ServletModelAttributeMethodProcessor(或ModelAttributeMethodProcessor)和@RequestParam注释参数处理由注册RequestParamMethodArgumentResolverRequestParamMapMethodArgumentResolver根据参数类型处理。

这里是Spring是如何使用这些HandlerMethodArgumentResolvers解决论据处理程序方法的解释:

在这两种情况下,@ModelAttribute@RequestParam,以约束从被检索的值ServletRequest parameters

你可以看看上面提到的类型的源代码,但这里是简单的细节。

对于@ModelAttribute,Spring将创建一个参数类型的实例。它将检查该实例的字段并尝试根据由名称和字段名称组成的命名/别名策略将参数值绑定到它们。它通常使用一组Converter实例将String(参数值始终为String值)转换为目标字段类型IntegerDate等等。您还可以注册自己的Converter类型以进行自定义转换。你也可以嵌套POJO类型。

对于@RequestParam,Spring将使用相同的Converter实例将参数值直接转换为带注释的参数类型。

请注意,参数值不会“丢弃”。它们在容器的请求处理周期期间被存储在HttpServletRequest中。您可以随时通过appropriate methods访问它们。

0

@ModelAttribute(参数)@SessionAttributes或从@ModelAttribute(方法)加载一个模型属性。

你不需要它只是绑定来自请求的值,但它会从@SessionAttributes加载后做到这一点。

@RequestParam将请求参数绑定到对象。

0
  • 在方法级别

当注释在方法级别使用它表示方法的目的是为了增加一个或多个模型属性。这些方法支持与@RequestMapping方法相同的参数类型,但不能直接映射到请求。

@ModelAttribute 
public void addAttributes(Model model) { 
    model.addAttribute("msg", "Welcome to the Netherlands!"); 
} 

将名为msg的属性添加到控制器类中定义的所有模型的方法。

在调用任何请求处理程序方法之前,Spring-MVC将始终首先调用该方法。 也就是说,在用@RequestMapping注解的控制器方法被调用之前调用@ModelAttribute方法。序列背后的逻辑是,在控制器方法内的任何处理开始之前,必须创建模型对象。

将相应的类注释为@ControllerAdvice也很重要。因此,您可以在模型中添加将被识别为全局的值。这实际上意味着对于响应部分中的每个方法,每个请求都存在默认值。

  • 作为方法的参数

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

在用户模型属性后面的代码片段中填充了提交给addUser端点的表单中的数据。 Spring MVC在调用提交方法之前在幕后执行此操作:

**@RequestMapping**(value = "/addUser", method = RequestMethod.POST) 
public String submit(@ModelAttribute("user") User user) { 
    return "userView"; 
} 

因此,它将表单数据与bean绑定。使用@RequestMapping注解的控制器可以具有用@ModelAttribute注释的自定义类参数。

这就是通常所说的Spring-MVC中的数据绑定,这是一种常见的机制,不需要单独解析每个表单字段。

1

@ModelAttribute:绑定整个Java对象(如Employee)。支持多个请求参数

@RequestParam:结合一个单一的请求参数(像的firstName)

一般而言,
@RequestParam是最适合读出一小则params的。

@ModelAttribute用于具有大量字段的表单。

@ModelAttribute为您提供了额外的功能,如数据绑定,验证和形式预先填充。

相关问题