java JSON 格式的 RestTemplate 中的 GET 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42142801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:23:45  来源:igfitidea点击:

GET request in RestTemplate in JSON

javaspringhttpgetresttemplate

提问by Fisher Coder

It's been troubling for a couple days already for a seemingly super straightforward question:

一个看似非常简单的问题已经困扰了几天:

I'm making a simple GET request using RestTemplate in application/json, but I keep getting

我正在使用 RestTemplate in 发出一个简单的 GET 请求application/json,但我不断收到

org.springframework.web.client.HttpClientErrorException: 400 Bad Request
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:636)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:592)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:552)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:470)

I did research and followed this tutorial, also I looked at solutions from this POST request via RestTemplate in JSON. But none of them helped, here's my code:

我做了研究并遵循了本教程,我还通过 JSON 中的 RestTemplate从这个POST 请求中查看了解决方案。但他们都没有帮助,这是我的代码:

RestTemplate restTemplate = new RestTemplate();    
HttpHeaders requestHeaders = new HttpHeaders();    
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
restTemplate.exchange(endpoint, HttpMethod.GET, requestEntity, String.class);

endpointis http://localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8")which works fine in Postman. itemIdsis a comma-separated list like below:

endpointhttp://localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8")该作品在邮差罚款。 itemIds是一个逗号分隔的列表,如下所示:

5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726

5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726

I also tried to use getForObjectlike below:

我也尝试使用getForObject如下:

String result = restTemplate.getForObject(endpoint, String.class);

which gives me this error:

这给了我这个错误:

org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type

I'm not sure what I missed or did wrong, but the same endpoint works perfectly on Postman, but the only difference is that I added Content-Type header in Postman app.

我不确定我错过了什么或做错了什么,但相同的端点在 Postman 上运行良好,但唯一的区别是我在 Postman 应用程序中添加了 Content-Type 标头。

This is my Request from Postman:

这是我对邮递员的要求:

GET /api/v1/items?itemIds=abc%2cdef%2cghi HTTP/1.1 Host: localhost:8080 Connection: keep-alive Postman-Token: 84790e06-86aa-fa8a-1047-238d6c931a68 Cache-Control: no-cache User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 Content-Type: application/json Accept: */* Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4

GET /api/v1/items?itemIds=abc%2cdef%2cghi HTTP/1.1 Host: localhost:8080 Connection: keep-alive Postman-Token: 84790e06-86aa-fa8a-1047-238d6c931a68 Cache-Control: no-cache User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 Content-Type: application/json Accept: */* Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4

So how can I correctly set content-type using RestTemplate if my above code is wrong?

那么如果我上面的代码是错误的,我如何使用 RestTemplate 正确设置内容类型?

Another deep dive, I've fired up Wiresharkto capture the two HTTP requests, here are the screenshots:

另一个深入研究,我启动了Wireshark来捕获两个 HTTP 请求,以下是屏幕截图:

The request from Postman: request from Postman

来自邮递员的请求: 邮递员的请求

The request from my Java code: request from Java program

来自我的 Java 代码的请求: 来自 Java 程序的请求

I still don't see why the one from my Java program throws 400 while the one from Postman works fine.

我仍然不明白为什么我的 Java 程序中的一个抛出 400 而 Postman 中的一个运行正常。

Thanks a lot.

非常感谢。

采纳答案by Fisher Coder

OK, eventually, one of my co-workers helped me figure out why, believe it or not, it's this simple:

好吧,最终,我的一位同事帮我弄清楚了原因,不管你信不信,就是这么简单:

The endpointwas like this: "http:localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8");

endpoint是这样的: "http:localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8");

However, it should be "http:localhost:8080/api/v1/items?itemIds=" + itemIds;

然而,应该是 "http:localhost:8080/api/v1/items?itemIds=" + itemIds;

itemIdsis just a comma-separated list.

itemIds只是一个逗号分隔的列表。

After URLEncoder encoding via "UTF-8" schema, this comma-separated list becomes itemIds=5400028914%2C5400029138%2C5400029138%2C5400029138%2C5400029138%2C5400028401%2C5400028918%2C5400028076

通过“UTF-8”模式进行 URLEncoder 编码后,这个逗号分隔的列表变为 itemIds=5400028914%2C5400029138%2C5400029138%2C5400029138%2C5400029138%2C5400028401%2C5400028918%2C5400028076

from

itemIds=5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726

itemIds=5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726

We don't need to URLEncoder to encode the URL when using RestTemplate, anyone could help me deepen my understanding here please?

我们在使用 RestTemplate 时不需要 URLEncoder 来编码 URL,有没有人可以帮我加深理解?

Thanks!

谢谢!

回答by David Doan

You don't need set "requestEntity" for a GET method, try your code like this:

你不需要为 GET 方法设置“requestEntity”,试试你的代码是这样的:

public ItemInfo getItemInfo() throws Exception {
    String url =
            "http://localhost:8080/api/v1/items?itemIds=abc";
    ObjectMapper objectMapper = new ObjectMapper();     
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
    String responseBody = response.getBody();
    handlerError(response, url);
    try {
        return objectMapper.readValue(responseBody, ItemInfo.class);
    } catch (IOException exception) {
        LOGGER.error("failed to send REST request", exception);
        throw new Exception(ErrorCode.NOT_AVAILABLE, url);
    }
}

private void handlerError(final ResponseEntity<String> response, final String url) throws Exception {
    String responseBody = response.getBody();
    try {
        if (RestUtil.isError(response.getStatusCode())) {
            ObjectMapper objectMapper = new ObjectMapper(); 
            MyInfoError myInfoError = objectMapper.readValue(responseBody, MyInfoError.class);
            throw new Exception(infoErreur, ErrorCode.UNKNOWN_CODE_ERROR);
        } else if (RestUtil.isNotFound(response.getStatusCode())) {
            throw new Exception(ErrorCode.NOT_AVAILABLE, "MyService");
        }
    } catch (IOException exception) {
        LOGGER.error("failed to send REST request", exception);
        throw new Exception(ErrorCode.NOT_AVAILABLE, url);
    }
}

I put it NULL because GET method not send any JSON request body/headers:

我把它设为 NULL,因为 GET 方法不发送任何 JSON 请求正文/标头:

restTemplate.exchange(url, HttpMethod.GET, null, String.class);

OR: put your headers in GET method like this:

或:将您的标题放在 GET 方法中,如下所示:

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<?> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);

For Example for POST you need to set requestEntity like below:

对于 POST 示例,您需要设置 requestEntity 如下:

ItemFormRequest request =
            new ItemFormRequest(1,"item no", "item name");
HttpEntity<ItemFormRequest> requestEntity = new HttpEntity<>(request);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        String responseBody = response.getBody();

Hope this help :)

希望这有帮助:)