如何让Spring @RestController接受JSON格式的参数而不是www-form-urlencoded?

时间:2015-08-01 00:56:58

标签: javascript java json spring-mvc spring-restcontroller

在JDK 1.8上使用Spring 4.1.7,我有一个@RestController类,如下所示:

@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向/ rest / servicea发送POST时,一切正常,我看到了值" 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类中遗漏了一些内容,要求它解析JSON而不是期待w​​ww-urlencoded数据。

我尝试更改@RequestMapping方法上的serviceA注释,以添加consumes="application/json"属性,但这没有效果。

使用JSON而不是POST正文中的urlencoded数据,我可以更改哪些内容?

2 个答案:

答案 0 :(得分:3)

@RequestParam javadoc状态

  

注释,指示应绑定方法参数   Web请求参数。

这是通过请求参数的各种ServletRequest方法检索的。例如,ServletRequest#getParameterMap()表示

  

请求参数是随请求一起发送的额外信息。对于   HTTP servlet,参数包含在查询字符串中或已发布   表格数据。

在您的第二个片段中,您也不会发送任何内容。您正在请求正文中发送JSON。

Spring有一个机制(它有许多,也是自定义的机制),用于将数据反序列化为您期望的数据。标准解决方案是@RequestBody,假设您有一个可以处理JSON的适当注册的HttpMessageConverter。如果类路径上有Jackson 2,则Spring会自动注册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 ...;
}

杰克逊允许您通过注释或通过ObjectMapper的配置来定义如何处理缺席值。

此处不涉及

@RestController。正如其javadoc所述,

  

带有此注释的类型被视为控制器所在的位置   @RequestMapping方法默认采用@ResponseBody语义。

答案 1 :(得分:0)

在我看来,您此时正在传递一个JSON对象,而不是一组参数,因此Spring无法与您发送给您提供的任何参数的内容相匹配。 / p>

尝试

@RequestBody List<ListUnit> listOfUnits

而不是@RequestParam