深入Jetty源码之Handler总述

Handler概述

Handler是Jetty中的核心接口,它用于处理所有连接以外的逻辑,比如对Servlet框架的实现,以及用户自定义的Handler等,它继承自LifeCycle和Destroyable接口,只有一个主要方法:handle,包含Request和Response实例。在深入Jetty源码之Connection中有写道在HttpConnection的handleRequest()方法中会最终调用Server的handle()或handleAsync()方法,并且传入HttpConnection自身作为参数以处理后续逻辑,在这里Server作为Handler的容器,在Server中以HttpConnection为参数的handle()和handleAsync()方法中,会调用向这个Handler容器中注册的所有Handler的handle()方法。即在使用Jetty时,我们首先要向Server注册相应的Handler实例。

Handler接口定义

Handler的接口定义如下:

public interface Handler extends LifeCycle, Destroyable {
    // 处理一个HTTP请求,并最终将响应写入Response中。不同的实现有不同的功能和逻辑,如WebAppContext实现一个Servlet容器,
    // 而ErrorHandler则向Response中写入一个包含错误码和原因的HTML页面。
    // 关于参数:
    // target表示Request的目标,它可以时一个URI或一个名字。即Request中的pathInfo字段。
    // baseRequest表示在HttpConnection中创建并解析的最初的Request,它没有被包装。
    // request表示一个HttpServletRequest,它可以同baseRequest相同的实例,也可以是一个经过包装后的HttpServletRequest。
    // response表示一个HttpServletResponse,它可以是经过包装的HttpServletResponse或在HttpConnection创建的最原始的HttpServletResponse。
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException;
    
    public void setServer(Server server);
    public Server getServer();
    
    public void destroy();
}

Handler类图


AbstractHandler

AbstractHandler继承自AggregateLifeCycle并实现了Handler接口,是基本上所有Handler的基类。它的实现也非常简单,它定义了Server成员,并实现了getServer和setServer方法,在setServer实现中,如果已存在的Server引用和新设置的Server不同,则先将自身从已存在的Server的Container中移除,然后将自身添加到新的Server的Container中,并更新内部对Server的引用实例。在destroy方法中,也会将自身从Server引用实例的Container中移除。

DefaultHandler

DefaultHandler直接继承自AbstractHandler,它可以用于Handler链表的末尾Handler,用于处理所有不能被其他Handler处理的请求:/favicon.ico -> 显示jetty图标,/ -> 显示404错误页面,并列出所有可用的ContextPath,任何其他请求显示404错误页面。图标的显示和可用ContextPath的列表显示都是可配的。

DumpHandler

DumpHandler直接继承自AbstractHandler,用于测试和调试,显示Request消息内容。它显示的信息有PathInfo、ContentType、CharacterEncoding、RequestLine、Headers、Parameters、CookieName、Cookies、Attributes、Content等。

ErrorHandler

ErrorHandler直接继承自AbstractHandler,用于处理错误页面,使用ContextHandler.setErrorHandler()或Server.addBean()注册。它显示出错代码、原因以及更详细的信息。其中异常栈从Request的javax.servlet.errro.exception中获取。

ErrorPageErrorHandler

ErrorPageErrorHandler继承自ErrorHandler,它可以配置不同的Exception和Response Status Code到不同的页面。Exception类型从Request中的javax.servlet.error.exception_type或javax.servlet.error.exception属性中获取,Response Status Code从Request中的javax.servlet.error.status_code属性中获取。使用Exception类型、Response Status Code、Response Status Code Range从_errorPages中查找在web.xml文件中注册的映射,如果有找到,则使用ServletContext中的RequestDispatcher将当前的Request、Response派发的其error处理逻辑;否则使用ErrorHandler中的逻辑。

ResourceHandler

ResourceHandler直接继承自AbstractHandler,用于处理静态资源以及If-Modified-Since头。使用PathInfo以及注册的或ContextHandler中的BaseResource作为Base查找Resource,如果找不到并且请求的类型是/jetty-stylesheet.css资源,则查找注册的或默认的stylesheet资源;如果查找到的资源是目录,如果URL不是以"/"结尾,则重定向到"URL/",否则查找是否有welcome list中配置的页面存在以显示,否则列出文件列表或者显示403 Forbidden页面;对If-Modified-Since请求头,如果资源存在LastModified属性,并且比请求中设置的值要小或相等(以秒为单位),返回304 Not Modified;根据文件名或PathInfo以及注册的MineTypes信息设置ContentType,设置Content-Length、Cache-Control、Last-Modified等响应头,将Resource内容写入Response中。

