使用Spring Boot我使用单一资源构建玩具REST服务,如下所示:
@RestController
@RequestMapping("/checkout")
public class CheckoutRestController {
@PostMapping("/book")
public boolean buyBook(@RequestParam CreditCard creditCard, @RequestParam ShippingAddress shippingAddress) {
return true;
}
}
CreditCard
和ShippingAddress
都是我编写过的POJO(普通的旧Java对象)。
我尝试使用此有效负载发布到此端点:
{
"creditCard" : {
"nameOnCard":"foo",
"number":12345678,
"expiryMonth":12,
"expiryYear":2018,
"ccv":100
},
"shippingAddress" : {
"steert":"foor",
"houseNumber":"1a",
"city":"bar",
"state":"bazz",
"country":"buzz",
"zipCode":"booz"
},
}
但是我收到了一个错误:
{
"timestamp": "2018-03-13T11:36:52.745+0000",
"status": 400,
"error": "Bad Request",
"message": "Required CreditCard parameter 'creditCard' is not present",
"path": "/checkout/book"
}
我知道一种解决方法是将两个POJO包装在一个请求包装器中,但除非我真的需要,否则我不愿意。
是否可以发布两个@RequestParam注释对象?如果是这样,JSON会是什么样的?
答案 0 :(得分:5)
@RequestParam
参数是查询参数,而不是正文参数。
这意味着你的方法:
@PostMapping("/book")
public boolean buyBook(@RequestParam CreditCard creditCard, @RequestParam
ShippingAddress shippingAddress) {
return true;
}
期待以下请求:
POST /checkout/book?creditCard=<...>&shippingAddress=<...>
但是,Spring不知道如何将String
查询参数转换为CreditCard
或ShippingAddress
。
您可以通过实施Converter
来解决此问题,如下所示:
public class StringToCreditCardConverter implements Converter<String, CreditCard> {
@Override
public CreditCard convert(String source) {
<...>
}
}
但是,我不建议这样做。
相反,我建议您执行以下操作:
@PostMapping("/book")
public boolean buyBook(@RequestBody BookCreationRequest bookCreationRequest) {
CreditCard creditCard = bookCreationRequest.getCreditCard();
ShippingAddress shippingAddress = bookCreationRequest.getShippingAddress();
...
}
bookCreationRequest
包含CreditCard
和ShippingAddress
字段:
public class BookCreationRequest {
private ShippingAddress shippingAddress;
private CreditCredit creditCard;
public ShippingAddress getShippingAddress() {...}
public CreditCard getCreditCard() {...}
public BookCreationRequest(ShippingAddress shippingAddress, CreditCard creditCard) {
this.creditCard = creditCard;
this.shippingAddress = shippingAddress;
}
然后期望JSON请求如下:
POST /checkout/book
Payload:
{
"creditCard": {
...
},
"shippingAddress": {
...
}
}
请注意,请求中只能有一个@RequestBody
参数。
答案 1 :(得分:2)
是 - 创建一个包装器Request对象。 这不是一种解决方法 - 它实际上是推荐的方法。
你在json中看到了:
{ //wrapper
{}, //first complex data object / mapped to pojo
{} //second complex data object / mapped to pojo
}
1)您可以使用@Valid
轻松地将验证应用于Request对象,从而验证两个POJO。
2)您不必担心有效载荷中的顺序。
3)您错误地使用了@RequestParam
。 @RequestBody
映射整个POST有效负载。您必须删除@RequestParam
注释,然后使用@RequestBody
。