73

我正在尝试在 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

请建议。提前致谢

4

7 回答 7

164

我会使用buildAndExpandfromUriComponentsBuilder来传递所有类型的 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"
 */
于 2016-03-15T20:16:08.650 回答
20

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);
于 2018-05-30T07:46:15.290 回答
6

使用带有参数映射的 TestRestTemplate.exchange 函数的单线。

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

像这样初始化的参数映射是一个groovy初始化程序*

于 2019-09-03T14:21:10.233 回答
2
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(空格 -> %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);用来添加路径参数的。文档说:

... 与 UriComponents.expand(Map) 或 buildAndExpand(Map) 相比,此方法在您需要提供 URI 变量而不构建 UriComponents 实例时很有用,或者可能预先扩展一些共享的默认值,例如主机和港口。...

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

于 2021-01-13T19:07:20.130 回答
1

从 5.3 版开始,您可以使用此 API 来执行此操作。

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

public static RequestEntity.BodyBuilder post(String uriTemplate, Object... uriVariables)
使用给定的字符串基 uri 模板创建一个 HTTP POST 构建器。

在文档中: https ://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/RequestEntity.html#post-java.net.URI-

或者

template.exchange(..., uriVariables)
于 2021-10-20T22:55:02.087 回答
0

一种简单的方法是:

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

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

然后添加查询参数。

于 2020-11-12T21:15:58.463 回答
0

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

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 http://myservice.com/accountsDetails?Key=Project_Project1_IN_Account1进行 GET 调用

于 2021-08-31T16:51:19.680 回答