国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
一次分布式架構(gòu)cms系統(tǒng)頁面靜態(tài)化模塊開發(fā)經(jīng)歷

項(xiàng)目背景

公司開發(fā)新的項(xiàng)目,選擇了分布式系統(tǒng)架構(gòu),同時(shí)項(xiàng)目中有大量圖文展示的需求,考慮到開發(fā)效率和性能問題,需要集成cms的功能,程序?qū)崿F(xiàn)后臺(tái)錄入數(shù)據(jù)靜態(tài)化。

技術(shù)架構(gòu)

Java開發(fā)、jdk1.8,項(xiàng)目整體的技術(shù)架構(gòu)大致是這樣的:


前端采用的bootstrap、extJs,權(quán)限采用shiro框架,搜索采用solr或者lucene(這個(gè)暫時(shí)沒有實(shí)現(xiàn))。

過往問題

在這個(gè)項(xiàng)目之前,公司有另一套cms系統(tǒng),做為公司主要經(jīng)營(yíng)業(yè)務(wù)的基礎(chǔ),它有很多優(yōu)點(diǎn),最主要的優(yōu)點(diǎn)是定制性強(qiáng),能適應(yīng)各種前端版式的頁面。另一個(gè)優(yōu)點(diǎn)是開發(fā)速度特別快,基于模版標(biāo)簽開發(fā),屏蔽了代碼級(jí)的復(fù)雜度和開發(fā)人員水平的差距。
弱點(diǎn)有三個(gè)
一、在于標(biāo)簽庫的實(shí)現(xiàn),完全是基于正則替換,然后處理標(biāo)簽表述的邏輯進(jìn)行查庫、處理。標(biāo)簽沒有實(shí)現(xiàn)語法樹,也沒有上下文,導(dǎo)致了多個(gè)標(biāo)簽函數(shù)嵌套的時(shí)候,某些時(shí)候無法正確實(shí)現(xiàn)替換邏輯。
二、沒有應(yīng)用更多的緩存技術(shù)(只實(shí)現(xiàn)了jvm內(nèi)的HashMap緩存),數(shù)據(jù)量大的任務(wù),生成速度在查庫上,有明顯的瓶頸。
三、生成失敗的模版,沒有給出足夠明確的錯(cuò)誤提示,輔助使用者調(diào)試錯(cuò)誤。

基本思路

整個(gè)大體流程

整個(gè)生成是基于freemarker模版引擎,項(xiàng)目初期,曾經(jīng)對(duì)比過velocity與freemarker,因?yàn)閒reemarker最后一次更新時(shí)間比較近,最終選擇了freemarker,其實(shí)兩者應(yīng)該差不多。

關(guān)鍵點(diǎn)

先曬一下目前的類結(jié)構(gòu)

一、自定義標(biāo)簽與自定義函數(shù)

freemarker支持實(shí)現(xiàn)TemplateMethodModelEx接口的自定義函數(shù),及實(shí)現(xiàn)TemplateDirectiveModel的自定義標(biāo)簽。上面代碼,fun包下面的就是自定義函數(shù),tags包下面的是自定義標(biāo)簽。
兩者的區(qū)別,
1、從調(diào)用方法來看,

arts(10, 10, ”, ”)

這種是自定義函數(shù)
<@arts menu="15" pagesize="15" sort="" sql="";arts, page></@arts>
這種是自定義標(biāo)簽
2、自定義函數(shù)有返回值,可以再套入別的函數(shù)進(jìn)行計(jì)算或者迭代。自定義標(biāo)簽沒有返回值,它會(huì)返回幾個(gè)變量,作用域只在標(biāo)簽體內(nèi)部。
3、自定義標(biāo)簽傳入的參數(shù)有Environment、TemplateDirectiveBody等等,即可以獲取其他位置定義的模版變量,又可以追加變量,還可以輸出字符串文本到最終生成的頁面上。自定義函數(shù),只能僅僅返回處理后的返回值。

二、freemarker生成靜態(tài)頁到指定路徑的方法

這個(gè)問題,基本上查api或者別的博客就能找到具體的方法,但是有些資料可能不準(zhǔn)確,這里我直接把我實(shí)現(xiàn)了的核心代碼貼出來。我使用的freemarker版本是2.3.23。

//成員變量private static Configuration config = new  Configuration(Configuration.VERSION_2_3_25);//config設(shè)置config.setLocale(Locale.CHINA);              config.setDefaultEncoding("utf-8");              config.setEncoding(Locale.CHINA, "utf-8");              config.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_25));StringTemplateLoader stringLoader = new StringTemplateLoader();  //content是模版內(nèi)容的字符串        stringLoader.putTemplate("siteTemplate",content);          config.setTemplateLoader(stringLoader);try(FileWriter out = new FileWriter(filePath.toFile());) {             Template template = config.getTemplate("siteTemplate","utf-8");               config.setCustomAttribute("customDataModel", dataModel);             template.process(dataModel, out);             out.flush();        } catch (Exception e) {            //異常處理        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

