带有参数的Spring RestTemplate GET

我必须进行REST调用,其中包括自定义标头和查询参数。我用头文件(没有正文)设置了我的HttpEntity,我使用RestTemplate.exchange()方法如下所示:

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");


Map<String, String> params = new HashMap<String, String>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);


HttpEntity entity = new HttpEntity(headers);


HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, params);

这在客户端失败,因为dispatcher servlet无法将请求解析到处理程序。调试之后,似乎没有发送请求参数。

当我使用请求体和没有查询参数与POST进行交换时,它工作得很好。

有人有什么想法吗?

673676 次浏览

我真是个白痴,我把查询参数和url参数搞混了。我有点希望有一个更好的方式来填充我的查询参数,而不是一个丑陋的连接字符串,但我们有。这只是一个用正确的参数构建URL的例子。如果你把它作为一个字符串传递,Spring也会为你处理编码。

uriVariables也在查询字符串中展开。例如,下面的调用将展开account和name的值:

restTemplate.exchange("http://my-rest-url.org/rest/account/{account}?name={name}",
HttpMethod.GET,
httpEntity,
clazz,
"my-account",
"my-name"
);

实际的请求url是

http://my-rest-url.org/rest/account/my-account?name=my-name
查看HierarchicalUriComponents.expandInternal(UriTemplateVariables)了解更多细节。 Spring的版本是3.1.3.

我正在尝试类似的东西,RoboSpice的例子帮助我解决了这个问题:

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");


HttpEntity<String> request = new HttpEntity<>(input, createHeader());


String url = "http://awesomesite.org";
Uri.Builder uriBuilder = Uri.parse(url).buildUpon();
uriBuilder.appendQueryParameter(key, value);
uriBuilder.appendQueryParameter(key, value);
...


String url = uriBuilder.build().toString();


HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request , String.class);

为了方便地操作URL / path / params /等等,你可以使用Spring的UriComponentsBuilder类创建一个URL模板,其中包含参数占位符,然后在RestOperations.exchange(...)调用中为这些参数提供值。它比手动连接字符串更干净,它会为你处理URL编码:

HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> entity = new HttpEntity<>(headers);


String urlTemplate = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("msisdn", "{msisdn}")
.queryParam("email", "{email}")
.queryParam("clientVersion", "{clientVersion}")
.queryParam("clientType", "{clientType}")
.queryParam("issuerName", "{issuerName}")
.queryParam("applicationName", "{applicationName}")
.encode()
.toUriString();


Map<String, ?> params = new HashMap<>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);


HttpEntity<String> response = restOperations.exchange(
urlTemplate,
HttpMethod.GET,
entity,
String.class,
params
);

我采取不同的方法,你可能同意或不同意,但我想从.properties文件控制,而不是编译的Java代码

内部应用程序。属性文件

端点。url = https://yourHost/resource?requestParam1={0}&requestParam2={1}

Java代码在这里,你可以写if或切换条件,以找出端点URL在.properties文件中是否有@PathVariable(包含{})或@RequestParam (yourURL?key=value)等…然后调用相应的方法…这样它是动态的,不需要在未来的一站式商店更改代码…

我试图在这里给出比实际代码更多的想法……试着为@RequestParam和@PathVariable等编写泛型方法…然后在需要时进行相应的调用

  @Value("${endpoint.url}")
private String endpointURL;
// you can use variable args feature in Java
public String requestParamMethodNameHere(String value1, String value2) {
RestTemplate restTemplate = new RestTemplate();
restTemplate
.getMessageConverters()
.add(new MappingJackson2HttpMessageConverter());


HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(headers);


try {
String formatted_URL = MessageFormat.format(endpointURL, value1, value2);
ResponseEntity<String> response = restTemplate.exchange(
formatted_URL ,
HttpMethod.GET,
entity,
String.class);
return response.getBody();
} catch (Exception e) { e.printStackTrace(); }

至少从Spring 3开始,不是使用UriComponentsBuilder来构建URL(这有点冗长),RestTemplate方法的许多接受参数路径中的占位符(不仅仅是exchange)。

从文档中可以看到:

许多RestTemplate方法接受URI模板和URI 模板变量,可以作为String变量,也可以作为 Map<String,String> . < / p >

例如,使用String变量:

restTemplate.getForObject(
"http://example.com/hotels/{hotel}/rooms/{room}", String.class, "42", "21");

或者使用Map<String, String>:

Map<String, String> vars = new HashMap<>();
vars.put("hotel", "42");
vars.put("room", "21");


restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{room}",
String.class, vars);

