简体   繁体   English

Spring MVC控制器方法返回400(错误请求)以响应jQuery ajax请求

[英]Spring MVC controller method returns 400 (bad request) in response to jQuery ajax request

I'm sending a jQuery ajax request to a Spring MVC controller method and getting the following response: 我正在向Spring MVC控制器方法发送jQuery ajax请求,并得到以下响应:

 { "timestamp" : "2016-02-10T23:47:14.770+0000",
 "status" : 400,↵  "error" : "Bad Request",
 "exception" : "org.springframework.http.converter.HttpMessageNotReadableException",
"message" : "Bad Request",
"path" : "/chart/add" }

This is the request: 这是请求:

$.ajax({
    type : "POST",
    contentType : "application/json; chartset=utf-8",
    url : "/chart/add",
    data : '{"id":"1","title":"ajax","description":"ajax"}',
    dataType : 'json',
    timeout : 100000,
    success : function(data) {
        console.log("SUCCESS: ", data);
    },
    error : function(e) {
        console.log("ERROR: ", e);
    },
    done : function(e) {
        console.log("DONE");
    }
});

And the following is the spring controller method: 以下是弹簧控制器方法:

@Controller
public class DatasetController {

    @Autowired private DatasetRepository datasetRepository;
    @Autowired private ChartSpecRepository chartSpecRepository;
    @Autowired private CustomerRepository customerRepository;
    @Autowired private ObjectMapper objectMapper;

    @RequestMapping(value="chart/add", method=RequestMethod.POST)
    public ModelAndView newChart(@RequestBody String json) {
        try {
            ModelAndView ret = new ModelAndView("chart");
            ObjectNode node = objectMapper.readValue(json, ObjectNode.class);
            ChartSpec chart = new ChartSpec();
            NewChartRequest request = objectMapper.convertValue(node, NewChartRequest.class);
            ChartSpec.ChartType chartType = toEnum(request.getChartType());
            String datasetName = request.getDatasetName();
            String customerId = request.getCustomerId();
            Integer bins = request.getBins();
            String[] columns = request.getColumns();
            CustomerDataset dataset = datasetRepository
                .findByCustomerIdAndName(customerId, datasetName);

            chart.setChartType(chartType);
            chart.setDatasetId(dataset.getId());
            chart.setColumns(columns);
            chart.setOptions(request.getOptions());
            chart.setBins(bins);

            if(chartType == ChartSpec.ChartType.HISTOGRAM && bins != null && columns.length > 0) {
                ret.addObject("dataset", histogram(dataset, bins, columns[0]));
            } else if(chartType == ChartSpec.ChartType.BAR && columns.length > 0) {
                ret.addObject("dataset", barChart(dataset, columns[0]));
            } else if(chartType == ChartSpec.ChartType.LINE && columns.length > 2) {
                ret.addObject("dataset", dataset.getColumns(columns[0], columns[1]));
            }

            if(ret.getModel().isEmpty())
                return new ModelAndView("error");

            chartSpecRepository.save(chart);
            return ret;

        } catch(JsonMappingException jme) {
            return new ModelAndView("error");
        } catch(JsonParseException jpe) {
            jpe.printStackTrace();
            return new ModelAndView("error");
        } catch(IOException ioe) {
            return new ModelAndView("error");
        }   
    }
}

The other posts I've seen on this topic seem to revolve around accidentally using @RequestParam instead of @ResquestBody, or not stringifying the JSON. 我在该主题上看到的其他帖子似乎围绕着意外地使用@RequestParam而不是@ResquestBody或不对JSON进行字符串化。 The ajax method above uses literal json instead of the stringified object I intend to use, just to rule out the possibility that the Json is incorrect. 上面的ajax方法使用文字json而不是我打算使用的字符串化对象,只是为了排除Json错误的可能性。

Interestingly, if I use 有趣的是,如果我使用

$.post("/chart/add", '{"id":"1","title":"ajax","description":"ajax"}')

the request goes through. 请求通过。 However, I'd like to get a sense of what I'm doing wrong in the ajax method, because I'd like to be able to specify my requests precisely. 但是,我想了解一下我在ajax方法中做错了什么,因为我希望能够精确地指定我的请求。

Regarding the specific exception thrown, HttpMessageNotReadableException, the Spring documentation says the following: 关于抛出的特定异常HttpMessageNotReadableException,Spring文档说如下:

Thrown by HttpMessageConverter implementations when the HttpMessageConverter.read(java.lang.Class, org.springframework.http.HttpInputMessage) method fails. 当HttpMessageConverter.read(java.lang.Class,org.springframework.http.HttpInputMessage)方法失败时,由HttpMessageConverter实现抛出。

However, I don't particularly follow the documentation after that point. 但是,在那之后,我不再特别关注文档。 Please let me know if I need to provide further information. 如果需要提供更多信息,请告诉我。 Any help is appreciated. 任何帮助表示赞赏。

Your problem is that you are forcing the content-type in your ajax call. 您的问题是您要在ajax调用中强制使用内容类型。

contentType : "application/json; chartset=utf-8"

As your controller is accepting a String object, the representation is incorrect. 由于您的控制器正在接受String对象,因此表示形式不正确。

you should either change your @RequestBody String json to a real object, using @RequestBody Document document or remove the content-type from your ajax call 您应该使用@RequestBody Document document@RequestBody String json更改为真实对象,或者从ajax调用中删除内容类型

I'd advice creating an object to avoid having to parse the json in your controller 我建议创建一个对象,以避免必须解析控制器中的json

your object could look something like this : 您的对象可能看起来像这样:

public class Document{
    int id;
    String title;
    String description;
    //getters /setters
}

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

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