Spring針對velocity實現了默認的file的resourceLoader,每次讀取的文件都是固定位置的,如果我們想實現隨時改變文件隨時頁面生效這種效果就很難實現了。
但是現實的應用場景中這樣的例子還不少,1營銷頁面,2產品化的配置管理等
實現方案,可以通過純前端的方式實現
比如:
1.把頁面模版寫在數據庫裏,然後寫死一個頁面,通過ajax從後臺取不同的模版,然後根據不同的數據做渲染展示
2.純後端模式實現,改造springmvc的view的render這層,保證每次渲染的時候,原有從文件系統讀模版改爲從db中讀模版。
本文主要採用第二種方案和大家做交流。
分析這個問題,首先要了解springMvc的DispatcherServlet處理鏈路
1. DispatcherServlet中獲取到controller返回的ModelAndView之後會通過render方法來獲取對應的view代碼如下:
2. resolveViewName()方法中,通過所有配置的viewResolver來進行resolveViewName。這個鏈路一直看下去,會到具體的viewResolver然後build出來view,這裏就不過多贅述,詳情看代碼。
3. 獲取到view之後,view會通過render()方法來做渲染,在渲染的過程中會通過VelocityView.doRender()來做渲染,然後通過getTemplate()獲取渲染需要的模版。
VelocityView.doRender() ----> getTemplate() ----> VelocityEngine.getTemplate() ---> RuntimeInstance.getTemplate() ---> ResourceManager.getResource()
重點看ResourceManager.getResource
該方法就是模版的具體獲取過程,如果第一次訪問,那麼走else分支,有了緩存走if分支,走else分支的會,會通過loader去獲取模版資源
可以看到最終判斷文件是否需要更新是通過loader來實現的,VelocityResourceLoader來加載具體的模版
看到這裏,我們可以明白了,控制velocity的模版獲取是通過loader來實現的。那麼如果我們想實現自己來從db裏面讀取模版,只需實現自己的loader即可(1.獲取模版,2控制何時更新模版)
但是問題來了!!!這個loader是何時spring給注入進去做的初始化呢?
繼續往下看
衆所周知spring配置velocity做展現層是通過VelocityConfigurer來實現的,VelocityConfigurer繼承自VelocityEngineFactory,通過各種參數實現了針對velocity的相關參數配置,主要的方法有:VelocityEngineFactory.initVelocityResourceLoader()
spring寫死了默認的loader名稱爲file
看到這裏大家應該比較清楚了,實現從db裏面讀取vm文件,我們只需要重寫兩個類即可
1.ResourceLoader(在loader中實現原有的從文件系統中讀取改爲從db中或者分佈式文件系統中讀取,並控制velocity的緩存管理,實現自己來管理這部分模版的緩存)
2.VelocityConfigurer(在初始化velocity的時候設置不同的classloader名稱,並且將自己新寫的ResourceLoader設置進去即可)
思路基本上就是上面的思路,由於公司代碼不能漏出,所以暫時不貼出重寫後的類了。
後續會在上幾篇博客嵌入了jetty的springMvc空框架上進行實現。敬請期待。
這篇文章也是斷斷續續靠晚上擠出來的一點點時間完成的。感覺工作忙了越來越沒寫技術博客的動力了,無奈記性太差,怕下次忘掉,又要翻源碼,所以就記錄一下思路吧。