关于Java的HttpURLConnection重定向问题 响应码303

我有一个Java函数,发送了一个POST请求,并获取响应头的Headers,使用 java.net.http 库能正常运行。

伪代码如下

java 复制代码
private static String loginPhone() throws Exception {
        String url1 = "https://api-user.xxx";
        String data1 = String.format("xxx=%s&redirect_uri=%s&xxx=xxx", CLIENT_ID, REDIRECT_URI);

        HttpRequest request1 = HttpRequest.newBuilder()
                .uri(new URI(url1))
                .header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
                .header("User-Agent", USER_AGENT)
                .POST(HttpRequest.BodyPublishers.ofString(data1))
                .build();

        HttpResponse<String> response1 = HttpClient.newHttpClient().send(request1, HttpResponse.BodyHandlers.ofString());
        String location = response1.headers().firstValue("XXX").orElse("");

        return location;
    }

现在我想把代码移植到Android,但是由于Android取缔了java.net.http,只能用HttpURLConnection,所以要对代码进行修改。

修改后伪代码如下

java 复制代码
    private void loginPhone() throws Exception {
        String url1 = "https://api-user.xxxxx";
        String data1 = String.format("client_id=%s&redirect_uri=%s&xxx=xxx", CLIENT_ID, REDIRECT_URI);
        String location = sendPostRequest4Headers(url1, data1);
        System.out.println("location->" + location);
    }


    private String sendPostRequest4Headers(String urlStr, String data) throws Exception {
        HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", CONTENT_TYPE);
        connection.setRequestProperty("User-Agent", MI_FIT_USER_AGENT);
        connection.setDoOutput(true);

        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = data.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
            os.flush();
        }

        // 获取响应状态码
        int responseCode = connection.getResponseCode();
        System.out.println("responseCode->" + responseCode);

        if (responseCode == 303) {
            // 获取重定向的 URL
            String location = connection.getHeaderField("XXX");
            System.out.println("XXX->" + location);
            return location;
        } else {
            return "";
        }
    }

貌似一切顺利,但是获取的结果就是不一样。下面的,始终无法让响应码为303,始终是200。

表明通信成功?!没有重定向?

最后调试了很久,发现原来HttpURLConnection有一个函数 的**getInstanceFollowRedirects** 和**setInstanceFollowRedirects**。

隐约意识到这就是问题所在。

这两个函数的解释如下:

getInstanceFollowRedirects

  • 功能 :该方法用于获取HttpURLConnection实例是否自动遵循重定向的当前设置。在进行 HTTP 请求时,服务器可能会返回重定向响应,告知客户端请求的资源已移动到其他位置。此方法能让开发者了解当前连接是否会自动处理这些重定向。

  • 返回值 :返回一个boolean值,true表示当前实例会自动遵循重定向,即会自动根据服务器返回的重定向信息继续发送请求到新的地址;false则表示不会自动遵循,需要开发者手动处理重定向。

  • 示例

    HttpURLConnection connection = (HttpURLConnection) new URL("https://example.com").openConnection();
    boolean followRedirects = connection.getInstanceFollowRedirects();
    System.out.println("是否自动遵循重定向:" + followRedirects);

setInstanceFollowRedirects

  • 功能 :用于设置HttpURLConnection实例是否自动遵循重定向。通过此方法,开发者可以根据具体需求来决定连接在遇到重定向时的行为。

  • 参数 :接受一个boolean类型的参数,true表示设置该连接实例自动遵循重定向,false表示不自动遵循。

  • 示例

    HttpURLConnection connection = (HttpURLConnection) new URL("https://example.com").openConnection();
    connection.setInstanceFollowRedirects(false);
    // 进行连接等后续操作

在实际应用中,如果不想让连接自动处理重定向,以便自己对重定向进行更精细的控制,比如记录重定向的次数、检查重定向的目标等,就可以将其设置为false

看AI给的建议,将此处设为false。成功。

成功的伪代码:

java 复制代码
    private String sendPostRequest4Headers(String urlStr, String data) throws Exception {
        HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection();
        connection.setRequestMethod("POST");
        connection.setInstanceFollowRedirects(false);

        connection.setRequestProperty("Content-Type", CONTENT_TYPE);
        connection.setRequestProperty("User-Agent", USER_AGENT);
        connection.setDoOutput(true);

        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = data.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
            os.flush();
        }

        // 获取响应状态码
        int responseCode = connection.getResponseCode();
        System.out.println("responseCode->" + responseCode);

        if (responseCode == 303) {
            // 获取重定向的 URL
            String location = connection.getHeaderField("XXX");
            System.out.println("XXX->" + location);
            return location;
        } else {
            return "";
        }
    }

原来一直不一致,是因为进行了重定向处理,难道java.net.http 库不会自动重定向?

在 Java 的java.net.http库中,默认情况下,HttpClient进行 POST 请求时会自动处理重定向。

HttpClient遵循 HTTP 协议的重定向规则,当服务器返回重定向状态码(如 301、302、303、307、308 等)时,HttpClient会自动根据重定向的目标地址发起新的请求。

以下是一个简单的示例代码:

复制代码
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

public class HttpPostRedirectExample {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newBuilder().build();
        HttpRequest request = HttpRequest.newBuilder()
               .uri(URI.create("http://example.com/somePath"))
               .POST(HttpRequest.BodyPublishers.ofString("param=value"))
               .build();

        // 发送请求并获取响应
        CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
        HttpResponse<String> response = responseFuture.get();

        System.out.println("状态码: " + response.statusCode());
        System.out.println("响应体: " + response.body());
    }
}

在上述代码中,如果请求的地址发生了重定向,HttpClient会自动处理,最终response会包含重定向后的最终响应结果。

如果不想让HttpClient自动处理重定向,可以在创建HttpClient时通过followRedirects方法进行设置,例如:

复制代码
HttpClient client = HttpClient.newBuilder()
       .followRedirects(HttpClient.Redirect.NEVER)
       .build();

上述代码通过followRedirects(HttpClient.Redirect.NEVER)设置了HttpClient不自动处理重定向。

相关推荐
Kapaseker8 分钟前
扶我起来,Compose Styles API 进阶
android·kotlin
名字还没想好☜14 分钟前
Go 并发实战:用 channel 实现 worker pool
java·数据库·后端·golang·go
人道领域21 分钟前
【LeetCode刷题日记】贪心算法理论与实战:455.分发饼干最优解
java·开发语言·数据结构·算法·leetcode·贪心算法
_abab25 分钟前
Java面试宝典:从基础到架构2
java·面试·架构
亘元有量-流量变现32 分钟前
内外联动精细化运营:解锁安卓APP推广降本增效新路径
android·用户运营·aso优化·亘元有量·方糖试玩
nVisual40 分钟前
nVisual:AI驱动的智能排障,平均响应时间缩短40%
android·人工智能·缓存
万亿少女的梦16842 分钟前
基于Spring Boot与Vue的繁星技术论坛系统设计与实现
java·spring boot·mysql·vue·系统设计
阿pin1 小时前
Android随笔-神经系统Handler
android·java·开发语言·handler
ch.ju1 小时前
Java程序设计(第3版)第四章——final修饰的方法和类
java·开发语言