上善若水
In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
posts - 146,comments - 147,trackbacks - 0

概述

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方法。
posted on 2014-05-17 23:20 DLevin 阅读(1935) 评论(1)  编辑  收藏 所属分类: Jetty

FeedBack:
# re: 深入Jetty源码之ServletHandler
2014-05-18 15:14 | 金利锁业
谢谢 博主分享  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: