已解决java.net.HttpRetryException异常的正确解决方法,亲测有效!!!

已解决java.net.HttpRetryException异常的正确解决方法,亲测有效!!!

文章目录

问题分析

报错原因

解决思路

解决方法

总结


在使用Java进行HTTP编程时,我们可能会遇到各种类型的异常。其中,java.net.HttpRetryException是一个特殊的IO异常,发生在HTTP请求需要重新发送但不能自动处理时。本文将根据问题分析、报错原因、解决思路和解决方法四个方面详细讨论这个问题。

问题分析

假设你正在编写一个Java程序,该程序用于向一个HTTP服务器发送POST请求。你首先创建了一个HttpURLConnection对象,然后设置请求方式为"POST",填充输出流并发送请求。代码可能如下:

import java.net.*;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            URL url = new URL("http://www.example.com");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);

            OutputStream os = conn.getOutputStream();
            // 填充输出流...
            
            conn.connect();
            // 处理响应...
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

当你运行此代码时,如果服务器返回了一个需要重新请求(比如HTTP 307/308临时重定向)但HttpURLConnection无法自动处理的状态码,你收到以下错误消息:

  

java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1681) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1595) at Main.main(Main.java:15)

  

在这个例子中,错误发生的原因是HttpURLConnection对象试图自动处理HTTP重定向,但由于正在流模式(streaming mode)下发送数据,所以不能重新发送请求。

报错原因

根据Java官方文档,java.net.HttpRetryException异常在以下情况下抛出:

  • HTTP协议需要重新发送一个请求,但无法自动执行。这通常发生在接收到某些特定的HTTP响应码(如307 Temporary Redirect和308 Permanent Redirect)但当前处于流模式发送数据时。
  • HTTP服务器要求认证。当服务器返回401 Unauthorized或者407 Proxy Authentication Required响应,并且缺失有效的认证信息时,也会抛出此异常。

在我们的问题中,报错原因是处于流模式下的POST请求遇到了HTTP重定向。

解决思路

解决java.net.HttpRetryException异常的关键在于理解并解决其抛出条件。具体来说,有两种可能的策略:

  1. 避免处于流模式下的HTTP请求遇到重定向。你可以考虑关闭HttpURLConnection的自动重定向功能,并手动处理重定向。
  2. 提供正确的认证信息,以满足服务器的认证要求。

解决方法

基于上述解决思路,我们可以通过以下步骤解决问题:

  1. 关闭HttpURLConnection的自动重定向功能。添加conn.setInstanceFollowRedirects(false);语句。

  2. 手动处理HTTP重定向。在连接后,检查HTTP响应码并根据需要处理重定向。

  3. 如果服务器要求认证,提供有效的认证信息。

修改后的代码如下:

import java.net.*;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            URL url = new URL("http://www.example.com");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setInstanceFollowRedirects(false);  // 关闭自动重定向

            OutputStream os = conn.getOutputStream();
            // 填充输出流...
            
            conn.connect();
            int responseCode = conn.getResponseCode();
            // 处理响应...
            if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP
                    || responseCode == HttpURLConnection.HTTP_MOVED_PERM) {
                // 手动处理HTTP重定向
                String location = conn.getHeaderField("Location");
                url = new URL(location);
                conn = (HttpURLConnection) url.openConnection();
                // 重新发送请求...
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,我们首先关闭了HttpURLConnection的自动重定向功能。然后,在收到HTTP 307或308响应时,从"Location"头获取新的URL,并重新建立连接。

总结

总的来说,java.net.HttpRetryException异常发生在需要重新发送HTTP请求但无法自动处理时。解决这个问题的关键是理解你的HTTP请求何时以及如何引发此异常,并据此修改代码,例如关闭自动重定向、手动处理重定向、提供有效的认证信息等。

以上是此问题报错原因的解决方法,欢迎评论区留言讨论是否能解决,如果本文对你有帮助 欢迎 关注 、点赞 、收藏 、评论, 博主才有动力持续记录遇到的问题!!!

博主v:XiaoMing_Java

 ??作者简介:嗨,大家好,我是 小明java问道之路互联网大厂后端研发专家,2022博客之星TOP3 / 博客专家 / CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网5万粉丝博主。


?? 文末获取联系 ??  ???? 精彩专栏推荐订阅收藏 ????

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

??Redis从入门到精通与实战??

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

??MySQL从入门到精通??

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

??计算机底层原理??

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

??数据结构与企业题库精讲??

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

??互联网架构分析与实战??

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

??Java全栈白宝书??

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术