CMS系統模版引擎設計(1):基礎類型

寫博文寫教程性質的內容,大家比較喜歡,具體的項目設計方案關注的人比較少,而且思路也不一定說的清楚,本身寫博文就比較辛苦,作者再偷點懶,那基本上就是一篇廢文。儘管如此,我還是想寫一下我做過的一個項目的模塊設計——CMS的模版引擎。呵呵,叫成“引擎”就是奪人眼球而已。其實就是一個標籤解釋的過程模塊。
做過網站的朋友都對CMS很熟悉,有的朋友也接觸過N多CMS系統,國內比較流行的有dedeCMS,phpCMS,帝國CMS,KingCMS,PowerEasyCMS等等,他們都有個共同的特點,就是前臺的實現是模版標籤機制。標籤的好處就是可以讓非專業開發人員通過特定的標籤實現數據調用。一段標籤表示一種數據的調用。那我的這個CMS也是幹這事的,不過是用.NET實現的。實現思路也是自己琢磨出來的,如有雷同,那真是太巧合了:)
從哪裏開始講呢?還是從業務開始吧!
當公司接到一個網站的單子後,就要估算價格。估算價格一般都要問開發經理這個網站的開發週期和難度(方便忽悠好要價),開發經理也就是我們技術leader,他會估算該網站大概需要多少頁面,需要什麼子模塊,需要幹多久(假如沒有CMS的話)。吶,這裏就有個重要的信息,就是需要多少頁面和什麼模塊。
做一個網站我們肯定要考慮他的功能模塊,也要考慮多少頁面。
功能模塊一般有 文章、圖片(相冊)、視頻、投票、留言、評論、下載、單頁、自定義表單等等。我們介紹模版,這些功能模塊就不多提了。
頁面的概念便是需要多少去製作的Page.aspx。一般有首頁(子站首頁)、封面頁(可以理解爲欄目封面)、列表頁、詳情頁、獨立頁(關於我們之類的),不同的數據類型還不一定一致,比如新聞和下載都是不一樣的頁。而模版的話不可能是要製作人員創建aspx的,他們只會用模版。所以通過這些信息我們能想到需要設計哪些類呢?
Page類、Template類、Label類,頁面、模版和標籤。
Label涉及到具體的標籤系列,咱暫且不說,先看Template如何設計?
一個模版有何設計的?有的CMS系統就是直接讀取靜態文件,但是我說這樣不好,我們要在代碼裏有他的具體類型才能更方便的處理。
    /// <summary>
    /// 模版類
    /// </summary>
    public class Template
    {
        /// <summary>
        /// 模版ID
        /// </summary>
        public Guid TemplateId { get; set; }
        /// <summary>
        /// 模版名稱
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 模版內容
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 是否爲部分視圖
        /// </summary>
        public bool IsPartial { get; set; }
    }

初步設計就是如此,增加了一個IsPartial屬性,因爲我們的模版或許會作爲部分視圖在其他模版裏調用,就像UserControl一樣。

那麼Page類的設計就略顯複雜了。我們想訪問一個Page起碼要有訪問路徑吧,所以就要有一個UrlPattern屬性,也就是訪問規則,因爲像詳細頁一般只是參數的變化,所以URL不能寫死,只能是一個規則。既然有規則,也會有一些參數,而且參數不一定是?name=value形式,可能是/value/value1形式,所以我們還得設計一個UrlPattern類。

    /// <summary>
    /// Url訪問規則
    /// </summary>
    public class UrlPattern
    {
        /// <summary>
        /// 具體規則
        /// </summary>
        public string Pattern { get; set; }
        /// <summary>
        /// 正則引擎
        /// </summary>
        public Regex Regex { get; set; }
        /// <summary>
        /// 參數列表
        /// </summary>
        public string[] Parameters { get; set; }
        /// <summary>
        /// 獲取某個參數的值
        /// </summary>
        /// <param name="rawurl">當前訪問的URL</param>
        /// <param name="name">參數名</param>
        /// <returns></returns>
        public string GetValue(string rawurl, string name)
        {
            throw new System.NotImplementedException();
        }
    }

是的,你沒看錯,我們要用正則表達式,這可能是對製作人員難度最大的部分。:)不過可以教他們初級的寫法,可以應付絕大多數需求。

比如我寫一個規則如下  /details/(?<articleid>\d+),這個表明參數名爲articleid,訪問規則就是 “/details/數字”

Page除了訪問URL外還要有緩存的概念,不然我們如何提升性能,你說是不?!緩存可能還會用標籤裏去,因爲如果Page不緩存只是緩存了某個標籤,所以Label也要有緩存,那麼我們是否需要設計一個緩存類呢?

    /// <summary>
    /// Page/Template/Label的緩存
    /// </summary>
    public class Cache
    {
        /// <summary>
        /// 緩存名
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 緩存秒數
        /// </summary>
        public int CacheSeconds { get; set; }
        /// <summary>
        /// 獲取緩存數據
        /// </summary>
        /// <returns></returns>
        public object GetData()
        {
            throw new System.NotImplementedException();
        }
        /// <summary>
        /// 移除緩存
        /// </summary>
        public void Remove()
        {
            throw new System.NotImplementedException();
        }
        /// <summary>
        /// 更新緩存
        /// </summary>
        /// <param name="data"></param>
        public void SetData(object data)
        {
            throw new System.NotImplementedException();
        }
    }

那麼Page類還應該有什麼?Labels!是的,我們不可能每次都去解釋模版來獲取所有的Label,而是Page被緩存後我們只需要訪問他的LabelCollection即可。那麼我們來看下Page的設計雛形吧。

   /// <summary>
    /// Page類
    /// </summary>
    public class Page
    {
        /// <summary>
        /// ID
        /// </summary>
        public Guid PageId { get; set; }
        /// <summary>
        /// 名稱
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 標題
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 關鍵字
        /// </summary>
        public string Keywords { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// 模版
        /// </summary>
        public Template Template { get; set; }
        /// <summary>
        /// 訪問路徑規則
        /// </summary>
        public UrlPattern UrlPattern { get; set; }
        /// <summary>
        /// 標籤
        /// </summary>
        public Label[] Labels { get; set; }
        /// <summary>
        /// 緩存
        /// </summary>
        public Cache Cache { get; set; }
        /// <summary>
        /// 顯示HTML代碼
        /// </summary>
        public void Render()
        {
            throw new System.NotImplementedException();
        }
    }

不錯哦,襖喲,不錯哦。

其實對於大型的站點,子站的概念是不可缺少的。或者我們的CMS需要支持多站點,那麼還需要一個Site類。

   /// <summary>
    /// 站點
    /// </summary>
    public class Site
    {
        /// <summary>
        /// 站點ID
        /// </summary>
        public Guid SiteId { get; set; }
        /// <summary>
        /// 站點名稱
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 站點備註
        /// </summary>
        public string Note { get; set; }
        /// <summary>
        /// 站點域名
        /// </summary>
        public string[] Domains { get; set; }
        /// <summary>
        /// 站點狀態
        /// </summary>
        public Status Status { get; set; }
        /// <summary>
        /// 站點的頁面
        /// </summary>
        public Page[] Pages { get; set; }
    }

站點一般包含多個可訪問的域名,所以有個Domains。當然站點包含N個Page。

好啦,初步的設計就到這了,下節我們講怎麼讓這些類運作起來。



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