参考:https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#rest-resttemplate-uri

如果你查看RestTemplateJavaDoc并搜索“URI Template”,你可以看到哪些方法可以使用占位符。

public static void main(String[] args) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE);
final String url = "https://host:port/contract/{code}";
Map<String, String> params = new HashMap<String, String>();
params.put("code", "123456");
HttpEntity<?> httpEntity  = new HttpEntity<>(httpHeaders);
RestTemplate restTemplate  = new RestTemplate();
restTemplate.exchange(url, HttpMethod.GET, httpEntity,String.class, params);
}

如果您为RestTemplate传递非参数参数,那么考虑到参数,您将为传递的每个不同URL都有一个Metrics。你想要使用参数化url:

http://my-url/action?param1={param1}&param2={param2}

而不是

http://my-url/action?param1=XXXX&param2=YYYY

第二种情况是使用UriComponentsBuilder类得到的结果。

实现第一个行为的方法如下:

Map<String, Object> params = new HashMap<>();
params.put("param1", "XXXX");
params.put("param2", "YYYY");


String url = "http://my-url/action?%s";


String parametrizedArgs = params.keySet().stream().map(k ->
String.format("%s={%s}", k, k)
).collect(Collectors.joining("&"));


HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(headers);


restTemplate.exchange(String.format(url, parametrizedArgs), HttpMethod.GET, entity, String.class, params);

在Spring Web 4.3.6中我也看到了

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)

这意味着你不必创建一个丑陋的地图

如果你有这个url

http://my-url/action?param1={param1}&param2={param2}

你可以选择

restTemplate.getForObject(url, Response.class, param1, param2)

restTemplate.getForObject(url, Response.class, param [])
    String uri = http://my-rest-url.org/rest/account/{account};


Map<String, String> uriParam = new HashMap<>();
uriParam.put("account", "my_account");


UriComponents builder = UriComponentsBuilder.fromHttpUrl(uri)
.queryParam("pageSize","2")
.queryParam("page","0")
.queryParam("name","my_name").build();


HttpEntity<String> requestEntity = new HttpEntity<>(null, getHeaders());


ResponseEntity<String> strResponse = restTemplate.exchange(builder.toUriString(),HttpMethod.GET, requestEntity,
String.class,uriParam);


//final URL: http://my-rest-url.org/rest/account/my_account?pageSize=2&page=0&name=my_name

RestTemplate:使用UriComponents (URI变量和请求参数)构建动态URI

将哈希映射转换为查询参数字符串:

Map<String, String> params = new HashMap<>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);


UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}


HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");


HttpEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity(headers), String.class);

如果你的url是http://localhost:8080/context path?msisdn={msisdn}&email={email}

然后

Map<String,Object> queryParams=new HashMap<>();
queryParams.put("msisdn",your value)
queryParams.put("email",your value)

适用于您所描述的resttemplate交换方法

我提供了一个RestTemplate GET方法的代码片段与路径参数示例

public ResponseEntity<String> getName(int id) {
final String url = "http://localhost:8080/springrestexample/employee/name?id={id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", id);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, String.class, params);
return response;
}

可以对String使用follow代码。

URL_EXAMPLE="http://{domain}/Index.php?Username={user}&password={password}";


String domain = "example.com";
String user = "user";
String password = "password";


String data=this.restTemplate.getForObject(URL_EXAMPLE,String.class,domain,user,password);

嗨,我建立url与查询参数使用这段代码:

UriComponentsBuilder.fromHttpUrl(url)
.queryParam("bikerPhoneNumber", "phoneNumberString")
.toUriString();

还有一个解决方法:

private String execute(String url, Map<String, String> params) {
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url)
// predefined params
.queryParam("user", "userValue")
.queryParam("password", "passwordValue");
params.forEach(uriBuilder::queryParam);
HttpHeaders headers = new HttpHeaders() \{\{
setContentType(MediaType.APPLICATION_FORM_URLENCODED);
setAccept(List.of(MediaType.APPLICATION_JSON));
}};
ResponseEntity<String> request = restTemplate.exchange(uriBuilder.toUriString(),
HttpMethod.GET, new HttpEntity<>(headers), String.class);
return request.getBody();


}