三、列表頁分頁,如何根據(jù)一個(gè)模版,動(dòng)態(tài)生成出一或多個(gè)分頁面

這個(gè)問題包括很多細(xì)節(jié),比如生成后的地址規(guī)則。假設(shè)目標(biāo)地址是news_index.html,那么第二頁就不能用這個(gè)地址,我的處理方式是news_index_x.html,x代表第幾頁,可以是2~n。但是第一頁就是原地址。
最關(guān)鍵
如果你也需要基于freemarker實(shí)現(xiàn)這個(gè)功能,大概機(jī)會(huì)發(fā)現(xiàn),最關(guān)鍵的問題,是如何在生成第一頁的時(shí)候,知道還有第二頁需要生成。因?yàn)楫a(chǎn)生多個(gè)分頁面,一般是在自定義標(biāo)簽里面,比如有一個(gè)循環(huán)數(shù)據(jù)列表的標(biāo)簽,發(fā)現(xiàn)一頁10條,無法顯示完,怎樣告知生成階段的代碼(就是上面那一段)。這是兩個(gè)完全不同的代碼區(qū)域和處理階段。
參考了另一款開源cms,我采取了一種有點(diǎn)技巧性的做法。核心思想就是,上面說到自定義標(biāo)簽,可以在生成后的頁面上,任意輸出字符串。假設(shè)標(biāo)簽中判斷還有下一頁,需要生成,就在頁面上輸出一段注釋,本頁面生成完以后,重新讀取生成的頁面,發(fā)現(xiàn)有包含此種注釋,則繼續(xù)生成下一頁。

下面貼一些代碼

//輸出還有下一頁的標(biāo)識(shí)env.getOut().write(LBLCommon.getHasNextPage(totalRecord, totalPage, pageIndex));public static String getHasNextPage(int recordCount, int totalPage, int pageindex) {        return hasNextPage+"_"+recordCount+"_"+totalPage+"_"+pageindex+"-->";    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

//生成靜態(tài)化頁面 this.writeUseFreeMarker(name, content, url, dataModel);
//分頁機(jī)制,查詢是否需要分頁————————————————————
this.morePageProcess(name, dataModel, url, rootPath, content, entry);

//處理分頁private void morePageProcess(String name, Map<String, Object> dataModel, String url, String rootPath, String content, Map.Entry<String, String> entry) throws Exception{    String html = this.readFile(url);    LBLPagerModel pager = checkHasNextPage(html);    if (pager != null) {        //重設(shè)置一個(gè)基礎(chǔ)的總記錄數(shù)        dataModel.put("totalRecord", pager.getRecordCount());        for (int i = 2; i<= pager.getTotalPage(); i ++) {            //設(shè)置頁碼            setPageIndex(dataModel, i);            url = rootPath + LBLCommon.getPageUrl(entry.getValue(), i);            this.writeUseFreeMarker(name, content, url, dataModel);        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

整個(gè)靜態(tài)化的部分,還有很多別的細(xì)節(jié)和坑,比如標(biāo)簽參數(shù)的轉(zhuǎn)型問題,生成靜態(tài)頁過程中模版exception的catch和反饋,查詢生成隊(duì)列情況的監(jiān)控模塊(基于mongo),標(biāo)簽設(shè)計(jì),自動(dòng)生成、定時(shí)生成、過濾生成…

總結(jié)

靜態(tài)化的功能,與業(yè)務(wù)結(jié)合的很緊密,好的標(biāo)簽設(shè)計(jì)非常重要,這個(gè)可能得靠多踩坑才能提升一點(diǎn)躲開雷區(qū)的能力。另外,這次的開發(fā)過程,也讓我更深刻的認(rèn)識(shí)到,深思熟慮,先慢后快,不寫一行垃圾代碼,才是最節(jié)約時(shí)間的開發(fā)模式。


更多有趣的信息,包括一個(gè)新的周更python主題,都在我的公眾號(hào),請(qǐng)掃描下方二維碼關(guān)注

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
國(guó)內(nèi)外最全的ASP.NET開源CMS匯總
搜索引擎喜歡抓取什么格式的網(wǎng)頁內(nèi)容?
搜索引擎優(yōu)化八大絕招 有效優(yōu)化你的CMS
CMS網(wǎng)頁模板技術(shù)
java利用freemarker生成html靜態(tài)頁面
FreeMarker如何生成靜態(tài)頁面
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服