java.net.ConnectException: Failed to connect to /192.168.1.108:8888
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:297)
at okhttp3.internal.connection.RealConnection.connectTunnel(RealConnection.kt:261)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:201)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
...
省略若干行...大家一起想象下...
public T create(final Class service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
@Override
protected Object adapt(Call call, Object[] args) {
call = callAdapter.adapt(call);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation continuation = (Continuation) args[args.length - 1];
// Calls to OkHttp Call.enqueue() like those inside await and awaitNullable can sometimes
// invoke the supplied callback with an exception before the invoking stack frame can return.
// Coroutines will intercept the subsequent invocation of the Continuation and throw the
// exception synchronously. A Java Proxy cannot throw checked exceptions without them being
// declared on the interface method. To avoid the synchronous checked exception being wrapped
// in an UndeclaredThrowableException, it is intercepted and supplied to a helper which will
// force suspension to occur so that it can be instead delivered to the continuation to
// bypass this restriction.
try {
return isNullable
? KotlinExtensions.awaitNullable(call, continuation)
: KotlinExtensions.await(call, continuation);
} catch (Exception e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
suspend fun Call.await(): T {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val body = response.body()
if (body == null) {
val invocation = call.request().tag(Invocation::class.java)!!
val method = invocation.method()
val e = KotlinNullPointerException("Response from " +
method.declaringClass.name +
'.' +
method.name +
" was null but response body type was declared as non-null")
continuation.resumeWithException(e)
} else {
continuation.resume(body)
}
} else {
continuation.resumeWithException(HttpException(response))
}
}
override fun onFailure(call: Call, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
业务方调用======
val repo: Repo = AcRetrofit.get().notificationApi.loadSettings()
public inline fun T.runCatching(block: T.() -> R): Result {
return try {
Result.success(block())
} catch (e: Throwable) {
Result.failure(e)
}
}
以看到它是将闭包函数 try catch 后包装成 Result 密封类返回
kotlin.Result 类是一个设计和扩展方法很全面的类,在 kotlin 里面各种特性的 API 之间起了至关重要的作用,其实现如下
@JvmInline
public value class Result @PublishedApi internal constructor(
@PublishedApi
internal val value: Any?
) : Serializable {
// discovery
/**
* Returns `true` if this instance represents a successful outcome.
* In this case [isFailure] returns `false`.
*/
public val isSuccess: Boolean get() = value !is Failure
/**
* Returns `true` if this instance represents a failed outcome.
* In this case [isSuccess] returns `false`.
*/
public val isFailure: Boolean get() = value is Failure
// value & exception retrieval
/**
* Returns the encapsulated value if this instance represents [success][Result.isSuccess] or `null`
* if it is [failure][Result.isFailure].
*
* This function is a shorthand for `getOrElse { null }` (see [getOrElse]) or
* `fold(onSuccess = { it }, onFailure = { null })` (see [fold]).
*/
@InlineOnly
public inline fun getOrNull(): T? =
when {
isFailure -> null
else -> value as T
}
/**
* Returns the encapsulated [Throwable] exception if this instance represents [failure][isFailure] or `null`
* if it is [success][isSuccess].
*
* This function is a shorthand for `fold(onSuccess = { null }, onFailure = { it })` (see [fold]).
*/
public fun exceptionOrNull(): Throwable? =
when (value) {
is Failure -> value.exception
else -> null
}
/**
* Returns a string `Success(v)` if this instance represents [success][Result.isSuccess]
* where `v` is a string representation of the value or a string `Failure(x)` if
* it is [failure][isFailure] where `x` is a string representation of the exception.
*/
public override fun toString(): String =
when (value) {
is Failure -> value.toString() // "Failure($exception)"
else -> "Success($value)"
}
// companion with constructors
/**
* Companion object for [Result] class that contains its constructor functions
* [success] and [failure].
*/
public companion object {
/**
* Returns an instance that encapsulates the given [value] as successful value.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@InlineOnly
@JvmName("success")
public inline fun success(value: T): Result =
Result(value)
/**
* Returns an instance that encapsulates the given [Throwable] [exception] as failure.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@InlineOnly
@JvmName("failure")
public inline fun failure(exception: Throwable): Result =
Result(createFailure(exception))
}
internal class Failure(
@JvmField
val exception: Throwable
) : Serializable {
override fun equals(other: Any?): Boolean = other is Failure && exception == other.exception
override fun hashCode(): Int = exception.hashCode()
override fun toString(): String = "Failure($exception)"
}
}
HttpResult :密封类,保存了基础数据 Headers,T 是 API 方法定义的请求返回值类型
sealed class HttpResult(open val responseHeader: Headers?) : Serializable {
...
}
Success:接口请求成功,保存接口请求的 Header 原始数据和适配器解析后的接口 body 数据,T 是 API 方法定义的请求返回值类型
/**
* Success response with body
*/
data class Success(val value: T, override val responseHeader: Headers?) :
HttpResult(responseHeader) {
override fun toString(): String {
return "Success($value)"
}
override fun exceptionOrNull(): Throwable? = null
}
/**
* Failure response with body,通常是接口返回错误
* @property code Int 错误码,默认是-1
* @property message message 接口错误信息
* @property throwable 原始错误类型
* @constructor
*/
data class ApiError(
val code: Int = -1,
val message: String? = null,
val throwable: Throwable,
override val responseHeader: Headers? = null,
) :
HttpResult(responseHeader) {
override fun toString(): String {
return "ApiError(message:$message,code:$code)"
}
override fun exceptionOrNull(): Throwable = throwable
}
NetworkError:通常是断网了
/**
* For example, json parsing error
*/
data class UnknownError(
val throwable: Throwable?,
override val responseHeader: Headers? = null,
) : HttpResult(responseHeader) {
override fun toString(): String {
super.toString()
return "UnknownError(throwable:${throwable?.message})"
}
override fun exceptionOrNull(): Throwable? = throwable
}
/**
* For example, json parsing error
*/
data class UnknownError(
val throwable: Throwable?,
override val responseHeader: Headers? = null,
) : HttpResult(responseHeader) {
override fun toString(): String {
super.toString()
return "UnknownError(throwable:${throwable?.message})"
}
override fun exceptionOrNull(): Throwable? = throwable
}
综上所述,HttpResult整体实现如下
sealed class HttpResult(open val responseHeader: Headers?) : Serializable {
// discovery
/**
* Returns `true` if this instance represents a successful outcome.
* In this case [isFailure] returns `false`.
*/
val isSuccess: Boolean get() = this is Success
/**
* Returns `true` if this instance represents a failed outcome.
* In this case [isSuccess] returns `false`.
*/
val isFailure: Boolean get() = this !is Success
/**
* Success response with body
*/
data class Success(val value: T, override val responseHeader: Headers?) :
HttpResult(responseHeader) {
override fun toString(): String {
return "Success($value)"
}
override fun exceptionOrNull(): Throwable? = null
}
/**
* Failure response with body,通常是接口返回错误
* @property code Int 错误码,默认是-1
* @property message message 接口错误信息
* @property throwable 原始错误类型
* @constructor
*/
data class ApiError(
val code: Int = -1,
val message: String? = null,
val throwable: Throwable,
override val responseHeader: Headers? = null,
) :
HttpResult(responseHeader) {
override fun toString(): String {
return "ApiError(message:$message,code:$code)"
}
override fun exceptionOrNull(): Throwable = throwable
}
/**
* Network error 通常是断网了
*/
data class NetworkError(
val error: Throwable,
override val responseHeader: Headers? = null,
) : HttpResult(responseHeader) {
override fun toString(): String {
return "NetworkError(error:${error.message})"
}
override fun exceptionOrNull(): Throwable = error
}
/**
* For example, json parsing error
*/
data class UnknownError(
val throwable: Throwable?,
override val responseHeader: Headers? = null,
) : HttpResult(responseHeader) {
override fun toString(): String {
super.toString()
return "UnknownError(throwable:${throwable?.message})"
}
override fun exceptionOrNull(): Throwable? = throwable
}
fun getOrNull(): T? = (this as? Success)?.value
/**
* Returns the encapsulated [Throwable] exception if this instance represents [failure][isFailure] or `null`
* if it is [success][isSuccess].
*
* This function is a shorthand for `fold(onSuccess = { null }, onFailure = { it })` (see [fold]).
*/
open fun exceptionOrNull(): Throwable? = null
companion object {
fun success(result: T, responseHeader: Headers?): HttpResult =
Success(result, responseHeader)
fun apiError(
code: Int = -1,
message: String? = null,
throwable: Throwable,
responseHeader: Headers?
): HttpResult =
ApiError(code, message, throwable, responseHeader)
fun networkError(
error: Throwable, responseHeader: Headers?
): HttpResult =
NetworkError(error, responseHeader)
fun unknownError(
throwable: Throwable?, responseHeader: Headers?
): HttpResult =
UnknownError(throwable, responseHeader)
}
}
class SuspendCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array,
retrofit: Retrofit
): CallAdapter<*, *>? {
//第一个泛型就是HttpResult类,这种情况可能是api接口没有声明协程suspend符号,抛出异常提醒
if (getRawType(returnType) == HttpResult::class.java) {
throw IllegalArgumentException("Method must be declare suspend, please check function declaration at API interface")
}
//协程挂起函数默认返回值是Call<*>,如果不满足该条件,那么返回null让retrofit选择其他家伙来Py
if (Call::class.java != getRawType(returnType)) {
return null
}
//检查Call内部的泛型是否包含了其他泛型
check(returnType is ParameterizedType) {
"return type must be HttpResult<*> or HttpResult for Call<*> check"
}
//获取Call类包裹的第一个泛型
val responseType = getParameterUpperBound(0, returnType)
//Call类包裹的第一个泛型不是HttpResult类,那么返回null,让retrofit选择其他 CallAdapter.Factory
if (getRawType(responseType) != HttpResult::class.java) {
return null
}
//确保HttpResult内部包的泛型其还包裹另外一层泛型,比如 HttpResult<*>
check(responseType is ParameterizedType) { "return type must be HttpResult<*> or HttpResult for HttpResult<*> check" }
//获取HttpResult类包裹的第一个泛型
val successBodyType = getParameterUpperBound(0, responseType)
return SuspendCallAdapter, Any>(
successBodyType
)
}
companion object {
@JvmStatic
fun create(): SuspendCallAdapterFactory {
return SuspendCallAdapterFactory()
}
}
}
class SuspendCallAdapter, R : Any>(
private val successType: Type,
) : CallAdapter>> {
override fun responseType(): Type = successType
override fun adapt(call: Call): Call> {
return SuspendHttpCall(call)
}
}
class SuspendCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array,
retrofit: Retrofit
): CallAdapter<*, *>? {
//第一个泛型就是HttpResult类,这种情况可能是api接口没有声明协程suspend符号,抛出异常提醒
if (getRawType(returnType) == HttpResult::class.java) {
throw IllegalArgumentException("Method must be declare suspend, please check function declaration at API interface")
}
//协程挂起函数默认返回值是Call<*>,如果不满足该条件,那么返回null让retrofit选择其他家伙来Py
if (Call::class.java != getRawType(returnType)) {
return null
}
//检查Call内部的泛型是否包含了其他泛型
check(returnType is ParameterizedType) {
"return type must be HttpResult<*> or HttpResult for Call<*> check"
}
//获取Call类包裹的第一个泛型
val responseType = getParameterUpperBound(0, returnType)
//Call类包裹的第一个泛型不是HttpResult类,那么返回null,让retrofit选择其他 CallAdapter.Factory
if (getRawType(responseType) != HttpResult::class.java) {
return null
}
//确保HttpResult内部包的泛型其还包裹另外一层泛型,比如 HttpResult<*>
check(responseType is ParameterizedType) { "return type must be HttpResult<*> or HttpResult for HttpResult<*> check" }
//获取HttpResult类包裹的第一个泛型
val successBodyType = getParameterUpperBound(0, responseType)
//整块注释,下面将动态配置泛型变为Repo<*>,不需要再手动声明为Repo<*>泛型================改动点
// check(Repo::class.java == getRawType(successBodyType)) {
//如果待处理的类型不是Repo类,那么报异常
// "return type must be HttpResult> or HttpResult>> for Repo<*> check"
// }
//将HttpResult<*>中的泛型<*>包裹为Repo<*>,方便解析
val repoParameterizedType =
Utils.ParameterizedTypeImpl(null, Repo::class.java, successBodyType)
return SuspendCallAdapter, Any>(
repoParameterizedType
)
}
3、自定义 SuspendHttpCall
internal class SuspendHttpCall, R : Any>(
private val delegate: Call,
) : Call> {
override fun enqueue(callback: Callback>) {
return delegate.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
val body = response.body()
var httpResult: HttpResult? = null
//================================================
//================================================
//===================1、响应成功===================
//================================================
//================================================
if (response.isSuccessful) {
body?.data?.apply {
//Repo.data不为空
httpResult = HttpResult.Success(this, response.headers())
} ?: run {
//响应body是null或者Repo的data为空的时候
httpResult = HttpResult.UnknownError(
IllegalArgumentException("response data is invalid"),
null
)
}
callback.onResponse(
this@SuspendHttpCall,
Response.success(httpResult)
)
return
}
//================================================
//================================================
//===================2、响应失败===================
//================================================
//================================================
onFailure(call, HttpException(response))
}
override fun onFailure(call: Call, throwable: Throwable) {
var meta: Meta? = null
var statusCode = -1
if (isHttpException(throwable)) {
val exception = throwable as HttpException
//从 exception 中解析 Repo.Meta 数据
meta = parseMetaData(exception)
statusCode = exception.code()
}
val result: HttpResult = generateHttpResult(throwable, meta, statusCode)
callback.onRespo nse(this@SuspendHttpCall, Response.success(result))
}
})
}
override fun isExecuted() = delegate.isExecuted
override fun clone() = SuspendHttpCall(
delegate.clone(),
)
override fun isCanceled() = delegate.isCanceled
override fun cancel() = delegate.cancel()
override fun execute(): Response> {
throw UnsupportedOperationException("NetworkResponseCall doesn't support execute")
}
override fun request(): Request = delegate.request()
override fun timeout(): Timeout = delegate.timeout()
}
fun generateHttpResult(
t: Throwable,
meta: Meta?,
statusCode: Int
): HttpResult {
if (isApiError(t, meta, statusCode)) {
return HttpResult.ApiError(
meta?.code ?: statusCode,
meta?.message,
t,
parseHeader(t),
)
}
if (isNonNetwork(t)) {
return HttpResult.NetworkError(t, parseHeader(t))
}
return HttpResult.UnknownError(t, parseHeader(t))
}
fun generateHttpResult(
t: Throwable,
meta: Meta?,
statusCode: Int
): HttpResult {
if (isApiError(t, meta, statusCode)) {
return HttpResult.ApiError(
meta?.code ?: statusCode,
meta?.message,
t,
parseHeader(t),
)
}
if (isNonNetwork(t)) {
return HttpResult.NetworkError(t, parseHeader(t))
}
return HttpResult.UnknownError(t, parseHeader(t))
}
js数组的操作;
一:数组的创建:
1、数组的创建
var array = new Array(); //创建一个数组
var array = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度
var arrayObj = new Array([element0[, element1[, ...[, elementN]]]
org.hibernate.TransactionException: JDBC begin failed: at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:68) at org.hibernate.impl.SessionImp
最近要接入微信的收货地址共享接口,总是不成功,折腾了好几天,实在没办法网上搜到的帖子也是骂声一片。我把我碰到并解决问题的过程分享出来,希望能给微信的接口文档起到一个辅助作用,让后面进来的开发者能快速的接入,而不需要像我们一样苦逼的浪费好几天,甚至一周的青春。各种羞辱、谩骂的话就不说了,本人还算文明。
如果你能搜到本贴,说明你已经碰到了各种 ed