Spring:@ModelAttribute VS@RequestBody

如果我说错了,请纠正我。 两者都可以用于 数据绑定

问题是何时使用@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){ }

据我所知,两者的目的是一样的。

谢谢!

55225 次浏览

如果使用 ModelAttribute注释,您可以直接访问 视图层中的“ pet”对象。此外,您可以在控制器上的方法中实例化此对象,以放置您的模型。看这个.

ModelAttribute 为您提供了使用这个对象部分的机会,但是使用 RequestBody,您可以获得所有请求体。

@ModelAttribute用于绑定来自请求参数的数据(以键值对的形式) ,

but @RequestBody is used for binding data from whole body of the request like POST,PUT.. request types which contains other format like json, xml.

对于我的理解,最简单的方法是,@ModelAttribute将接受一个查询字符串。因此,所有数据都通过 URL 传递到服务器。

对于 @RequestBody,所有数据都将通过一个完整的 JSON 主体传递给服务器。

我发现@RequestBody (也将一个类注释为@RestController)更适合 AJAX 请求,因为它可以完全控制发出的请求的内容,并且内容以 XML 或 JSON (因为 Jackson)的形式发送。这使得内容可以轻松地创建模型对象。相反,@ModelAttribute 似乎更适合有“命令”对象支持表单的表单(这可能不一定是模型对象)。

我认为@ModelAttribute 和@RequestBody 有着相同的用途,只是有所不同 是@ModelAttribute 用于普通的春季 MVC,@RequestBody 用于 REST Web 服务。它是“路径变量”和“路径参数”。但在这两种情况下,我们可以混合使用。我们可以在 REST 中使用@Pathvariable,反之亦然。

如果你想做文件上传,你必须使用 @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;
}

使用@ModelAttribute,可以在 URL 参数中传递数据,使用@RequestBody,可以将数据作为 JSON 主体传递。如果您正在制作一个 REST API,那么最好使用@RequestBody。在大多数 youtube 教程中,你可能会发现使用@ModelAttribute ——这仅仅是因为它们可能演示了有关 Spring MVC 的概念,并使用 URL 来传递数据。

我们需要使用以下 jsp 标记将您的实体绑定到 jsp 表单字段:
这个表单来自 spring tag 库:
下面是不完整的 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 实例化。

  1. 为此,控制器类(在类定义级别)需要有 @RequestMapping注释。
  2. 您需要具有如下的处理程序方法参数
@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 (用于从 form 到“ Login”的 jsp 绑定)。如果没有显示以下任何一个 jsp,则会抛出各种异常

  1. 获得者/接收者
  2. 缺省构造函数
  3. AddAttribute (“ login”,login) ;
  4. 类级别@RequestMapping
  5. 方法参数 level@ModelAttribute

此外,jsp 中的处理程序操作方法,以上表单中的 action="save",以及处理程序方法可能看起来如下:

@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";
}

重要的学习是:

  1. 在启动表单之前,Spring 应该有适当的注释来指示表单的后台 bean,在上面的例子中,“后台 bean”或“绑定对象”是带有适当处理程序方法的参数注释 @ModelAttribute("login") Login login的 Login 登录