在业务开发中,对于同一类逻辑处理,一般都是都是归类为一组集合,类似于一条业务链来处理,流程如下:
举个例子,在下单过程中,会对生成订单进行很多条件判断。通常,会定义一个校验接口Validator定义生成订单的条件判断业务的抽象;在下单过程因为有很多不同的条件判断,所以,就会在下单的服务中,定义类似于一组的校验业务,例如,定义集合List<Validator> validators。
如果,在链式业务处理过程中,对于不同的订单会有校验逻辑需要满足条件才能判断,这时如何进行过滤呢?如果在不同的下单场景需要动态的添加或者修改一些校验条件,应该如何操作呢?有的业务有不同的优先级和先后顺序,应该如何设计?下面以tomcat中Filter过滤器链,Netty的事件链式处理为例,来介绍常见的链式设计。tomcat的filter过滤器链基于List集合,Netty的事件链表基于链表实现。
tomcat中Filter过滤器的实现
在tomcat中,对于Http请求通常会进行用户身份的校验,权限的验证,日志处理等等业务的拦截和过滤。模仿tomcat实现的伪代码,定义Filter接口实现过滤业务的封装,CompositeFilter定义一组的过滤逻辑处理集合,FilterChain决定每次执行的FIlter的选择逻辑,每次执行时,从条件过滤组中筛选满足条件的过滤器Filter进行。过滤器链执行流程的大致如下:
CompositeFilter以List集合存储所有Filter,如果需要对Filter进行排序,可以继承Ordered接口。FilterChain根据List集合的index,从0到index-1的顺序来获取Filter。Filter,CompositeFilter,FilterChain伪代码定义如下:
/**
* 过滤器,继承Ordered自定义过滤器的优先级
**/
public interface Filter extends Ordered{
/**
* 过滤
*/
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
}
/**
* 过滤器每次执行的筛选定义
**/
public interface FilterChain {
void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}
/**
* 过滤器集合定义,使用List集合进行封装
**/
public class CompositeFilter implements Filter {
// 过滤器列表
private List<? extends Filter> filters = new ArrayList();
public CompositeFilter() {
}
public void setFilters(List<? extends Filter> filters) {
// 根据定义的顺序排序
this.filters = AnnotationAwareOrderComparator.sort(new ArrayList(filters));
}
/**
* 过滤逻辑
**/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
(new CompositeFilter.VirtualFilterChain(chain, this.filters)).doFilter(request, response);
}
/**
* 内部类实现自定义的FilterChain,根据list集合的index,从0开始顺序的选择Filter进行处理
*/
private static class VirtualFilterChain implements FilterChain {
private final FilterChain originalChain;
private final List<? extends Filter> additionalFilters;
// 起始筛选的index
private int currentPosition = 0;
public VirtualFilterChain(FilterChain chain, List<? extends Filter> additionalFilters) {
this.originalChain = chain;
this.additionalFilters = additionalFilters;
}
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (this.currentPosition == this.additionalFilters.size()) {
this.originalChain.doFilter(request, response);
} else {
++this.currentPosition;
// 根据index从过滤器集合中选择Filter
Filter nextFilter = (Filter)this.additionalFilters.get(this.currentPosition - 1);
nextFilter.doFilter(request, response, this);
}
}
}
}
Netty中事件过滤器链的处理
在基于Socket的网络编程中,当Socket绑定接口时,连接或断开,读取或者写入数据时,都会有不同的业务需要处理。例如,从Socket读取数据,或者写人数据时,通常会进行数据的编码节码,数据的业务处理。Netty是对网络编程的封装,定义了ChannelHandler实现对各种事件的触发的时的业务逻辑,定义ChannelPipeline基于链表集合实现对所有的事件处理逻辑封装,ChannelHandlerContext基于前后事件的绑定,实现了对于每次执行事件触发时,事件的选择逻辑。其执行流程如下:
ChannelPipeline的默认实现类是DefaultChannelPipeline 在添加具体的ChannelHandler实现类时,会把ChannelHandler封装为AbstractChannelHandlerContext ,通过AbstractChannelHandlerContext 指定ChannelHandler前后的关联节点。ChannelHandler,ChannelPipeline,ChannelHandlerContext接口源码如下:
/**
* 各类Socket事件的具体业务定义的父接口
*/
public interface ChannelHandler {
/**
* 新增handler
*/
void handlerAdded(ChannelHandlerContext ctx) throws Exception;
/**
*删除handler
*/
void handlerRemoved(ChannelHandlerContext ctx) throws Exception;
/**
* 异常的处理
*/
@Deprecated
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
}
/**
* 基于链表实现AbstractChannelHandlerContext的封装,基于头部和尾部的数据数据添加,各类事件监听的统一调用
*/
public class DefaultChannelPipeline implements ChannelPipeline {
/**
* 链表head与tail节点定义
*/
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
/**
* 链表首部插入逻辑
*/
private void addFirst0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext nextCtx = head.next;
newCtx.prev = head;
newCtx.next = nextCtx;
head.next = newCtx;
nextCtx.prev = newCtx;
}
/**
* 链表首部插尾部入逻辑
*/
private void addLast0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception { }
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { }
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
onUnhandledInboundException(cause);
}
/**
* 读取数据事件逻辑
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
onUnhandledInboundMessage(msg);
}
/**
* 写入数据事件逻辑
*/
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
unsafe.write(msg, promise);
}
}
/**
* 链表事件筛选逻辑
*/
abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
implements ChannelHandlerContext, ResourceLeakHint {
/**
* 读取数据逻辑
*/
@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
invokeChannelRead(findContextInbound(), msg);
return this;
}
/**
* 选取next指定的AbstractChannelHandlerContext执行
*/
private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound);
return ctx;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/13616.html