Jetty - Handler源码分析

Posted 小路不懂2

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jetty - Handler源码分析相关的知识,希望对你有一定的参考价值。

1. 描述

基于Jetty-9.4.8.v20171121。

Handler是Jetty服务处理器,用户Server处理HTTP请求。

Handler可以做如下处理:

(1)完全生成HTTP响应;

(2)检查或修改请求然后调用其他Handler,比如HandlerWrapper;

(3)传递请求给一个或多个Handlers,比如HandlerCollection;

1.1 类图

(1)AbstractHandler继承ContainerLifeCycle提供:

  (a)启停行为

  (b)bean容器

  (c)基本的dump支持

  (d)Server引用

  (e)ErrorDispatchHandler处理错误

(2)实现HandlerContainer接口的Handler可以包含其他Handlers,可以是一个HandlerWrapper或多个HandlerList/HandlerCollection;

(3)HandlerWapper是一个装饰器模式的装饰类,其子类如GzipHandler,ResourceHandler实现不同的装饰效果,如下类图:

// 装饰器模式 -- 核心类
class Decorator implements Component
{
       private Component component;  // 维持一个对抽象构件对象的引用
       public Decorator(Component component)  // 注入一个抽象构件类型的对象
       {
              this.component=component;
       }
 
       public void operation()
       {
              component.operation();  //调用原有业务方法
       }
}

(4)HandlerCollection和HandlerList包含多个Handler。

 

1.2 API

 

@ManagedObject("Jetty Handler")
public interface Handler extends LifeCycle, Destroyable
{
    /**
     * Handle a request.
     * 
     * @param target
     *            The target of the request - either a URI or a name.
     * @param baseRequest
     *            The original unwrapped request object.
     * @param request
     *            The request either as the {@link Request} object or a wrapper of that request. The
     *            <code>{@link HttpConnection#getCurrentConnection()}.{@link HttpConnection#getHttpChannel() getHttpChannel()}.{@link HttpChannel#getRequest() getRequest()}</code>
     *            method can be used access the Request object if required.
     * @param response
     *            The response as the {@link Response} object or a wrapper of that request. The
     *            <code>{@link HttpConnection#getCurrentConnection()}.{@link HttpConnection#getHttpChannel() getHttpChannel()}.{@link HttpChannel#getResponse() getResponse()}</code>
     *            method can be used access the Response object if required.
     * @throws IOException
     *             if unable to handle the request or response processing
     * @throws ServletException
     *             if unable to handle the request or response due to underlying servlet issue
     */
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException;

    public void setServer(Server server);

    @ManagedAttribute(value="the jetty server for this handler", readonly=true)
    public Server getServer();

    @ManagedOperation(value="destroy associated resources", impact="ACTION")
    public void destroy();
}

2. AbstractHandler

AbstractHandler是Handler的基本实现。

// 实现ContainerLifeCycle提供基本能力:(1)启停行为(2)bean容器化(3)基本的dump支持(4)Server引用(5)错误处理Handler
@ManagedObject("Jetty Handler")
public abstract class AbstractHandler extends ContainerLifeCycle implements Handler
{
    private static final Logger LOG = Log.getLogger(AbstractHandler.class);

    private Server _server; // Server

    public AbstractHandler()
    {
    }
    
    @Override
    public abstract void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;

    // 生成错误页面,当DispatchType.ERROR,handle可以调用该方法
    protected void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        Object o = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        int code = (o instanceof Integer)?((Integer)o).intValue():(o!=null?Integer.valueOf(o.toString()):500);
        o = request.getAttribute(RequestDispatcher.ERROR_MESSAGE);
        String reason = o!=null?o.toString():null;
        
        response.sendError(code,reason);
    }
    
    /* 
     * @see org.eclipse.thread.LifeCycle#start()
     */
    @Override
    protected void doStart() throws Exception
    {
        if (LOG.isDebugEnabled())
            LOG.debug("starting {}",this);
        if (_server==null)
            LOG.warn("No Server set for {}",this);
        super.doStart();
    }

    /* 
     * @see org.eclipse.thread.LifeCycle#stop()
     */
    @Override
    protected void doStop() throws Exception
    {
        if (LOG.isDebugEnabled())
            LOG.debug("stopping {}",this);
        super.doStop();
    }

    @Override
    public void setServer(Server server)
    {
        if (_server==server)
            return;
        if (isStarted())
            throw new IllegalStateException(STARTED);
        _server=server;
    }

    @Override
    public Server getServer()
    {
        return _server;
    }

    @Override
    public void destroy()
    {
        if (!isStopped())
            throw new IllegalStateException("!STOPPED");
        super.destroy();
    }

    @Override
    public void dumpThis(Appendable out) throws IOException
    {
        out.append(toString()).append(" - ").append(getState()).append(\'\\n\');
    }

     // 处理DispatcherType.ERROR的分发
    public static abstract class ErrorDispatchHandler extends AbstractHandler
    {
        @Override
        public final void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
        {
            if (baseRequest.getDispatcherType()==DispatcherType.ERROR)
                doError(target,baseRequest,request,response);
            else
                doNonErrorHandle(target,baseRequest,request,response);
        }

        // 处理所有非DispatcherType.ERROR
        protected abstract void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
    }

}

3. HandlerWrapper 

HandlerWrapper实现的是一个典型的装饰器模式。

 @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        Handler handler=_handler; // 被装饰对象的handle方法
        if (handler!=null)
            handler.handle(target,baseRequest, request, response);
    }

4. HandlerCollection

Handlers集合,默认实现是按照顺序执行所有handle方法,不管响应码和异常。子类可以改变调用顺序或者调用规则 

@ManagedObject("Handler of multiple handlers")
public class HandlerCollection extends AbstractHandlerContainer
{
    private final boolean _mutableWhenRunning;
    private volatile Handler[] _handlers;
    
    @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException
    {
        if (_handlers!=null && isStarted())
        {
            MultiException mex=null;

            for (int i=0;i<_handlers.length;i++) // 依次调用handle方法
            {
                try
                {
                    _handlers[i].handle(target,baseRequest, request, response);
                }
                catch(IOException e)
                {
                    throw e;
                }
                catch(RuntimeException e)
                {
                    throw e;
                }
                catch(Exception e)
                {
                    if (mex==null)
                        mex=new MultiException();
                    mex.add(e);
                }
            }
            if (mex!=null)
            {
                if (mex.size()==1)
                    throw new ServletException(mex.getThrowable(0));
                else
                    throw new ServletException(mex);
            }

        }
    }
}

5. HandlerList

继承HandlerCollection,调用每一个Handler,遇到3种情况会退出:(1)抛出异常(2)响应被提交(3)整数的响应状态  

@Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException // 异常退出
    {
        Handler[] handlers = getHandlers();

        if (handlers!=null && isStarted())
        {
            for (int i=0;i<handlers.length;i++)
            {
                handlers[i].handle(target,baseRequest, request, response);
                if ( baseRequest.isHandled()) // 退出
                    return;
            }
        }
    }  

总的来说,Handler采用装饰器模式,通过继承父装饰类,自定义不同的handlr处理逻辑。

以上是关于Jetty - Handler源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Jetty与Tomcat的区别

引起:java.lang.ClassNotFoundException:org.mortbay.jetty.Handler

Handler机制源码分析笔记

源码分析|Handler内存泄漏分析及解决

Jetty - Connector源码分析

Jetty - Container源码分析