顺便提及:Resource是Jetty中对静态资源的抽象,其子类有URLResource、FileResource、JarResource、JarFileResource、BadResource等。类似Spring中对Resource抽象,不详述。

AbstractHandlerContainer

AbstractHandlerContainer继承自AbstractHandler,并实现了HandlerContainer接口。HandlerContainer接口定义如下:

public interface HandlerContainer extends LifeCycle {
    // 返回当前Handler包含的所有Handler
    public Handler[] getHandlers();
    // 返回当前Handler和其所有子Handler包含的所有Handler
    public Handler[] getChildHandlers();
    // 返回所有当前Handler和其所有子Handler包含的所有Handler中类型为指定类型的Handler
    public Handler[] getChildHandlersByClass(Class<?> byclass);
    // 返回第一个所有当前Handler和其所有子Handler包含的所有Handler中类型为指定类型的Handler
    public <T extends Handler> T getChildHandlerByClass(Class<T> byclass);
}
AbstractHandlerContainer主要实现了两个方法:

// 将所有当前handler或其子handler中类型为byClass的Handler添加到list中,并返回该list实例
protected Object expandHandler(Handler handler, Object list, Class<Handler> byClass);
// 从root的HandlerContainer中找到handler所在的HandlerContainer实例,并且该HandlerContainer必须属于type类型
public static <T extends HandlerContainer> T findContainerOf(HandlerContainer root,Class<T>type, Handler handler);

HandlerCollection

HandlerCollection继承自AbstractHandlerContainer,它使用Handler数组作为容器来存储Handler,并且可已配置是否在启动后还能修改这个容器,以及启动是是否并行启动:

    private final boolean _mutableWhenRunning;
    private volatile Handler[] _handlers;
    private boolean _parallelStart=false; 
在handle()方法实现中,遍历数组中所有的Handler,调用其handle()方法。
在setHandlers()和setServer()方法实现中,需要生成并分发handler的Relationship发生变化的事件给在Server中的Container中注册的Listener,以及更新相应Handler中对Server的引用。

HandlerList

它继承自HandlerCollection,只是重写了handle()方法的逻辑,即在HandlerList中,它遍历整个Handlers 数组直到有异常发生或baseRequest的isHandled()返回true(什么时候baseRequest的handled属性会被设置为true呢?在发送请求之前或相应状态码被设置);而HandlerCollection则会遍历整个Handlers数组直到一个RuntimeException发生或IOException发生或整个Handler数组遍历完成,如果中途有出现其他异常最后统一抛出。

ContextHandlerCollection

ContextHandlerCollection继承自HandlerCollection,使用PathMap存储请求URI到ContextHandler的映射。

HotSwapHandler

HotSwapHandler继承自AbstractHandlerContainer,支持动态的替换内部的Handler(即在设置Handler时,如果当前Handler已经启动,则并立即启动新设置的Handler,并停止原来的Handler)。它使用Composite模式,内部只是使用一个Handler来保存一个集合的Handler,因而如果要注册多个Handler,则这个Handler的类型需要HandlerContainer。

HandlerWrapper

HandlerWrapper继承自AbstractHandlerContainer,它类似Composite模式,使用一个Handler本身来表达一个HandlerContainer,因而同HotSwapHandler,它只是包含一个Handler字段用与表示、存储Handler集合,并且其实现也和HotSwapHandler类似,所不同的是它不会动态的启动新设置的Handler,即它只是一个Handler的Wrapper。 

ConnectHandler

ConnectHandler继承自HandlerWrapper,它实现了一个代理服务器。

DebugHandler

DebugHandler继承自HandlerWrapper,用于测试时使用,在logs 目录中yyyy_mm_dd.debug.log文件的形式纪录请求的时间和URL以及响应的时间和响应状态码,并设置线程名为请求URL。

IPAccessHandler

IPAccessHandler继承自HandlerWrapper,用于添加可以使用或需要组织的IP列表,并返回403 Forbidden响应。

RequestLogHandler

RequestLogHandler继承自HandlerWrapper,在所有handler处理结束后,将Request和Response使用RequestLog类打印到日志中。

StatisticsHandler

StatisticsHandler继承自HandlerWrapper,用于纪录一些统计信息,如请求数、请求时间、dispatched数与时间、suspended数、resume数、expire数、1xx到5xx的响应数、响应总的字节数等。

时间: 2024-10-30 12:04:54

深入Jetty源码之Handler总述的相关文章

深入Jetty源码之ContextHandler

