春天:@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的主要内容,如果未能解决你的问题,请参考以下文章

@ModelAttribute运用详解

@ModelAttribute 的使用

spring学习之@ModelAttribute运用详解

Spring MVC @ModelAttribute 方法

spring mvc@ModelAttribute与@SessionAttributes的执行流程

(转)spring学习之@ModelAttribute运用详解