【问题标题】:RestTemplate: How to send URL and query parameters togetherRestTemplate:如何一起发送 URL 和查询参数
【发布时间】:2016-06-30 03:43:57
【问题描述】:

我正在尝试在 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 以便参数将 id 添加到 url

请建议。提前致谢

【问题讨论】:

    标签: java resttemplate url-parameters query-parameters path-parameter


    【解决方案1】:

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

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

    public static RequestEntity.BodyBuilder post(String uriTemplate, 对象... 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)
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        我会使用UriComponentsBuilder 中的buildAndExpand 来传递所有类型的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"
         */
        

        【讨论】:

        • 但是“UriComponentsBuilder”类在 Spring 3 中不可用。Spring 3 有什么替代解决方案吗?
        • 你的意思是urlParams.put("planet", "Mars");?您的 url 模板有 {planet}
        • @Shannon 对,感谢您注意到错字。现在已经修复了,
        【解决方案4】:
        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-

        【讨论】:

          【解决方案5】:

          一种简单的方法是:

          String url = "http://test.com/Services/rest/{id}/Identifier"
          
          UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build();
          uriComponents = uriComponents.expand(Collections.singletonMap("id", "1234"));
          

          然后添加查询参数。

          【讨论】:

            【解决方案6】:

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

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

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

            【讨论】:

            • 您是否尝试过使用路径变量。这里您的示例使用查询参数进行演示,并提出了关于路径参数的问题。
            【解决方案7】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-09-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-19
              • 1970-01-01
              • 2017-10-27
              • 2012-12-07
              相关资源
              最近更新 更多