Spring RestTemplate getForObject URL不适用于Apple iTunes

时间:2015-12-16 12:50:20

标签: java spring spring-rest

我创建了以下简单测试来查询iTunes:

@Test
fun loadArtist()
{
    val restTemplate = RestTemplate()

    val builder = UriComponentsBuilder.fromHttpUrl("https://itunes.apple.com/search")
    builder.queryParam("term", "howling wolf")
    builder.queryParam("entity", "allArtist")
    builder.queryParam("limit", 1)

    println("\n\nURL ${builder.toUriString()}")

    val result = restTemplate.getForObject(builder.toUriString(), String::class.java);
    println("Got artist: $result")
}

输出意外:

URL https://itunes.apple.com/search?term=howling%20wolf&entity=allArtist&limit=1
Got artist: 

{
 "resultCount":0,
 "results": []
}

将生成的网址粘贴到浏览器中 会给出预期的结果 - 艺术家返回。

https://itunes.apple.com/search?term=howling%20wolf&entity=allArtist&limit=1

此外,对查询进行硬编码有效:

val result = restTemplate.getForObject("https://itunes.apple.com/search?term=howling%20wolf&entity=allArtist&limit=1", String::class.java);

。 。问题似乎只发生在包含空格的term查询中。

出了什么问题?除了手工组装URL,如何修复?

1 个答案:

答案 0 :(得分:1)

似乎是对空格进行双重编码的情况。来自RestTemplate Javadoc:

  

对于每个HTTP方法,有三种变体:两种接受URI   模板字符串和URI变量(数组或映射),而第三个接受   一个URI。请注意,对于URI模板,假设编码为   必要的,例如restTemplate.getForObject(" http://example.com/hotel   list")成为" http://example.com/hotel%20list"。这也意味着   URI模板或URI变量已经编码,双重编码   会发生,例如http://example.com/hotel%20list变成了   http://example.com/hotel%2520list)。为了避免使用URI方法   用于提供(或重用)先前编码的URI的变体。准备   这样一个完全控制编码的URI,考虑使用   UriComponentsBuilder。

因此看起来getForObject实际上会查询https://itunes.apple.com/search?term=howling%2520wolf&entity=allArtist&limit=1,从而导致结果为空。你总是可以用" +"替换空格。在您的术语中或尝试使其中一个类跳过编码过程。