Freemarker模板引擎:解決NonHashException字符串比較問題

Freemarker模板引擎:解決NonHashException字符串比較問題

本文旨在解決在使用apache Freemarker模板引擎時,遇到的freemarker.core.NonHashException: Expected a hash, but this has evaluated to a String 錯誤,并提供正確的字符串比較方法。該錯誤通常發生在嘗試訪問對象屬性時,Freemarker將其誤判為字符串。通過理解Freemarker的字符串處理方式,可以有效避免此類問題。

問題分析

在使用Freemarker模板引擎進行開發時,當嘗試訪問一個對象的屬性,并進行字符串比較時,可能會遇到NonHashException。例如,在spring mvc項目中,從Controller傳遞一個Java對象到Freemarker模板,并嘗試訪問該對象的string類型的屬性時,可能會出現如下錯誤:

freemarker.core.NonHashException: For "." left-hand operand: Expected a hash, but this has evaluated to a string (wrapper: f.t.SimpleScalar): ==> previousSearch.status  [in template "ticket/search.ftlh" at line 22, column 66]

這個錯誤表明Freemarker期望.左邊的操作數是一個Hash(類似于Java中的map),但實際卻是一個字符串。

原因探究

出現這種問題的原因在于Freemarker對字符串的處理方式與Java有所不同。在Java中,我們通常使用.equals()方法來比較字符串的內容。但在Freemarker中,推薦使用==運算符來進行字符串比較。

解決方案

將Freemarker模板中的.equals()方法替換為==運算符即可解決此問題。

例如,將以下代碼:

<option value="ALL" <#if previousSearch.status.equals("ALL")>selected</#if>>Alle anzeigen</option>

修改為:

<option value="ALL" <#if previousSearch.status == "ALL">selected</#if>>Alle anzeigen</option>

通過這種方式,Freemarker可以正確地比較字符串,從而避免NonHashException。

示例代碼

假設有一個Java類 TicketSearchForm:

import lombok.Data;  @Data public class TicketSearchForm {     private String status = "ALL"; }

spring mvc Controller中,將該對象傳遞到Freemarker模板:

import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping;  @Controller public class TicketController {      @GetMapping("/search")     public String search(Model model) {         TicketSearchForm previousSearch = new TicketSearchForm();         previousSearch.setStatus("OPEN"); // 設置狀態為OPEN         model.addAttribute("previousSearch", previousSearch);         return "ticket/search"; // 假設模板文件為 ticket/search.ftlh     } }

對應的Freemarker模板 ticket/search.ftlh:

     <option value="ALL" <#if previousSearch.status == "ALL">selected</#if>>Alle anzeigen</option>     <option value="OPEN" selected>Offen     <option value="DONE" selected>Geschlossen 

在這個例子中,使用previousSearch.status == “ALL” 來比較字符串,可以正確地根據previousSearch對象的status屬性值來設置元素的默認選項。

注意事項

  • 始終使用==運算符在Freemarker模板中比較字符串。
  • 確保傳遞到Freemarker模板的對象屬性類型與模板中使用的類型一致。
  • 在復雜的場景下,可以使用Freemarker提供的內置函數,如?string 將其他類型轉換為字符串后再進行比較。

總結

解決Freemarker模板引擎中NonHashException的關鍵在于理解Freemarker對字符串的處理方式。通過使用==運算符代替.equals()方法進行字符串比較,可以避免該錯誤的發生,并確保模板的正確執行。 記住,Freemarker的語法與Java有所不同,需要仔細區分。

? 版權聲明
THE END
喜歡就支持一下吧
點贊7 分享