春天:@ModelAttribute VS @RequestBody
Posted
技术标签:
【中文标题】春天:@ModelAttribute VS @RequestBody【英文标题】:Spring: @ModelAttribute VS @RequestBody 【发布时间】:2014-03-16 10:47:49 【问题描述】:如果我错了,请纠正我。 两者都可用于数据绑定。
问题是什么时候使用@ModelAttribute?
@RequestMapping(value="/owners/ownerId/pets/petId/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute Pet pet)
另外,什么时候使用@RequestBody?
@RequestMapping(value = "/user/savecontact", method = RequestMethod.POST
public String saveContact(@RequestBody Contact contact)
据我了解,两者的目的相似。
谢谢!!
【问题讨论】:
【参考方案1】:如果你使用ModelAttribute注解,你可以在view layer中直接访问你的“pet”对象。此外,您可以在控制器上的方法中实例化此对象以放置模型。 see this。
ModelAttribute 让您有机会使用此对象的部分,但使用 RequestBody,您可以获得所有请求正文。
【讨论】:
【参考方案2】:@ModelAttribute
用于绑定来自请求参数的数据(在键值对中),
但@RequestBody
用于绑定来自整个请求体的数据,如 POST、PUT.. 包含其他格式(如 json、xml)的请求类型。
【讨论】:
JSON 也是 key value only ,JSON 数据与请求参数有何不同?【参考方案3】:据我了解,最简单的方法是,@ModelAttribute
将采用查询字符串。因此,所有数据都通过 url 传递到服务器。
对于@RequestBody
,所有的数据都会通过一个完整的JSON体传递给服务器。
【讨论】:
简单地说@RequestBody 指定了请求的主体。 @ResponseBody 指定响应的正文。 @ModelAttribute 和 @RequestParam 用于从 URL 解码查询参数。唯一的区别是 @modelAttribute 将绑定所有字段并给出一个完整的对象。但是如果您使用 @RequestParam 您已经通过手动映射所有字段来构建整个对象。欲了解更多信息see here ModelAttribute 和 RequestParam 用于从 URL 解码查询参数 - 那么 Get 和 Post HTTP 方法有什么用?使用 Post ,您的参数不会在 URL 中发送 @CharlesC - 所以 ModelAttribute 将从请求正文(使用 POST 方法)中以键值对字符串的形式选择数据,而 RequestBody 将选择 JSON 格式的数据?【参考方案4】:我发现@RequestBody(也将类注释为@RestController)更适合AJAX请求,您可以完全控制发出的请求的内容并且内容以XML或JSON的形式发送(因为Jackson) .这允许内容轻松创建模型对象。相反,@ModelAttribute 似乎更适合有支持表单的“命令”对象(可能不一定是模型对象)的表单。
【讨论】:
【参考方案5】:我认为@ModelAttribute 和@RequestBody 都有相同的用途,只有区别 @ModelAttribute 用于普通 Spring MVC,@RequestBody 用于 REST Web 服务。它是@PathVariable 和@PathParam。但在这两种情况下,我们都可以混合使用。我们可以在 REST 中使用 @PathVariable,反之亦然。
【讨论】:
【参考方案6】:如果你想上传文件,你必须使用@ModelAttribute
。使用@RequestBody
,这是不可能的。示例代码
@RestController
@RequestMapping(ProductController.BASE_URL)
public class ProductController
public static final String BASE_URL = "/api/v1/products";
private ProductService productService;
public ProductController(ProductService productService)
this.productService = productService;
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public ProductDTO createProduct(@Valid @ModelAttribute ProductInput productInput)
return productService.createProduct(productInput);
ProductInput 类
@Data
public class ProductInput
@NotEmpty(message = "Please provide a name")
@Size(min = 2, max = 250, message = "Product name should be minimum 2 character and maximum 250 character")
private String name;
@NotEmpty(message = "Please provide a product description")
@Size(min = 2, max = 5000, message = "Product description should be minimum 2 character and maximum 5000 character")
private String details;
@Min(value = 0, message = "Price should not be negative")
private float price;
@Size(min = 1, max = 10, message = "Product should have minimum 1 image and maximum 10 images")
private Set<MultipartFile> images;
【讨论】:
我也确认了 您能否详细说明请求调用的外观?我正在发送一个带有图像的请求,但我的对象中得到了空值。 @AhmedAziz 我的对象中也有空值,你能帮我解决这个问题吗【参考方案7】:使用@ModelAttribute,您可以在URL 参数中传递数据,而使用@RequestBody,您可以将其作为JSON 正文传递。如果您正在制作 REST API,那么最好使用 @RequestBody。在大多数 youtube 教程中,您可能会发现使用 @ModelAttribute - 这仅仅是因为它们可能正在演示有关 Spring MVC 的概念并使用 URL 来传递数据。
【讨论】:
是否在 URL 参数中传递数据取决于使用的 HTTP 方法而不是 @ModelAttribute 使用 Post ,参数不会在 URL 中传递,而是在请求正文中传递【参考方案8】:我们需要使用以下 jsp 标签来将您的实体数据绑定到 jsp 表单字段: 表单来自spring标签库: 以下不是完整的html,但我希望你能自我介绍:
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<form:form action="save" method="post" modelAttribute="patient">
<table>
<tr>
<td>Name</td>
<td>
<form:input path="patient.patient_name" /> <br />
</td>
</tr>
<tr>
<td>Phone</td>
<td>
<form:input path="patient.phone_number" /> <br />
</td>
</tr>
<tr>
<td colspan="2"><button type="submit">Submit</button></td>
</tr>
</table>
</form:form>
表单必须被处理两次,一次是在渲染表单之前,在此期间我们需要为属性值modelAttribute="patient"
提供适当的bean实例化。
-
为此,控制器类(在类定义级别)您需要有
@RequestMapping
注释。
你需要有handler方法参数如下
@GetMapping("logincreate")
public String handleLoginCreate(@ModelAttribute("login") Login login, Model model)
System.out.println(" Inside handleLoginCreate ");
model.addAttribute("login",login);
return "logincreate";
Spring 将扫描所有处理程序方法@ModelAttribute
并使用 Login 类的默认构造函数对其进行实例化,并调用其所有 getter 和 setter(用于从表单到“登录”的 jsp 绑定)。如果缺少以下任何一项,jsp都不会显示,会抛出各种异常
-
getter/setter
默认构造函数
model.addAttribute("login",login);
类级别@RequestMapping
方法参数级别@ModelAttribute
另外,jsp中action的handler方法,如上式action="save"
,handler方法也可能是这样的:
@PostMapping("save")
public String saveLoginDetails(@ModelAttribute("login") Login login, Model model)
//write codee to insert record into DB
System.out.println(" Inside save login details ");
System.out.println("The login object is " + login.toString());
System.out.println("The model object contains the login attribute"+ model.getAttribute("login"));
loginService.saveLogin(login);
return "welcome";
重要的学习是:
-
在启动表单之前,spring应该有适当的注解来指示表单的backing bean,在上面的例子中,“backing bean”或“binding object”是Login login,带有适当的handler方法的参数注解
@ModelAttribute("login") Login login
【讨论】:
以上是关于春天:@ModelAttribute VS @RequestBody的主要内容,如果未能解决你的问题,请参考以下文章