Jetspeed-2 心得隨筆(4)-Portal Page的呈現(xiàn)
Posted on 2006-07-17 17:06 開源愛好者 閱讀(891) 評(píng)論(0) 編輯 收藏 所屬分類: Portal
先看一下在JSR168中提到的Portal page,可以了解一個(gè)Portal Page上大概有哪些element:

OK...進(jìn)入本次主題
PSML:
PSML的全名是Portal Structure Markup Language。J2用PSML來定義Portal內(nèi)的各種resource,包括Page、Folder、Link、Security、Menus等等,有關(guān)J2的PSML詳細(xì)介紹在此http://portals.apache.org/jetspeed-2/guides/guide-psml.html。
這裡要特別提一下PSML Page。在J2中,一個(gè)PSML Page就代表一個(gè)Portal page,其根元素為<page>,裡面指定了這個(gè)Portal page所包含的portlet及排列方式(ex: 2行或3行)、這個(gè)Portal page所使用的樣板(稍後會(huì)提到的layout)還有這個(gè)Portal page的外觀(稍後會(huì)提到的decoration)等等。
另外一個(gè)要特別說明的是在PSML Page中所使用的<fragment>這個(gè)tag。fragment有portlet和layout二種,用type這個(gè)屬性來區(qū)別;<fragment type="portlet">代表一個(gè)portlet,<fragment type="layout">代表這個(gè)page所用的layout;然而不管是哪一種fragment,name屬性的值都應(yīng)該依照"portlet-app-id::portlet-id"的格式。
以之前範(fàn)例中的Sample.psml為例,根元素是<page>,所以這是一個(gè)PSML Page;第一個(gè)<fragment>是layout fragment,指定了這個(gè)page所使用的layout,name屬性的值為"jetspeed-layouts::VelocityTwoColumns"。第二個(gè)<fragment>就是範(fàn)例的echo portlet,name屬性的值為"sample::EchoPortlet",就符合之前所描述的格式。
事實(shí)上,layout fragment其實(shí)也是portlet。看一下C:\tomcat\webapps\jetspeed\WEB-INF\apps\裡有一個(gè)jetspeed-layouts目錄,就是J2內(nèi)部的一個(gè)Portlet application。因此"jetspeed-layouts::VelocityTwoColumns"會(huì)對(duì)到這個(gè)目錄下portlet-id為VelocityTwoColumns的portlet。總之,J2的layout也是portlet,如果再研究一下,其實(shí)還是個(gè)Velocity Bridge的portlet.
layout:
J2中的layout指的是用來排列Portal page中各個(gè)portlet的樣板。預(yù)設(shè)的情況下,J2用Velocity來實(shí)現(xiàn)layout。
decoration:
J2中的decoration是用來裝飾Portal page和portlet使其美觀,分為layout-decoration和portlet-decoration兩種。layout-decoration負(fù)責(zé)一整個(gè)Portal page(因此叫page-decoration),而portlet-decoration負(fù)責(zé)每一個(gè)Portlet fragment。預(yù)設(shè)的情況下,J2用Velocity和CSS來實(shí)現(xiàn)decoration。當(dāng)J2在呈現(xiàn)一Portal page時(shí),會(huì)依照這個(gè)Portal page指定的layout來排列這個(gè)page上的各個(gè)portlet,並且使用這個(gè)page所指定的layout-decoration和portlet-decoration來美化這個(gè)page和所有的portlet。有關(guān)decoration的細(xì)節(jié)可參考http://portals.apache.org/jetspeed-2/guides/guide-decorators.html
Aggregator:
在J2中,一個(gè)Portal page的request最後通常會(huì)傳給一個(gè)Aggregator,然後由Aggregator負(fù)責(zé)跟Portal page內(nèi)包含的所有portlet溝通並聚合各個(gè)portlet fragment以產(chǎn)生整個(gè)Portal page。以之前舉例的jetspeed-pipeline來說(C:\tomcat\webapps\jetspeed\WEB-INF\assembly\pipelines.xml),可以看到aggregatorValve這個(gè)bean被注入了org.apache.jetspeed.aggregator.PageAggregator這個(gè)Aggregator;再參考C:\tomcat\webapps\jetspeed\WEB-INF\assembly\aggregation.xml中,可已知道這個(gè)bean的實(shí)作是org.apache.jetspeed.aggregator.impl.PageAggregatorImpl。
來看一下這個(gè)PageAggregatorImpl的中用來產(chǎn)生Portal page的方法(部份省略修改):
首先要注意一下傳入的是一個(gè)J2的RequestContext物件,基本上可以視為是用來存放這次request相關(guān)資訊的一個(gè)context;此外,可以把ContentFragement物件視為portlet。而其中第6行取得root fragment,實(shí)際上就是取得前面所說的layout fragment,也就是"jetspeed-layouts::VelocityTwoColumns"這個(gè)portlet。
接著再看一下第9行的aggregateAndRender()方法(部份省略修改):
由上面的code,可以了解到J2先把整個(gè)page上所有的portlet由外到內(nèi)串起來,再由內(nèi)到外一個(gè)一個(gè)做render的動(dòng)作,而每render完一個(gè)portlet,就加上對(duì)應(yīng)的decoration,直到做完整個(gè)page。
在第12行中,render的動(dòng)作實(shí)際上是renderer透過Pluto來呼叫portlet(實(shí)際上是ContentFragment物件被包成portlet window)的render方法。PortletRendererImpl.render()這個(gè)方法裡使用了常見的Worker Thread和Observer樣式,以達(dá)到render多個(gè)portlet的功能,有興趣的不妨研究一下。
那如果想要新加外觀呢??最簡單的方式,就是先參考J2的layout portlet寫自已的layout,然後加入decoration。講起來容易,不過layout可是不太容易寫的,因?yàn)闋砍兜降募夹g(shù)還蠻多,而且對(duì)J2也要有一定了解;但是如果能做出來,安裝就不會(huì)太麻煩。也許等以後J2紅起來以後,會(huì)有各式各樣的外觀可以玩吧...
其他參考資料:
Portal Design Doc : http://portals.apache.org/jetspeed-2/guides/guide-portal-design.html
簡介J2中有關(guān)Portal Page的一些概念
Jetspeed Power Tool (JPT) : http://portals.apache.org/jetspeed-2/guides/guide-jpt.html
開發(fā)layout和decoration時(shí)會(huì)用到

