roller是如何展現頁面的?

先說說本人的技術背景,以免說錯了被磚砸!在確定用roller做二次開發之前,本人沒有用struts2、velocity、openjpa,只是匆匆看了一本《深入淺出struts2》電子書,然後是一邊讀roller源代碼一邊摸索這些技術是怎麼實現相關功能的。到今天已經半個月有餘,寫博當備忘。

 

在今天的這篇文章中我打算談談roller是如何展現一個博客頁面的,我們知道一個頁面最終在用戶的瀏覽器被展現是一些html代碼。生成html代碼有很多種方式和技術,roller使用的是velocity模板技術。個人覺得roller使用velocity可能有以下原因:

1、roller要考慮博客頁面展現的多樣性

2、博客頁面主題的可自定義

 

velocity的模板技術無疑很好的符合這兩點要求。

 

在roller中,是怎樣用velocity來展現頁面的呢?先來說說roller中主題、樣式、模板的關係,如果沒有好好使用一下roller的自定義主題的功能而是僅僅看源代碼,還真有點難於搞清楚roller是如何展現頁面的。

 

在roller中,一個主題對應一個樣式,一個主題可以包含多個模板,模板是頁面上的一些部件,比如菜單欄可以用一個模板;日曆也可以用一個模板等等。當用戶選擇不同的主題時,由於主題包含的模板不同則展現的內容也不同。樣式就是我們一般指的css代碼。

 

下面我們按照程序的執行順序來說說roller頁面的生成過程。在前面的文章《說說ROLLER的PageServlet類》中我們已經談了一些相關的內容,比如用戶想直接進入某個博客abc,當緩存中沒有時就要生成頁面。我們今天就接着這裏開始講。

 

roller是一個多用戶博客系統,每個博客要展現的內容都不一樣。當用戶要進入abc時,roller用一個Weblog類的對象來代表abc,通過這個對象就可以獲取到這個博客相關的一些內容,比如博客名稱、博客日誌列表、博客使用的主題等等。

 

有了Weblog對象,我們也就可以知道某個博客使用的是什麼主題,此主題包含多少個模板了。有了主題roller僅僅知道要展現成什麼樣子,而裏面的數據從哪裏來?

 

roller把博客頁面內容各部抽象成一個Model接口,比較代表菜單的、有代表頁面的等等,此接口有兩個方法:

1、public String getModelName();

2、public void init(Map params) throws WebloggerException;

 

此接口有幾個實現類,分別是:CalendarModel、ConfigModel、MenuModel、PageModel、SiteModel等。這些類的對象是要在velocity的模板文件中被使用的。引用的名字是他們的getModelName方法返回的內容,比如下面vm代碼:

 

       ################ weblog.vm #######################
    #set($pager = $model.getWeblogEntriesPager()) 
        <div class="next-previous">
            #if ($model.results)
                #showWeblogSearchAgainForm($model.weblog)
                #showNextPrevSearchControl($pager)
            #else
                #showNextPrevEntriesControl($pager)
            #end
        </div>


################## menu-list.vm #####################
<div id="menu">
#foreach( $menu in $menuModel.getMenus() )

 

分別引用的對象是PageModel、MenuModel。

 

 

 在PageServlet中,執行下面代碼完成一個頁面的數據組織:

            // Load models for pages
            String pageModels = WebloggerConfig.getProperty("rendering.pageModels");
            ModelLoader.loadModels(pageModels, model, initData, true);

 

完成數據的組織就該交的velocity來生成頁面了。在PageServlet中,roller先根據模板對象去獲取一個Renderer,然後創建一個CachedContent緩存對象,先把Renderer生成的頁面內容放在CachedContent中,再通過流把頁面輸出到用戶的瀏覽器中。

 

 

 如何獲得一個渲染器renderer,roller費了一番周折。

 

 

renderer = RendererManager.getRenderer(page);

 

 在這個getRenderer()方法中,RendererManager一開始就被初始化,並且從roller.properties中讀取用戶配置的rendering.rollerRendererFactories值,如果用戶沒有特殊要求的話,一般是這個值:

 

org.apache.roller.weblogger.ui.rendering.velocity.VelocityRendererFactory

 

RendererManager會把請求交給VelocityRendererFactory這個類的對象處理。VelocityRendererFactory會new一個VelocityRenderer對象返回,但VelocityRenderer對象是roller自己定義的類,真正幹活的是velocity的Template類,此類作爲VelocityRenderer的一個屬性,當new一個VelocityRenderer時,調用velocityEngine.getTemplate(name, encoding)方法一個velocity的Template 。

 

剩下的事情就交給velocity引擎去做了,velocity怎麼去構建一個他它自己的Template對象我就不清楚了。但通過觀察velocity.properties文件發現,這兩個類值得留意:

ThemeResourceLoader、RollerResourceLoader。

 

這兩個類都繼承了velocity的ResourceLoader類,其中的都有public InputStream getResourceStream(String name)方法,這個方法跟加載模板內容有關!

 

ThemeResourceLoader會調用ThemeManager的方法,而ThemeManager在啓動的時候會把系統預定義的模板加載到內存中。

RollerResourceLoader會調用數據庫去獲取一個模板內容。

 

這裏得說說roller爲了主題的多樣化、個性化而提供的一個自定義主題功能,如果用戶自定義了主題,則roller會把主題相關的模板等信息保存到db中,因此就需要到db中查詢主題模板信息。

 

 

從velocity引擎得到template後,渲染器Renderer在PageServlet中被用來生產頁面,具體就是由velocity的template來做,怎麼做?筆者精力有限先了解到這。

 

題外話:roller有個功能,就是可以把某個博客設置爲站點主頁。如果我們用roller來做一個小網站,又不想搞得太複雜,可以專門做一個主頁的模板,並且有一個博客使用,再用一個類取主頁相關的數據並實現Model,這樣就可以用既有緩存功能又簡單。所以好的代碼擴展就是比較方便

 

下次說說roller如何緩存頁面。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章