如何统计Java应用发起的所有HTTP/HTTPS请求?
统计Java应用所有HTTP/HTTPS请求的简便方法
方案1:字节码增强(无需修改业务代码,覆盖所有HTTP库)
如果你的应用混用了多种HTTP客户端(HttpURLConnection、OkHttp、Apache HttpClient、Java 11+ HttpClient等),字节码增强是最省心的方案——它能在JVM层面拦截所有HTTP请求的核心方法,自动计数,不用逐个修改业务代码。
以ByteBuddy为例,实现一个Agent来拦截常见HTTP客户端的请求方法:
import net.bytebuddy.agent.ByteBuddyAgent; import net.bytebuddy.ByteBuddy; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatchers; import java.lang.instrument.Instrumentation; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicInteger; public class HttpRequestCounterAgent { private static final AtomicInteger requestCount = new AtomicInteger(0); public static void premain(String args, Instrumentation inst) { // 拦截HttpURLConnection的connect方法 new ByteBuddy() .redefine(java.net.HttpURLConnection.class) .method(ElementMatchers.named("connect")) .intercept(MethodDelegation.to(Interceptor.class)) .make() .installOn(inst); // 拦截OkHttp的Call.execute()和enqueue() new ByteBuddy() .redefine(okhttp3.Call.class) .method(ElementMatchers.named("execute").or(ElementMatchers.named("enqueue"))) .intercept(MethodDelegation.to(Interceptor.class)) .make() .installOn(inst); // 拦截Java 11+ HttpClient的send()和sendAsync() new ByteBuddy() .redefine(java.net.http.HttpClient.class) .method(ElementMatchers.named("send").or(ElementMatchers.named("sendAsync"))) .intercept(MethodDelegation.to(Interceptor.class)) .make() .installOn(inst); } public static class Interceptor { public static Object intercept(@Origin Method method, @AllArguments Object[] args, @SuperCall Callable<?> callable) throws Exception { requestCount.incrementAndGet(); return callable.call(); } } // 对外提供获取计数的方法 public static int getRequestCount() { return requestCount.get(); } }
使用时,把Agent打包成jar,启动应用时添加JVM参数:-javaagent:http-request-counter-agent.jar,就能自动统计所有请求。
方案2:针对各HTTP客户端添加拦截器(需适配对应库)
如果不想用字节码增强,可以给每个使用的HTTP客户端添加专属拦截器,统一计数:
- OkHttp:添加自定义Interceptor
AtomicInteger requestCount = new AtomicInteger(0); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(chain -> { requestCount.incrementAndGet(); return chain.proceed(chain.request()); }) .build();
- Java 11+ HttpClient:添加请求过滤器
AtomicInteger requestCount = new AtomicInteger(0); HttpClient client = HttpClient.newBuilder() .filter((req, next) -> { requestCount.incrementAndGet(); return next.send(req, HttpResponse.BodyHandlers.ofString()); }) .build();
- Apache HttpClient:添加请求拦截器
AtomicInteger requestCount = new AtomicInteger(0); CloseableHttpClient client = HttpClientBuilder.create() .addInterceptorFirst((request, context) -> requestCount.incrementAndGet()) .build();
这种方式需要确保所有HTTP客户端实例都添加了拦截器,适合对代码可控的场景。
方案3:自定义URLStreamHandlerFactory(覆盖HttpURLConnection)
如果你的应用主要基于HttpURLConnection,可以通过自定义URLStreamHandlerFactory来拦截所有HTTP/HTTPS请求:
AtomicInteger requestCount = new AtomicInteger(0); URL.setURLStreamHandlerFactory(protocol -> { if ("http".equals(protocol) || "https".equals(protocol)) { return new sun.net.www.protocol.http.Handler() { @Override protected URLConnection openConnection(URL u) throws IOException { requestCount.incrementAndGet(); return super.openConnection(u); } }; } return null; });
注意:这个方法需要在应用启动时尽早调用,且JVM层面仅允许调用一次。
内容的提问来源于stack exchange,提问作者Volodya Lombrozo
相关产品推荐
相关产品推荐

