这个问题一直困扰着我,我花了很多时间在这里,并试图找到正确的答案并尝试许多不同的修复。
我有一个Spring MVC Controller,在这里定义:
@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工具验证此代码将从此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以确保它能正确地击中控制器。 / p>
我也确实在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 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
答案 0 :(得分:2)
这需要做很多工作,但我终于明白了。
动词GET不能满足我的需要......我是个白痴。没有多少工作可以使我的参数作为请求数据中的对象发送。因此,让我展示一下我必须更改的代码才能使其正常工作。
SmartGWT RestDataSource,我改变了; fetchProps.setHttpMethod( “GET”); to 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-app中,所以现在,这可以避免任何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,这也很有效。
我希望所有这些工作都能为别人带来回报!