【问题标题】:"HttpMessageNotReadableException Required request body is missing" when trying to make a post request尝试发出发布请求时出现“HttpMessageNotReadableException 所需的请求正文丢失”
【发布时间】:2017-10-03 23:32:04
【问题描述】:

我有一个控制器类,其中包含一些方法,其中一种方法应该接受 POST 请求并使用该 POST 请求正文中的 JSON 创建一个新帐户。

当我尝试使用 curl 发出 POST 请求时,我收到 错误提示

{"timestamp":1493988808871,"status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Required request body is missing: org.springframework.http.ResponseEntity<?> com.example.AccountRestController.add(java.lang.String,java.lang.String)","path":"/users/add"}

我正在使用的 curl 命令

curl -X POST --data '{"userName":"bepis", "password":"xyz"}' -H "Content-Type:application/json" http://localhost:8080/users/add

AccountRestController

@RequestMapping(method = RequestMethod.POST, value = "/add", produces = { MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> add(@RequestBody String username, @RequestBody String password) {
    Account result = accountRepository.save(new Account (username, password));
    return new ResponseEntity<>(result, HttpStatus.CREATED);
}

【问题讨论】:

  • 换成ResponseEntity&lt;?&gt; add(@RequestParam("userName") String userName, @RequestParam("password") String password)怎么办?

标签: java spring-mvc


【解决方案1】:

您不能使用多个@RequestBody。您需要将所有内容包装到一个类中,该类将用于匹配您的请求正文。

here也有同样的回答。

还有一个 JIRA issue 表示被拒绝的功能请求。

注意:如果你想少写,你可以用@PostMapping代替@RequestMapping(method = RequestMethod.POST)

注意: @RequestParam@PathVariable 用于从 URI 而非正文中提取数据。

注意:同样适用于来自ASP.NET WebAPI 的等效[FromBody] 属性。

完整示例:

下面我创建了一个与您的案例类似的工作示例:

请求 DTO

public class AccountCreateRequest {

    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

响应 DTO

public class AccountCreateResponse {

    private String userName;
    private String password;

    public AccountCreateResponse() {
    }

    public AccountCreateResponse(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

控制器

@RestController
@RequestMapping("/v1/account")
public class AccountController {

    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseStatus(HttpStatus.CREATED) AccountCreateResponse add(@RequestBody() AccountCreateRequest account) {
        AccountCreateResponse response = new AccountCreateResponse(account.getUserName(), account.getPassword());
        return response;
    }
}

卷曲请求

curl -X POST --data '{"userName":"bepis", "password":"xyz"}' -H "Content-Type:application/json" http://localhost:8080/v1/account

【讨论】:

  • 感谢您让我发出 POST 请求,但用户名和密码的变量始终为空。我将方法参数更改为 @RequestBody 帐户输入
  • @LightningJimmyJoeJohnson 看看我上次的编辑。我为您提供了一个与您需要的类似的工作示例。
  • 为什么有两个不同的类?为什么不使用 AccountCreateResponse,因为它们在功能上是相同的。
  • 只是指出请求和响应对象的一个​​例子。你可以随意使用。通常我为请求和响应创建单独的 DTO,因为可以处理复杂的业务场景,而且在大多数情况下,就我而言,我遇到这两个是不同的。这引入了复杂性但更灵活。如果适用于您的情况,您可以使用相同的类。
【解决方案2】:

所以我将 @Requestbody 更改为单个 @RequestBody,就像 andreim 所说的那样,它修复了我的错误请求错误,但由于某种原因,帐户用户名始终是 null 发布请求通过时。

我搞砸了一些事情,最终导致我从

交换了 Account 构造函数参数的顺序
Account(String username, String password)

Account(String password, String username)

这出于某种原因起作用,让我使用正确的值发出我的帖子请求。后来出于好奇,我决定将参数交换回Account(String username, String password) 并且发布请求仍然按预期工作。

我不知道我做了什么来摆脱 null 问题,但它似乎已经奏效了。

【讨论】:

    猜你喜欢
    • 2022-06-24
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 2020-05-06
    相关资源
    最近更新 更多