<Portlet开发指南>第五章
五、 Portlet接口和相关生命周期接口
Portlet接口是Portlet API中的主要点和关键点。所有portlet直接或者间接的实现这个接口。Portlet可以选择性的实现EventPortlet 和ResourceServingPortlet接口来实现附加的功能。GenericPortlet类实现了Portlet,EventPortlet 、ResourceServingPortlet三个接口,开发者可以方便继承GenericPortlet来开发portlet。
Portlet 实例的数量
Portlet部署描述符中(portlet.xml)中定义了portlet容器怎么创建portlet实例。默认情况下,portlet不是在分布式环境中,portlet容器必须实例化和使用唯一的一个portlet实例。如果是在分布式环境中每个jvm维护一个portlet实例。不过这些都是对portlet容器实现厂商的规定,开发者一般不用过多关注。
Portlet生命周期
和servlet一样,portlet容器管理着portlet的生命周期,portlet生命周期定义了portlet怎么被加载、实例化、初始化,怎么接受客户端发过来的request,怎么销毁。Portlet生命周期通过portlet接口中的init、 processAction、render 、 destroy几个方法来实现。当然EventPortlet 和ResourceServingPortlet接口中定义了附加的一些方法。
加载和实例化
Portlet容器负责加载和实例化portlet。加载和实例化可以发生在portlet刚部署时,亦可以延时到有请求要访问这个portlet。Portlet容器的类加载器要与servlet容器的类加载器一致。当Portlet容器加载好portlet后就会实例化这个portlet。
初始化
当portlet被实例化之后,portlet容器必须先初始化这个portlet才能让请求访问这个portlet。Portlet容器调用portlet接口的init方法初始化portlet。这里很像servlet的方式,在portlet接口的init方法中可以调用PortletConfig接口的对象,通过PortletConfig的实例可以访问portlet.xml中的一些初始化参数和ResourceBundle。和servlet一样可以通过PortletConfig访问PortletContext接口的对象,PortletContext是用来保存上下问信息的。PortletConfig和PortletContext请见后续章节。
结束服务
Portlet容器没有必要一直加载这portlet的实例,这要看中间件实现厂商的决定。当portlet容器决定去掉某个portlet的服务的时候,它会调用destory方法,开发者可以在desyory方法中作一些释放资源和保存必要信息的功能。例如portlet容器可以在决定减少服务器内容资源或者app server停止的时候来调用这个方法,什么时间、什么策略来调用主要看中间件实现厂商的决定。当portlet容器调用destory之前,它会让目前还在执行的thread执行完成,当然为了避免永远等待下去,portlet容器也会有相应的策略来结束这种等待。一旦destory方法被调用,portlet就不能再接受任何请求,如果容器想重启启动这个portlet,就要重复之前的加载、实例化、初始化过程。如果在在调用destory的过程中出现了RuntimeException,portlet容器必须保证portlet可以正常毁灭。当portlet被毁灭掉之后,portlet对应的对象就释放,等待垃圾收集。
Portlet 的个性化
Portlet 定义 和 Portlet Entity
Portlet定义包括一组带有默认值的preferences,这组preferences用来创建preferences对象。在运行时,当portlet被request请求的时候,portlet自身还带着一组preferences。这些与特定的preferences绑定的portlet产生的结果被定义成Portlet Entity。这些preferences一般定义在portlet.xml里面,当然portal和portlet容器也提供了途径在运行时增加、修改这些preferences。
Portlet Window
在portal页面中的每个portlet,我们叫做一个portlet window,portlet window和portlet entity是多对多关系。
Request请求处理
当portlet对象被初始化的时候,portlet对象就可以处理portlet容器发过来的request请求了。Portlet接口定义了两个方法来处理请求processAction方法和render方法。附加的可以实现 EventPortlet and ResourceServingPortlet 接口定义的processEvent 和 serveResource.方法。
当portlet容器\portal调用portlet的processAction方法的时候,portlet request对象被封装成一个action request送给processAction方法。作为这个action处理的结果,这个portlet可能发布一些portlet event,这时候另外的portlet的processEvent会被调用,在processEvent会有一个event request对象。当portlet容器\portal调用portlet的render方法是,会在render方法中有一个render request对象。当portlet容器\portal调用portlet的serveResource方法是,会在render方法中有一个resource request对象。
通常情况下portlet的请求时url出发的,这些有portlet生成的url叫做Portlet URL.Portlet URL分为三类action URLs, render URLs, 和 resource URLs.
假设这种场景,一个portal页面中有n个portlet(n>1),那么一个portlet action请求会触发一个antion请求、0-m个portlet event请求,n个render请求。一个render url触发的请求,会触发n个render 请求。一个resource url触发的请求,会触发一个resource 请求。
如果是一个process请求,那个portlet容器必须先调用这个portlet processaction方法。等待process方法完成之后才能调用event方法。等来event方法调用完成之后再调用这个页面中所有portlet的render方法,除非某个portlet定义了缓存。值得注意的是render方法的调用时没有特定顺序的。
如果是一个render请求,portlet容器调用页面中所有portlet的render方法,除非某个portlet定义了缓存。值得注意的是render方法的调用时没有特定顺序的。
如果是一个resource请求,portlet容器调用页面中所有portlet的serveResource方法,除非某个portlet定义了缓存。
如果portlet中定了缓存,portal可以按照策略不调用portlet的render、serveResource请求。
之前也说过如果摸个portlet一段时间没有被请求,可能被portlet容器给销毁掉。
Action Request
一般情况下action Request请求用来修改数据库、portlet preferences等信息。
processAction 方法有两个参数ActionRequest 和 ActionResponse.可以通过ActionRequest获得action参数、window state、portlet mode,portal context、portlet session、portlet preferences 数据。
在processAction可以调用redirect方法,与servelt进行页面的redirect。
可以通过调用ActionResponse改变window 状态、portlet模式,要修改portlet模式,前提是当前用户有这个权限来进入到相关的portlet模式。
可以在ActionResponse放render Parameter。
portlet可以把一个action请求委派给servlet处理。
Portlet可以通过ActionResponse的setEvent方法来发布事件
Event Request
一般情况下event request用来在不同portlet之间进行协作。
EventPortlet接口的processEvent方法有两个参数EventRequest 和EventResponse。
可以从EventRequest 中得到event payload, window state, portlet mode, render parameters, portal context, portlet session 、 portlet preferences 数据.
Portlet可以在通过EventResponse来window 状态、portlet模式,要修改portlet模式,前提是当前用户有这个权限来进入到相关的portlet模式。
可以在EventResponse放render Parameter。
portlet可以把一个event请求委派给servlet处理。
Portlet可以通过EventResponse的setEvent方法来发布事件
Render Request
一般情况下render请求用来产生展现内容。
Portlet接口的render方法有两个参数RenderRequest和 RenderResponse。
可以从RenderRequest得到请求参数、window state, portlet mode, render parameters, portal context, portlet session 、 portlet preferences 数据.
Portlet可以通过本身的renderResponse来产生内容,或者委托给servlet\jsp。
Render请求不应该触发任何的状态的改变,也就是说render请求时幂等的。
Resource Request
Resource request是为了服务资源和内容片断,可以通过实现ResourceServingPortlet接口来做此工作。ResourceServingPortlet接口的serveResource方法有两个参ResourceRequest和 ResourceResponse.
可以从ResourceRequest得到请求参数、window state, portlet mode, render parameters, portal context, portlet session 、 portlet preferences 数据.
portlet可以通过本身的serveResource来产生内容,或者委托给servlet\jsp。
GenericPortlet
GenericPortlet 是一个抽象类,它实现了Portlet、EventPortlet、ResourceServingPortlet三个接口,所以它提供了为events, resource and render 请求提供服务的能力,我们开发的时候一般继承 GenericPortlet类。
Action Dispatching
GenericPortlet中的processAction来处理分发,也可以使用注解的方式。
Event Dispatching
GenericPortlet中的processEvent来处理分发,也可以使用注解的方式。
Resource Serving Dispatching
GenericPortlet中的serveTesource来处理分发,也可以使用注解的方式。
Rendering Dispatching
GenericPortlet中的render来处理分发,也可以使用注解的方式。不过一般情况下render方法会根据portlet state把请求分发给
n doView for handling VIEW requests
n doEdit for handling EDIT requests
n doHelp for handling HELP requests
并行执行的请求
由于portlet容器处理portlet请求的时候是并行的,所以portlet开发者必须处理话portlet的并行问题
请求处理异常
在处理portlet请求的时候可能会抛PortletException,
PortletSecurityException 、UnavailableException
线程安全
与servlet一样,在实现portlet是要注意线程安全的问题。