You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jsoup捕获HttpStatusException时获取Retry-After响应头?

解决Jsoup 429状态下获取Retry-After响应头的问题

核心思路:忽略HTTP错误码,直接获取响应对象

默认情况下,Jsoup遇到4xx/5xx状态码会抛出HttpStatusException,导致无法拿到响应头。通过ignoreHttpErrors(true)配置,可让Jsoup不抛出异常,直接返回包含错误状态的Connection.Response,从而正常读取响应头。

修改后的代码示例

Connection.Response response = Jsoup.connect(urlstr)
        .ignoreHttpErrors(true) // 关键设置:不抛出HTTP错误异常
        .execute();

int statusCode = response.statusCode();
if (statusCode == 200) {
    // 请求成功,处理响应内容
} else if (statusCode == 429) {
    // 获取Retry-After头
    String retryAfter = response.headers().get("Retry-After");
    if (retryAfter != null) {
        // 解析延迟时长(支持秒数或HTTP日期格式)
        try {
            long delaySeconds = Long.parseLong(retryAfter);
            Thread.sleep(delaySeconds * 1000);
        } catch (NumberFormatException e) {
            // 日期格式解析失败时用默认延迟
            Thread.sleep(60 * 1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
} else {
    // 处理其他错误状态码
}

补充说明

  • ignoreHttpErrors(true)会让Jsoup返回所有状态码的响应,需自行判断状态码区分成功/失败场景。
  • Retry-After头有两种格式:秒数字符串(如120)或HTTP日期字符串(如Fri, 01 Jan 2025 12:00:00 GMT),需根据实际情况解析。
  • 若必须保留原异常捕获逻辑,可通过反射访问HttpStatusException内部的response字段(不推荐,依赖内部实现易失效):
catch (final HttpStatusException e) {
    if (e.getStatusCode() == 429) {
        try {
            Field responseField = HttpStatusException.class.getDeclaredField("response");
            responseField.setAccessible(true);
            Connection.Response errorResponse = (Connection.Response) responseField.get(e);
            String retryAfter = errorResponse.headers().get("Retry-After");
            // 处理延迟逻辑
        } catch (NoSuchFieldException | IllegalAccessException ex) {
            // 反射失败时的降级处理
        }
    }
}

内容的提问来源于stack exchange,提问作者JonB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:15:01