Last active
February 10, 2021 04:16
-
-
Save twiceyuan/98e4620ca9a5b11409b7385239517498 to your computer and use it in GitHub Desktop.
[Chain Demo Code] 模拟 OkHttp 中 Interceptor 的工作原理 #Java #Pattern
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
resp前缀1=(resp前缀2=(resp前缀3=(resp(req前缀3=(req前缀2=(req前缀1=(twiceYuan))))))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interceptor1: request -> Hello | |
interceptor2: request -> [Hello] | |
---------------- Real Call ---------------- | |
interceptor2: response -> [Hello]'s response | |
interceptor1: response -> {[Hello]'s response} | |
Request Success: {[Hello]'s response} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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