OK...進(jìn)入本次主題
PSML:
PSML的全名是Portal Structure Markup Language。J2用PSML來定義Portal內(nèi)的各種resource,包括Page、Folder、Link、Security、Menus等等,有關(guān)J2的PSML詳細(xì)介紹在此http://portals.apache.org/jetspeed-2/guides/guide-psml.html。
這裡要特別提一下PSML Page。在J2中,一個(gè)PSML Page就代表一個(gè)Portal page,其根元素為<page>,裡面指定了這個(gè)Portal page所包含的portlet及排列方式(ex: 2行或3行)、這個(gè)Portal page所使用的樣板(稍後會(huì)提到的layout)還有這個(gè)Portal page的外觀(稍後會(huì)提到的decoration)等等。
另外一個(gè)要特別說明的是在PSML Page中所使用的<fragment>這個(gè)tag。fragment有portlet和layout二種,用type這個(gè)屬性來區(qū)別;<fragment type="portlet">代表一個(gè)portlet,<fragment type="layout">代表這個(gè)page所用的layout;然而不管是哪一種fragment,name屬性的值都應(yīng)該依照"portlet-app-id::portlet-id"的格式。
以之前範(fàn)例中的Sample.psml為例,根元素是<page>,所以這是一個(gè)PSML Page;第一個(gè)<fragment>是layout fragment,指定了這個(gè)page所使用的layout,name屬性的值為"jetspeed-layouts::VelocityTwoColumns"。第二個(gè)<fragment>就是範(fàn)例的echo portlet,name屬性的值為"sample::EchoPortlet",就符合之前所描述的格式。
事實(shí)上,layout fragment其實(shí)也是portlet。看一下C:\tomcat\webapps\jetspeed\WEB-INF\apps\裡有一個(gè)jetspeed-layouts目錄,就是J2內(nèi)部的一個(gè)Portlet application。因此"jetspeed-layouts::VelocityTwoColumns"會(huì)對(duì)到這個(gè)目錄下portlet-id為VelocityTwoColumns的portlet。總之,J2的layout也是portlet,如果再研究一下,其實(shí)還是個(gè)Velocity Bridge的portlet.
layout:
J2中的layout指的是用來排列Portal page中各個(gè)portlet的樣板。預(yù)設(shè)的情況下,J2用Velocity來實(shí)現(xiàn)layout。
decoration:
J2中的decoration是用來裝飾Portal page和portlet使其美觀,分為layout-decoration和portlet-decoration兩種。layout-decoration負(fù)責(zé)一整個(gè)Portal page(因此叫page-decoration),而portlet-decoration負(fù)責(zé)每一個(gè)Portlet fragment。預(yù)設(shè)的情況下,J2用Velocity和CSS來實(shí)現(xiàn)decoration。當(dāng)J2在呈現(xiàn)一Portal page時(shí),會(huì)依照這個(gè)Portal page指定的layout來排列這個(gè)page上的各個(gè)portlet,並且使用這個(gè)page所指定的layout-decoration和portlet-decoration來美化這個(gè)page和所有的portlet。有關(guān)decoration的細(xì)節(jié)可參考http://portals.apache.org/jetspeed-2/guides/guide-decorators.html
Aggregator:
在J2中,一個(gè)Portal page的request最後通常會(huì)傳給一個(gè)Aggregator,然後由Aggregator負(fù)責(zé)跟Portal page內(nèi)包含的所有portlet溝通並聚合各個(gè)portlet fragment以產(chǎn)生整個(gè)Portal page。以之前舉例的jetspeed-pipeline來說(C:\tomcat\webapps\jetspeed\WEB-INF\assembly\pipelines.xml),可以看到aggregatorValve這個(gè)bean被注入了org.apache.jetspeed.aggregator.PageAggregator這個(gè)Aggregator;再參考C:\tomcat\webapps\jetspeed\WEB-INF\assembly\aggregation.xml中,可已知道這個(gè)bean的實(shí)作是org.apache.jetspeed.aggregator.impl.PageAggregatorImpl。
來看一下這個(gè)PageAggregatorImpl的中用來產(chǎn)生Portal page的方法(部份省略修改):
1 | publicvoid build( RequestContext context ){//取得requested page ContentPage page=context.getPage(); //取得 root fragment ContentFragment root = page.getRootContentFragment(); //aggregate及render各個(gè)Portlet,基本上render的結(jié)果都寫到context裡 aggregateAndRender(root, context, page); ? //將結(jié)果寫入response context.getResponse().getWriter().write(root.getRenderedContent()); } |
首先要注意一下傳入的是一個(gè)J2的RequestContext物件,基本上可以視為是用來存放這次request相關(guān)資訊的一個(gè)context;此外,可以把ContentFragement物件視為portlet。而其中第6行取得root fragment,實(shí)際上就是取得前面所說的layout fragment,也就是"jetspeed-layouts::VelocityTwoColumns"這個(gè)portlet。
接著再看一下第9行的aggregateAndRender()方法(部份省略修改):
1 | protectedvoid aggregateAndRender( ContentFragment f, RequestContext context, ContentPage page ){ ? Iterator children = f.getContentFragments().iterator(); while (children.hasNext()){ ContentFragment child = (ContentFragment) children.next(); //遞迴 aggregateAndRender(child, context, page); }// 開始真正做render的動(dòng)作,基本上render的結(jié)果都寫到context裡 renderer.render(f, context); //renderer是org.apache.jetspeed.aggregator.impl.PortletRendererImpl//加上decoration addStyle(context, f.getDecorator(),ContentFragment.PORTLET); } |
由上面的code,可以了解到J2先把整個(gè)page上所有的portlet由外到內(nèi)串起來,再由內(nèi)到外一個(gè)一個(gè)做render的動(dòng)作,而每render完一個(gè)portlet,就加上對(duì)應(yīng)的decoration,直到做完整個(gè)page。
在第12行中,render的動(dòng)作實(shí)際上是renderer透過Pluto來呼叫portlet(實(shí)際上是ContentFragment物件被包成portlet window)的render方法。PortletRendererImpl.render()這個(gè)方法裡使用了常見的Worker Thread和Observer樣式,以達(dá)到render多個(gè)portlet的功能,有興趣的不妨研究一下。
那如果想要新加外觀呢??最簡單的方式,就是先參考J2的layout portlet寫自已的layout,然後加入decoration。講起來容易,不過layout可是不太容易寫的,因?yàn)闋砍兜降募夹g(shù)還蠻多,而且對(duì)J2也要有一定了解;但是如果能做出來,安裝就不會(huì)太麻煩。也許等以後J2紅起來以後,會(huì)有各式各樣的外觀可以玩吧...

其他參考資料:
Portal Design Doc : http://portals.apache.org/jetspeed-2/guides/guide-portal-design.html
簡介J2中有關(guān)Portal Page的一些概念
Jetspeed Power Tool (JPT) : http://portals.apache.org/jetspeed-2/guides/guide-jpt.html
開發(fā)layout和decoration時(shí)會(huì)用到