簡介
StringTemplate是一種基于java的模板引擎庫,類似于velocity,F(xiàn)reeMarker??梢杂糜谏稍创a、web頁面、電子郵件等多種樣式的文本。選擇StringTemplate的原因是因為相較于其他的模板引擎,他的功能更加強大。
使用
1、使用maven添加依賴
<dependency>
<groupId>org.antlr</groupId>
<artifactId>ST4</artifactId>
<version>4.0.8</version>
<scope>compile</scope>
</dependency>
2、demo
2.1示例:
import org.stringtemplate.v4.ST;
...
ST hello = new ST("Hello, <name>");
hello.add("name", "World");
System.out.println(hello.render());
輸出:
Hello, World
2.2 StringTemplate基本語法
"Hello, <name>" 模板中有一個表達式<name>,代碼中使用world替換了該表達式中的內(nèi)容,于是輸出了“Hello, World”。
基本元素
text
<expr>
<!comment !>
其中,text為文本內(nèi)容,<expr>為表達式,<!comment !>為注釋??梢允褂?<" 或 "\>"來避免文本內(nèi)容與表達式的沖突。使用ST也支持"$name$"這種方式來表示表達式。
2.3 條件表達式
ST支持條件表達式,簡單實例如下:
// 第二個和第三個參數(shù)用于定義表達式的頭尾字符
ST hello = new ST("Hello, $if(name)$$name$$endif$", '$', '$');
hello.add("name", "risk");
System.out.println(hello.render());
輸出:
Hello, risk
可以看到這里使用了"$..$"方式來定義表達式,表達式中來如果$name$存在,則將$name$輸出。
換一種方式將更加容易看懂
ST hello = new ST("Hello, <if(name)><name><endif>");
hello.add("name", "risk");
System.out.println(hello.render());
注意:條件表達式中,條件只支持true或false這兩種方式,若是傳入的內(nèi)容為null,則當(dāng)中false處理,表達式無法支持name=="parrt"這種運算形式的內(nèi)如。
2.4 模板組
StringTemplate的一個強大的功能是模板功能,模板功能有點類似函數(shù)的使用方式,模板定義如下:
templateName(args, agrs, ...) ::+= "模板內(nèi)容"
上述模板方式支持單行內(nèi)容,這里展示一個簡單的示例:
STGroup stg = new STGroupString("sqlTemplate(columns,condition) ::= \"select <columns> from table where 1=1 <if(condition)>and <condition><endif> \"");
ST sqlST = stg.getInstanceOf("sqlTemplate");
sqlST.add("columns","order_id");
sqlST.add("condition", "dt='2017-04-04'");
System.out.print(sqlST.render());
輸出:
from select order_id from table where 1=1 and dt='2017-04-04'
對于模板定義,同時支持如下兩種方式:
- 1、模板內(nèi)容為多行
templateName(args, agrs, ...) ::+= <<
模板內(nèi)容
模板內(nèi)容
>>
- 2、模板內(nèi)容多行,且忽略換行符和縮進
templateName(args, agrs, ...) ::+= <%
模板內(nèi)容
模板內(nèi)容
%>
因此可以將上例中的sql寫成如下方式更好:
STGroup stg = new STGroupString("sqlTemplate(columns,condition) ::= <<select <columns> \n" +
"from table \n" +
"where 1=1 <if(condition)>and <condition><endif> >>");
ST sqlST = stg.getInstanceOf("sqlTemplate");
sqlST.add("columns","order_id");
sqlST.add("condition", "dt='2017-04-04'");
System.out.print(sqlST.render());
輸出:
select order_id
from table
where 1=1 and dt='2017-04-04'
當(dāng)模板過于復(fù)雜時,以硬編碼的方式將模板寫在代碼中,實在很麻煩,因此將模板內(nèi)容寫入到文件dataExtarctSql.stg中,內(nèi)容如下:
sqlTemplate(columns,condition)
::= <<select <columns;separator=",">
from table
where 1=1 <if(condition)>and <condition><endif>
>>
這里將<columns> 修改為 <columns;separator=","> 這樣可以在列名中插入多個列名,并以","分割。
java代碼如下:
STGroup stg = new STGroupFile("dataExtractSql.stg");
ST sqlST = stg.getInstanceOf("sqlTemplate");
List<String> columnList = new LinkedList<String>();
columnList.add("order_id");
columnList.add("price");
columnList.add("phone");
sqlST.add("columns", columnList);
sqlST.add("condition", "dt='2017-04-04'");
System.out.print(sqlST.render());
輸出:
select order_id,price,phone
from table
where 1=1 and dt='2017-04-04'
2.5模板組的簡單使用
當(dāng)一個模板比較復(fù)雜時,可以拆分成多個模板,以模板組的方式使用更加方便。
模板文件dataExtarctSql.stg如下:
/**模板外注釋sql模板*/
sqlTemplate(columns,condition,joinKey,tableName,childColumns,childJoinKey,childTableName,childCdtion)
::= <<
<! 模板內(nèi)注釋 !>
select <columns;separator=",">,<childColumns:{item|t2.<item>};separator=",">
from <tableName> as t1 left join (<childSqlTemplate(childColumns, childCdtion)>) as t2 on t1.<joinKey>=t2.<childJoinKey>
where 1=1 <if(condition)>and <condition><endif>
>>
/**模板外注釋sql子模板*/
childSqlTemplate(childColumns, childCdtion)
::= <<
select <childColumns;separator=",">
from <childTableName>
where 1=1 <if(childCdtion)>and <childCdtion><endif>
>>
模板中有兩個模板函數(shù)sqlTemplate、childSqlTemplate,childSqlTemplate作為一個子模板被sqlTemplate調(diào)用。sqlTemplate中select 后面的列名分為兩部分,一部從數(shù)組變量columns中獲取,并以“,”進行分割,另一部分從數(shù)組childColumns中獲取,使用“,”分割的同時,也為每個列名增加了“t2.”的前綴,即子查詢的別名。from部分中將childSqlTemplate函數(shù)模板作為一個子查詢進行join。這樣獲得了一個比較復(fù)雜的sql語句。
java代碼如下:
STGroup stg = new STGroupFile("dataExtractSql.stg");
ST sqlST = stg.getInstanceOf("sqlTemplate");
List<String> columnList = new LinkedList<String>();
columnList.add("order_id");
columnList.add("price");
columnList.add("phone");
columnList.add("user");
sqlST.add("columns", columnList);
sqlST.add("condition", "dt='2017-04-04'");
sqlST.add("joinKey", "user");
sqlST.add("tableName", "orderTable");
List<String> childColumnList = new LinkedList<String>();
childColumnList.add("user");
childColumnList.add("userLeave");
childColumnList.add("userLocation");
sqlST.add("childColumns", childColumnList);
sqlST.add("childJoinKey", "user");
sqlST.add("childTableName", "userTable");
String result = sqlST.render();
System.out.print(result);
輸入內(nèi)容如下:
select order_id,price,phone,user,t2.user,t2.userLeave,t2.userLocation
from orderTable as t1 left join (select user,userLeave,userLocation
from userTable
where 1=1 ) as t2 on t1.user=t2.user
where 1=1 and dt='2017-04-04'