本篇主要介绍dubbo的隐式传参如何使用以及其原理。通过隐式传参,我们可以在不改动接口的情况下传递一些额外的数据给服务端来实现一些特定的功能。
概念
什么是隐式传参,我们看名字基本就能够猜出来,暗地里把参数传给服务提供者。先思考一下我们平时是怎么使用dubbo的(如何搭建并进行调用),一般都是服务提供方会定义好接口然后交给客户端来引入使用,也就是一开始客户端就知道服务端有哪些接口以及其定义是怎么样的。而隐式传参则是客户端自己定义的参数,客户端和服务端要约定好想要传哪些参数,客户端传了之后服务端可以取出来做一些处理。
更通俗的说:
现在华山派招弟子,有心法系和剑系两项可以选择,你进入华山派的话正常只能练其中一项,但是你可以在选择任何一项之后自己偷偷带一本秘籍过去修炼,这偷偷带过去的东西就是隐式传参。
使用
下面用一个例子来说明一下如何进行使用,本例子要达到的目的是日志唯一追踪号传递,具体的细节在这篇已经讲过dubbo Filter使用,这里就讲一下其中涉及到的隐式传参怎么做的。在那篇例子中,我们写到一段代码:
//对于服务提供端,Activate改为Constants.PROVIDER
@Activate(group = {Constants.CONSUMER})
public class UniqIdTraceFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//此处逻辑可以自定义
String traceId = UUID.randomUUID().toString().replace("-", "");
RpcContext.getContext().setAttachment("traceId", traceId);
return invoker.invoke(invocation);
}
}
这段代码里 RpcContext.getContext().setAttachment("traceId", traceId);
这句话就是隐式传参的使用。我们看下 setAttachment
方法的定义:
这里可以看出来其中就是一个map,key就是我们要传递给服务端的参数的键,value就是服务端将会获取到的值,具体如何使用你可以在服务端自定义。这里传递traceId给服务端之后,服务端就可以通过RpcContext.getContext().getAttachment("traceId")
来获取到日志唯一追踪号。
原理
借着使用来讲一下隐式传参的原理。基于上面的例子,我们知道使用隐式传参很简单:
RpcContext.getContext().setAttachment("traceId", traceId)
我们看下 dubbo 是如何做到从客户端传递到服务端的。在上面的例子中,我们在客户端请求过去的时候,经过了 Filter,在 Filter 中加入了我自己的定义的隐式传参的内容 traceId,在org.apache.dubbo.rpc.protocol.AbstractInvoker#invoke
的逻辑中会将我们RpcContext中的参数传递到 RpcInvocation 中,如图:
这个 RpcInvocation 就是客户端请求服务端带过去的是数据。在服务端接收到的请求内容中,我们可以看到traceId,其他的是dubbo自己需要处理的参数:
在我们讲 dubbo Filter使用 的时候讲到过dubbo有一些自己内置的 Filter,其中有一个 Filter 叫做 ContextFilter,该 Filter 就会将收到的 RpcInvocation 中的参数设置到 RpcContext中去:
大概的实现原理就是如此,其实也非常简单。
总结
本篇已经对隐式传参讲得非常清楚了,这里的案例是用的Filter的方式设置和获取参数,大家也可以在其他代码逻辑上去传递和获取,如果对于原理篇还是不理解,可以自己参照原理篇说的调试下。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。