网络层架构设计与实战十四错误码和重连功能设计与实现
2018-02-07 22:17
363 查看
一、注解
1、重连和重试
在进行网络连接的时候,有可能出现网络连接出错的情况,一般的做法都是重新去尝试,网络框架也是可以对这些进行处理的,如果认为某些接口是比较重要的,可以进行一些重试。重试的话可能有一些最大的连接次数,因为它不可能是无限的重试,如果无限地重试可能导致堆栈的溢出。最大的重试次数需要开发者自己去指定,重连的功能在网络框架中如何去设计呢?可以通过annotation进行配置,然后去实现这样的功能,这样在代码上也是比较简单的。
2、定义重试的注解
3、在request中定义变量
4、在builder中创建
5、对变量进行赋值并将变量返回
6、对注解进行处理
二、异步请求网络框架
1、定义变量初始化并赋值
2、httpclient功能的主要作用主要做一个网络层框架的抽象,它的基本作用主要是提供了一些网络层的基本操作,可以在这个地方增加一些异步请求的功能。异步请求的前提是线程应该在哪儿?所以需要新增一个成员变量ExecutorService mExecutor
3、在builder中定义
4、调用设置线程池的方法
5、定义重试
6、
发生异常时进行重试处理
代码:
运行后如果出错,会进行重试操作
1、重连和重试
在进行网络连接的时候,有可能出现网络连接出错的情况,一般的做法都是重新去尝试,网络框架也是可以对这些进行处理的,如果认为某些接口是比较重要的,可以进行一些重试。重试的话可能有一些最大的连接次数,因为它不可能是无限的重试,如果无限地重试可能导致堆栈的溢出。最大的重试次数需要开发者自己去指定,重连的功能在网络框架中如何去设计呢?可以通过annotation进行配置,然后去实现这样的功能,这样在代码上也是比较简单的。
2、定义重试的注解
3、在request中定义变量
4、在builder中创建
5、对变量进行赋值并将变量返回
6、对注解进行处理
二、异步请求网络框架
1、定义变量初始化并赋值
2、httpclient功能的主要作用主要做一个网络层框架的抽象,它的基本作用主要是提供了一些网络层的基本操作,可以在这个地方增加一些异步请求的功能。异步请求的前提是线程应该在哪儿?所以需要新增一个成员变量ExecutorService mExecutor
3、在builder中定义
4、调用设置线程池的方法
5、定义重试
6、
发生异常时进行重试处理
代码:
package com.nice; import com.nice.convert.Convert; import com.nice.http.HttpDns; import com.nice.http.HttpResponse; import com.nice.http.Request; import com.nice.http.Response; import com.nice.http.client.okhttp.OkHttpClient; import com.nice.http.client.origin.OriginHttpClient; import com.nice.utils.TypeUtils; import com.nice.utils.Utils; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.List; import java.util.concurrent.ExecutorService; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; /** * 高度抽象的网络层接口 * <p>主要提供升级超时、域名校验、证书认证、DNS等功能</p> * * @author nate * @since 2017/10/12. */ public class HttpClient implements Call { private static boolean OK_HTTP_REQUEST = Utils.isExist("okhttp3.OkHttpClient"); private int mWriteTimeOut; private int mReaderTimeOut; private int mConnectTimeOut; private SSLSocketFactory mSSLSocketFactory; private HostnameVerifier mHostnameVerifier; private Call mRealHttpClient; private HttpDns mHttpDns; private Request mRequest; private Callback mCallback; private ExecutorService mExecutor; private List<Convert> mConverts; private int mRetryCount; public HttpClient(Builder builder) { mWriteTimeOut = builder.mWriteTimeOut; mReaderTimeOut = builder.mReaderTimeOut; mConnectTimeOut = builder.mConnectTimeOut; mSSLSocketFactory = builder.mSSLSocketFactory; mHostnameVerifier = builder.mHostnameVerifier; mHttpDns = builder.mHttpDns; mExecutor = builder.mExecutor; mConverts = builder.mConverts; } public HttpDns getHttpDns() { return mHttpDns; } public int getReaderTimeOut() { return mReaderTimeOut; } public int getConnectionTimeOut() { return mConnectTimeOut; } public int getWriteTimeOut() { return mWriteTimeOut; } public SSLSocketFactory getSSLSocketFactory() { return mSSLSocketFactory; } public HostnameVerifier getHostnameVerifier() { return mHostnameVerifier; } private boolean canRetry() { return mRetryCount < mRequest.getRetryCount(); } private void retry() { if (mCallback != null && mRequest != null) { mRetryCount++; System.out.println("重试第" + mRetryCount + "次"); enqueue(mRequest, mCallback); } } @Override public HttpResponse execute(Request request) throws IOException { if (OK_HTTP_REQUEST) { mRealHttpClient = new OkHttpClient(this); } else { mRealHttpClient = new OriginHttpClient(this); } return mRealHttpClient.execute(request); } /** * 异步处理网络请求 * * @param request 网络请求对象 * @param callback 回调方法 */ public void enqueue(final Request request, final Callback callback) { this.mRequest = request; this.mCallback = callback; mExecutor.execute(new Runnable() { @Override public void run() { invoke(request, callback.getClass()); } }); } /** * 将服务器数据转化成对应的类型 * * @param response httpResponse * @param type 转换成的类型 * @param <T> 返回值类型 * @return 返回对应的值 * @throws IOException */ private <T> T convertResponse(HttpResponse response, Type type) throws IOException { Object result = response; for (int i = 0; i < mConverts.size(); i++) { Object data = mConverts.get(i).parse(result, type); if (data != null) { result = data; } } return (T) result; } private <T> Response parseResponse(T result, HttpResponse httpResponse) { return new Response(result, httpResponse); } public <T> T invoke(Request request, Class responseType) { Type type = TypeUtils.getType(responseType); HttpResponse httpResponse; final T result; try { httpResponse = execute(request); result = convertResponse(httpResponse, type); } catch (Throwable e) { e.printStackTrace(); onFailure(e); if (canRetry()) { retry(); return null; } return null; } Response response = parseResponse(result, httpResponse); onSuccess(response); return result; } private void onSuccess(Response response) { mCallback.onSuccess(response); } private void onFailure(Throwable error) { mCallback.onFailure(error); } public static class Builder { public static HostnameVerifier DEFAULT_HOST_NAME_VERIFIER = new DefaultHostnameVerifier(); public static SSLSocketFactory DEFAULT_SSL_SOCKET_FACTORY = getDefaultSocketFactory(); private int mWriteTimeOut; private int mReaderTimeOut; private int mConnectTimeOut; public SSLSocketFactory mSSLSocketFactory; private HostnameVerifier mHostnameVerifier; private HttpDns mHttpDns; private ExecutorService mExecutor; private List<Convert> mConverts; /** * 默认的域名校验实现 */ static class DefaultHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { return true; } } /** * 默认的证书管理 */ static class DefaultTrustManger implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } public static SSLSocketFactory getDefaultSocketFactory() { SSLContext context = null; try { context = SSLContext.getInstance("TLS"); context.init(null, new TrustManager[]{new DefaultTrustManger()}, new SecureRandom()); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return context.getSocketFactory(); } public SSLSocketFactory getSocketFactory(InputStream inputStream) throws Exception { CertificateFactory factory = CertificateFactory.getInstance("x.509"); X509Certificate certificate = (X509Certificate) factory.generateCertificate(inputStream); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("ca", certificate); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); SSLContext context = SSLContext.getInstance("TLS"); context.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); return context.getSocketFactory(); } /** * 设置写入时间 * * @param timeOut 设置的时间值 * @return {@link Builder} */ public Builder setWriteTimeOut(int timeOut) { this.mWriteTimeOut = timeOut; return this; } /** * 设置读取的时间 * * @param timeOut 设置的时间值 * @return {@link Builder} */ public Builder setReaderTimeOut(int timeOut) { this.mReaderTimeOut = timeOut; return this; } /** * 设置网络连接时间 * * @param timeOut 设置的时间值 * @return {@link Builder} */ public Builder setConnectionTimeOut(int timeOut) { this.mConnectTimeOut = timeOut; return this; } /** * 设置SSLSocket * * @param factory 具体的SSLSocketFactory实现 * @return {@link Builder} */ public Builder setSSLSocketFactory(SSLSocketFactory factory) { this.mSSLSocketFactory = factory; return this; } /** * 设置域名校验 * * @param verifier 具体的域名校验实现 * @return {@link Builder} */ public Builder setHostnameVerifier(HostnameVerifier verifier) { this.mHostnameVerifier = verifier; return this; } /** * 设置HttpDns查询实现 * * @param dns 具体的HttpDns查询实现 * @return {@link Builder} */ public Builder setHttpDns(HttpDns dns) { this.mHttpDns = dns; return this; } /** * 设置线程池 * * @param service 线程池的实现 * @return {@link Builder} */ public Builder setExecutors(ExecutorService service) { this.mExecutor = service; return this; } /** * 设置转换的类型 * * @param converts 转换类型的集合 * @return {@link Builder} */ public Builder setConverts(List<Convert> converts) { this.mConverts = converts; return this; } /** * 判断是否使用的了Http代理 */ private void proxy() { String host = System.getProperty("http.proxyHost"); String port = System.getProperty("http.proxyPort"); if (host != null && port != null) { mHttpDns = null; } } /** * 构建HttpClient对象 * * @return {@link HttpClient} */ public HttpClient builder() { proxy(); return new HttpClient(this); } } }
运行后如果出错,会进行重试操作
相关文章推荐
- 网络层架构设计与实战十六https功能设计与实现
- 测试网络层架构设计与实战十七https功能设计与实现之单向认证和双向认证
- 一步步实现自己的框架系列(一):初步架构功能设计
- 网络层架构设计与实战五之客户端设计之请求头响应头的封装
- 基于.NET平台的分层架构实战(四)——实体类的设计与实现
- 基于.NET平台的分层架构实战(四)——实体类的设计与实现
- Android开发本地及网络Mp3音乐播放器(十四)网络音乐下载功能实现
- 网络层架构设计与实战一
- 网络层架构设计与实战六客户端设计之工厂模式封装httpRequest
- 基于.NET平台的分层架构实战(五)——接口的设计与实现
- 基于.NET平台的分层架构实战(五)——接口的设计与实现
- [.NET领域驱动设计实战系列]专题七:DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能
- 网络层架构设计与实战三之线程池原理及线程的终止
- 构建NetCore应用框架之实战篇(五):BitAdminCore框架1.0登录功能设计实现及源码
- Android开发本地及网络Mp3音乐播放器(十四)网络音乐下载功能实现
- 优雅设计封装基于Okhttp3的网络框架(二):多线程下载功能原理设计 及 简单实现
- 架构,改善程序复用性的设计~第三讲 实现一种功能的代码只能出现在一处
- Android实战简易教程<三十八>(模仿腾讯QQ的网络状态提示和设置功能实现)
- 网络层架构设计与实战七框架拓展设计之支持原生的HttpUrlConnection方式请求和响应
- 基于.NET平台的分层架构实战(五)——接口的设计与实现