Resource及其子类的分析
Resource 是一个抽象类。
是基础的资源类,对外露暴出统一的REST接口。Resource封装了Context、Request和Response,完成从REST概念向超文本概念的转换。
从前面说过的Compoent、Application、Services、Filter、Router到后面会讲的Finder,都是在REST层面的概念,Resource是REST到HTML的转换界面,是REST的终端(EndPoint)。
从Component到Resource,经过Application、Services、Filter、Route、Finder,都是调用Uniform的handle()方法,从设计模式上看,很像装饰者模式。
Services提供了多种可以配置的服务,可以根据需要增加;Filter、Router和Finder也可以根据需要进行系统行为的修改。这种类似装饰者模式的设计,提供了灵活的复用和扩展空间。这个Restlet框架核心就是这个装饰者模式,装饰的对象就是Resource。
一、Resource的生命周期
Resource有一个清晰的生命周期:
然后,调用init(Context, Request, Response)方法。
再然后是doInit() 为子类提供一些定制行为。
上面由Resource定义的方法执行完毕后,开始执行统一的 handle() 方法。在ClientResource和ServerResource中对handle()方法有不同的实现。
最后,在release() 方法调用之前先调用 doRelease() 方法,这个方法也是Resource定义的抽象方法,目的是给子类提供一些操作的扩展。
当出现错误和异常情况,可以通过覆写 doCatch(Throwable) 完成错误和异常的捕获和处理。
二、ServerResource
ServerResource是Resource的子类,是服务器端的基础资源类,封装了Request和Response。在两种情况下,ServerResource 的生命周期是由Finder来管理的:
1、一种是创建子类的时候,由Finder提供的create()方法直接创建的;
2、一种是创建的子类,关联组件的时候,通过 Filter.setNext() 或者Router.attach() 设置到Filter或者Router 上的。
ServerResource的handle()方法,是REST向HTML开始转换的地方。
1、 判断 isConditional() 和 isNegotiated() 来决定 doConditionalHandle(), doNegotiatedHandle() 和 doHandle() 哪个方法被执行。
2、在执行过程中,任何的 ResourceException 的出现,都会记录到当前的线程环境中并通过 setStatus(Status, Throwable, String)设置状态,为statusService处理提供状态。
三、doConditionalHandle(), doNegotiatedHandle() 和 doHandle()的判断过程
1、isConditional()是判断请求中是否包含以下内容:
If-Match
If-Modified-Since
If-None-Match
If-Range
If-Unmodified-Since
如果没有,则执行下一个判断isNegotiated() 。
2、isNegotiated() 判断调用的方法是否需要参数,如果不需要就直接跳过,执行 doHandle()。
3、 doHandle()
从doHanlde()这里,调用对应http method的方法,put()、get()、post()、delete()、head()、options()以及其他自定义的方法。