这个问题整天困扰着我,我在这里花了很多时间,在谷歌上试图找到正确的答案并尝试了很多不同的修复。
我有一个在这里定义的 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 字符串如下所示: String s1 = "{\"userId\":3, \"ddUserId\":301010651, \"customerCode\":\"QA\", \"customerId\":8}"; 是的,我使用了 Jackson ObjectMapper 工具来验证此代码是否可以正确地从该字符串映射到一个对象,反之亦然。当我查看 POJO 时,它确实实现了 Serializable,并且它确实有一个默认构造函数。
Junit 测试效果很好,并且确实返回了数据:
MockHttpServletRequestBuilder requestBuilder =
MockMvcRequestBuilders.get("/invoices/searchAndCount").contentType(MediaType.APPLICATION_JSON)
.content(test);
this.mockMvc.perform(requestBuilder).andDo(print());
这确实调用了控制器,我可以从输出中看到标头是什么,并且我可以看到我实际上得到了很棒的真实数据。所以我觉得在控制器方面我能做的不多。
对控制器的真正调用来自 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 打开我的网络应用程序。在 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
注意请求头:Accept: 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-services 调用没有创建正确的标题。
更新:我将以下代码添加到 SmartGWT RestDataSource transformRequest 方法:
Map<String, String> httpHeaders = new HashMap<String, String>();
httpHeaders.put("Accept", "*/*");
httpHeaders.put("Content-Type", "application/json");
dsRequest.setHttpHeaders(httpHeaders);
我可以添加“接受”请求标头,但仍然收到 415 Unsupported Media 错误消息。当我添加“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