春季MVC:请解释@RequestParam和@ModelAttribute之间的区别

我是Spring MVC的新手。请帮我解压缩文档。

文档

春季MVC文档状态(强调我的):

  • @ModelAttributeon 方法参数指示应从模型中检索该参数。如果模型中不存在,则应首先实例化参数,然后将其添加到模型中。一旦出现在模型中,就应该从具有匹配名称的所有请求参数中填充参数的字段。类将请求参数名称(包括查询字符串参数和表单字段)与按名称对属性字段进行建模进行匹配。

  • @RequestParam 将请求参数绑定到控制器中的方法参数

免责声明/澄清器

我知道和不是一回事,不是相互排斥的,不执行相同的角色,并且可以同时使用,就像在这个问题中一样 - 确实,可以用来填充字段。我的问题更倾向于他们内部运作之间的差异。@ModelAttribute@RequestParam@RequestParam@ModelAttribute

问题:

(用于方法参数,而不是方法)和之间有什么区别?具体说来:@ModelAttribute@RequestParam

  • 源:是否具有相同的信息/人口来源,即URL中的请求参数,这些参数可能已作为被编辑的表单/模型的元素提供?@RequestParam@ModelAttributePOST
  • 用法:用 的变量被丢弃(除非传递到模型中),而用 的变量自动馈送到模型中返回,这是否正确?@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填充类的字段,然后类填充要传递回视图的模型的属性

这是正确的吗?


答案 1

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

不要将“模型”一词与会话混淆。http 会话通常为:、服务器响应,然后 。当你使用注释时,你总是在构造一个你已经注释过的任何东西的实例,这就是让你认为“将东西提供给模型”可能会使变量持续存在的原因。这是不正确的,一旦完成,这些变量就不应该再成为浏览器/服务器对话的一部分,除非它们已保存在会话中。HTTP.GETHTTP.POST@ModelAttributeHttpServletRequest

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

是的!为了正确起见,请告诉Spring使用其默认的Web数据绑定器,用来自.选择将此数据传递回视图取决于程序员。当你有一个用 注释的方法时,每次代码命中该 servlet 时都会调用它。当您具有该方法的参数之一时,我们正在讨论传入的Http表单数据绑定。@ModelAttributeHttpServletRequest@ModelAttribute@ModelAttribute

打电话是说;在底层,Java允许您通过执行键值查找>从请求对象中获取值。返回的值的类型为对象。如果您没有在Web应用程序中使用Spring,那么您将键入很多内容。@RequestParamrequest.getParameter("foo")HttpServletRequest

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

如果您在控制器中用一个实例注释方法,则 Spring 将始终构造一个实例,并将其提供给您的方法。数据绑定发挥作用的地方是当在方法的参数中使用此注释时;Spring 查看 的实例,并查看它是否可以将请求中的数据与 实例上的正确属性相匹配。这是基于 java 属性约定,在该约定中,您有一个字段,例如和公共 getter 和 setter,称为 and 。这可能看起来很神奇,但是如果您要打破约定,您的Spring数据绑定将停止工作,因为它无法知道从哪里绑定数据,您仍然会得到一个实例,但属性不会设置为请求中的任何值。@ModelAttribute("fooBar") FooBar fooBarFooBarHttpServletRequestFooBarfoogetFoosetFooHttpServletRequestFooBar


答案 2

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

@RequestParam:绑定单个请求参数(如名字)

通常,
最适合阅读少量参数。@RequestParam

@ModelAttribute当您的表单包含大量字段时,将使用此参数。

@ModelAttribute为您提供其他功能,例如数据绑定,验证和表单预填充。


推荐