Jetty 架构——Handler组件

如果大家觉得文章有错误内容,欢迎留言或者私信讨论~

  之前我们提到 Jetty 就是由多个 Connector 和 Handler 以及一个线程池组成,基本的架构如下图所示:
Jetty 架构——Handler组件_第1张图片

  今天我们需要学习的 Jetty 的 Handler,Handler 的设计非常有意思,可以说是 Jetty 的灵魂,Jetty 通过 Handler 实现了高度的可定制化,那么具体是如何实现的呢?让我们继续看下去。

Handler 是什么

  Handler 就是一个接口,他有一堆的实现类, Jetty 的 Connector 组件调用这些接口来处理 Servlet 请求,我们先来看看这个接口定义成什么样子。

public interface Handler extends LifeCycle, Destroyable
{
    //处理请求的方法
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException;
    
    //每个Handler都关联一个Server组件,被Server管理
    public void setServer(Server server);
    public Server getServer();

    //销毁方法相关的资源
    public void destroy();
}

  Handler 接口的定义非常简洁,主要就是用 handler 方法来处理请求,它跟 Tomcat 一样也有 ServletRequest 和 ServletResponse 两个参数。这个接口还有 setServer、getServer 方法,也就是说需要 server 组件来管理。一般来说 Handler 的加载会加载一些资源到内存,也就是需要 destroy 方法。

Handler 继承

  Handler 毕竟只是一个接口,完成具体功能还是得它的子类。那么 Handler 有哪些子类呢?它们的继承关系又是怎样的?这些子类是如何实现 Servlet 容器功能的呢?

  Jetty 的一些默认 Handler 之间的继承关系还是比较复杂,我们来看简化版的类图:
Jetty 架构——Handler组件_第2张图片

  一般来说,有接口就必然有抽象类,Handler 的抽象类是 AbstractHandler。但是 AbstractHandler 之下有 AbstractHandlerContainer,这是什么呢?这是因为为了实现链式调用,一个 Handler 内部必然要有其他 Handler 的引用,所以这个类的名字才有 Container, 意思就是这样的 Handler 里包含了其他 Handler 的引用。

  理解了 AbstractHandlerContainer,再来看看它的两个子类—— HandlerWrapper 和 HandlerCollection,长话短说,它们两个都是 Handler,不同的是前者是只包含了一个 Handler 的引用,而后者则是包含了一个 Handler 数组的引用。

Jetty 架构——Handler组件_第3张图片

  接下来看左边的 HandlerWrapper,它有两个子类:Server 和 ScopedHandler。Server 比较好理解,它本身是 Handler 模块的入口,必然要将请求传递给其他 Handler 来处理,为了触发其他 Handler 的调用,所以它是一个 HandlerWrapper。再看 ScopedHandler,它也是一个比较重要的 Handler,实现了“具有上下文信息”的责任链调用。

  再看右边的跟 HandlerWrapper 对等的还有 HandlerCollection,HandlerCollection 其实维护了一个 Handler 数组。至于为什么要维护一个 Handler 的数组,因为 Jetty 可能需要同时支持多个 Web 应用,如果每个 Web 应用有一个 Handler 入口,那么多个 Web 应用的 Handler 就成了一个数组。

Handler 的类型

  虽然类图上的 Handler 有很多,但本质上只有三类:

  1. 第一种是协调 Handler, 这种 Handler 负责将请求路由到另一组 Handler 上,比如上图的 HandlerCollection,它内部维护一个 Handler 数组,当请求到来时,它负责将请求转发到数组中的某个 Handler 中。
  2. 第二种是过滤器 Handler, 这种 Handler 就是上图的 HandlerWrapper,处理完请求将请求转发到下一个 Handler,所有继承了 HandlerWrapper 的Handler 都具有过滤器类型的特征。
  3. 第三种是**内容 Handler,**说白了就是会真正调用 Servlet 来处理请求,生成响应的内容,比如 ServletHandler。

如何实现 Servlet 规范

  上文提到,Handler 是有保存上下文信息的,如ServletHandler、ContextHandler 以及 WebAppContext 等,它们实现了 Servlet 规范,那具体是怎么实现的呢?

  为了方便理解,我们来看看如何使用 Jetty 启动一个 web 应用

//新建一个WebAppContext,WebAppContext是一个Handler
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/mywebapp");
webapp.setWar("mywebapp.war");

//将Handler添加到Server中去
server.setHandler(webapp);

//启动Server
server.start();
server.join();

  主要是分为两步:

  1. 第一步创建一个 WebAppContext,接着设置一些参数到这个 Handler 中,就是告诉 WebAppContext 你的 WAR 包放在哪,Web 应用的访问路径是什么?
  2. 第二步就是把新创建的 WebAppContext 添加到 Server 中,然后启动 Server。

  Servlet 的规范中有 Context、Servlet、Filter、Listener 和 Session 等,Jetty 要实现上下文、要支持 Servlet 规范,就应该有相应的 Handler 来实现这些功能。因此,Jetty 设计了 3 个组件:ContextHandler、ServletHandler 和 SessionHandler 来实现 Servlet 规范中规定的功能,而WebAppContext 本身就是一个 ContextHandler ,另外它还负责管理 ServletHandler 和 SessionHandler。

  那 ContextHandler 是什么?ContextHandler 会创建并初始化 Servlet 规范里的,同时 ContextHandler 还包含了一组能够让你的 Web 应用运行起来的 Handler,可以这样理解,Context 本身也是一种 Handler,它里面包含了其他的 Handler,这些 Handler 能处理某个特定 URL 下的请求。比如,ContextHandler 包含了一个或者多个 ServletHandler。

  再来看 ServletHandler,它实现了 Servlet 规范中的 Servlet、Filter 和 Listener 的功能。ServletHandler 依赖 FilterHolder、ServletHolder、ServletMapping、FilterMapping 这四大组件。FilterHolder 和 ServletHolder 分别是 Filter 和 Servlet 的包装类,每一个 Servlet 与路径的映射会被封装成 ServletMapping,而 Filter 与拦截 URL 的映射会被封装成 FilterMapping。

  SessionHandler 从名字就知道它的功能,用来管理 Session。除此之外 WebAppContext 还有一些通用功能的 Handler,比如 SecurityHandler 和 GzipHandler,同样从名字可以知道这些 Handler 的功能分别是安全控制和压缩 / 解压缩。

  WebAppContext 会将这些 Handler 构建成一个执行链,通过这个链会最终调用到我们的业务 Servlet。我们通过一张图来理解一下。

Jetty 架构——Handler组件_第4张图片

  对于 Jetty 来说,请求处理模块就被抽象成 Handler,不管是实现了 Servlet 规范的 Handler,还是实现通用功能的 Handler,比如安全、解压缩等,我们可以任意添加或者裁剪这些“功能模块”,从而实现高度的可定制化。

你可能感兴趣的:(Tomcat,jetty,架构,servlet)