SmartGWT RestDataSource到Spring REST Controller GET返回415错误

问题描述 投票:1回答:1

这个问题整天困扰着我,我在这里花了很多时间,在Google上试图找到正确的答案并尝试许多不同的解决方法。

我有一个在这里定义的Spring MVC控制器:

@RequestMapping(value = "/searchAndCount", method = RequestMethod.GET, produces = "application/json", headers =
{ "Accept=application/json", "Content-Type=application/json" }, consumes = "application/json")
public @ResponseBody
RequestResults<?> searchAndCount(@RequestBody SearchInvoiceDTO searchInvoiceDto)
{
      RequestResults<?> requestResults = invoiceApprovalService.searchAndCount(searchInvoiceDto);
    return requestResults;
}

我知道大多数情况下,简单的参数都可以发送回去,但是在这种情况下,我发现最好将所有搜索条件放在一个对象中并发送过来。这就是为什么我要执行@RequestBody。

根据以前的修复,我确保它具有接受JSON输出可能需要的两个标头。

JSON字符串如下所示:字符串s1 =“ {\” userId \“:3,\” ddUserId \“:301010651,\” customerCode \“:\” QA \“,\” customerId \“:8}”;是的,我已使用Jackson的ObjectMapper工具验证此代码将正确地从此String映射到Object,反之亦然。当我查看POJO时,它确实实现了Serializable,并且确实具有默认构造函数。

Junit测试非常棒,并且确实返回了数据:

MockHttpServletRequestBuilder requestBuilder =
        MockMvcRequestBuilders.get("/invoices/searchAndCount").contentType(MediaType.APPLICATION_JSON)
        .content(test);

    this.mockMvc.perform(requestBuilder).andDo(print());

这确实调用了Controller,从输出中可以看到标头是什么,并且可以看到我实际上返回了很棒的真实数据。因此,我觉得从他的控制者那边我可以做的不多。

对控制器的真正调用来自SmartGWT RestDataSource。

RequestMethod在数据源中定义,这是init方法:

private InvoiceDataSource(String id)
{
    setID(id);
    setClientOnly(false);

    // set up FETCH to use GET requests
    OperationBinding fetch = new OperationBinding();
    fetch.setOperationType(DSOperationType.FETCH);
    fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
    fetch.setDataFormat(DSDataFormat.JSON);
    DSRequest fetchProps = new DSRequest();
    fetchProps.setHttpMethod("GET");
    fetch.setRequestProperties(fetchProps);

    // set up ADD to use POST requests
    OperationBinding add = new OperationBinding();
    add.setOperationType(DSOperationType.ADD);
    add.setDataProtocol(DSProtocol.POSTMESSAGE);
    // ===========================================
    DSRequest addProps = new DSRequest();
    addProps.setHttpMethod("POST");
    add.setRequestProperties(addProps);

    // set up UPDATE to use PUT
    OperationBinding update = new OperationBinding();
    update.setOperationType(DSOperationType.UPDATE);
    update.setDataProtocol(DSProtocol.POSTMESSAGE);
    // ===========================================
    DSRequest updateProps = new DSRequest();
    updateProps.setHttpMethod("PUT");
    // updateProps.setContentType("application/json");
    update.setRequestProperties(updateProps);

    // set up REMOVE to use DELETE
    OperationBinding remove = new OperationBinding();
    remove.setOperationType(DSOperationType.REMOVE);
    DSRequest removeProps = new DSRequest();
    removeProps.setHttpMethod("DELETE");
    remove.setRequestProperties(removeProps);

    // apply all the operational bindings
    setOperationBindings(fetch, add, update, remove);

    init();
}

