Обнаружение прерывания HTTP в Java
Я делаю вызов REST для внешней системы с Java. Если есть какие-либо прерывания соединения, например, если внешняя система отключена, мне нужен прослушиватель, чтобы обнаружить это и выполнить соответствующие действия. Пожалуйста, дайте мне знать, смогу ли я достичь этого на Java. Предпочтительно в Java 8.
В настоящее время я не получаю никаких исключений, если попаду в такую ситуацию. У меня есть код ниже
Client client = ClientBuilder.newClient();
WebTarget target = client.target(HOSTNAME);
Invocation.Builder requestBuilder;
requestBuilder = target.path(URL).request(MediaType.APPLICATION_JSON)
.header(HEADER_AUTHORIZATION, AUTH_TOKEN);
Response response = null;
if (HTTP_POST.equalsIgnoreCase(method)) {
try{
response = requestBuilder.post(Entity.entity(message, MediaType.APPLICATION_JSON_TYPE));
}catch(Exception ex ){
ex.printStackTrace();
}
} else if (HTTP_GET.equalsIgnoreCase(method)) {
response = requestBuilder.get();
}
String executeMessage = null;
if(response != null){
if (response.getStatus() == 200) {
executeMessage = response.readEntity(String.class);
return new JSONObject(executeMessage);
} else {
executeMessage = response.readEntity(String.class);
final JSONObject status = new JSONObject();
status.put(STATUS_CODE, response.getStatus());
status.put(STATUS_INFO, response.getStatusInfo());
status.put("response", executeMessage);
final JSONObject error = new JSONObject();
error.put(ERROR, status);
return error;
}
}
Ответы
Ответ 1
Если вы используете Spring Boot, вы можете попробовать декларативный клиент REST под названием Feign:
@FeignClient(url = "example.com", fallback = YourTestFeignClient.YourTestFeignClientFallback.class)
public interface YourTestFeignClient {
@RequestMapping(method = RequestMethod.POST, value = "/example/path/to/resource/{id}")
YourTestResponse requestExternalResource(@RequestParam("id") Long id, SomeRequestDTO requestDTO);
@Component
public static class YourTestFeignClientFallback implements YourTestFeignClient {
@Override
public YourTestResponse requestExternalResource(Long id, SomeRequestDTO requestDTO) {
YourTestResponse testResponse = new YourTestResponse();
testResponse.setMessage("Service unavailable");
return testResponse;
}
}
}
Все, что вам нужно сделать, это ввести YourTestFeignClient
в свой код и вызвать метод requestExternalResource
на нем. Это вызовет POST example.com/example/path/to/resource/34
с телом JSON, взятым из SomeRequestDTO
. В случае, если запрос не выполнен, возвращается метод возврата внутри YourTestFeignClientFallback
, который затем возвращает некоторые данные по умолчанию.
Ответ 2
Вы можете создать свой собственный прослушиватель и сделать асинхронные вызовы Http с результатами, переданными обратно вызывающему классу, когда HTTP-ответ/ошибка будет готова. Например (с опечатками):
Создайте интерфейс, который будет реализован вашим основным классом, и ваш Http-клиент будет использовать...
public interface MyHttpListener {
public httpComplete(MyHttpResults results);
}
Реализовать в своем основном классе.
public MyClass implements MyHttpListener {
public void processHttpRequests(){
for(int i=0; i<10; i++){
// instantiate your Http Client class
HttpClient client = new HttpClient();
// register the listener
client.addHttpListener(this);
// execute whatever URL you want and you are notified later when complete
client.executeRequest("http://whatever");
}
}
public httpRequestComplete(MyHttpResults results) {
// do something with the results
results.getResponseCode();
results.getRawResponse();
results.whatever();
}
}
Добавить метод в ваш HttpClient для приема слушателей
public class MyHttpClient {
List<MyHttpListener> httpListenerList = new ArrayList();
// register listeners
public void addHttpListener(MyHttpListener listener){
httpListenerList.add(listener);
}
// this is the method that processes the request
public void executeRequest(String url) {
// do whatever you were doing previously here
// optional POJO to wrap the results and/or exceptions
MyHttpResults results = new MyHttpResults();
results.withResponseCode(response.getResponseCode());
results.withResponse(responseAsString);
results.withException(ex);
results.withWhatever(whatever);
// notify listeners
notify(results);
}
public void notify(MyHttpResults results){
// notify listeners
for(MyHttpListener listener : httpListenerList){
listener.httpComplete(results);
}
}
}
Ответ 3
Если вы хотите постоянно проверять внешнюю службу REST, независимо от того, находится ли она в автономном режиме, вам нужно настроить какой-то периодический запрос ping. Любой ответ будет означать, что услуга находится в режиме онлайн. Отсутствие ответа в течение некоторого периода времени будет означать, что что-то не так.
Проблема, с которой вы сталкиваетесь, возникает из-за того, что метод java TCP Socket connect
блокируется и время ожидания подключения по умолчанию java socket равно 0, что на самом деле бесконечно, как сказано в javadoc.
Таким образом, это означает, что вы не получите никакого ответа по умолчанию, если служба отключена.
Единственный правильный и простой вариант - установить тайм-аут. В вашем случае самым простым способом было бы использовать настройку свойств Jersey Client
, например:
Client client = ClientBuilder.newClient();
// One second timeout may not be a really good choice unless your network is really fast
client.property(ClientProperties.CONNECT_TIMEOUT, 1000);
И только в этом случае вы получите исключение, которое укажет, что служба REST, которую вы пытаетесь выполнить ping, не принимает соединения.
Установите тайм-аут с осторожностью в соответствии с реальными возможностями сети, в некоторых случаях это должно быть более 5 или даже 15 секунд (например, WiFi и GPRS-соединения).