有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JSON中RestTemplate中的java GET请求

一个看似超级直截了当的问题已经困扰了几天:

我在application/json中使用RestTemplate发出一个简单的GET请求,但我一直在获取

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)

我做了研究并遵循了这个tutorial,我还研究了这个POST request via RestTemplate in JSON的解决方案。但他们都没有帮助,以下是我的代码:

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

endpointhttp://localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8")在邮递员中效果很好。 itemIds是一个逗号分隔的列表,如下所示:

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

我还尝试使用getForObject,如下所示:

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

这给了我一个错误:

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

我不确定我错过了什么或做错了什么,但同一个端点在Postman上运行得很好,但唯一的区别是我在Postman应用程序中添加了Content Type header

这是我从邮递员那里得到的请求:

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

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

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

邮递员的请求:request from Postman

来自Java代码的请求:request from Java program

我仍然不明白为什么我Java程序中的一个抛出400,而Postman程序中的一个运行良好

非常感谢


共 (2) 个答案

  1. # 1 楼答案

    好的,最终,我的一位同事帮我弄明白了为什么,信不信由你,事情很简单:

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

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

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

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

    来自

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

    在使用RestTemplate时,我们不需要使用URLEncoder来编码URL,任何人都可以在这里帮助我加深理解吗

    谢谢

  2. # 2 楼答案

    您不需要为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);
        }
    }
    

    我将其设置为NULL,因为GET方法不发送任何JSON请求正文/标题:

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

    或:将标题放在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);
    

    例如,对于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();
    

    希望这有帮助:)