以下是我的REST API代码:
@RequestMapping(value = "/get", method = RequestMethod.POST, produces = { "application/json" })
@ApiOperation(value = "get data by key.", notes = "return json string value.")
public JsonObjectResponse<String> get(
@ApiParam(required = true, name = "regionName", value = "region name") @RequestParam("regionName") String regionName,
@ApiParam(required = true, name = "key", value = "region key,Default is uuid") @RequestParam("key") String key) throws UnsupportedEncodingException
{
JsonObjectResponse<String> jr = new JsonObjectResponse<String>();
//key = decodeJsonString(key); // added for junit
String val = adfService.onPath(regionName).get(key);
jr.setState(StateCode.SUCCESS);
jr.setData(JsonObject.create().append(key,val).toJson());
return jr;
}
我正在尝试传递参数:
regionName=/fusion/table1&key={"fusionTbl1DetailNo":"fusionNo001","pk":"PK0001"}
如果我通过swagger-ui调用它,它会这样调用:
http://localhost:8080/service/basic/get?regionName=%2Ffusion%2Ftable1&key=%7B%22fusionTbl1DetailNo%22%3A%22fusionNo001%22%2C%22pk%22%3A%22PK0001%22%7D&token=8652493a-4147-43f4-af3a-bcb117fb7d42`
它对参数进行了编码,这些参数也可以在服务器端自动解码。
当我想为此API添加测试用例时,我使用restTemplate.exchange方法,代码如下:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
for (Entry<String, String> entry : queryParamMap.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
if (uriParamMap != null) {
url = builder.buildAndExpand(uriParamMap).toUriString();
} else {
url = builder.toUriString();
}
if (StringUtils.isEmpty(requestBody)) {
if (bodyParamMap != null) {
requestBody = parseMapToParams(bodyParamMap);
} else {
requestBody = "";
}
}
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json", Charset.forName("UTF-8"));
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
// headers.add("Accept", "application/json");
// headers.set(HttpHeaders.ACCEPT, "application/json");
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
// headers.add("Accept-Encoding", "gzip, deflate, br");
headers.set("Accept-Charset", "utf-8");
headers.set("Accept-Encoding", "gzip");
headers.add("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6");
headers.add("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
headers.add(TestBase.TOKEN_HEADER, TestBase.getTokenId());
HttpEntity<String> request = new HttpEntity<>(body, headers);
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
ResponseEntity<String> response = restTemplate.exchange(url, httpMethod, request, String.class);
localresponse.set(response);
System.out.println("response:" + response);
return response;
我使用UriComponentsBuilder
附加参数,它会将网址格式化为
http://localhost:8080/service/basic/get?regionName=/fusion/table1&key=%7B%22fusionTbl1DetailNo%22:%22fusionNo001%22,%22pk%22:%22PK0001%22%7D
方法exchange
的。但是,当服务器端收到呼叫时,它没有解码参数key
,它的值仍然是:
%7B%22fusionTbl1DetailNo%22:%22fusionNo001%22,%22pk%22:%22PK0001%22%7D
为什么?我比较了swagger调用的标题设置,添加了额外的设置,没有效果:(。
答案 0 :(得分:1)
尝试以下内容:
ResponseEntity<String> res = restTemplate.exchange("http://localhost:8080/service/basic/get?regionName={arg1}&key={arg2}", HttpMethod.POST, null, String.class,"/fusion/table1", "{\"fusionTbl1DetailNo\":\"fusionNo001\",\"pk\":\"PK0001\"}");
arg1
和arg2
将替换为
"/fusion/table1"
和"{\"fusionTbl1DetailNo\":\"fusionNo001\",\"pk\":\"PK0001\"}"
我在null
中发送requestEntity
,因为没有请求正文和请求参数在uriVariables中。
答案 1 :(得分:1)
RestTemplate上的Spring文档读取:
对于每个HTTP方法,有三种变体:两种接受URI 模板字符串和URI变量(数组或映射),而第三个接受 一个URI。请注意,对于URI模板,假设编码为 必要的,例如restTemplate.getForObject(&#34; http://example.com/hotel list&#34;)成为&#34; http://example.com/hotel%20list&#34;。这也意味着 URI模板或URI变量已经编码,双重编码 会发生,
看起来你正在使用一个带有URI模板字符串的RestTemplate交换方法,因此你不应该对url-string进行编码。
首先在
上编码url-stringbuilder.toUriString()
然后又在交换电话上。所以问题似乎是客户端的双重编码,而不是服务器端的解码不足
答案 2 :(得分:1)
而不是toUriString()
使用,UriComponentsBuilder.fromUriString(url).queryParam("name","John Doe").build().toString();