## 2.7 自定義資源加載器
如果模板資源來自其他地方,如數據庫,或者混合了數據庫和物理文件,或者模板是加密的,則需要自定義一個資源加載器。資源加載器需要實現ResourceLoader類。如下:
```java
public interface ResourceLoader{
/**
* 根據key獲取Resource
*
* @param key
* @return
*/
public Resource getResource(String key);
/** 檢測模板是否更改,每次渲染模板前,都需要調用此方法,所以此方法不能占用太多時間,否則會影響渲染功能
* @param key
* @return
*/
public boolean isModified(Resource key);
/**
* 關閉ResouceLoader,通常是GroupTemplate關閉的時候也關閉對應的ResourceLoader
*/
public void close();
/** 一些初始化方法
* @param gt
*/
public void init(GroupTemplate gt);
/** 用于include,layout等根據相對路徑計算資源實際的位置.
* @param resource 當前資源
* @param key
* @return
*/
public String getResourceId(Resource resource, String key);
}
```
如下是一個簡單的內存ResourceLoader
```java
public class MapResourceLoader implements ResourceLoader{
Map data;
public MapResourceLoader(Map data){
this.data = data;
}
@Override
public Resource getResource(String key){
String content = (String) data.get(key);
if (content == null)
return null;
return new StringTemplateResource(content, this);
}
@Override
public boolean isModified(Resource key){
return false;
}
@Override
public boolean exist(String key){
return data.contain(key);
}
@Override
public void close(){
}
@Override
public void init(GroupTemplate gt){
}
@Override
public String getResourceId(Resource resource, String id){
//不需要計算相對路徑
return id;
}
}
```
init方法可以初始化GroupTemplate,比如讀取配置文件的root屬性,autoCheck屬性,字符集屬性,以及加載functions目錄下的所有模板方法 如FileResourceLoader 的 init方法
```java
@Override
public void init(GroupTemplate gt){
Map<String, String> resourceMap = gt.getConf().getResourceMap();
if (this.root == null){
this.root = resourceMap.get("root");
}
if (this.charset == null){
this.charset = resourceMap.get("charset");
}
if (this.functionSuffix == null){
this.functionSuffix = resourceMap.get("functionSuffix");
}
this.autoCheck = Boolean.parseBoolean(resourceMap.get("autoCheck"));
File root = new File(this.root, this.functionRoot);
this.gt = gt;
if (root.exists()){
readFuntionFile(root, "", "/".concat(functionRoot).concat("/"));
}
}
```
readFuntionFile 方法將讀取functions下的所有模板,并注冊為方法
```java
protected void readFuntionFile(File funtionRoot, String ns, String path){
String expected = ".".concat(this.functionSuffix);
File[] files = funtionRoot.listFiles();
for (File f : files){
if (f.isDirectory()){
//讀取子目錄
readFuntionFile(f, f.getName().concat("."), path.concat(f.getName()).concat("/"));
} else if (f.getName().endsWith(functionSuffix)){
String resourceId = path + f.getName();
String fileName = f.getName();
fileName = fileName.substring(0, (fileName.length() - functionSuffix.length() - 1));
String functionName = ns.concat(fileName);
FileFunctionWrapper fun = new FileFunctionWrapper(resourceId);
gt.registerFunction(functionName, fun);
}
}
}
```
Resource類需要實現OpenReader方法,以及isModified方法。對于模板內容存儲在數據庫中,openReader返回一個Clob,isModified 則需要根據改模板內容對應的lastUpdate(通常數據庫應該這么設計)來判斷模板是否更改
```java
public abstract class Resource{
/**
* 打開一個新的Reader
*
* @return
*/
public abstract Reader openReader();
/**
* 檢測資源是否改變
*
* @return
*/
public abstract boolean isModified();
```
參考例子可以參考beetl自帶的ResourceLoader
- Beetl 3 中文文檔
- 第一部分 基礎用法
- 1.1 安裝
- 1.2 快速開始
- 1.3 模板基礎配置
- 1.4 模板加載器
- 1.5 定界符與占位符
- 1.6 注釋
- 1.7 變量定義
- 1.8 屬性
- 1.9 數學表達式
- 1.10 循環語句
- 1.11 條件語句
- 1.12 異常捕獲
- 1.13 虛擬屬性
- 1.14 函數調用
- 1.15 安全輸出(重要)
- 1.16 輸出格式化
- 1.17 標簽
- 1.18 調用Java方法與屬性
- 1.19 嚴格MVC控制
- 1.20 指令
- 1.21 錯誤處理
- 1.22 Beetl小工具
- 1.23 Escape
- 第二部分 高級用法
- 2.1 配置GroupTemplate
- 2.2 自定義方法
- 2.3 自定義格式化函數
- 2.4 自定義標簽
- 2.5 自定義虛擬屬性
- 2.6 使用額外的資源加載器
- 2.7 自定義資源加載器
- 2.8 使用CompositeResourceLoader
- 2.9 自定義錯誤處理器
- 2.10 自定義安全管理器
- 2.11 注冊全局共享變量
- 2.12 自定義布局
- 2.13 性能優化
- 2.14 定制輸出
- 2.15 定制模板引擎
- 2.16 直接運行Beetl腳本
- 2.17 模板校驗
- 第三部分 Web 集成
- 3.1 Web提供的全局變量
- 3.2 集成技術開發指南
- 3.3 Servlet集成
- 3.4 SpringMVC集成
- 3.5 Spring Boot集成
- 3.6 Jodd集成
- 3.7 JFinal4 集成方案
- 3.8 Nutz集成
- 3.9 Struts2集成
- 3.10 整合ajax的局部渲染技術
- 3.11 在頁面輸出錯誤提示信息
- 附錄
- 4.1 內置方法
- 4.2 Spring相關函數
- 4.3 Spring security
- 4.4 shiro
- 4.5 內置格式化方法
- 4.6 內置標簽函數
- 4.7 內置html標簽
- 4.8 性能優化
- 4.9 Eclipse 插件
- 4.10 性能測試對比