Dubbo Filter的實踐——向Dubbo服務傳遞上下文環境信息

原創地址:https://my.oschina.net/u/3039671/blog/833589前端

需求

通常dubbo的service層都是一些通用的,無狀態的服務。可是在某些特殊的需求下,須要傳遞一些上下文環境,打個不恰當的比方,例如須要在每次調用dubbo的服務的時候,記錄一下用戶名或者須要知道sessionid等。數據庫

解決辦法1

若是是在項目設計的時候就意識到這一點的話,就好辦,把全部的dubbo服務請求的參數都封裝一個公共的父類,把一些上下文環境在放在父類的屬性中。api

這樣作的好處就是,dubbo接口的參數都統一的,在Dubbo中能夠作一些統一的處理(例如把上下文環境取出來,放在ThreadLocal中)。session

解決辦法2

可是並非全部的項目一開始就有這個需求的,可是忽然有一天他猝不及防的出現了(好比本人就接到要使用多數據,每次前端請求的時候根據參數選擇使用的數據庫),若是項目已經基本定型的狀況下,再改形成上面的解決辦法,改動量太大(不怕麻煩的也能夠,可是本人就比較懶)。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

Dubbo Filter

代碼以下,很簡單

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);
    }
}

怎麼寫Dubbo Filter

第一步:建立一個類實現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白名單等等

相關文章
相關標籤/搜索