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

使用java.net.URL时如何打印User-Agent请求头?

如何记录java.net.URL请求的User-Agent头信息?

问题背景

我用java.net.URL打开URL时,尝试通过connection.getRequestProperties()记录请求头,但没有任何输出。调试时能看到请求头存在于connection.delegate.http.requests中,想用反射读取delegate字段,却遇到模块权限错误:

Unable to make field private final sun.net.www.protocol.https.DelegateHttpsURLConnection sun.net.www.protocol.https.HttpsURLConnectionImpl.delegate accessible: module java.base does not "opens sun.net.www.protocol.https" to unnamed module 

即使添加了--add-exports java.base/sun.net.www.protocol.https=ALL-UNNAMED参数也没用,想知道怎么记录User-Agent的值。


解决方法

1. 手动设置时直接记录

如果是你自己设置的User-Agent,在设置后直接打印即可,简单可靠:

URLConnection connection = new URL("https://example.com").openConnection();
// 自定义User-Agent
String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36";
connection.setRequestProperty("User-Agent", userAgent);
// 直接记录
LOGGER.info("User-Agent: {}", userAgent);

InputStream is = connection.getInputStream();

2. 获取JDK默认的User-Agent

JDK会默认使用系统属性http.agent作为User-Agent,直接读取这个属性就能拿到默认值:

String defaultUserAgent = System.getProperty("http.agent");
LOGGER.info("Default User-Agent: {}", defaultUserAgent);

这个值就是JDK自动添加到请求里的User-Agent。

3. 修正反射参数(不推荐生产环境)

之前用--add-exports不对,需要用--add-opens来开放内部包的字段访问权限,在VM参数里添加:

--add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED
--add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED

然后用反射读取内部字段:

import org.apache.commons.lang3.reflect.FieldUtils;
import sun.net.www.protocol.http.HttpURLConnection;
import sun.net.www.protocol.https.DelegateHttpsURLConnection;

// 确保connection是HttpsURLConnectionImpl实例
if (connection instanceof sun.net.www.protocol.https.HttpsURLConnectionImpl) {
    try {
        // 读取delegate字段
        DelegateHttpsURLConnection delegate = (DelegateHttpsURLConnection) FieldUtils.readField(connection, "delegate", true);
        // 读取delegate里的http字段
        HttpURLConnection httpConn = (HttpURLConnection) FieldUtils.readField(delegate, "http", true);
        // 获取请求列表里的第一个请求对象
        Object request = ((List<?>) FieldUtils.readField(httpConn, "requests", true)).get(0);
        // 读取User-Agent
        String userAgent = (String) FieldUtils.readField(request, "userAgent", true);
        LOGGER.info("User-Agent from internal: {}", userAgent);
    } catch (IllegalAccessException | IndexOutOfBoundsException e) {
        LOGGER.error("Failed to read User-Agent", e);
    }
}

注意:这种方式依赖JDK内部实现,不同版本可能失效,不建议生产环境用。

4. 开启JDK内部日志(推荐)

JDK的sun.net.www.protocol.http.HttpURLConnection会在DEBUG级别输出完整请求信息,包括所有请求头。只要在日志框架里开启对应的日志级别就行:
比如用Logback的话,在logback.xml里加:

<logger name="sun.net.www.protocol.http.HttpURLConnection" level="DEBUG"/>

这样日志里会自动输出请求的User-Agent等头信息。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 03:06:07