admin管理员组

文章数量:1332359

Using Spring 4.1.7 on JDK 1.8, I have an @RestController class that looks like this:

@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:

    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:

    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.

I tried changing the @RequestMapping annotation on the serviceA method to add the consumes="application/json" attribute, but that had no effect.

What can I change to make this work, using JSON rather than urlencoded data in the POST body?

Using Spring 4.1.7 on JDK 1.8, I have an @RestController class that looks like this:

@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:

    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:

    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.

I tried changing the @RequestMapping annotation on the serviceA method to add the consumes="application/json" attribute, but that had no effect.

What can I change to make this work, using JSON rather than urlencoded data in the POST body?

Share Improve this question edited Aug 1, 2015 at 1:33 Sotirios Delimanolis 280k62 gold badges713 silver badges737 bronze badges asked Aug 1, 2015 at 0:56 JaredJared 26.1k25 gold badges86 silver badges114 bronze badges 1
  • It seems you've misunderstood what a request parameter represents. It's either a query parameter or a form parameter. You're not sending either in your second example. – Sotirios Delimanolis Commented Aug 1, 2015 at 1:14
Add a ment  | 

2 Answers 2

Reset to default 3

The @RequestParam javadoc states

Annotation which indicates that a method parameter should be bound to a web request parameter.

This is retrieved through the various ServletRequest methods for request parameters. For example, ServletRequest#getParameterMap() which states

Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.

In your second snippet, you aren't sending either. You're sending JSON in the request body.

Spring has a mechanism (it has many, and custom ones) for deserializing that into the data you expect. The standard solution is @RequestBody, assuming you have an appropriately registered HttpMessageConverter that can handle the JSON. Spring automatically registers MappingJackson2HttpMessageConverter if you have Jackson 2 on the classpath, which can correctly deserialize JSON into Java POJO types.

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

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

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.

@RestController is not involved here. As its javadoc states,

Types that carry this annotation are treated as controllers where @RequestMapping methods assume @ResponseBody semantics by default.

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.

Try

@RequestBody List<ListUnit> listOfUnits

instead of @RequestParam

本文标签: