Skip to content

Instantly share code, notes, and snippets.

@twiceyuan
Last active February 10, 2021 04:16
Show Gist options
  • Save twiceyuan/98e4620ca9a5b11409b7385239517498 to your computer and use it in GitHub Desktop.
Save twiceyuan/98e4620ca9a5b11409b7385239517498 to your computer and use it in GitHub Desktop.
[Chain Demo Code] 模拟 OkHttp 中 Interceptor 的工作原理 #Java #Pattern
package com.twiceyuan.playground.kotlin.pattern.chain
data class Params(val requestName: String)
data class Result(
val responseBody: String
)
interface Interceptor<P, R> {
interface Chain<P, R> {
fun params(): P
fun params(params: P): R
}
fun intercept(chain: Chain<P, R>): R
}
class CallChain<P, R>(
private val finalChain: Interceptor.Chain<P, R>,
private val request: P,
private val interceptors: List<Interceptor<P, R>>,
private val index: Int
) : Interceptor.Chain<P, R> {
override fun params(): P {
return request
}
override fun params(params: P): R {
if (index == interceptors.size) {
return finalChain.params(params)
}
val next = CallChain(finalChain, params, interceptors, index + 1)
val interceptor = interceptors[index]
return interceptor.intercept(next)
}
}
object MockClient {
var interceptors = listOf<Interceptor<Params, Result>>()
fun request(request: Params): Result {
val finalChain = object: Interceptor.Chain<Params, Result> {
override fun params(): Params {
return request
}
override fun params(params: Params): Result {
return Result("resp(${params.requestName})")
}
}
return CallChain(finalChain, request, interceptors, 0).params(request)
}
}
fun main() {
MockClient.interceptors = listOf(
object : Interceptor<Params, Result> {
override fun intercept(chain: Interceptor.Chain<Params, Result>): Result {
val request = chain.params()
val response = chain.params(Params("req前缀1=(${request.requestName})"))
return Result("resp前缀1=(${response.responseBody})")
}
},
object : Interceptor<Params, Result> {
override fun intercept(chain: Interceptor.Chain<Params, Result>): Result {
val request = chain.params()
val response = chain.params(Params("req前缀2=(${request.requestName})"))
return Result("resp前缀2=(${response.responseBody})")
}
},
object : Interceptor<Params, Result> {
override fun intercept(chain: Interceptor.Chain<Params, Result>): Result {
val request = chain.params()
val response = chain.params(Params("req前缀3=(${request.requestName})"))
return Result("resp前缀3=(${response.responseBody})")
}
},
)
val response = MockClient.request(Params("twiceYuan"))
println(response.responseBody)
}
resp前缀1=(resp前缀2=(resp前缀3=(resp(req前缀3=(req前缀2=(req前缀1=(twiceYuan)))))))
interceptor1: request -> Hello
interceptor2: request -> [Hello]
---------------- Real Call ----------------
interceptor2: response -> [Hello]'s response
interceptor1: response -> {[Hello]'s response}
Request Success: {[Hello]'s response}
import java.util.ArrayList;
import java.util.List;
/**
* Created by twiceYuan on 2017/7/20.
* 参考 Python Decorator 重写后的版本
*/
public class PyRequestManager {
public static void main(String args[]) {
// 原始请求日志
MockServer.addInterceptor(chain -> request -> {
System.out.println("interceptor1: request -> " + request.body);
Response response = chain.proceed(request);
System.out.println("interceptor1: response -> " + response.body);
return response;
});
// Interceptor1 : 在参数体前后添加 []
MockServer.addInterceptor(chain -> request -> {
Request newRequest = new Request("[" + request.body + "]");
return chain.proceed(newRequest);
});
// Interceptor2 : 在响应体前后添加 {}
MockServer.addInterceptor(chain -> request -> {
Response response = chain.proceed(request);
return new Response("{" + response.body + "}");
});
// 最终请求日志
MockServer.addInterceptor(chain -> request -> {
System.out.println("interceptor2: request -> " + request.body);
Response response = chain.proceed(request);
System.out.println("interceptor2: response -> " + response.body);
return response;
});
Response response = MockServer.request(new Request("Hello"));
System.out.println("\nRequest Success: " + response.body);
}
static class MockServer {
static List<Interceptor> mInterceptors = new ArrayList<>();
static Response request(Request request) {
return request(request, mInterceptors);
}
static Response request(Request request, List<Interceptor> interceptors) {
Chain chain = realCall();
for (Interceptor interceptor : interceptors) {
chain = interceptor.call(chain);
}
return chain.proceed(request);
}
private static Chain realCall() {
return request -> {
System.out.println("---------------- Real Call ----------------");
return new Response(request.body + "'s response");
};
}
static void addInterceptor(Interceptor interceptor) {
mInterceptors.add(interceptor);
}
}
interface Interceptor {
Chain call(Chain chain);
}
interface Chain {
Response proceed(Request request);
}
static class Request {
String body;
Request(String body) {
this.body = body;
}
}
static class Response {
String body;
Response(String body) {
this.body = body;
}
}
}
import java.util.ArrayList;
import java.util.List;
/**
* Created by twiceYuan on 2017/7/20.
*/
public class RequestManager {
public static void main(String args[]) {
// 打印日志拦截器1
MockServer.addInterceptor(chain -> {
Request request = chain.request();
System.out.println("interceptor1: request -> " + request.body);
Response response = chain.proceed(request);
System.out.println("interceptor1: response -> " + response.body);
return response;
});
// Interceptor1 : 在请求体前后添加 []
MockServer.addInterceptor(chain -> {
Request request = new Request("[" + chain.request().body + "]");
return chain.proceed(request);
});
// Interceptor2 : 在响应体前后添加 {}
MockServer.addInterceptor(chain -> {
Response response = chain.proceed(chain.request());
return new Response("{" + response.body + "}");
});
// 打印日志拦截器2
MockServer.addInterceptor(chain -> {
Request request = chain.request();
System.out.println("interceptor2: request -> " + request.body);
Response response = chain.proceed(request);
System.out.println("interceptor2: response -> " + response.body);
return response;
});
Response response = MockServer.request(new Request("Hello"));
System.out.println("\nRequest Success: " + response.body);
}
static class MockServer {
static List<Interceptor> mInterceptors = new ArrayList<>();
static Response request(Request request) {
return request(request, mInterceptors);
}
static Response request(Request request, List<Interceptor> interceptors) {
if (interceptors.size() == 0) {
return realCall(request);
} else {
Interceptor interceptor = interceptors.get(0);
// 只要存在拦截器,就构造一个责任链
return interceptor.call(new Chain() {
@Override
public Request request() {
// 每个链中的请求都回调同一个对象,这样每次针对于请求做操作都是操作在同一个对象上
// 然后拦截器通过使用 proceed 传入处理后的请求,讲请求对象传给下一链
return request;
}
@Override
public Response proceed(Request request) {
// 传递给下一链时,从当前拦截器列表中删除当前拦截器
List<Interceptor> newInterceptors = new ArrayList<>(interceptors);
newInterceptors.remove(interceptor);
return MockServer.request(request, newInterceptors);
}
});
}
}
private static Response realCall(Request request) {
System.out.println("---------------- Real Call ----------------");
return new Response(request.body + "'s response");
}
static void addInterceptor(Interceptor interceptor) {
mInterceptors.add(interceptor);
}
}
interface Interceptor {
Response call(Chain chain);
}
interface Chain {
Request request();
Response proceed(Request request);
}
static class Request {
String body;
Request(String body) {
this.body = body;
}
}
static class Response {
String body;
Response(String body) {
this.body = body;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment