Rpc网络框架

本文介绍了基于Java的RPCService网络框架的使用方法,包括如何创建自定义service、初始化RpcServiceFactory以及如何通过动态代理实现网络请求的代理类。详细讲解了RpcServiceFactory、RpcClientFactoryService和RpcServiceProxy的创建过程,以及执行RPC调用的关键步骤,如设置拦截器、执行策略和数据传输配置。
摘要由CSDN通过智能技术生成

RPCService网络框架

SourceService sourceService = NetUriWrapper.newRpcService(
mContext, SourceService.class, Constant.BASE_TEST_URL, null);
sourceService.getContents(request, new DDRpcCallback() {…}
此处的自定义service需要继承rpcservice接口
public static T newRpcService(Context context, Class clazz, String url, Object request) {
if (request != null) {
String json = (new GsonBuilder()).serializeNulls().create().toJson(request);
return (new RpcServiceFactory(context)).newRpcService(clazz, url + (url.endsWith(“/”) ? “” : “/”) + “SignParam=” + URLEncoder.encode(json));
} else {
return (new RpcServiceFactory(context)).newRpcService(clazz, url);
}
}
外部调用,通过RPCServiceFactory
初始化 RpcClientFactoryService;
通过RpcClientFactoryService 初始化RpcClient;
通过动态代理生成网络请求的代理类(比如此处的sourceservice);

public RpcServiceFactory(final Context context) {
this.mContext = context.getApplicationContext();
this.mClientFactoryService = new RpcClientFactoryService(this.mContext);
}
创建RpcClientFactoryService
//加载所有添加注解@ServiceProvider(RpcClientFactory.class)的实例
static final ServiceLoader FACTORIES = ServiceLoader.load(RpcClientFactory.class);
public RpcClient<? extends RpcRequest, ? extends RpcResponse> getRpcClient(final Uri uri) {
final String scheme = uri.getScheme();

for (final RpcClientFactory factory : FACTORIES) {
    if (factory.isSchemeSupported(scheme)) {
        //协议匹配上通过自定义RpcClientFactory获取RpcClient
        record(getClass(), false, SDCARD_RPC_CRASH_DUMP_LOG);
        return factory.newRpcClient(this.mContext);
    }
}

record(getClass(), true, SDCARD_RPC_CRASH_DUMP_LOG);

try {
    if (null != sDefaultClientFactoryObj) {
        if (null != sIsSchemeSupportedMethod) {
            boolean supported = (boolean) sIsSchemeSupportedMethod.invoke(sDefaultClientFactoryObj, scheme);
            if (supported && sNewRpcClientMethod != null) {
                  //没有自定义RpcClientFactory或未匹配上协议,则通过默认的RpcClientFactory
                  //(在static块中通过反射初始化的HttpRpcClientFactory)来获取RpcClient对象:默认支持http与https协议
                return (RpcClient<? extends RpcRequest, ? extends RpcResponse>) sNewRpcClientMethod.invoke(sDefaultClientFactoryObj, this.mContext);
            }
        }
    }
} catch (Throwable e) {
    e.printStackTrace();
}

throw new UnsupportedSchemeException(scheme);

}
创建client
T newRpcService(final Class clazz, final Uri uri, final Object ref) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, new RpcServiceProxy(this, clazz, uri, ref));
}

RpcServiceProxy(final RpcServiceFactory factory, final Class<? extends RpcService> clazz, final Uri uri, final Object ref) { this.mSvcFactory = factory; this.mRpcClazz = clazz; this.mRpcUri = uri; this.mRpcMethods = Collections.unmodifiableSet(new HashSet(Arrays.asList(this.mRpcClazz.getMethods()))); //获取所有rpc类的方法 this.mRef = ref; this.mTransporter = this.getServiceTransporter(clazz); this.mHandler = new Handler(Looper.getMainLooper()); } public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (this.mRpcMethods.contains(method)) { //包含当前方法 final Class<?>[] exceptionTypes = method.getExceptionTypes();
try {
return execute(proxy, method, args);//真正执行
} catch (final RuntimeException e) {
throw e;
} catch (final Throwable e) {
for (final Class<?> exceptionType : exceptionTypes) {
if (exceptionType.isAssignableFrom(e.getClass())) {
throw e;
}
}

        throw new RuntimeException(e);
    }
}

if (OBJECT_METHODS.contains(method)) {
    return method.invoke(proxy, args);  //此处为默认object方法
}

throw new NoSuchMethodException(method.toGenericString());

}
创建代理类,如果执行了自定义rpc接口中的方法,会走到代理类execute中

private Object execute(Object proxy, Method method, Object[] args) throws Throwable {
final Class<?> returnType = method.getReturnType();
final RpcClient.Builder clientBuilder = this.mSvcFactory.getRpcClient(this.mRpcUri.getScheme()).newBuilder();
//获取client
setRpcInterceptors(method, clientBuilder);
//遍历注解,设置拦截器
setRpcOptions(method, clientBuilder);
//遍历注解,增加失败重试策略
setDnsResolver(method, clientBuilder);
//遍历注解,设置域名解析策略
setRpcTransporter(method, clientBuilder);
//遍历注解,数据传输配置
// Execute RPC
final RpcClient client = clientBuilder.build();
final RpcRequest request = client.newRequestBuilder()
.setUrl(this.mRpcUri.toString())
.setRpcClient(client)
.setRpcService(this.mRpcClazz, method, args)
//这里设置request的信息,获取注解,添加path,request对象,http method
.build();
final Rpc<RpcRequest, RpcResponse> rpc = client.newRpc(request);
final boolean async = null != args && args.length > 0 && args[args.length - 1] instanceof RpcService.Callback;
final Object result;

if (async) {//如果是异步操作
    final RpcService.Callback<Object> callback = (RpcService.Callback<Object>) args[args.length - 1];
    final ThreadType threadType = getTargetThreadType(method, args);
    result = rpc.enqueue(new Rpc.Callback<RpcRequest, RpcResponse>() {
        //最终调用okhttprpc的enqueue0,再调用realcall.newcall.enqueue
        //再调用dispatcher.enqueue,执行AsyncCall,这个call放在下面解释
        @Override
        public void onSuccess(final RpcResponse response) {
            try {
                final Object result = response.getContent();
                switch (threadType) {//线程模式
                case MAIN:
                    mHandler.post(new Runnable() {//切换到主线程
                        public void run() {
                            try {
                                callback.onSuccess(result);
                            } catch (final Throwable t) {
                                callOnFailure(request, callback, new IOException(t));
                            }
                        }
                    });
                    break;
                default:
                    try {
                        callback.onSuccess(result);
                    } catch (final Throwable t) {
                        callOnFailure(request, callback, new IOException(t));
                    }
                    break;
                }
            } catch (final IOException e) {
                onFailure(request, e);
            } catch (final Throwable t) {
                onFailure(request, new IOException(t));
            }
        }
        @Override
        public void onFailure(final RpcRequest request, final IOException e) {
            ...
        }
    });
    if (Rpc.class.isAssignableFrom(returnType)) {
        return rpc;
    }
} else {
    result = rpc.execute().getContent();   //同步
}
if (void.class.equals(returnType) || Void.class.equals(returnType)) {
    return null;
}
return result;

}

AsyncCall
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super(“OkHttp %s”, new Object[]{RealCall.this.redactedUrl()});
this.responseCallback = responseCallback;
}
String host() {
return RealCall.this.originalRequest.url().host();
}
Request request() {
return RealCall.this.originalRequest;
}
RealCall get() {
return RealCall.this;
}
protected void execute() {
RealCall.this.statisticalContext.traceExecuteTime();
int tid = Process.myTid();
RealCall.this.logEventListener.callStart(RealCall.this, tid);
boolean signalledCallback = false;
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(String.format(“OneNet %s”, RealCall.fixUrl(RealCall.this.originalRequest.url.toString())));
try {
Response response = RealCall.this.getResponseWithInterceptorChain();
//真正执行,添加拦截链,包括client的,还有其他拦截器。
if (RealCall.this.retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
this.responseCallback.onFailure(RealCall.this, new IOException(“Canceled”));
} else {
signalledCallback = true;
this.responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException var8) {
RealCall.this.logEventListener.callFailed(RealCall.this, var8);
if (signalledCallback) {
Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var8);
} else {
this.responseCallback.onFailure(RealCall.this, var8);
}
} finally {
RealCall.this.logEventListener.callEnd(RealCall.this);
RealCall.this.client.dispatcher().finished(this);
Thread.currentThread().setName(oldName);
}

}

欢迎使用Markdown编辑器

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

居中的图片: Alt

居中并且带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
统计用区划代码和城乡划分代码发布说明: 一、编制依据 2008年7月,国务院批复同意国家统计局与民政部、住建部、公安部、财政部、国土部、农业部共同制定的《关于统计上划分城乡的规定》(国函〔2008〕60号),自2008年8月1日实施,正式奠定了统计上划分城乡的理论依据和方法基础。随后,国家统计局印发《统计用区划代码和城乡划分代码编制规则》(国统字〔2009〕91号)。 二、区划范围 统计用区划代码和城乡划分代码的区划范围,是国家统计局开展统计调查的区划范围。未包括我国台湾省、香港特别行政区、澳门特别行政区。 三、发布内容 12位统计用区划代码和3位城乡分类代码。 四、适用领域 《国务院关于统计上划分城乡规定的批复》(国函〔2008〕60号)明确指出:“本规定作为统计上划分城乡的依据,不改变现有的行政区划、隶属关系、管理权限和机构编制,以及土地规划、城乡规划等有关规定”。各级各部门在使用统计用区划代码和城乡划分代码时,请务必结合实际情况。 五、几个具体问题的说明 (一)补充编制开发区统计汇总识别码情况。为满足统计调查工作组织和数据汇总的需要,国家统计局对一些符合条件的开发区编制了统计汇总识别码。统计汇总识别码在统计用区划代码的县级码段上编制,其码段为71~80。 (二)关于河北省沧州市任丘市的苟各庄镇、鄚州镇、七间房乡、保定市高阳县的龙化乡统计用区划代码临时调整情况的说明。按照河北省委、省政府关于对雄安新区周边部分区域实施托管的通知要求,沧州市任丘市的苟各庄镇、鄚州镇、七间房乡划归雄县实施统计上托管,保定市高阳县的龙化乡划归安新县实施统计上托管。为确保统计调查工作的顺利开展, 国家统计局对苟各庄镇、鄚州镇、七间房乡、龙化乡的统计用十二位区划代码进行了临时调整,具体调整为:鄚州镇代码由130982104000变更为130638106000;苟各庄镇代码由130982105000变更为130638107000;七间房乡代码由130982206000变更为130638205000;龙化乡代码由130628204000变更为130632203000。上述变更后的统计用区划代码为临时代码,待民政部门对雄安新区上述4个乡镇区划调整确认后,再将临时代码变更为正式统计用区划代码。 (三)关于黑龙江省大兴安岭地区县级单位统计用区划代码调整情况说明。民政部民函〔2018〕50号文件撤销黑龙江省大兴安岭地区漠河县(六位区划代码为232723),设立漠河市(六位区划代码为232701)。为执行国家标准,保证统计部门与民政部门名称相同的县级单位六位区划代码的一致性,国家统计局根据《统计用区划代码和城乡划分代码编制规则》(国统字〔2009〕91号),调整黑龙江省大兴安岭地区所辖的加格达奇区、松岭区、新林区和呼中区的六位统计用区划代码,具体调整为:加格达奇区代码由232701变更为232761;松岭区代码由232702变更为232762;新林区代码由232703变更为232763;呼中区代码由232704变更为232764。 (四)此版本区划代码与第四次全国经济普查区划代码的相关说明。此版本区划代码是调查截止日期为2018年10月31日的统计用区划代码。由于第四次全国经济普查清查工作于2018年8月开始,四经普的清查和登记工作中采用2018年6月15日的统计用区划代码。第四次全国经济普查数据处理使用2018年10月31日的统计用区划代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值