原创地址: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白名单等等