SOFARPC 提供了一套良好的可扩展性机制,为各个模块提供 SPI(Service Provider Interface) 的能力。
SOFARPC 对请求与响应的过滤链(FilterChain)处理方式为:
通过多个过滤器 Filter 来进行具体的拦截处理。
允许用户自定义 Filter 扩展,且自定义 Filter 的执行顺序在内置 Filter 之后。
下文将就自定义 Filter 类及其生效进行说明:
自定义 Filter 类
自定义 Filter 类需继承 com.alipay.sofa.rpc.filter.Filter
类。示例如下:
package com.alipay.sofa.rpc.customfilter;
import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.request.SofaRequest;
import com.alipay.sofa.rpc.core.response.SofaResponse;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.filter.FilterInvoker;
import com.alipay.sofa.rpc.log.Logger;
import com.alipay.sofa.rpc.log.LoggerFactory;
public class CustomEchoFilter extends Filter{
/**
* Logger for CustomEchoFilter
**/
private static final Logger LOGGER =LoggerFactory.getLogger(CustomEchoFilter.class);
@Override
public boolean needToLoad(FilterInvoker invoker){
// 判断一些条件,自己决定是否加载这个 Filter。
return true;
}
@Override
public SofaResponse invoke(FilterInvoker invoker,SofaRequest request) throws SofaRpcException{
// 调用前打印请求。
LOGGER.info("echo request : {}, {}", request.getInterfaceName()+"."+ request.getMethod(),
request.getMethodArgs());
// 继续调用。
SofaResponse response = invoker.invoke(request);
// 调用后打印返回值。
if(response ==null){
return response;
}else if(response.isError()){
LOGGER.info("server rpc error: {}", response.getErrorMsg());
}else{
Object ret = response.getAppResponse();
if(ret instanceof Throwable){
LOGGER.error("server biz error: {}",(Throwable) ret);
}else{
LOGGER.info("echo response : {}", response.getAppResponse());
}
}
return response;
}
}
自定义 Filter 类生效方式
自定义 Filter 类支持如下生效方式:
API 方式
该方式可以指定生效的 provider 或 consumer。示例如下:
// 服务提供者 providerConfig.setFilterRef(Arrays.asList(new CustomFilter())); // 服务调用者 consumerConfig.setFilterRef(Arrays.asList(new CustomFilter()));
@Extension 注解 + 扩展文件 + 编码注入
处理步骤如下:
处理自定义 Filter 类。
@Extension("customer") public class CustomFilter extends Filter{ @Override public boolean needToLoad(FilterInvoker invoker){ return true; } @Override public SofaResponse invoke(FilterInvoker invoker,SofaRequest request) throws SofaRpcException{ SofaResponse response = invoker.invoke(request); return response; } }
创建扩展文件。
文件名:以 Filter 为后缀。例如:
com.alipay.sofa.rpc.filter.Filter
。文件路径:为固定路径。位于
META-INF/services/sofa-rpc/
下。
完整示例:
META-INF/services/sofa-rpc/com.alipay.sofa.rpc.filter.Filter
。扩展文件内容如下:customer=com.alipay.sofa.rpc.custom.CustomFilter
注入编码。
// 服务提供者 providerConfig.setFilter(Arrays.asList(“customer”)); // 服务调用者 consumerConfig.setFilter(Arrays.asList(“customer”));
@Extension 注解 + 扩展文件 + @AutoActive 注解
处理步骤如下:
处理自定义 Filter 类。
@Extension(“customer”) @AutoActive(providerSide =true, consumerSide =true) public class customerFilter extends Filter{ @Override public boolean needToLoad(FilterInvoker invoker){ return true; } @Override public SofaResponse invoke(FilterInvoker invoker,SofaRequest request) throws SofaRpcException{ SofaResponse response = invoker.invoke(request); return response; } }
说明使用 2 个注解
@Extension
和@AutoActive
处理 Filter 类可以免去编码注入。作用域为所有 provider 或 consumer。其中,参数providerSide
表示是否生效于服务端;参数consumerSide
表示是否生效于客户端。创建扩展文件。
文件名:以 Filter 为后缀。例如
com.alipay.sofa.rpc.filter.Filter
。文件路径:固定路径,位于
META-INF/services/sofa-rpc/
下。
完整示例:
META-INF/services/sofa-rpc/com.alipay.sofa.rpc.filter.Filter
。扩展文件内容如下:customer=com.alipay.sofa.rpc.custom.CustomFilter