【问题标题】:RestTemplate URI template syntaxRestTemplate URI 模板语法
【发布时间】:2017-01-23 20:20:00
【问题描述】:

在我的项目中,我在客户端应用程序中使用 RestTempate 来访问现有服务。服务本身返回一个有效 URI 模板列表,我尝试使用的模板看起来像

http://corpdomain.com/service{?idparam}

在运行时,它应该扩展为类似

http://corpdomain.com/service?idparam=12345

问题是,RestTemplate 的 getForObject() 不知道如何处理“{?idparam}”符号。如果我给它 URI http://corpdomain.com/service?idparam={idparam},一切正常。但这不是服务器返回给我的 URI 模板。

你知道如何让 RestTemplate.getForObject() 在模板中使用 {?idparam} 类型表示法吗?

您知道是否有任何关于 URI 模板语法的文档吗?

我目前正在浏览 Spring 的 Java 源代码,最终应该能够找到解决方案。然而,真正困扰我的是缺乏文档或第三方信息。

提前谢谢大家!

【问题讨论】:

  • 好吧,看来我知道是怎么回事了。速记符号 http://corpdomain.com/service{?idparam} 不是来自任何 Spring 库,它是使用 Affordance 库 (github.com/dschulten/hydra-java) 构建的。但我仍然不明白为什么 Spring 和 Affordance 都没有尝试记录他们正在使用的 URI 模板格式。

标签: java spring templates uri


【解决方案1】:

该服务似乎正在返回 RFC 6570 URI 模板,其中包括 {?foo}{+foo} 之类的符号 are not supported by Spring

有一个库 Handy URI Templates 实现了 RFC 6570 规范。

【讨论】:

    【解决方案2】:

    您可以将 uri 变量作为 getForObject 方法的一部分传递

    getForObject(String url, Class<T> responseType, Map<String,?> uriVariables)
    

    文档:http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

    或者你可以使用 UriComponentsBuilder 的 build 和 expand 方法,如下所示:

            String url="http://localhost:8080/test?idparam={idparam}";
            RestTemplate restTemplate=new RestTemplate();
            Map<String,String> uriVariables=new HashMap<String,String>();
            uriVariables.put("idparam", "1234");
            UriComponents builder=UriComponentsBuilder.fromHttpUrl(url).buildAndExpand(uriVariables);
            System.out.println(" url built "+builder.toUri());
    

    输出:

     url built http://localhost:8080/test?idparam=1234
    

    如果查询参数是动态的,因为您不确定要传递的 url,您可以执行以下操作:

        UriComponentsBuilder builder=UriComponentsBuilder.fromHttpUrl(url);
        Map<String,String> uriVariables =builder.build().getQueryParams().toSingleValueMap();
        //set or get required query params
        restTemplate.getForObject(url, String.class, uriVariables);
    

    【讨论】:

      【解决方案3】:

      我不熟悉那种语法。但是,我会定义一个 BASE_SERVICE_URL 并将其与 UriComponentsBuilder 一起使用来创建您的 URL。它看起来像这样

        private static final String BASE_SERVICE_URL = "http://corpdomain.com/service"
      
          public void doTheThing(String idParam) {
          ...
          UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
                  .queryParam("idparam", idparam)
          ...
          HttpEntity<String> response = restTemplate.exchange(
              builder.build().encode().toUri(), 
              HttpMethod.GET, 
              entity, 
              String.class);
          }
      

      【讨论】:

      • 这种方法可行,但是,我的问题是我试图不自己构建 URI。我正在尝试依赖服务返回给我的模板,所以我的客户不需要知道做.queryParam("idparam", idparam)
      • 如果服务器返回非标准语法,您将不得不在您的端进行一些解析,以将 {?somequerystringvar} 转换为 spring 可以理解的内容。我可能是错的,但我以前没有见过这种语法,它可能是我所知道的标准。也许您可以实现一个方法,将 URI 中所有出现的 {?queryparam} 都转换为 ?queryparam=queryparamvalue 语法
      • @ferahgo 服务器正在返回一个 rfc6570 level 4 标准 uri 模板。 Spring 只了解 1 级。
      猜你喜欢
      • 2020-12-06
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      相关资源
      最近更新 更多