Spring RestTemplate обменивается POST HttpClientException с любым ответом не 200 OK - PullRequest
0 голосов
/ 19 мая 2018

Таким образом, текущая проблема, с которой я сталкиваюсь, заключается в том, что я получаю

Servlet.service () для сервлета [dispatcherServlet] в контексте с исключением пути path [] [Обработка запроса не удалась;вложенное исключение - org.springframework.web.client.HttpClientErrorException: 404 null] с первопричиной org.springframework.web.client.HttpClientErrorException 404 null

в моем клиентском коде что-либо отвечает с любым кодом, отвечающим моим серверомкроме ответа OK 200.Так что в этом случае я намеренно возвращал ответ 404 в своем коде сервера, сделав это с заголовком и телом, без заголовка и тела, но я все еще получаю то же исключение с кодом состояния HTTP, с которым я отвечаю в коде сервера иnull, который в этом случае я предполагаю, чтобы быть телом ответа.Первоначально в своем серверном коде я всегда возвращал ResponseEntity<>("Sent", HttpStatus.OK), но поскольку в своем серверном коде я делаю HTTP-запрос в другом месте, если он отвечает чем-либо, кроме 200 OK, тогда мой клиентский код не будет знать об этом, поэтому вместо этого я возвращаюфактический ответ, возвращаемый из HTTP-запроса в коде моего сервера, обратно в код моего клиента, когда я столкнулся с этой проблемой.

Код клиента

public String callFruitBasket(Fruit fruitRequest) {
    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.setContentType(MediaType.APPLICATION_JSON);

    HttpEntity<Fruit> fruit = new HttpEntity<>(fruitRequest, requestHeaders);
    System.out.println("Fruit headers: " + fruit.getHeaders());

    ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
    System.out.println("Full response: " + response);

    return response.getBody();
}

Код сервера

@PostMapping("/fruitBasket/send")
public ResponseEntity<String> sendFruitBasket(@RequestBody Fruit fruit) {
   // works fine, old response
   // return new ResponseEntity<>("Sent", HttpStatus.OK);

   return new ResponseEntity<>("Baaad Request", HttpStatus.BAD_REQUEST);
}

Так что на данный момент в моем коде сервера я не сделалНе добавляю никаких заголовков к моему ответу, но я уже пробовал это с добавлением Content-Type, однако я обнаружил, что все еще получаю то же исключение в своем клиентском коде, поэтому я на 100% уверен, что проблема лежит где-то в моем клиентском коде.Первоначально, когда я передал ответ 200 OK, распечатка полного ответа была в порядке в коде клиента с отображением:

Full Response: <200 OK,Sent,{Content-Type=[text/plain;charset=UTF-8], Content-Length=[4], Date=[Sat, 19 May 2018 09:10:21 GMT]}>

Что бы я ожидал от любого другого кода статуса Http, такого как 400 и 404, будетто же самое, но с ответом 400 или 404 вместо 200 OK.Я попытался поиграться с заголовками как клиентского, так и серверного кода, так как я читал в различных постах здесь, что это обычно является причиной получения такого типа исключения, которое наводит меня на мысль, что в моем клиенте может быть что-то фундаментальное, упущенноекод или что это ожидаемое поведение для exchange () и что я неправильно понимаю.

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Поведение RestTemplate по умолчанию при обнаружении кодов ответа об ошибке выдает исключение.В случае 4xx это HttpClientErrorException, а в случае 5xx: HttpServerErrorException (оба расширяются HttpStatusCodeException).Spring достигает этого, используя ResponseErrorHandler (и его имплементация по умолчанию - DefaultResponseErrorHandler )

Один из способов справиться с этим - поймать их:

try {
    ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch(HttpClientErrorException e) {
    //handle 4xx errors
} catch(HttpServerErrorException e) {
    //handle 5xx errors
}

Если вам нужно настроить это поведение (некоторые остальные API используют эти коды при отправке законных ответов на некоторые запросы, которые затем могут потребоваться обрабатывать, как вы делаете с ответом 2xx), вы можете создать собственную реализацию ResponseErrorHandler, реализовавэто или расширение DefaultResponseHandler, а затем регистрация вашего обработчика с помощью RestTemplate во время его инициализации:

public class MyResponseErrorHandler extends DefaultResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        // check if response code is an error in here or just use default implementation
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // handle different response codes
        // (default spring behaviour is throwing an exception)
    }
}

И регистрация:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyResponseErrorHandler());
// now RestTemplate's behaviour for error status codes is customized
0 голосов
/ 19 мая 2018

Здесь нет ничего плохого.Это исключение будет сгенерировано, если вы получите ошибочный код состояния.

Вам просто нужно обернуть код на стороне клиента в try-catch и перехватить исключение, а затем делать все, что вы хотите с ним сделать.

try {
    ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch (HttpStatusCodeException e) {
    e.getMessage();
}
...