关于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不自动处理重定向。

相关推荐
许苑向上31 分钟前
Redisson 分布式锁底层原理实现详解
java·redis·分布式
守城小轩35 分钟前
Brave 132 编译指南 Android 篇 - 编译和运行 (七)
android·chrome·chrome devtools·指纹浏览器·浏览器开发·brave·隐私浏览器
P7进阶路36 分钟前
Spring全家桶简介
java·后端·spring
XuanRanDev4 小时前
【构建工具】Gradle 8中Android BuildConfig的变化与开启方法
android
非晓为骁4 小时前
【Android】Android Studio 中文乱码问题解决方案
android·ide·android studio
magic 2454 小时前
内存中的缓存区
java·开发语言
web150854159354 小时前
Spring Cloud Gateway
android·前端·后端
画个太阳作晴天4 小时前
Android13修改多媒体默认音量
android·framework
Dnelic-4 小时前
Android 数据库查询对比(APN案例)
android·数据库·数据库开发·telephony
m0_748238924 小时前
mysql的主从配置
android·mysql·adb