简体   繁体   English

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

[英]How can I get a Spring @RestController to accept parameters in JSON format rather than www-form-urlencoded?

Using Spring 4.1.7 on JDK 1.8, I have an @RestController class that looks like this: 在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);
}

When I send a POST to /rest/servicea from a javascript like this, everything works, and I see the values "a", "b", and "c" printed in my log: 当我从这样的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 
    })

However, when I try to change the call from the javascript to this (to change the protocol to REST rather than www-urlencode), I get the default values (defaultParmA, defaultParmB, defaultParmC) in my log: 但是,当我尝试将调用从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 
    })

I think I'm missing something in the @RestController class to get it to parse the JSON rather than expecting www-urlencoded data. 我想我在@RestController类中缺少一些东西来让它解析JSON,而不是期望使用www-urlencoded数据。

I tried changing the @RequestMapping annotation on the serviceA method to add the consumes="application/json" attribute, but that had no effect. 我尝试更改serviceA方法上的@RequestMapping批注以添加consumes="application/json"属性,但这没有任何效果。

What can I change to make this work, using JSON rather than urlencoded data in the POST body? 使用JSON而不是POST正文中的经过urlencoded的数据,我可以做些什么更改以使其起作用?

The @RequestParam javadoc states @RequestParam javadoc状态

Annotation which indicates that a method parameter should be bound to a web request parameter. 指示方法参数应绑定到Web请求参数的注释。

This is retrieved through the various ServletRequest methods for request parameters. 可通过各种ServletRequest方法获取请求参数。 For example, ServletRequest#getParameterMap() which states 例如, 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. 对于HTTP Servlet,参数包含在查询字符串或发布的表单数据中。

In your second snippet, you aren't sending either. 在第二个片段中,您都不发送任何一个。 You're sending JSON in the request body. 您正在请求正文中发送JSON。

Spring has a mechanism (it has many, and custom ones) for deserializing that into the data you expect. Spring有一种机制(有很多和自定义的),可以将其反序列化为所需的数据。 The standard solution is @RequestBody , assuming you have an appropriately registered HttpMessageConverter that can handle the JSON. 标准解决方案是@RequestBody ,假设您具有可以正确处理JSON的适当注册的HttpMessageConverter Spring automatically registers MappingJackson2HttpMessageConverter if you have Jackson 2 on the classpath, which can correctly deserialize JSON into Java POJO types. 如果您在类路径上具有Jackson 2,Spring会自动注册MappingJackson2HttpMessageConverter ,它可以正确地将JSON反序列化为Java POJO类型。

The documentation gives a number of examples and explains how you would use it. 文档提供了许多示例,并说明了如何使用它。 With JSON, you could define a POJO type with fields that correspond to the ones you send 使用JSON,您可以使用与您发送的字段相对应的字段来定义POJO类型

class RequestPojo {
    private String paramA;
    private String paramB;
    private String paramC;
    // and corresponding getters and setters
}

and add a @RequestBody annotated parameter of this type to your handler method 并将此类型的@RequestBody注释的参数添加到您的处理程序方法中

public ServiceAResponse serviceA(@RequestBody RequestPojo pojo) {
    pojo.getParamB(); // do something
    return ...;
}

Jackson lets you define, through annotations or through configuration of the ObjectMapper , how to deal with absent values. Jackson允许您通过注释或通过ObjectMapper配置来定义如何处理缺少的值。

@RestController is not involved here. @RestController不在此处。 As its javadoc states, 如其javadoc所述,

Types that carry this annotation are treated as controllers where @RequestMapping methods assume @ResponseBody semantics by default. 带有此注释的类型被视为控制器,其中@RequestMapping方法默认情况下采用@ResponseBody语义。

It looks to me like you are passing a single JSON object at this point, rather than a set of parameters, hence Spring cannot match what you're sending to any of the parameters you've provided. 在我看来,您此时正在传递单个JSON对象,而不是一组参数,因此Spring无法将您发送的内容与您提供的任何参数进行匹配。

Try 尝试

@RequestBody List<ListUnit> listOfUnits

instead of @RequestParam 而不是@RequestParam

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM