RestTemplate: 如何同时发送 URL 和查询参数

我试图传递路径参数和查询参数在一个 URL,但我得到了一个奇怪的错误。下面是代码

    String url = "http://test.com/Services/rest/{id}/Identifier"
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1234");
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
.queryParam("name", "myName");
String uriBuilder = builder.build().encode().toUriString();
restTemplate.exchange(uriBuilder , HttpMethod.PUT, requestEntity,
class_p, params);

我的网址变成了 http://test.com/Services/rest/%7Bid%7D/Identifier?name=myName

我该怎么做才能成功。我期望 http://test.com/Services/rest/{id}/Identifier?name=myName,这样 params 就会将 id 添加到 url 中

请建议。预先感谢

222745 次浏览

我将使用 UriComponentsBuilder中的 buildAndExpand来传递所有类型的 URI 参数。

例如:

String url = "http://test.com/solarSystem/planets/{planet}/moons/{moon}";


// URI (URL) parameters
Map<String, String> urlParams = new HashMap<>();
urlParams.put("planet", "Mars");
urlParams.put("moon", "Phobos");


// Query parameters
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
// Add query parameter
.queryParam("firstName", "Mark")
.queryParam("lastName", "Watney");


System.out.println(builder.buildAndExpand(urlParams).toUri());
/**
* Console output:
* http://test.com/solarSystem/planets/Mars/moons/Phobos?firstName=Mark&lastName=Watney
*/


restTemplate.exchange(builder.buildAndExpand(urlParams).toUri() , HttpMethod.PUT,
requestEntity, class_p);


/**
* Log entry:
* org.springframework.web.client.RestTemplate Created PUT request for "http://test.com/solarSystem/planets/Mars/moons/Phobos?firstName=Mark&lastName=Watney"
*/

来自 Michal Foksa的答案的一个问题是,它首先添加查询参数,然后展开路径变量。如果查询参数包含括号,例如 {foobar},这将导致异常。

安全的方法是首先展开路径变量,然后添加查询参数:

String url = "http://test.com/Services/rest/{id}/Identifier";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1234");
URI uri = UriComponentsBuilder.fromUriString(url)
.buildAndExpand(params)
.toUri();
uri = UriComponentsBuilder
.fromUri(uri)
.queryParam("name", "myName")
.build()
.toUri();
restTemplate.exchange(uri , HttpMethod.PUT, requestEntity, class_p);

使用带参数映射的 TestRestTemplate.exchange 函数的一行程序。

restTemplate.exchange("/someUrl?id={id}", HttpMethod.GET, reqEntity, respType, ["id": id])

像这样初始化的 params 映射是一个 太棒了初始化程序 *

一个简单的方法是:

String url = "http://test.com/Services/rest/{id}/Identifier"


UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build();
uriComponents = uriComponents.expand(Collections.singletonMap("id", "1234"));

然后添加查询参数。

String url = "http://test.com/Services/rest/{id}/Identifier";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1234");
URI uri = UriComponentsBuilder.fromUriString(url)
.buildAndExpand(params)
.toUri();
uri = UriComponentsBuilder
.fromUri(uri)
.queryParam("name", "myName")
.build()
.toUri();
restTemplate.exchange(uri , HttpMethod.PUT, requestEntity, class_p);

安全的方法是首先展开路径变量,然后添加查询参数:

对我来说,这会导致重复编码,例如将空格解码为% 2520(space->% 20->% 25)。

我用以下方法解决了这个问题:

String url = "http://test.com/Services/rest/{id}/Identifier";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1234");
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(url);
uriComponentsBuilder.uriVariables(params);
Uri uri = uriComponentsBuilder.queryParam("name", "myName");
.build()
.toUri();
restTemplate.exchange(uri , HttpMethod.PUT, requestEntity, class_p);

本质上,我使用 uriComponentsBuilder.uriVariables(params);来添加路径参数:

... 与 UriComponent. expand (Map)或 buildAndExpand (Map)不同,当您需要提供 URI 变量而不需要构建 UriComponent 实例时,或者可能需要预先展开一些共享的默认值,如 host 和 port,这种方法非常有用。...

资料来源: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html#uriVariables-java.util.Map-

下面是工作代码,在创建查询参数时,我必须在各自的占位符中传递两个值。

String queryParam = "Key=Project_{ProdjectCode}_IN_{AccountCode}"


Map<String, String> queryParamMap = new HashMap<>();
queryParamMap.put("ProjectCode","Project1");
queryParamMap.put("AccountCode","Account1");


UriComponents builder = UriComponentsBuilder.fromHttpUrl("http://myservice.com/accountsDetails").query(queryParam).buildAndExpand(queryParamMap);


restTemplate.exchange(builder.toUriString(), HttpMethod.GET,httpEntity,MyResponse.class);

以上代码将对 url 进行 GET 调用 Http://myservice.com/accountsdetails ? 关键字 = Project _ project1 _ IN _ Account1

从5.3版本开始,您就可以使用这个 API 来完成这项工作。

RequestEntity.post(urlString, urlParam1, urlParam2).headers(...).body(requestBody);

Public static RequestEntity. BodyBuilder post (String uriTemplate, 对象... uriVariables)
使用给定的字符串 base uri 模板创建一个 HTTPPOST 构建器。

在医生那里: Https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/requestentity.html#post-java.net.uri-

或者

template.exchange(..., uriVariables)