我怎样才能让 Spring @RestController 接受 JSON 格式的参数而不是 www-form-urlencoded?
How can I get a Spring @RestController to accept parameters in JSON format rather than www-form-urlencoded?
在 JDK 1.8 上使用 Spring 4.1.7,我有一个 @RestController class 看起来像这样:
@RestController
public class ServiceAController {
public static final Logger LOG = Logger.getLogger(ServiceAController.class);
@RequestMapping(value="/rest/servicea", method=RequestMethod.POST)
public ServiceAResponse serviceA(@RequestParam(value="parmA", defaultValue="defaultParmA") String parmA,
@RequestParam(value="parmB", defaultValue="defaultParmB") String parmB,
@RequestParam(value="parmC", defaultValue="defaulParmC") String parmC) {
LOG.info("Inside Service A handler: " + parmA + " B: "+ parmB + " C: "+ parmC);
}
当我像这样从 javascript 发送 POST 到 /rest/servicea 时,一切正常,我看到值 "a"、"b",并且 "c" 打印在我的日志中:
var data = {
"parmA": "a",
"parmB": "b",
"parmC": "c"
}
$.ajax({
type: "POST",
url: "./rest/servicea",
contentType: "application/x-www-form-urlencoded",
data: data,
dataType: "json",
success: submitAuthSuccess,
error: submitAuthFailure
})
但是,当我尝试将调用从 javascript 更改为此(将协议更改为 REST 而不是 www-urlencode)时,我得到了默认值(defaultParmA、defaultParmB、defaultParmC)我的日志:
var data = {
"parmA": "a",
"parmB": "b",
"parmC": "c"
}
$.ajax({
type: "POST",
url: "./rest/servicea",
contentType: "application/json",
data: JSON.stringify(data),
dataType: "json",
success: submitAuthSuccess,
error: submitAuthFailure
})
我想我在 @RestController class 中遗漏了一些东西来让它解析 JSON 而不是期待 www-urlencoded 数据。
我尝试更改 serviceA
方法上的 @RequestMapping
注释以添加 consumes="application/json"
属性,但没有效果。
在 POST 正文中使用 JSON 而不是 urlencoded 数据,我可以更改什么来使这项工作正常进行?
在我看来,您此时正在传递单个 JSON 对象,而不是一组参数,因此 Spring 无法匹配您发送给任何参数的内容你已经提供了。
尝试
@RequestBody List<ListUnit> listOfUnits
而不是@RequestParam
@RequestParam
javadoc 声明
Annotation which indicates that a method parameter should be bound to
a web request parameter.
这是通过请求参数的各种 ServletRequest
方法检索的。例如,ServletRequest#getParameterMap()
表示
Request parameters are extra information sent with the request. For
HTTP servlets, parameters are contained in the query string or posted
form data.
在你的第二个片段中,你也没有发送。您正在请求正文中发送 JSON。
Spring 有一种机制(它有很多自定义机制)可以将其反序列化为您期望的数据。如果类路径上有 Jackson 2,标准解决方案是 @RequestBody
, assuming you have an appropriately registered HttpMessageConverter
that can handle the JSON. Spring automatically registers MappingJackson2HttpMessageConverter
,它可以正确地将 JSON 反序列化为 Java POJO 类型。
documentation 给出了一些示例并解释了如何使用它。使用 JSON,您可以定义一个 POJO 类型,其中包含与您发送的字段相对应的字段
class RequestPojo {
private String paramA;
private String paramB;
private String paramC;
// and corresponding getters and setters
}
并将此类型的 @RequestBody
注释参数添加到您的处理程序方法
public ServiceAResponse serviceA(@RequestBody RequestPojo pojo) {
pojo.getParamB(); // do something
return ...;
}
Jackson 允许您通过注释或配置 ObjectMapper
来定义如何处理缺失值。
@RestController
这里不涉及。正如其 javadoc 所述,
Types that carry this annotation are treated as controllers where
@RequestMapping
methods assume @ResponseBody
semantics by default.
在 JDK 1.8 上使用 Spring 4.1.7,我有一个 @RestController class 看起来像这样:
@RestController
public class ServiceAController {
public static final Logger LOG = Logger.getLogger(ServiceAController.class);
@RequestMapping(value="/rest/servicea", method=RequestMethod.POST)
public ServiceAResponse serviceA(@RequestParam(value="parmA", defaultValue="defaultParmA") String parmA,
@RequestParam(value="parmB", defaultValue="defaultParmB") String parmB,
@RequestParam(value="parmC", defaultValue="defaulParmC") String parmC) {
LOG.info("Inside Service A handler: " + parmA + " B: "+ parmB + " C: "+ parmC);
}
当我像这样从 javascript 发送 POST 到 /rest/servicea 时,一切正常,我看到值 "a"、"b",并且 "c" 打印在我的日志中:
var data = {
"parmA": "a",
"parmB": "b",
"parmC": "c"
}
$.ajax({
type: "POST",
url: "./rest/servicea",
contentType: "application/x-www-form-urlencoded",
data: data,
dataType: "json",
success: submitAuthSuccess,
error: submitAuthFailure
})
但是,当我尝试将调用从 javascript 更改为此(将协议更改为 REST 而不是 www-urlencode)时,我得到了默认值(defaultParmA、defaultParmB、defaultParmC)我的日志:
var data = {
"parmA": "a",
"parmB": "b",
"parmC": "c"
}
$.ajax({
type: "POST",
url: "./rest/servicea",
contentType: "application/json",
data: JSON.stringify(data),
dataType: "json",
success: submitAuthSuccess,
error: submitAuthFailure
})
我想我在 @RestController class 中遗漏了一些东西来让它解析 JSON 而不是期待 www-urlencoded 数据。
我尝试更改 serviceA
方法上的 @RequestMapping
注释以添加 consumes="application/json"
属性,但没有效果。
在 POST 正文中使用 JSON 而不是 urlencoded 数据,我可以更改什么来使这项工作正常进行?
在我看来,您此时正在传递单个 JSON 对象,而不是一组参数,因此 Spring 无法匹配您发送给任何参数的内容你已经提供了。
尝试
@RequestBody List<ListUnit> listOfUnits
而不是@RequestParam
@RequestParam
javadoc 声明
Annotation which indicates that a method parameter should be bound to a web request parameter.
这是通过请求参数的各种 ServletRequest
方法检索的。例如,ServletRequest#getParameterMap()
表示
Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.
在你的第二个片段中,你也没有发送。您正在请求正文中发送 JSON。
Spring 有一种机制(它有很多自定义机制)可以将其反序列化为您期望的数据。如果类路径上有 Jackson 2,标准解决方案是 @RequestBody
, assuming you have an appropriately registered HttpMessageConverter
that can handle the JSON. Spring automatically registers MappingJackson2HttpMessageConverter
,它可以正确地将 JSON 反序列化为 Java POJO 类型。
documentation 给出了一些示例并解释了如何使用它。使用 JSON,您可以定义一个 POJO 类型,其中包含与您发送的字段相对应的字段
class RequestPojo {
private String paramA;
private String paramB;
private String paramC;
// and corresponding getters and setters
}
并将此类型的 @RequestBody
注释参数添加到您的处理程序方法
public ServiceAResponse serviceA(@RequestBody RequestPojo pojo) {
pojo.getParamB(); // do something
return ...;
}
Jackson 允许您通过注释或配置 ObjectMapper
来定义如何处理缺失值。
@RestController
这里不涉及。正如其 javadoc 所述,
Types that carry this annotation are treated as controllers where
@RequestMapping
methods assume@ResponseBody
semantics by default.