Apache HTTP 客户端和 Spring RestTemplate 之间的区别

Difference between Apache HTTP Client and Spring RestTemplate

我正在调用 Google Translate API,一个是通过 Apache HTTP 客户端,另一个是通过 Spring 的 RestTemplate,得到不同的结果。两者的 GETing 完全相同 URL:

我想将 "Professeur des écoles" 从法语翻译成英语。

使用的 URL 是(为了便于阅读分成两行):

private static String URL = "https://www.googleapis.com/language/translate/v2?
key=AIzaSyBNv1lOS...&source=fr&target=en&q=Professeur+des+%C3%A9coles";

阿帕奇:

@Test
public void apache() throws IOException {
    String response = Request.Get(URL).execute().returnContent().asString();
    System.out.println(response);
}

Returns(正确):

{ "data":{ "translations": [ { "translatedText": "School teacher" } ] } }

@Test
public void spring() {
    RestTemplate template = new RestTemplate();
    String response = template.getForObject(URL, String.class);
    System.out.println(response);
}

Returns(错误):

{ "data":{ "translations": [ { "translatedText": "Professor + of +% C3% A9coles" } ] } }

我是否在 RestTemplate HTTP header 配置中遗漏了什么?

RestTemplate 接受 String URL 的方法执行 URL 编码。

For each HTTP method there are three variants: two accept a URI template string and URI variables (array or map) while a third accepts a URI. Note that for URI templates it is assumed encoding is necessary, e.g. restTemplate.getForObject("http://example.com/hotel list") becomes "http://example.com/hotel%20list". This also means if the URI template or URI variables are already encoded, double encoding will occur, e.g. http://example.com/hotel%20list becomes http://example.com/hotel%2520list).

大概您提供了以下 String 作为第一个参数

https://www.googleapis.com/language/translate/v2?key=MY_KEY&source=fr&target=en&q=Professeur+des+%C3%A9coles

必须对字符 % 进行编码。因此,您的 q 参数值变为

Professeur%2Bdes%2B%25C3%25A9coles

如果您decode,则相当于

Professeur+des+%C3%A9coles

Google 的翻译服务不知道如何处理 %C3%A9coles

如文档所示

To avoid that use a URI method variant to provide (or re-use) a previously encoded URI. To prepare such an URI with full control over encoding, consider using UriComponentsBuilder.

与其使用接受 String URL 的重载,不如自己构建一个 URI 并使用它。


Apache 的 HttpComponents Fluent API 没有指定行为,但字符串值似乎按原样使用。