概述 ContextHandler继承自ScopedHandler,它是Jetty中实现对一个Web Application的各种资源进行管理,并串联实现整个Servlet框架的类,比如它部分实现了ServletContext接口,并且在其doScope方法中为当前Request的执行提供了相应的环境,如设置servletPath.pathInfo.设置ServletContext到ThreadLocal中.在Jetty中,Servlet的执行流程和框架由ServletHandler实现,Sec

深入Jetty源码之Connector

Connector概述 Connector是Jetty中可以直接接受客户端连接的抽象,一个Connector监听Jetty服务器的一个端口,所有客户端的连接请求首先通过该端口,而后由操作系统分配一个新的端口(Socket)与客户端进行数据通信(先握手,然后建立连接,但是使用不同的端口).不同的Connector实现可以使用不同的底层结构,如Socket Connector.NIO Connector等,也可以使用不同的协议,如Ssl Connector.AJP Connector,从而在不同的C

库-配置QT5.5.0源码包时总出现找不到工具链,各种情况尝试如下:请纠错!!!

问题描述 配置QT5.5.0源码包时总出现找不到工具链,各种情况尝试如下:请纠错!!! 前提: 自己用户的shell:修改了$HOME/.bashrc 中的export PATH=/usr/local/arm/arm-2009q3/bin:$PATH 系统环境变量:修改了/etc/profile 中的 export PATH=/usr/local/arm/arm-2009q3/bin:$PATH 全部用户的shell:修改了/etc/bash.bashrc中的 export PATH=/usr/

深入Jetty源码之Connection

概述 当Jetty中的Connector收到一个客户端的连接时(ServerSocket或ServerSocketChannel的accept()方法返回),Connector会首先创建一个ConnectedEndPoint用于和连接的底层(Socket.Channel)打交道(读写数据),在创建的ConnectedEndPoint时会同时使用该EndPoint创建相应类型的Connection,然后会创建一个Task仍给线程池,最终线程池会启动一个线程启动这个Task,而在这个Task中调用C

深入Jetty源码之SecurityHandler

概述 Jetty的强大之处在于可以自由的配置某些组建的存在与否,以提升性能,减少复杂度,而其本身也因为这种特性而具有很强的可扩展性.SecurityHandler就是Jetty对Servlet中Security框架部分的实现,并可以根据实际需要装卸和替换.Servlet的安全框架主要有两个部分:数据传输的安全以及数据授权,对数据传输的安全,可以使用SSL对应的Connector实现,而对于数据授权安全,Servlet定义了一套自己的框架. Servlet的安全框架支持两种方式的验证:首先,是用于

深入Jetty源码之Servlet框架及实现(ServletRequest、ServletResponse)

概述 Servlet是Server Applet的缩写,即在服务器端运行的小程序,而Servlet框架则是对HTTP服务器(Servlet Container)和用户小程序中间层的标准化和抽象.这一层抽象隔离了HTTP服务器的实现细节,而Servlet规范定义了各个类的行为,从而保证了这些"服务器端运行的小程序"对服务器实现的无关性(即提升了其可移植性).在Servlet规范有以下几个核心类(接口):ServletContext:定义了一些可以和Servlet Container交互的

深入Jetty源码之Servlet框架及实现(AsyncContext、RequestDispatcher、HttpSession)

概述 Servlet是Server Applet的缩写,即在服务器端运行的小程序,而Servlet框架则是对HTTP服务器(Servlet Container)和用户小程序中间层的标准化和抽象.这一层抽象隔离了HTTP服务器的实现细节,而Servlet规范定义了各个类的行为,从而保证了这些"服务器端运行的小程序"对服务器实现的无关性(即提升了其可移植性).在Servlet规范有以下几个核心类(接口):ServletContext:定义了一些可以和Servlet Container交互的

深入Jetty源码之Servlet框架及实现(Servlet、Filter、Registration)

概述 Servlet是Server Applet的缩写,即在服务器端运行的小程序,而Servlet框架则是对HTTP服务器(Servlet Container)和用户小程序中间层的标准化和抽象.这一层抽象隔离了HTTP服务器的实现细节,而Servlet规范定义了各个类的行为,从而保证了这些"服务器端运行的小程序"对服务器实现的无关性(即提升了其可移植性).在Servlet规范有以下几个核心类(接口):ServletContext:定义了一些可以和Servlet Container交互的

深入Jetty源码之ServletHandler

概述 ServletHandler继承自ScopedHandler,是Jetty中用于存储所有Filter.FilterMapping.Servlet.ServletMapping的地方,以及用于实现一次请求所对应的Filter链和Servlet执行流程的类.对Servlet的框架实现中,它也被认为是Handler链的末端,因而在它的doHandle()方法中没有调用nextHandle()方法. ServletHandler的成员 正如前面提到的,ServletHandler是一个用于管理Fi