我必须进行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);

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

当我使用请求体和没有查询参数的POST做一个交换时,它工作得很好。

有人有什么想法吗?


当前回答

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

其他回答

如果您的url是http://localhost:8080/context path?msisdn = {msisdn}电子邮件= {email}

然后

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

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

为了方便地操作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
);

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

至少从Spring 3开始,许多RestTemplate方法不是使用UriComponentsBuilder来构建URL(这有点啰嗦),而是在参数路径中接受占位符(不仅仅是交换)。

从文档中可以看到:

Many of the RestTemplate methods accepts a URI template and URI template variables, either as a String vararg, or as Map<String,String>. For example with a String vararg: restTemplate.getForObject( "http://example.com/hotels/{hotel}/rooms/{room}", String.class, "42", "21"); Or with a 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

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

还有一个解决方法:

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();

}