Spring RestTemplate GET参数

时间:2011-11-28 14:21:39

标签: java spring rest

我必须进行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进行交换而没有查询参数时,它可以正常工作。

有没有人有任何想法?

13 个答案:

答案 0 :(得分:372)

要轻松操作URL / path / params /等,您可以使用Spring的UriComponentsBuilder类。手动连接字符串更清晰,它会为您处理URL编码:

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("msisdn", msisdn)
        .queryParam("email", email)
        .queryParam("clientVersion", clientVersion)
        .queryParam("clientType", clientType)
        .queryParam("issuerName", issuerName)
        .queryParam("applicationName", applicationName);

HttpEntity<?> entity = new HttpEntity<>(headers);

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

答案 1 :(得分:123)

uriVariables也在查询字符串中展开。例如,以下调用将扩展帐户和名称的值:

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

所以实际的请求网址将是

http://my-rest-url.org/rest/account/my-account?name=my-name

查看HierarchicalUriComponents.expandInternal(UriTemplateVariables)以获取更多详细信息。 Spring的版本是3.1.3。

答案 2 :(得分:36)

好的,所以我是个白痴,我把查询参数与url参数混淆了。我有点希望有一个更好的方法来填充我的查询参数,而不是一个丑陋的连接字符串,但我们有。这只是用正确的参数构建URL的情况。如果你把它传递给一个String Spring也会为你处理编码。

答案 3 :(得分:18)

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

来自文档:

  

许多RestTemplate方法接受URI模板和URI   模板变量,可以是String vararg,也可以是。{   Map<String,String>

     

例如使用String vararg:

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/{hotel}", 
    String.class, vars);

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

如果您查看RestTemplate的{​​{3}}并搜索&#34; URI模板&#34;,您可以看到哪些方法可以使用占位符。

答案 4 :(得分:17)

我正在尝试类似的事情,the RoboSpice example helped me work it out

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

答案 5 :(得分:3)

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

在application.properties文件中

endpoint.url = https://yourHost/resource?requestParam1= {0}&amp; requestParam2 = {1}

Java代码在这里,您可以编写if或switch条件以查明.properties文件中的端点URL是否包含@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(); }

答案 6 :(得分:3)

    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变量和Request参数)构建动态URI

答案 7 :(得分:2)

如果您为RestTemplate传递非参数化的参数,那么考虑到参数,您将为每个传递的单个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);

答案 8 :(得分:2)

在Spring Web 4.3.6中,我也看到了

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

这意味着您不必创建丑陋的地图

因此,如果您有此网址

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

你可以做

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

restTemplate.getForObject(url, Response.class, param [])

答案 9 :(得分:1)

另一种使用UriComponentsBuilder的解决方案(转换现有的HashMap):

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

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

 HttpEntity entity = new HttpEntity(headers);

 UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
 for (Map.Entry<String, String> entry : params.entrySet()) {
     builder.queryParam(entry.getKey(), entry.getValue());
 }
 HttpEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, String.class);

答案 10 :(得分:1)

我提供了带有路径参数示例的 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;
}

答案 11 :(得分:0)

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

答案 12 :(得分:0)

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