SpringCloudAlibaba学习系列(2)dubbo自定义Filter

本文介绍了如何在Dubbo中实现自定义的RPC过滤器(Filter),包括创建Filter类、配置Filter文件、配置Dubbo服务提供者与消费者,以及在特定服务中应用和剔除Filter的详细步骤。通过Filter可以实现请求拦截、鉴权、日志记录等功能。
摘要由CSDN通过智能技术生成

目录

一、简介

二、实战

1、创建filter类

2、配置Filter文件

3、配置dubbo

4、查看效果

5、配置service的Filter

5、service剔除provider统一配置的Filter

三、other


一、简介

        我们再开发web应用的时候,通常会需要继承javax.servlet.Filter的接口类来实现统一拦截请求进行处理的功能,如鉴权、日志、Xss攻击拦截等。那么在微服务dubbo框架处理RPC请求的时候,我们是否也有这样的需求,需要对远程服务调用的每一个接口实现自定义的Filter呢?

        dubbo提供了调用拦截扩展的方式,通过继承org.apache.dubbo.rpc.Filter的接口类,服务提供方和服务消费方调用过程都可以进行拦截。

        本文是基于上篇文章进行的配置实现(SpringCloudAlibaba学习系列(2)dubbo集成),所以这里就不继续重复去搭建项目,只做重点代码配置验证。

二、实战

1、创建filter类

package com.sam.cloud.provider.filter;

import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FirstRpcFilter implements Filter {
    private final Logger LOG = LoggerFactory.getLogger(FirstRpcFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        LOG.info("我是执行的First的filter:FirstRpcFilter");
        return invoker.invoke(invocation);
    }
}

这里就是通过集成org.apache.dubbo.rpc.Filter类实现;为了方便后续的验证,这里还创了两个filter:SecondRpcFilter和ThirdRpcFilter

package com.sam.cloud.provider.filter;

import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SecondRpcFilter implements Filter {
    private final Logger LOG = LoggerFactory.getLogger(SecondRpcFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        LOG.info("我是执行的second的filter:SecondRpcFilter");
        return invoker.invoke(invocation);
    }
}
package com.sam.cloud.provider.filter;

import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ThirdRpcFilter implements Filter {
    private final Logger LOG = LoggerFactory.getLogger(ThirdRpcFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        LOG.info("我是执行的third的filter:ThirdRpcFilter");
        return invoker.invoke(invocation);
    }
}

2、配置Filter文件

在resources目录下创建文件夹/META-INF/dubbo,然后创建纯文本文件:com.alibaba.dubbo.rpc.Filter,内容为:

firstRpcFilter=com.sam.cloud.provider.filter.FirstRpcFilter
secondRpcFilter=com.sam.cloud.provider.filter.SecondRpcFilter
thirdRpcFilter=com.sam.cloud.provider.filter.ThirdRpcFilter

3、配置dubbo

a、作为全局的provider配置使用Filter,有两种方式,基于properties和基于注解

  • 基于properties:在bootstarp.properties中添加配置,排序就是执行顺序
    dubbo.provider.filter=firstRpcFilter,secondRpcFilter,thirdRpcFilter
  • 基于注解:@Activate(group = {CommonConstants.PROVIDER}, order = 1),如果是消费者使用group的值为CommonConstants.CONSUMER,如果是提供者和消费者都用到,就两个都加上,order代表当存在多个自定义filter时执行的顺序。这里只需要在FirstFilter的类上加上注解就可以开启使用。
package com.sam.cloud.provider.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Activate(group = {CommonConstants.PROVIDER}, order = 1)
public class FirstRpcFilter implements Filter {
    private final Logger LOG = LoggerFactory.getLogger(FirstRpcFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        LOG.info("我是执行的First的filter:FirstRpcFilter");
        return invoker.invoke(invocation);
    }
}

剩余两个类SecondRpcFilter和ThirdRpcFilter也加上同样的注解

4、查看效果

启动提供者magic-provider,然后启动magic-consumer,然后请求接口,查看日志打印为:

INFO#2021-09-12 16:09:58.958#[]#我是执行的First的filter:FirstRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的second的filter:SecondRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的third的filter:ThirdRpcFilter

5、配置service的Filter

上面说的是全局的provider或者consumer配置,但在实际开发中,我们可能会出现需要这个filter只作用在某个service的类中,我们需要怎么样去弄呢?

只需要在注解@DubboService中配置filter就可以,首先先按照第1步和第2步创建了一个Auth的鉴权filter:AuthRpcFilter,不需要设置激活注解@Activate,接着在service实现类的注解设置filter = {"authRpcFilter"},代码如下:

AuthRpcFilter:(这里有个点要注意,如果要使用spring管理的bean,不能用@Resource来注入,需要实现参数的set方法,dubbo会自动进行注入,像下面的代码AuthHandler类的注入那样)

package com.sam.cloud.provider.filter;

import com.sam.cloud.provider.filter.handler.AuthHandler;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class AuthRpcFilter implements Filter {
    private final Logger LOG = LoggerFactory.getLogger(AuthRpcFilter.class);

    //dubbo自己会对这些bean进行注入,不需要再标注@Resource让Spring注入
    private AuthHandler authHandler;

    public void setAuthHandler(AuthHandler authHandler) {
        this.authHandler = authHandler;
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        LOG.info("我是执行的鉴权filter:AuthRpcFilter");
        return invoker.invoke(invocation);
    }
}

MagicProviderFacadeImpl:

package com.sam.cloud.provider.facade;

import com.sam.cloud.provider.api.domain.UserDTO;
import com.sam.cloud.provider.api.facade.MagicProviderFacade;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(version = "1.0.0", group = "magic", interfaceClass = MagicProviderFacade.class,
        filter = {"authRpcFilter"})
public class MagicProviderFacadeImpl implements MagicProviderFacade {

    @Override
    public UserDTO queryUser(String name) {
        UserDTO user = new UserDTO();
        user.setUserId(1);
        user.setName("sam");
        user.setAge(1L);
        return user;
    }
}

启动验证输出日志如下:

INFO#2021-09-12 16:09:58.958#[]#我是执行的First的filter:FirstRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的second的filter:SecondRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的third的filter:ThirdRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的鉴权filter:AuthRpcFilter

5、service剔除provider统一配置的Filter

在做业务的时候,可能会出现某个service实现不需要执行某个provider提供的统一filter,这时候可以采用特殊符号“-”进行标识剔除,如下代码:

package com.sam.cloud.provider.facade;

import com.sam.cloud.provider.api.domain.UserDTO;
import com.sam.cloud.provider.api.facade.MagicProviderFacade;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(version = "1.0.0", group = "magic", interfaceClass = MagicProviderFacade.class,
        filter = {"-secondRpcFilter", "authRpcFilter"})
public class MagicProviderFacadeImpl implements MagicProviderFacade {

    @Override
    public UserDTO queryUser(String name) {
        UserDTO user = new UserDTO();
        user.setUserId(1);
        user.setName("sam");
        user.setAge(1L);
        return user;
    }
}

filter = {"-secondRpcFilter", "authRpcFilter"}就代表这个service会按照顺序执行firstRpcFilter,thirdRpcFilter,authRpcFilter,而忽略secondRpcFilter。

执行日志如下:

INFO#2021-09-12 16:09:58.958#[]#我是执行的First的filter:FirstRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的third的filter:ThirdRpcFilter
INFO#2021-09-12 16:09:58.958#[]#我是执行的鉴权filter:AuthRpcFilter

三、other

参考官网文档:(调用拦截扩展 | Apache Dubbo

1、用户自定义的 filter 都是默认在dubbot内置 filter 之后执行;目前dubbo内置的filter有如下:

  • org.apache.dubbo.rpc.filter.EchoFilter
  • org.apache.dubbo.rpc.filter.GenericFilter
  • org.apache.dubbo.rpc.filter.GenericImplFilter
  • org.apache.dubbo.rpc.filter.TokenFilter
  • org.apache.dubbo.rpc.filter.AccessLogFilter
  • org.apache.dubbo.rpc.filter.CountFilter
  • org.apache.dubbo.rpc.filter.ActiveLimitFilter
  • org.apache.dubbo.rpc.filter.ClassLoaderFilter
  • org.apache.dubbo.rpc.filter.ContextFilter
  • org.apache.dubbo.rpc.filter.ConsumerContextFilter
  • org.apache.dubbo.rpc.filter.ExceptionFilter
  • org.apache.dubbo.rpc.filter.ExecuteLimitFilter
  • org.apache.dubbo.rpc.filter.DeprecatedFilter

2、特殊值 default,表示缺省扩展点插入的位置。比如:filter="xxx,default,yyy",表示 xxx 在缺省 filter 之前执行,yyy 在缺省 filter 之后执行

3、特殊符号 -,表示剔除。比如:filter="-foo1",剔除添加缺省扩展点 foo1。比如:filter="-default",剔除添加所有缺省扩展点。

4、provider 和 service 同时配置的 filter 时,累加所有 filter,而不是覆盖。比如:<dubbo:provider filter="xxx,yyy"/> 和 <dubbo:service filter="aaa,bbb" />,则 xxx,yyy,aaa,bbb 均会生效。如果要覆盖,需配置:<dubbo:service filter="-xxx,-yyy,aaa,bbb" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值