Building an Enterprise-Level OkHttp Interceptor System from Scratch: Dynamic Token, Retry Strategy, and In-Depth Source Code Analysis

Introduction

This article focuses on the OkHttp interceptor, building an enterprise-level network request framework from scratch. Through practical cases such as dynamic token management, intelligent retry strategies, and enhanced logging, combined with in-depth source code analysis, we will thoroughly explain the underlying logic and engineering applications of interceptors. The code examples cover the latest features of OkHttp 4.12.0, helping you solve complex scenarios in real projects and build a robust network layer architecture!

1. Core Concepts and Architecture Analysis

1.1 Dual-Link Model of Interceptors

OkHttp interceptors are divided into Application Interceptors and Network Interceptors, with the workflow as follows:

  • Application Interceptors: Globally effective, can modify request headers/parameters, and support caching responses (e.g., directly returning cached data without a network request)
  • Network Interceptors: Triggered only during network requests, bypassing cached responses, commonly used for protocol upgrades (e.g., HTTP/2) or compression processing

1.2 Interceptor Execution Chain Diagram

Building an Enterprise-Level OkHttp Interceptor System from Scratch: Dynamic Token, Retry Strategy, and In-Depth Source Code AnalysisEditor

The interceptor chain in the source code is managed by <span>RealInterceptorChain</span>, which includes core components such as <span>RetryAndFollowUpInterceptor</span> (retry and redirect), <span>BridgeInterceptor</span> (request encapsulation), and <span>CacheInterceptor</span> (cache control).

2. Setting Up the Development Environment from Scratch

2.1 Adding Dependencies

<!-- build.gradle configuration --
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
    implementation 'cn.hutool:hutool-http:5.8.19' // Hutool simplifies request parameter handling
}</code>

2.2 Basic Interceptor Implementation

// Custom interceptor: Add dynamic token
public class DynamicTokenInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        
        // 1. Get the current token (e.g., from SharedPreferences or singleton management)
        String token = TokenManager.getToken();
        
        // 2. Modify request header
        Request newRequest = originalRequest.newBuilder()
                .header("Authorization", "Bearer " + token)
                .build();
        
        // 3. Continue the request chain
        return chain.proceed(newRequest);
    }
}

2.3 Integrating into OkHttpClient

OkHttpClient client = new OkHttpClient.Builder()
        // Add application interceptor (globally effective)
        .addInterceptor(new DynamicTokenInterceptor())
        // Add network interceptor (e.g., logging interceptor)
        .addNetworkInterceptor(new LoggingInterceptor())
        // Set timeout policy
        .connectTimeout(30, TimeUnit.SECONDS)
        .build();

3. Advanced Enterprise-Level Practices

3.1 Dynamic Token Refresh Mechanism

// Automatically refresh and retry request when token expires
public class TokenRefreshInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        
        try {
            Response response = chain.proceed(request);
            
            // 1. Check if the token has expired (e.g., HTTP 401 status code)
            if (response.code() == 401) {
                // 2. Refresh token
                TokenManager.refreshToken();
                
                // 3. Rebuild request
                Request newRequest = request.newBuilder()
                        .header("Authorization", "Bearer " + TokenManager.getNewToken())
                        .build();
                
                // 4. Retry request
                return chain.proceed(newRequest);
            }
            
            return response;
        } catch (IOException e) {
            // Handle exceptions (e.g., network errors)
            throw e;
        }
    }
}

3.2 Intelligent Retry Strategy

// Custom retry interceptor (supports exponential backoff)
public class RetryInterceptor implements Interceptor {
    private static final int MAX_RETRY = 3;

    @Override
    public Response intercept(Chain chain) throws IOException {
        int retryCount = 0;
        
        while (true) {
            try {
                return chain.proceed(chain.request());
            } catch (IOException e) {
                if (++retryCount >= MAX_RETRY) {
                    throw e;
                }
                
                // Exponential backoff: retry after 2^retryCount seconds
                long backoff = (long) Math.pow(2, retryCount) * 1000;
                try {
                    Thread.sleep(backoff);
                } catch (InterruptedException ignored) {}
            }
        }
    }
}

3.3 Advanced Logging Interceptor

// Custom logging interceptor (supports JSON format output)
public class CustomLoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        long startTime = System.currentTimeMillis();
        
        // Print request information
        Log.d("OkHttp", "【Request Start】" + request.url());
        Log.d("OkHttp", "Headers: " + request.headers());
        
        Response response = chain.proceed(request);
        long duration = System.currentTimeMillis() - startTime;
        
        // Print response information
        Log.d("OkHttp", "【Response Complete】" + response.code() + " Duration: " + duration + "ms");
        if (response.body() != null) {
            Log.d("OkHttp", "Body: " + response.body().string());
        }
        
        return response;
    }
}

4. Performance Optimization and Source Code Analysis

4.1 Thread-Safe Handling

// Safe token management class (using AtomicReference)
public class TokenManager {
    private static final AtomicReference<string> token = new AtomicReference<>();

    public static void setToken(String newToken) {
        token.set(newToken);
    }

    public static String getToken() {
        return token.get();
    }
}</string>

4.2 Interceptor Execution Chain Source Code Analysis

The core of the OkHttp interceptor chain is <span>RealInterceptorChain</span>, and its execution process is as follows:

  1. RetryAndFollowUpInterceptor: Handles retries, redirects, and error recovery
  2. BridgeInterceptor: Converts user requests into HTTP protocol format
  3. CacheInterceptor: Decides whether to use cache based on caching strategy
  4. ConnectInterceptor: Establishes a connection with the server
  5. CallServerInterceptor: Executes the actual network request and reads the response

4.3 Interceptor Addition Order Control

// The order of adding interceptors affects execution logic
OkHttpClient client = new OkHttpClient.Builder()
        // First add token management interceptor
        .addInterceptor(new TokenRefreshInterceptor())
        // Then add retry interceptor
        .addInterceptor(new RetryInterceptor())
        // Finally add logging interceptor
        .addInterceptor(new CustomLoggingInterceptor())
        .build();

Conclusion

This article provides an in-depth analysis of the underlying principles and engineering applications of OkHttp interceptors, from setting up the environment from scratch to advanced enterprise-level practices. Through cases of dynamic token management, intelligent retry strategies, and source code execution chain analysis, it demonstrates how to flexibly apply interceptors in real projects. Mastering these skills will enable you to build a robust network layer architecture, solve complex problems in real scenarios, and enhance the maintainability and scalability of your code!

Leave a Comment