Итак, текущая проблема, с которой я столкнулся, заключается в том, что я получаю
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 null] with root cause 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 Status, такого как 400 и 404, будет таким же, но с 400 или 404 в ответе вместо 200 OK. Я пробовал поиграть с заголовками как в клиентском, так и в серверном коде, поскольку я читал в различных сообщениях здесь, что это обычно является причиной получения такого типа исключения, что заставляет меня думать, что в моем клиенте может быть чего-то фундаментального. code или что это ожидаемое поведение для exchange () и что я неправильно его понимаю.
@Art Решил проблему, спасибо, добавив try catch, я могу получить все из исключения.




Здесь нет ничего плохого. Это исключение будет выдано, если вы получите ошибочный код состояния.
Вам просто нужно обернуть свой клиентский код в try-catch и перехватить исключение, а затем сделать с ним все, что вы хотите.
try {
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch (HttpStatusCodeException e) {
e.getMessage();
}
Ура, мне не пришло в голову заключить исключение в try catch> <
Поведение 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
Спасибо за ответ, я должен быть в порядке с попыткой catch @htshame, упомянутой уже протестировавшей его, но приятно знать, что я могу настроить его дальше, если это необходимо.
Вы не получаете правильный код ответа и сообщение, а каждый раз получаете 400? Можете ли вы также сказать, как вы инициализировали RestTemplate.