结论

先把结论放最前面,可忽略后面的过程

  • org.apache.dubbo.rpc.Filter与com.alibaba.dubbo.rpc.Filter没区别
  • spring.dubbo.provider.filter: 无该配置,服务中的该配置是用于xml中配置provider的filter
  • provider filter或service filter可具体给这个provider或service配置过滤器
  • 如果想去掉某个filter,可在 provider filter或service filter配置的前面加-
  • 排序在filter类上定义,order越小,优先级越高
@Activate(group = { CommonConstants.PROVIDER }, order = -100)
  • 优先级越高的filterinvoker.invoke(invocation)前的越早执行,invoker.invoke(invocation)后的越晚执行

配置

org.apache.dubbo.rpc.Filtercom.alibaba.dubbo.rpc.Filter配置

apiExceptionFilterV1=com.didichuxing.dd596.driver.car.biz.filter.ApiExceptionFilterV1

provider filter配置

<dubbo:provider registry="registry" group="${dubbo.group.default}" filter="-DidiErrorHandleFilter">

service filter配置

<dubbo:service
            registry="registry" interface="com.didichuxing.dd596.driver.car.api.VehicleRemoteService" filter="apiExceptionFilter"
            ref="vehicleRemoteService" version="1.0.0${dubbo.version.suffix.provider}" />

服务中配置的dubbo exception filter不生效

原因1

当不配置到service时,已存在优先级更低的过滤器ErrorHandleFilter,该过滤器优先级更低,故invoker.invoke(invocation)后更先执行,后面再执行时,就不存在exception,所以ApiExceptionFilter不会执行

原因2

当不存在ErrorHandleFilter时,在ApiExceptionFilter中虽然改写了result,但是未清除exception信息,导致后面的ProviderExceptionFilter执行时,再次改写result

问题:为什么添加到service上就生效了

当把ApiExceptionFilter添加到service上时,虽然仍然没有调整优先级,但是会先执行其它的全局过滤器,最后执行该ApiExceptionFilter,而在执行ApiExceptionFilter时,改写了result,在打印日志的filter中会将改写后的打印出来(request_out),但是之后的error filter会重写,所以获取到的响应有问题

附1-测试过程

初始

    1. org.apache.dubbo.rpc.Filter中配置apiExceptionFilter
    1. com.alibaba.dubbo.rpc.Filter中配置apiExceptionFilterV2
    1. provider filter添加apiExceptionFilterV3
    1. service filter添加apiExceptionFilterV4

其中apiExceptionFilterV3、apiExceptionFilterV4均在org.apache.dubbo.rpc.Filter中配置

结果上述4个apiExceptionFilter均会执行

结论
所以3、4配置或不配置都不影响过滤器的执行

测试-

在3、4中配置时,前面加上- v1、v2执行,v3、v4不执行,说明如果添加了过滤器,可在某个provider或service中排除

测试com.alibaba.dubbo.rpc.Filter

将apiExceptionFilterV3、apiExceptionFilterV4均放入 com.alibaba.dubbo.rpc.Filter
v1、v2执行

测试Activate

新增 v6、v7、v8
v6: 只添加@Activate(group = "provider", order = 6)注解
v7: 不添加注解,添加org.apache.dubbo.rpc.Filter
v8: 不添加注解,添加org.apache.dubbo.rpc.Filter及spring.dubbo.provider.filter

6、7、8均不会执行

测试不添加spring.dubbo.provider.filter

v9: 只添加@Activate(group = "provider", order = 9)注解,添加spring.dubbo.provider.filter
只执行v9并不会执行

测试只添加@Activate注解

v10: 只添加@Activate(group = "provider", order = 10)注解,service filter中添加
service filter中添加无论添加 ApiExceptionFilterV10还是apiExceptionFilterV10,服务均无法启动

附2-ApiExceptionFilter

@Activate(group = "provider")
public class ApiExceptionFilter implements Filter {

    private static final ILog LOGGER = LogFactory.getLog(ApiExceptionFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Result result = invoker.invoke(invocation);
        try {
            // 处理异常
            if (result != null && result.hasException()) {
                Throwable e = result.getException();
                if (e instanceof NullPointerException) {
                    LOGGER.error("api_exception||errMsg=java.lang.NullPointerException||e=",e);
                }   else if (e instanceof IllegalArgumentException) {
                    return buildResult(result,UserErrorEnum.PARAM_ERROR.getCode(), StringUtils.isNotEmpty(e.getMessage()) ? e.getMessage() : "Parameter invalid");
                } else if (e instanceof CarBizException){
                    return buildResult(result,((CarBizException) e).getCode(), ((CarBizException) e).getMsg());
                }else if (e instanceof RpcBizException) {
                    // 包装返回的errMsg
                    int code = ((RpcBizException) e).getCode();
                    String msg = ((RpcBizException) e).getMsg();
                    return buildResult(result,code, msg);
                } else if (e instanceof RpcException) {
                    return buildResult(result,((RpcException) e).getCode(), e.getMessage());
                } else if (e instanceof Exception) {
                    LOGGER.error("api_exception||e=",e);
                    return buildResult(result,UserErrorEnum.SYSTEM_ERROR.getCode(), UserErrorEnum.SYSTEM_ERROR.getDesc());
                }
            }
            return result;
        } catch (Exception e) {
            LOGGER.error("api_exception_invoke_error||errMsg={}", e);
            return result;
        }

    }

    private Result buildResult(Result result,int code, String msg) {

        RpcResult rpcResult = new RpcResult();
        // 处理RPC错误
        rpcResult.setCode(code);
        rpcResult.setMsg(msg);
        result.setValue(rpcResult);
        return result;
    }
}

待优化点

  • 将优先级调到最高@Activate(group = "provider",order = 100)
  • 构造 result时,设置exception为null
private Result buildResult(Result result,int code, String msg) {

    RpcResult rpcResult = new RpcResult();
    // 处理RPC错误
    rpcResult.setCode(code);
    rpcResult.setMsg(msg);
    result.setValue(rpcResult);
    result.setException(null);
    return result;
}