为了后续扩展方便,搞个filter支持,就抄一个servlet的filter吧。
在写mvc项目时,经常会用到filter,可以给一个请求做前置或者后置处理。如下:
@WebFilter(filterName = "requestFilter", urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("我进来了");
chain.doFilter(request, response);
System.out.println("我要走了");
}
@Override
public void destroy() {
System.out.println("filter destroy");
}
}
这是一种责任链模式的实现,debug看下调用栈可以了解框架是怎么实现的。
定义filter接口,使用者如果要添加过滤逻辑需要集成这个接口。
public interface RpcFilter {
void doFilter(RpcRequest request, RpcResponse response, RpcFilterChain filterChain);
}
filter持有者
public class RpcFilterChain implements RpcCode {
private RpcFilter[] filters = new RpcFilter[0];
private int pos;
private RpcServiceInfo serviceInfo;
private RpcServiceExecutor serviceExecutor;//最终要执行请求的处理器
public RpcFilterChain(List<RpcFilter> filterList, RpcServiceInfo serviceInfo, RpcServiceExecutor serviceExecutor) {
if (filterList != null && !filterList.isEmpty()) {
this.filters = new RpcFilter[filterList.size()];
this.filters = filterList.toArray(this.filters);
}
this.serviceInfo = serviceInfo;
this.serviceExecutor = serviceExecutor;
}
public void doFilter(RpcRequest request, RpcResponse response) {
if (pos < filters.length) {
RpcFilter filter = filters[pos++];
filter.doFilter(request, response, this);
return;
}
if (serviceExecutor == null) {
response.error(SERVICE_NOT_FOUND, "service not exist: " + serviceInfo);
return;
}
serviceExecutor.execute(request, response);
}
}
rpc server 接收到请求后先初始化一个责任链,然后触发。
public RpcResponse execute(RpcRequest rpcRequest) {
RpcServiceInfo rpcServiceInfo = new RpcServiceInfo(rpcRequest.getAppName(), rpcRequest.getServiceName());
RpcFilterChain chain = new RpcFilterChain(filters, rpcServiceInfo, serviceExecutorMap.get(rpcServiceInfo));
RpcResponse rpcResponse = new RpcResponse();
try {
chain.doFilter(rpcRequest, rpcResponse);
} catch (Exception e) {
rpcResponse.error(e);
}
return rpcResponse;
}