Spring:绑定对象有和没有@ModelAttribute
Posted
技术标签:
【中文标题】Spring:绑定对象有和没有@ModelAttribute【英文标题】:Spring : binding object with and without @ModelAttribute 【发布时间】:2017-07-16 16:35:03 【问题描述】:我是 Spring 的新手,正在注册一个用户。我确实喜欢这个。
@RequestMapping("/register")
public String register(@ModelAttribute User user,BindingResult result)
if(!result.hasErrors())
userSerive.register(user);
return "welcome";
这很好用,但这里的问题是我的welcome.jsp
页面中不需要这个user
对象,所以为什么要让模型对象更重。所以我尝试不使用@ModelAttribute
,这也适用于我,如下所示.
@RequestMapping("/register")
public String register(User user,BindingResult result)
if(!result.hasErrors())
userSerive.register(user);
return "welcome";
所以我只想知道两者的优缺点和如果我真的不需要jsp
中的user
对象,这是最佳实践。是@ModelAttribute
需要除了将对象添加到模型之外,还有哪些 spring 隐式绑定没有。@ModelAttribute
是更安全的绑定方式还是其他方式?
我想将我的查询分类为以下 4 种类型的请求。如果我不需要在视图中发送数据并且我的请求是以下任何一种,那么使用和不使用 @ModelAttribute
会有什么区别-
-
查询字符串,即GET中的表单数据
请求有效负载或正文,即 POST 中的表单数据
ajaxified GET 请求中的 json 数据
POST 请求中的 json 数据 - 我想这不会在两者中的任何一个中绑定。
@RequestBody
为必填项。
【问题讨论】:
你不能在这个问题上开始赏金,因为赏金每次都必须升值,下一个增量是 100 代表。 【参考方案1】:在您的情况下,两个方法签名之间的行为可能(见下文...)没有区别。
两者都将请求参数绑定到user
,并将生成的对象作为属性user
添加到模型中——该属性名称派生自方法参数的非大写类型名称User
。
@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));
如果您要在中间添加自己的,例如UserHandlerMethodArgumentResolver
,然后您可以使用 @ModelAttribute
告诉 Spring 以默认方式处理特定参数,而不是使用您的自定义参数解析器类。
【讨论】:
这是 OP 问题的答案。【参考方案2】:这个问题很有用,但是我看这里的回复没有正确回答这个问题。
我阅读了 *** 中的更多线程,发现这个非常有用: https://***.com/a/26916920/1542363
对于我自己如何决定使用哪一个,如果我只需要绑定并且不想将参数对象存储在模型中,那么不要使用@ModelAttribute
。
【讨论】:
除了发送到jsp之类的视图之外,我还没有找到将参数对象存储在模型中的任何原因。是的,我的问题是关于是否有任何其他原因。【参考方案3】:除了将对象添加到模型之外,Spring MVC 还使用它将绑定对象提供给控制器方法,您可以在其中使用它,在您的情况下“注册”。
是的,@ModelAtttribute 是 Spring MVC 中将传入的帖子数据绑定到对象的最安全和最好的方法。
【讨论】:
【参考方案4】:查看此帖子here。它涵盖了有关 ModelAttribute 的大量细节。
ModelAttribute 只能与表单编码的请求数据一起使用。它无法将 json/xml 请求数据与数据对象绑定。为此,您必须使用 RequestBody。
【讨论】:
【参考方案5】:除了@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】:查看当前 (Spring 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
。
【讨论】:
【参考方案7】:如 Spring MVC 文档中所述 - @ModelAttribute 注解可用于方法或方法参数。当然,我们可以在一个控制器中同时使用两者。
方法注释
@ModelAttribute("person")
public Person getPerson()
return new Person();
这种方法的目的是在模型中添加属性。所以在我们的例子中,person 键将 person 对象作为模型中的值。在同一控制器中,在 @RequestMapping 方法之前调用控制器中的 @ModelAttribute 方法。
方法参数
public String processForm(@ModelAttribute("person") Person person)
person.getStuff();
参见 spring 文档http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args
【讨论】:
您缺少上下文。根据我的用例,我不需要视图层中的模型,我可以使用和不使用@ModelAttribute
在 java 中绑定 formdata,如果我们不需要,这两种方法有什么区别这个模型在 jsp 中。以上是关于Spring:绑定对象有和没有@ModelAttribute的主要内容,如果未能解决你的问题,请参考以下文章
java问题:有个类Student Student stu=null 与Student stu= new Student()有和区别