DBConnManager)src/
├── com/action/TestAction.java # Action
├── com/ResultGather.java # 資料存取封裝
├── conn/DBConnManager.java # 連接池
└── xwork.xml # Action 映射
template/
└── test.flt # FreeMarker 模板
TestAction.javapublic class TestAction extends ActionSupport {
private List lis; // 對應模板 ${lis}
private ResultGather rs;
public List getLis() { return lis; }
public String execute() throws Exception {
rs = new ResultGather();
// 查詢所有用戶,回傳 List
ResultGather.javapublic List selectRS(String sqlStr) {
this.sql = sqlStr;
return selectRS();
}
public List selectRS() {
List rsall = new ArrayList();
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
DBConnManager conn = DBConnManager.getInstance();
con = conn.getConnection("mssql");
stmt = con.createStatement();
rs = stmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
while (rs.next()) {
Map row = new HashMap(cols);
for (int i = 1; i <= cols; i++) {
row.put(rsmd.getColumnName(i), rs.getObject(i));
}
rsall.add(row);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關閉資源...
}
return rsall;
}
關鍵:使用 ResultSetMetaData 動態獲取欄位名,構建 List 通用結構,FreeMarker 即可通用迭代。
<action name="test" class="com.action.TestAction">
<result type="freemarker" name="success">/test.flt</result>
</action>
test.flt<#list lis as x>
${x.username},${x.passWord}<br>
</#list>
<#list sequence as item> 迭代${item.key} 存取 Map 值 (FreeMarker 自動處理 null 顯示為空字串)| 語法 | 說明 | 範例 |
|---|---|---|
${expr} | 輸出運算式結果 | ${user.name} |
<#if cond>...</#if> | 條件判斷 | <#if user.age > 18>成年</#if> |
<#list seq as x>...</#list> | 迭代 | <#list users as u>${u.name}</#list> |
<#include "inc.ftl"> | 引入片段 | 頁首/頁尾共用 |
<#macro name(p)>...</#macro> | 定義巨集 | 可重用 UI 元件 |
?html, ?url, ?json_string | 內建轉義 | ${content?html} |
?size, ?first, ?last | 集合屬性 | <#if list?size > 0> |
// Action 新增分頁參數
private int page = 1;
private int pageSize = 10;
// SQL 改為分頁查詢 (SQL Server 2000: TOP + NOT IN / ROW_NUMBER)
// 模板新增分頁導航
<#if page > 1><a href="test.action?page=${page-1}">上一頁</a></#if>
<#if hasNext><a href="test.action?page=${page+1}">下一頁</a></#if>
| 優點 | 缺點 |
|---|---|
| 嚴格分離邏輯與視圖 | FreeMarker 語法學習曲線 |
| 模板可獨立測試 (無 Servlet 容器) | 標籤庫生態不如 JSP 豐富 |
| 效能優於 JSP (編譯為 Java 類、緩存) | IDE 支援較弱 (早期版本) |
| 支援巨集/繼承/包含,模組化強 | 國際化 (i18n) 需自行整合 |
struts.xml,FreeMarker 整合內建@Controller + FreeMarkerConfigurer + FreeMarkerViewResolverspring-boot-starter-freemarker 自動配置,模板放 src/main/resources/templates/WebWork 2 + FreeMarker 以 Action 封裝業務邏輯 → 返回 List 實現乾淨的 MVC 分離。核心技巧在於 ResultSetMetaData 動態構建 Map,使模板不依賴具體領域類。此模式在現代 Spring MVC + Thymeleaf/FreeMarker 中依然適用,是「控制器薄、模板無邏輯、資料結構通用」的經典實踐。