我必须进行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也会为你处理编码。

其他回答

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。

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

如果您的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交换方法

还有一个解决方法:

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

}

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

内部应用程序。属性文件

endpoint。url = https://host/resource?

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