深入Jetty源码之ServletHandler

概述

ServletHandler继承自ScopedHandler,是Jetty中用于存储所有Filter、FilterMapping、Servlet、ServletMapping的地方,以及用于实现一次请求所对应的Filter链和Servlet执行流程的类。对Servlet的框架实现中,它也被认为是Handler链的末端,因而在它的doHandle()方法中没有调用nextHandle()方法。 

ServletHandler的成员

正如前面提到的,ServletHandler是一个用于管理Filter、FilterMapping、Servlet、ServletMapping的容器,因而它需要一下成员用于存储这些它管理的实例:

     private  FilterHolder[] _filters= new  FilterHolder[0]; 
     private  FilterMapping[] _filterMappings; 
     
     private  ServletHolder[] _servlets= new  ServletHolder[0]; 
     private  ServletMapping[] _servletMappings; 
     
     private   final  Map<String,FilterHolder> _filterNameMap=  new HashMap<String,FilterHolder>(); 
     private  List<FilterMapping> _filterPathMappings; 
     private  MultiMap<String> _filterNameMappings; 
     
     private   final  Map<String,ServletHolder> _servletNameMap= new HashMap<String,ServletHolder>(); 
     private  PathMap _servletPathMap;

其中FilterHolder和ServletHolder分别用于存储Filter、Servlet实例以及其配置信息,即web.xml配置文件中的<filter>、<servlet>的配置信息(参考:  Servlet、Filter、Registration的实现 );而FilterMapping和ServletMapping则是FilterName到URL Pattern的mapping信息,以及ServletName到URL Pattern的mapping信息,即web.xml中的<filter-mapping>、<servlet-mapping>信息。 
其中FilterMapping包含了一个Filter适用的所有URL Pattern、Servlets、DispatcherType以及对应FilterHolder信息: 

     private   int  _dispatches=DEFAULT; 
     private  String _filterName; 
     private   transient  FilterHolder _holder; 
     private  String[] _pathSpecs; 
     private  String[] _servletNames;

它有appliesTo()方法用于判断传入的path和dispatcherType是否符包含当前Filter。对于URL Pattern:*.do=>anything.do, /foo/poo/abc.do, /path/to/*=>/path/to, /path/to/abdc。 
而ServletMapping包含了ServletName和其适用的所有URL Pattern,它的URL Pattern的mapping规则和FilterMapping中的规则一样: 

     private  String _servletName; 
     private  String[] _pathSpecs;

在管理Filter和FilterMapping中,可以使用FilterHolder、pathSpec、DispatcherType向_filters数组中添加一个FilterHolder,并向_filterMappings数组中添加一个FilterMapping实例;而由该方法引申出来的,可以直接传入Filter实例、Filter类实例、Filter类名,而由方法内部创建对应的FilterHolder实例;DispatcherType可以是一个EnumSet类型的DispatcherType;可以直接添加Filter或FilterMapping或两个同时添加;也可以使用prependFilterMapping将新的FilterMapping添加到数组前。对Servlet和ServletMapping管理也是类似,使用ServletHolder和pathSpec添加_servlets数组和_servletMappings数组,并引申出Servlet可以是实例、Servlet类名、Servlet类实例,而由内部创建ServletHolder实例;也可以单独的添加ServletHolder或ServletMapping实例。 
在ServletHandler中还有_filterNameMap和_servletNameMap实例用于存储FilterName到FilterHolder以及ServletName到ServletHolder的映射,它在每次_filters、_servlets数组更新时都会随着更新,并且在doStart方法中也会再更新一次;另外对Filter还有_filterPathMapping用于存储所有FilterMapping的一个List,_filterNameMapping用于存储ServletName到多个FilterMapping的MultiMap,对Servlet中也有_servletPathMap,包含pathSpec到ServletHolder的PathMap,他们在每次_filterMappings、_servletMappings更新时以及doStart方法中都会被更新。而在start时也会start所有的FilterHolder和ServletHolder,对所有FilterHolder的start按其定义顺序进行,而对ServletHolder的start,则按其InitOrder排序。 

doScope方法实现

doScope方法用于准备执行环境,其实现逻辑为:如果传入的target不是ServletName(即以"/"开头,表示它为Path),则使用该target从_servletPathMap中找到对应的ServletHolder,并计算出当前的ServletPath和PathInfo,如果时INCLUDE类型的Dispatch,设置Request的javax.servlet.include.serlvet_path,javax.servlet.include.path_info属性为计算出来的值,否则设置Request的ServletPath和PathInfo的值为计算出的值;对target为ServletName,ServletHolder的实例从_servletNameMap字段中查找。然后将当前找到的ServletHolder作为UserIdentityScope设置到Request中,以及设置org.eclipse.multipartConfig属性为ServletHolder中的MultipartConfig实例。在刚方法退出时,将UserIdentityScope、ServletPath、PathInfo还原回原来的值。 

doHandle方法实现

doHandle方法用于真正实现执行逻辑:它首先通过target找到FilterChain实例,对于target为path时,它遍历整个_filterPathMapping的列表,选出所有符合pathInContext的FilterHolder数组,以及从_filterNameMappings中找出所有ServletHolder中存储的ServletName对应的FilterMapping并且DispatcherType相符合的FilterMapping数组,以及注册的ServletName为"*"的FilterMapping且DispatcherType相符的FilterMapping数组,合并这些数组,并一同用Request、ServletHolder创建FilterChain实例;对target为ServletName时,只需要查找_filterNameMapping字段中的FilterMapping。如果没有FilterHolder实例,则向客户端发送404 Not Found响应;否则如果FilterChain实例不为null,调用其doFilter方法,传入ServletRequest和ServletResponse参数,在FilterChain的doFilter方法中它回一次遍历Filter的doFilter方法,直到最后调用ServletHolder的handle方法;否则,直接调用ServletHolder的handle方法。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值