原創地址:https://my.oschina.net/u/3039671/blog/833589前端
通常dubbo的service層都是一些通用的,無狀態的服務。可是在某些特殊的需求下,須要傳遞一些上下文環境,打個不恰當的比方,例如須要在每次調用dubbo的服務的時候,記錄一下用戶名或者須要知道sessionid等。數據庫
若是是在項目設計的時候就意識到這一點的話,就好辦,把全部的dubbo服務請求的參數都封裝一個公共的父類,把一些上下文環境在放在父類的屬性中。api
這樣作的好處就是,dubbo接口的參數都統一的,在Dubbo中能夠作一些統一的處理(例如把上下文環境取出來,放在ThreadLocal中)。session
可是並非全部的項目一開始就有這個需求的,可是忽然有一天他猝不及防的出現了(好比本人就接到要使用多數據,每次前端請求的時候根據參數選擇使用的數據庫),若是項目已經基本定型的狀況下,再改形成上面的解決辦法,改動量太大(不怕麻煩的也能夠,可是本人就比較懶)。ide
其實Dubbo的文檔中已經有這個解決辦法,就是隱式傳參,ui
http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E9%9A%90%E5%BC%8F%E4%BC%A0%E5%8F%82spa
只須要在調用方加一個切面,在服務方加一個filter.net
代碼以下設計
/** * 在調用service的接口以前,加入一些dubbo的隱式參數 * Created by hzlizhou on 2017/2/6. */ @Aspect @Component public class DubboServiceContextAop { @Pointcut("execution(* com.打碼.打碼..service.api.*.*(..))") public void serviceApi() { } @Before("serviceApi()") public void dubboContext(JoinPoint jp) { Map<String, String> context = new HashMap<>(); // todo you want do RpcContext.getContext().setAttachments(context); } }
本項目service的package命名都是 com.打碼.打碼.模塊名.service.api 所以只須要一個execution就好了,這也是養成統一的包命名的好處code
代碼以下,很簡單
public class DubboContextFilter implements Filter { @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { String var= RpcContext.getContext().getAttachment(從Aop中放入的); //todo 其餘相關處理 return invoker.invoke(invocation); } }
第一步:建立一個類實現Filter接口,如上面的DubboContextFilter
注意是com.alibaba.dubbo.rpc.Filter
第二步:在resources中建立文件
META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
注意是 META-INF文件下的dubbo文件夾下的"com.alibaba.dubbo.rpc.Filter"文件
並在裏面加入,也就是第一步中建立的類的路徑
dubboContextFilter=com.打碼.打碼.打碼.打碼.打碼.DubboContextFilter
第三步:在配置文件中加入
<dubbo:provider filter="dubboContextFilter" />
其實dubbo內置了一些filter,咱們能夠自定義本身的filter來完成一些和業務流程無關的邏輯,例如能夠寫IP白名單等等