## 1.15 安全輸出(重要)
[TOC]
安全輸出是任何一個模板引擎必須重視的問題,否則,將極大困擾模板開發者。Beetl中,如果要輸出的模板變量為null,則beetl將不做輸出,這點不同于JSP,JSP輸出null,也不同于Freemarker,如果沒有用`!`,它會報錯。
模板中還有倆種情況會導致模板輸出異常
- 有時候模板變量并不存在,這時候必須報錯,如果簡單忽略不輸出(Velocity就是這樣),很容易留坑
- 模板變量為null,但輸出的是此變量的一個屬性,如 `${user.wife.name}`
針對前兩種情況,可以在變量引用后加上 `!` 以提醒beetl這是一個安全輸出的變量,變量確實有可能不存在
如 `${user.wife.name! }`,即使user不存在,或者user為null,或者user.wife為null,或者user.wife.name為null beetl都不將輸出
可以在!后增加一個常量(字符串,數字類型等),或者另外一個變量,方法,本地調用,作為默認輸出,譬如:
`${user.wife.name!"單身"}`,如果user為null,或者user.wife為null,或者user.wife.name為null,輸出`單身`
譬如
`${user.birthday!@System.constants.DefaultBir}`, 表示如果user為null,或者user. birthday為null,輸出`System.constants.DefaultBir`
還有一種情況很少發生,但也有可能,輸出模板變量發生的任何異常,如變量內部拋出的一個異常
這需要使用格式${!(變量)},這樣,在變量引用發生任何異常情況下,都不作輸出,譬如
`${!(user.name)}`,Beetl將會調用 `user.getName()` 方法,如果發生異常,Beetl 將會忽略此異常,繼續渲染
值得注意的是,在變量后加上!不僅僅可以應用于占位符輸出(但主要是應用于占位符輸出),也可以用于表達式中,如:
```javascript
<%
var k = user.name!'N/A'+user.age!;
%>
<%
${k}
%>
```
如果 user 為 null ,則 k 值將為`N/A`
在有些模板里,可能整個模板都需要安全輸出,也可能模板的部分需要安全輸出,使用者不必為每一個表達式使用!,可以使用beetl的安全指示符號來完成安全輸出 如:
```javascript
<%
DIRECTIVE SAFE_OUTPUT_OPEN;
%>
${user.wife.name}
模板其他內容,均能安全輸出……
<%
//關閉安全輸出。
DIRECTIVE SAFE_OUTPUT_CLOSE;
%>
```
Beetl 不建議每一個頁面都使用 `DIRECTIVE SAFE_OUTPUT_OPEN`,這樣,如果真有不期望的錯誤,不容易及時發現,其次,安全輸出意味著 Beetl 會有額外的代碼檢測值是否存在或者是否為null,性能會略差點。所以建議及時關閉安全輸出(這不是必須的,但頁面所有地方是安全輸出,可能不容易發現錯誤)
如果你的所有模板都想安全輸出,可以配置,但不推薦。嚴格了錯誤,就像 try-catch 吃掉異常一樣不容易發現這是個錯誤
```
SAFE_OUTPUT=true
```
在 for-in 循環中 ,也可以為集合變量增加安全輸出指示符號,這樣,如果集合變量為null,也可以不進入循環體,如:
```javascript
<%
var list = null;
for(item in list!){
}elsefor{
print("no data");
}
%>
```
### 1.15.1 變量是否存在
```javascript
<%
if(has(flag)){
print("flag變量存在,可以訪問")
}
%>
```
如果需要判斷變量是否存在,如果存在,還有其他判斷條件,通常都這么寫
```javascript
<%
if(has(flag)&&flag==0){
//code
}
%>
```
如果flag存在,而且值是0,都將執行if語句
但是,有更為簡便的方法是直接用安全輸出,如
```javascript
<%
if(flag!0==0){
//code
}
%>
```
flag!0 取值是這樣的,如果flag不存在,則為0,如果存在,則取值flag的值,類似三元表達式 if((has(flag)?flag:0)==0)
### 1.15.2 安全輸出表達式
安全輸出表達式可以包括
- 字符串常量,如 ${user.count!"無結果"}
- boolean常量 ${user.count!false}
- 數字常量,僅限于正數,因為如果是負數,則類似減號,容易誤用,因此,如果需要表示負數,請用括號,如${user.count!(-1)}
- class直接調用,如${user.count!@User.DEFAULT_NUM}
- 方法調用,如 ${user.count!getDefault() }
- 屬性引用,如 ${user.count!user.maxCount }
- 任何表達式,需要用括號
- 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 性能測試對比