Freemarker模板引擎NonHashException:字符串比較的正確方式

Freemarker模板引擎NonHashException:字符串比較的正確方式

本文旨在解決在使用apache Freemarker模板引擎時遇到的NonHashException,該異常通常發生在嘗試訪問字符串屬性時,提示期望一個哈希值卻得到了字符串。文章將詳細解釋Freemarker中字符串比較的正確方法,并提供示例代碼,幫助開發者避免類似錯誤,提高模板開發效率。

在使用Freemarker模板引擎時,開發者可能會遇到freemarker.core.NonHashException異常,特別是當處理字符串比較時。這個異常通常表明Freemarker期望一個哈希(類似于Java中的map對象),但實際卻得到了一個字符串。本文將深入探討這個問題,并提供解決方案。

問題分析

在Java代碼中,使用.equals()方法比較字符串的內容是很常見的做法。然而,在Freemarker模板中,情況有所不同。Freemarker對字符串的處理方式與Java有所區別,直接使用.equals()方法可能會導致NonHashException。

考慮以下示例,假設有一個名為previousSearch的對象,其中包含一個名為status的字符串屬性:

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

在Freemarker模板中,嘗試使用.equals()方法進行字符串比較:

<select name="status" id="status" class="form-control select2">     <option value="ALL" <#if previousSearch.getStatus().equals("ALL")>selected</#if>>Alle anzeigen</option>     <option value="OPEN" <#if previousSearch.status.equals("OPEN")>selected</#if>>Offen</option>     <option value="DONE" <#if previousSearch.status.equals("DONE")>Geschlossen</option> </select>

這段代碼可能會拋出NonHashException,因為Freemarker不推薦使用.equals()方法進行字符串比較。

解決方案

在Freemarker中,應該使用==運算符來比較字符串。這與Java中比較對象引用是否相等不同,在Freemarker中,==運算符用于比較字符串的內容是否相等。

修改上面的示例代碼,使用==運算符進行字符串比較:

<select name="status" id="status" class="form-control select2">     <option value="ALL" <#if previousSearch.status == "ALL">selected</#if>>Alle anzeigen</option>     <option value="OPEN" <#if previousSearch.status == "OPEN">selected</#if>>Offen</option>     <option value="DONE" <#if previousSearch.status == "DONE">Geschlossen</option> </select>

通過將.equals()替換為==運算符,可以避免NonHashException,并正確地比較字符串的內容。

示例代碼

以下是一個更完整的示例,展示了如何在spring mvc中使用Freemarker進行字符串比較:

Java Controller:

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"); // 設置初始狀態         model.addAttribute("previousSearch", previousSearch);         return "ticket/search";     } }

Freemarker Template (ticket/search.ftlh):

<!DOCTYPE html> <html> <head>     <title>Ticket Search</title> </head> <body>     <h1>Ticket Search Form</h1>     <select name="status" id="status" class="form-control select2">         <option value="ALL" <#if previousSearch.status == "ALL">selected</#if>>Alle anzeigen</option>         <option value="OPEN" <#if previousSearch.status == "OPEN">selected</#if>>Offen</option>         <option value="DONE" <#if previousSearch.status == "DONE">Geschlossen</option>     </select> </body> </html>

在這個例子中,Controller將TicketSearchForm對象傳遞給Freemarker模板。模板使用==運算符比較previousSearch.status屬性與不同的字符串值,從而正確地設置

注意事項

  • 空值處理: 在進行字符串比較之前,確保要比較的字符串不為空。可以使用Freemarker的?has_content指令來檢查變量是否為空。

    <#if previousSearch.status?? && previousSearch.status == "OPEN">     ... </#if>
  • 大小寫敏感: Freemarker的字符串比較是大小寫敏感的。如果需要進行大小寫不敏感的比較,可以使用?lower_case或?upper_case指令將字符串轉換為統一的大小寫形式。

    <#if previousSearch.status?lower_case == "open">     ... </#if>

總結

在使用Freemarker模板引擎時,理解其字符串比較的特殊性至關重要。通過使用==運算符而不是.equals()方法,可以避免NonHashException,并正確地進行字符串比較。此外,注意空值處理和大小寫敏感性,可以編寫出更健壯、更可靠的Freemarker模板。掌握這些技巧將有助于提高模板開發效率,并減少潛在的錯誤。

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