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源码分析的更多相关文章

  1. Jetty - Container源码分析

    1. 描述 Container提供管理bean的能力. 基于Jetty-9.4.8.v20171121. 1.1 API public interface Container { // 增加一个bea ...

  2. Jetty 9 源码分析 Connector及Server类(一)

    本文的源码基于Jetty9,主要分析了Jetty 的Connector与Server类间在Jetty启动过程中的一些细节.Jetty9 对以前的Connector体系进行了重构, 结构与6和7都不同, ...

  3. Jetty - Connector源码分析

    1. 描述 基于Jetty-9.4.8.v20171121. Connector接受远程机器的连接和数据,允许应用向远程机器发送数据. 1.2 类图 从类图看出AbstractConnector继承C ...

  4. Jetty - LifeCycle源码分析

    1. 描述 基于Jetty-9.4.8.v20171121. LifeCycle主要管理Jetty里面通用组件的生命周期,比如组件启动中.启动.运行.停止中.停止等,实现该接口就可以定义一套生命周期. ...

  5. Handler 源码分析

    Handler用法: 无参 Handler 构造函数实例化一个 Handler 类型的全局变量,并重写其 handleMessage 方法,在某一方法内调用 Handler 的 sendEmptyMe ...

  6. Android之Handler源码深入分析

    闲着没事,就来看看源码,看看源码的各种原理,会用只是简单的,知道为什么才是最牛逼的. Handler源码分析那,从使用的步骤来边用边分析: 1.创建一个Handler对象:new Handler(ge ...

  7. Android异步消息传递机制源码分析

    1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.p ...

  8. 【Android】Handler、Looper源码分析

    一.前言 源码分析使用的版本是 4.4.2_r1. Handler和Looper的入门知识以及讲解可以参考我的另外一篇博客:Android Handler机制 简单而言:Handler和Looper是 ...

  9. jetty加载spring-context容器源码分析

    带着疑问开始 web.xml的顺序问题 先拿一个最简单的spring mvc web.xml来说问题,如下图:如果我将三者的顺序倒置或是乱置,会产生什么结果呢? 启动报错?还是加载未知结果?还是毫无影 ...

随机推荐

  1. C/C++控制台输出时设置字体及背景颜色

    1.改变整个控制台的颜色用 system("color 0A"); 其中color后面的0是背景色代号,A是前景色代号.各颜色代码如下: 0=黑色 1=蓝色 2=绿色 3=湖蓝色  ...

  2. PhpStorm 对 AngularJS 的支持

    非常喜爱用AngularJS来构建web应用程序的前端吗? PhpStorm 使得在其上进行 AngularJS 相关的工作同其它得到IDE支持的编程语言的工作一样容易! AD:51CTO首届中国AP ...

  3. MFC【17-1】线程和线程同步化

    17.1线程 对于Windows来说所有的线程都是一样的,但MFC却把线程区分为两种类型:User Interface(UI) threads(用户界面(UI)线程)和Worker threads(工 ...

  4. 【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读

      2015-05-08 00:15 3896人阅读 评论(10) 收藏 举报 本文章已收录于:   分类: 软件开发进阶(419) 作者同类文章X Unix/Linux杂项(118) 作者同类文章X ...

  5. subline 配置,本地项目代码下断点来调试远程项目

    参考: https://my.oschina.net/ptk/blog/299464 1. 文件 tts.sublime-project 的配置如下: { "folders": [ ...

  6. Spring整合JMS——三种connectionFactory

    1.SingleConnectionFactory:对于建立JMS服务器链接的请求会一直返回同一个链接,并且会忽略Connection的close方法调用.(org.springframework.j ...

  7. automake--关于两个文件configure.in和Makefile.am的编写

    http://blog.csdn.net/shanzhizi/article/details/30251763 automake主要通过编辑Makefile.am来控制它的行为,下面就常用的三个Mak ...

  8. 在页面左右一个悬浮div兼容IE6 IE7 8 9 Firefox chrome

    在页面左右一个悬浮div兼容IE6 IE7 8 9 Firefox chrome #identifier-pannel { bottom: 345px; margin-left: 512px; pos ...

  9. Textarea自动适用高度且无滚动条解决方案

    今日的系统需要动态显示一项数据库里面的内容,该内容包含换行等格式字符,要求如实的反应在页面上. 最初解决办法是使用textarea控件,代码如下: <textarea style="b ...

  10. ES6 变量解构用法

    1.数组解构,可以设置默认值 'use strict'; let [x, y = 'b'] = ['a']; //控制台输出b console.log(y); 2.对象解构 'use strict'; ...