天天看點

Dubbo服務治理篇——Dubbo Filter實戰

熟悉Dubbo的同學或朋友,都會知道,一般dubbo的service層都是一些通用的,無狀态的服務。但是在某些特殊的需求下,我們又需要傳遞一些上下文環境,打個不恰當的比方,例如需要在每次調用dubbo的服務的時候,記錄一下使用者名或者需要知道sessionid等。

解決辦法1

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

Dubbo服務治理篇——Dubbo Filter實戰

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

解決辦法2

但是并不是所有的項目一開始就有這個需求的,但是突然有一天他猝不及防的出現了(比如本人就接到要使用多資料,每次前端請求的時候根據參數選擇使用的資料庫),如果項目已經基本定型的情況下,再改造成上面的解決辦法,改動量太大(不怕麻煩的也可以,但是本人就比較懶)。

改造方案

Dubbo服務治理篇——Dubbo Filter實戰

隻需要在調用方加一個切面,在服務方加一個filter切面

代碼如下

/**
 * 在調用service的接口之前,加入一些dubbo的隐式參數
 * Created by binghe
 */
@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就行了,這也是養成統一的包命名的好處

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"檔案

Dubbo服務治理篇——Dubbo Filter實戰

并在裡面加入,也就是第一步中建立的類的路徑

dubboContextFilter=com.打碼.打碼.打碼.打碼.打碼.DubboContextFilter      

第三步:在配置檔案中加入

<dubbo:provider filter="dubboContextFilter" />      

小結

其實dubbo内置了一些filter,我們可以自定義自己的filter來完成一些和業務流程無關的邏輯,例如可以寫IP白名單等等