dubbo中攔截生產者或消費者服務方法調用


比如當前有個需求,需要攔截dubbo的服務提供方或者服務消費方的方法,判斷參數中是否包含某個關鍵字進行攔截阻止執行,那么我們可以通過使用dubbo的SPI機制通過實現Filter類來攔截,話不多說直接上代碼:

1、新建一個類實現dubbo的Filter接口

/**
 * 回滾任務Dubbo攔截正在回滾或備份小區的方法調用,阻止執行
 * @author wl
 * @date 2019-08-16 13:24
 */
@Activate(group={ Constants.PROVIDER, Constants.CONSUMER })
public class DubboRollbackTaskFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(DubboRollbackTaskFilter.class);

    private RedisTemplate redisTemplate;

    /**
     * Filter中@Autowired會失效
     * 使用dubbo自動注入redisTemplate類
     * @param redisTemplate
     */
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public static final String ROLLBACK_READIS_KEY = "server_rollback_task_region_ids";

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        try {
            String method = invocation.getMethodName();
            String name = invoker.getInterface().getName();
            Object[] args = invocation.getArguments();
            String ageString = JSON.toJSONString(args);
            // redis中獲取數據
            Object redisValues = redisTemplate.opsForValue().get(DubboRollbackTaskFilter.ROLLBACK_READIS_KEY);
            logger.debug(">>>>>dubboRollbackTaskFilter-className:{},method:{},args:{},redisValues:{}", name, method, ageString, JSON.toJSONString(redisValues));
            if (null != redisValues && redisValues.toString().trim().length() > 0) {
                String[] regionIds = redisValues.toString().split(",");
                for (String regionId : regionIds) {
                    if (regionId.trim().length() <= 0) {
                        continue;
                    }
                    // 只要包含當前有處理的小區,那么直接拋出參數異常
                    if (ageString.contains(regionId)) {
                        logger.info(">>>>>dubboRollbackTaskFilter-攔截:{},method:{},args:{},regionId:{}", name, method, ageString, regionId);
                        return new RpcResult(new IllegalArgumentException("回滾任務攔截提示:當前小區正在備份或回滾數據,一切操作不允許執行!"));
                    }
                }
            }
        } catch (Exception e) {
            // 攔截異常,不影響正常操作
            logger.error(">>>>>dubboRollbackTaskFilter-異常", e);
        }
        return invoker.invoke(invocation);
    }
}

2、META-INF下新建文件

  

  文件內容為:

dubboRollbackTaskFilter=com.qdingnet.pcloud.helper.utils.DubboRollbackTaskFilter

  至此就可以成功的攔截你想攔截的東西

3、下面解釋幾個點:

  1、關於@Activate,Activate注解表示一個擴展是否被激活,可以放在類定義和方法上,dubbo用它在spi擴展類定義上,表示這個擴展實現被激活。

    具體如何實現可以百度或看下(這篇文章

    如果不使用此注解可以直接在配置中添加

    1.1 比如配置中添加   dubbo.provider.filter =dubboServiceFilter 

    1.2 或者在dubbo配置xml中添加 <dubbo:provider filter="xxxFilter" /> 或者 <dubbo:consumer filter="xxxFilter" /> 使Filter生效

  2、關於在Filter中使用@Resoure@Autowired

    在dubbo攔截器中以上兩個注解是不會生效的,我們可以用以下兩種方式注入

    2.1 可以采取通過setter方式來注入其他的bean,就像最上面的代碼示例

    2.2 通過Spring的ApplicationContextAware接口

      

    2.3 直接從Spring中取,ServiceBean.getSpringContext().getBean(clazz)

  3、說說攔截的invoke返回方式

    如果想直接返回自定義的攔截,直接使用dubbo提供的RpcResult,然后將異常作為參數傳給此類進行返回


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM