Spring:带有和不带@ModelAttribute的绑定对象

时间:2017-02-25 22:41:37

标签: spring data-binding modelattribute

我是Spring新手并注册用户。我确实喜欢这个。

@RequestMapping("/register")
    public String register(@ModelAttribute User user,BindingResult result){
       if(!result.hasErrors()){
         userSerive.register(user);
       }
     return "welcome";
}

这很好用,但问题是我在user页面中不需要这个welcome.jsp对象,所以为什么要让模型对象更重。所以我试过没有@ModelAttribute ,这对我来说也很有用。

@RequestMapping("/register")
    public String register(User user,BindingResult result){
       if(!result.hasErrors()){
         userSerive.register(user);
       }
     return "welcome";
}

所以我只想知道什么是专业人士和如果我真的不需要user jsp中的@ModelAttribute对象,那么这两者都是最好的做法。 @ModelAttribute除了@ModelAttribute之外还做其他任何事情。将对象添加到Model中,弹簧隐式绑定没有。是@RequestBody更安全的绑定方式还是其他?

我想在以下4种类型的请求中对我的查询进行分类。如果我不需要在视图中发送数据并且我的请求是以下任何一项,那么使用csv会有什么区别 -

  1. 查询字符串,即GET中的表单数据
  2. 请求有效负载或正文,即POST中的表单数据
  3. json数据在ajaxified GET requst中
  4. POST中的
  5. json数据请求 - 我想这两者都不会绑定。 writefile = r'./myfile.csv' data = ['COLUMN A', 'COLUMN B', 'COLUMN C', 'COLUMN D', 'COLUMN E'] with open(writefile, 'w') as f: writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC) writer.writerow(data) 是必需的。

7 个答案:

答案 0 :(得分:4)

在您的情况下,可能(见下文......)两种方法签名之间的行为没有区别。

两者都将请求参数绑定到user,并将结果对象作为属性User添加到模型中 - 此属性名称派生自方法参数的资本化类型名称{{1 }}

@ModelAttribute可用于自定义属性的名称,例如@ModelAttribute("theUser"),或者向代码的读者提示在视图中使用此参数。但正如你所说,这些都不适用于你的用例。

无论您是否使用@ModelAttribute注释,Spring中的相同代码都将用于填充参数 - 相关代码为org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor

因此,在您的代码中使用public String register(User user, BindingResult result)签名对我来说更有意义。将@ModelAttribute注释添加到模型中不需要的方法参数可能会让读取代码的人感到困惑。

稍微长一点的答案是只是是您在案件中指定@ModelAttribute的理由 - 但它非常神秘且不太可能。

Spring处理程序方法中的方法参数由HandlerMethodArgumentResolver个实例填充。这些是可配置的,并依次尝试每个参数。

默认的处理程序方法参数解析器如下所示(请参阅RequestMappingHandlerAdapter):

resolvers.add(new ServletModelAttributeMethodProcessor(false));

...

resolvers.add(new ServletModelAttributeMethodProcessor(true));

如果您要在中间添加自己的,例如a UserHandlerMethodArgumentResolver,您可以使用@ModelAttribute告诉Spring以默认方式处理特定参数,而不是使用自定义参数解析器类。

答案 1 :(得分:2)

这个问题非常有用,但我没有看到这里的答复正确回答了问题。

我通过stackoverflow中的更多线程阅读,发现这个非常有用: https://stackoverflow.com/a/26916920/1542363

对于我自己如何决定使用哪一个,如果我只需要绑定而不想在模型中存储参数对象,则不要使用@ModelAttribute

答案 2 :(得分:1)

除了向Model添加对象外,Spring MVC还使用它将绑定对象提供给Controller方法,在这种方法中你可以使用它,在你的情况下“注册”。

是的@ModelAtttribute是Spring MVC中最安全,最好的方法,可以将传入的帖子数据绑定到一个对象。

答案 3 :(得分:1)

查看此帖子here。它涵盖了ModelAttribute的大量详细信息。

ModelAttribute只能与表单编码的请求数据一起使用。它无法将json / xml请求数据与数据对象绑定。为此,您必须使用RequestBody。

答案 4 :(得分:0)

如Spring MVC文档中所述 - @ModelAttribute注释可用于方法或方法参数。当然,我们可以在一个控制器中同时使用它们。

方法注释

public String processForm(@ModelAttribute("person") Person person){
    person.getStuff();
}

此方法的目的是在模型中添加属性。所以在我们的例子中,person key将person对象作为Model中的值。控制器中的@ModelAttribute方法在@RequestMapping方法之前在同一个控制器中调用。

方法参数

{{1}}

请参阅spring文档http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args

答案 5 :(得分:0)

除了@ryanp的完美答案外,我想补充一下:

对于现代spring mvc项目,最确定的是会使用@Controller和@RequestMapping等注释来提供请求处理程序,在内部,Spring MVC使用RequestMappingHandlerAdapter.invokeHandlerMethod()来处理用户提供的HandlerMethod请求。如果查看RequestMappingHandlerAdapter,它会设置一个参数解析器集合来为HandlerMethod准备参数,通过查看集合,您可以了解Spring MVC解析请求的方式和顺序,并填充用户提供的参数。所以这是源代码:

```的Java

/**
 * Return the list of argument resolvers to use including built-in resolvers
 * and custom resolvers provided via {@link #setCustomArgumentResolvers}.
 */
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

    // Annotation-based argument resolution
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    resolvers.add(new ServletModelAttributeMethodProcessor(false));
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    resolvers.add(new RequestAttributeMethodArgumentResolver());

    // Type-based argument resolution
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RedirectAttributesMethodArgumentResolver());
    resolvers.add(new ModelMethodProcessor());
    resolvers.add(new MapMethodProcessor());
    resolvers.add(new ErrorsMethodArgumentResolver());
    resolvers.add(new SessionStatusMethodArgumentResolver());
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    resolvers.add(new ServletModelAttributeMethodProcessor(true));

    return resolvers;
}

```

值得注意的是底部的Catch-all解析器。 Spring MVC使用处理@RequestParam和@ModelAttribute的两个解析器,分别处理非注释的简单类型和pojo类型参数。这就是为什么在OP的测试中,如果有@ModelAttribute则没关系。

令人遗憾的是,它在Spring MVC的参考资料中并不清楚。

答案 6 :(得分:0)

查看当前(春季5.1.5)文档(https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-arguments):

控制器方法参数-其他任何参数[GP-不带注释]:

If a method argument is not matched to any of the earlier values in this table and
it is a simple type (as determined by BeanUtils#isSimpleProperty),
it is a resolved as a @RequestParam. Otherwise, it is resolved as a @ModelAttribute.

因此,如果在控制器映射的方法中有一个非简单的属性作为参数,则完全等同于将其注释为@ModelAttribute