[Fetch设置为POSTMESSAGE,这似乎是使用transformReponse传递数据的最佳方法。

@Override
protected Object transformRequest(DSRequest dsRequest)
{
    // gets the correct URL - (web-app-root)/rest/invoices/searchAndCount
    postProcessTransform(dsRequest);

    System.out.println("InvoiceDataSource: transformRequest: START");
    dsRequest.setContentType("application/json");
    JavaScriptObject jso = dsRequest.getData();

    // setting more headers, but this doesn't seem to change anything
    dsRequest.setAttribute("Access-Control-Allow-Origin", "*");
    dsRequest.setAttribute("Content-Type", "application/json");
    dsRequest.setAttribute("Accept", "application/json");

    String s1 = JSON.encode(jso);
    System.out.println("InvoiceDataSource: transformRequest: FINISH: s1=" + s1);
    return s1;
}

由于我知道他有正确的URL,所以我也吐出来变量“ s1”也具有正确的JSON数据,我再次测试了该JSON以确保它能正确命中控制器。

我也确实有pom.xml文件中定义的Jackson依赖项。我还在springmvc-servlet.xml文件中设置了消息转换器。如果这些都不正确,则单元测试将无法进行。但是,如果您需要查看pom.xml文件或springmvc-servlet.xml文件,请告诉我。

我整天都在研究和尝试很多东西,到目前为止……没有运气。希望我提供了足够的信息,但是如果您需要更多信息,请告诉我。最终,我希望可以对SmartGWT RestDataSource进行调整,以将正确的数据传递到此控制器,以实际从中获取数据。

更新:当我在Eclipse中使用Jetty运行此程序时,我正在使用Firefox 23.0.1打开我的Web应用程序。在Eclipse的控制台中,可以看到以下内容:

[WARN] 415 - GET /rest/invoices/searchAndCount (127.0.0.1) 1440 bytes
Request headers
  Host: 127.0.0.1:8888
  User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Language: en-US,en;q=0.5
  Accept-Encoding: gzip, deflate
  Cookie: GLog=%7B%0D%20%20%20%20left%3A22%2C%20%0D%20%20%20%20top%3A11%2C%20%0D%20%20%20%20width%3A705%2C%20%0D%20%20%20%20height%3A855%2C%20%0D%20%20%20%20priorityDefaults%3A%7B%0D%20%20%20%20%20%20%20%20Log%3A4%0D%20%20%20%20%7D%2C%20%0D%20%20%20%20defaultPriority%3A3%2C%20%0D%20%20%20%20trackRPC%3Atrue%0D%7D
   Connection: keep-alive
   If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT
 Response headers
  Content-Type: text/html; charset=iso-8859-1
  Content-Length: 1440
  Accept: application/json

注意,Request标头:接受:text / html,application / xhtml + xml,application / xml; q = 0.9,/; q = 0.8不显示application / json另外,请求标头:“ Content-Type”不存在

当我使用Chrome时,结果是:

[WARN] 415 - GET /rest/invoices/searchAndCount (127.0.0.1) 1440 bytes
Request headers
   Host: 127.0.0.1:8888
   Connection: keep-alive
   Accept: */*
   User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36
   DNT: 1
   Accept-Encoding: gzip,deflate,sdch
   Accept-Language: en-US,en;q=0.8
   If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT
   Cache-Control: max-age=0
Response headers
   Content-Type: text/html; charset=iso-8859-1
   Content-Length: 1440
   Accept: application/json

当我从JUnit测试运行时,总是存在“ Content-Type:application / json”。因此,似乎虽然我告诉SmartGWT RestDataSource我在多个地方都使用JSON ...但是Web服务调用并未创建正确的标头。

更新:我将以下代码添加到SmartGWT RestDataSource transformRequest方法中:

    Map<String, String> httpHeaders = new HashMap<String, String>();
    httpHeaders.put("Accept", "*/*");
    httpHeaders.put("Content-Type", "application/json");
    dsRequest.setHttpHeaders(httpHeaders);

我可以添加“接受”请求标头,但仍然收到415不支持的媒体错误消息。当我添加“ Content-Type”请求标头时,会收到400 BAD REQUEST错误消息。

我现在在控制台中得到这个:

[WARN] 400 - GET /rest/invoices/searchAndCount (127.0.0.1) 1418 bytes
Request headers
   Host: 127.0.0.1:8888
   User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0
   Accept: */*
   Accept-Language: en-US,en;q=0.5
   Accept-Encoding: gzip, deflate
   Connection: keep-alive
   If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT
   Content-Type: application/json
Response headers
   Content-Type: text/html; charset=iso-8859-1
   Content-Length: 1418
json spring-mvc smartgwt same-origin-policy
1个回答
2
投票

[这花了很多工作,但我终于想通了。

动词GET不能满足我的需要...我是个白痴。通过将我的参数作为对象发送到请求数据中,可以使GET正常工作。因此,让我展示一下为完成这项工作而必须更改的代码。

SmartGWT RestDataSource,我更改了;fetchProps.setHttpMethod(“ GET”);到fetchProps.setHttpMethod(“ POST”);我仍然保留:fetch.setDataProtocol(DSProtocol.POSTMESSAGE);

    // set up FETCH to use GET requests
    OperationBinding fetch = new OperationBinding();
    fetch.setOperationType(DSOperationType.FETCH);
    fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
    fetch.setDataFormat(DSDataFormat.JSON);
    // ===========================================
    DSRequest fetchProps = new DSRequest();
    fetchProps.setHttpMethod("POST");
    fetchProps.setContentType("application/json");
    fetch.setRequestProperties(fetchProps);

同样也在RestDataSource的“ transformRequest”方法中添加:

    Map<String, String> httpHeaders = new HashMap<String, String>();
    httpHeaders.put("Content-Type", "application/json");
    httpHeaders.put("Accept", "application/json");
    dsRequest.setHttpHeaders(httpHeaders);

这可以确保无论我使用的是哪种浏览器,都手动设置了这两个标头。

Spring MVC Controller驻留在同一个Web应用程序中,因此,在我可以对其进行测试之前,这可以避免任何SOP跨站点域问题。同时,我控件的标题如下:

@RequestMapping(value = "/searchAndCount", method = RequestMethod.POST, headers =
{ "Accept=application/json", "Content-Type=application/json" })
public @ResponseBody
ArrayList<?> searchAndCountPOST(@RequestBody SearchInvoiceDTO searchInvoiceDto)

这项工作很受欢迎,它返回了我的数据。我原来的单元测试是在做一个MockMVc.get,并且一直有效。它必须已经识别出经过的数据,并将GET更改为POST才能正常工作。我的单元测试现在已更改为POST,并且效果也很好。

我希望所有这些工作都能为别人带来回报!

© www.soinside.com 2019 - 2024. All rights reserved.