java.io.IOException: время ожидания соединения истекло VS HttpTimeoutException на HTTP-клиенте java 11

Я использую http-клиент Java 11 (java.net.http).

Метод send() объявляет эти исключения:

@throws IOException
@throws InterruptedException
@throws IllegalArgumentException
@throws SecurityException

Меня интересует отлов исключений, вызванных тайм-аутом. Я подумал, что лучший способ сделать это — поймать HttpTimeoutException (расширяет IOException)

Однако иногда я вижу, что когда происходит тайм-аут, возникает исключение:

java.io.IOException: Connection timed out

Теперь мне интересно:

  1. Почему возникает более общее исключение?
  2. Как должен быть написан catch, чтобы убедиться, что все возможные исключения, связанные с тайм-аутом, перехвачены?

person user12396421    schedule 31.08.2020    source источник
comment
Ваше предложение catch может учитывать IOException|HttpTimeoutException| InterruptedByTimeoutException|TransportTimeoutException — это унаследованные исключения тайм-аута от IOExceptions, могут быть и другие унаследованные исключения InterruptedException docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/   -  person planben    schedule 31.08.2020


Ответы (1)


@Override
public <T> HttpResponse<T>
send(HttpRequest req, BodyHandler<T> responseHandler)
    throws IOException, InterruptedException
{
    CompletableFuture<HttpResponse<T>> cf = null;
    try {
        cf = sendAsync(req, responseHandler, null, null);
        return cf.get();
    } catch (InterruptedException ie) {
        if (cf != null )
            cf.cancel(true);
        throw ie;
    } catch (ExecutionException e) {
        final Throwable throwable = e.getCause();
        final String msg = throwable.getMessage();

        if (throwable instanceof IllegalArgumentException) {
            throw new IllegalArgumentException(msg, throwable);
        } else if (throwable instanceof SecurityException) {
            throw new SecurityException(msg, throwable);
        } else if (throwable instanceof HttpConnectTimeoutException) {
            HttpConnectTimeoutException hcte = new HttpConnectTimeoutException(msg);
            hcte.initCause(throwable);
            throw hcte;
        } else if (throwable instanceof HttpTimeoutException) {
            throw new HttpTimeoutException(msg);
        } else if (throwable instanceof ConnectException) {
            ConnectException ce = new ConnectException(msg);
            ce.initCause(throwable);
            throw ce;
        } else if (throwable instanceof SSLHandshakeException) {
            // special case for SSLHandshakeException
            SSLHandshakeException he = new SSLHandshakeException(msg);
            he.initCause(throwable);
            throw he;
        } else if (throwable instanceof SSLException) {
            // any other SSLException is wrapped in a plain
            // SSLException
            throw new SSLException(msg, throwable);
        } else if (throwable instanceof IOException) {
            throw new IOException(msg, throwable);
        } else {
            throw new IOException(msg, throwable);
        }
    }
}

См. метод ниже, который является внутренним методом HttpClientImpl.java. Обрабатывайте все исключения, которыми вы хотите управлять, и, соответственно, вы можете реализовать свой код.

Если вы обрабатываете HttpConnectTimeoutException, IOException, HttpTimeoutException, вы защищены.

person omkarjoshi    schedule 31.08.2020
comment
Вы имеете в виду отлов IOException и поиск в сообщении, если оно содержит тайм-аут соединения? - person user12396421; 31.08.2020
comment
Это был бы плохой дизайн, поскольку вы можете построить свою обработку исключений на основе некоторого сообщения, которое может измениться в будущем. Реализуйте только блок catch IOException и внутренне проверьте с помощью оператора instanceOf и внедрите там свою логику исключения (все остальные исключения, насколько я вижу, расширяют IOException. Таким образом, вам нужно реализовать только один блок catch). - person omkarjoshi; 31.08.2020
comment
Согласен, но я до сих пор не понимаю, как вы планируете определять время ожидания, когда оно приходит в виде java.io.IOException: время ожидания соединения истекло, перехват IOException недостаточно хорош, поскольку есть много причин для его выбрасывания - person user12396421; 31.08.2020
comment
Вы правы, когда выбрасывается IOException, единственный способ, которым вы можете идентифицировать на данный момент, основан на сообщении. - person omkarjoshi; 31.08.2020