首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Spring MVC 整合 FreeMarker 完整配置指南 (XML + Java Config 雙版本)

     編輯:Java 程式設計入門

環境資訊

  • 框架:Spring MVC 3.2.x / 4.x / 5.x 通用
  • 模板引擎:FreeMarker 2.3.20+
  • 建構工具:Maven / Gradle

步驟 1:引入依賴

Maven

<!-- FreeMarker 核心 -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.32</version> <!-- 建議升級至較新版本 -->
</dependency>
<!-- Spring 對 FreeMarker 的支援 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.3.21</version> <!-- 對應 Spring 版本 -->
</dependency>

Gradle

implementation 'org.freemarker:freemarker:2.3.32'
implementation 'org.springframework:spring-context-support:5.3.21'

步驟 2:FreeMarker 設定檔 (src/main/resources/conf/freemarker.properties)

tag_syntax=auto_detect
template_update_delay=0          # 開發環境設 0 即時生效,生產建議 >0 或 -1
default_encoding=UTF-8
output_encoding=UTF-8
locale=zh_TW                     # 繁體中文環境
date_format=yyyy-MM-dd
time_format=HH:mm:ss
datetime_format=yyyy-MM-dd HH:mm:ss
number_format=0.##               # 數字預設格式
boolean_format=true,false

步驟 3:Spring 配置 (二選一)

方案 A:XML 配置 (spring-servlet.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="https://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
           https://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           https://www.springframework.org/schema/mvc
           https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 1. 載入屬性檔 -->
    <bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" value="classpath:conf/freemarker.properties" />
    </bean>

    <!-- 2. FreeMarker 核心配置 -->
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/ftl/" />
        <property name="freemarkerVariables">
            <map>
                <entry key="xml_escape" value-ref="fmXmlEscape" />
            </map>
        </property>
        <property name="configuration" ref="freemarkerConfiguration" />
    </bean>
    <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />

    <!-- 3. 視圖解析器 -->
    <bean id="freeMarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
        <property name="viewNames">
            <array><value>*.ftl</value></array>
        </property>
        <property name="contentType" value="text/html; charset=UTF-8" />
        <property name="exposeRequestAttributes" value="true" />
        <property name="exposeSessionAttributes" value="true" />
        <property name="exposeSpringMacroHelpers" value="true" />
        <property name="requestContextAttribute" value="request" />
        <property name="order" value="1" /> <!-- 優先於 JSP 解析器 -->
    </bean>

    <!-- 靜態資源處理 (別忘了) -->
    <mvc:resources mapping="/static/**" location="/static/" />
    <mvc:annotation-driven />
</beans>

方案 B:Java Config (推薦,Spring 3.1+)

@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public FreeMarkerConfigurer freemarkerConfig() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPath("/WEB-INF/ftl/");
        configurer.setDefaultEncoding("UTF-8");
        // 直接設定 Configuration 屬性
        Properties props = new Properties();
        props.setProperty("template_update_delay", "0");
        props.setProperty("locale", "zh_TW");
        props.setProperty("number_format", "0.##");
        configurer.setFreemarkerSettings(props);
        
        // 共享變數
        Map<String, Object> variables = new HashMap<>();
        variables.put("xml_escape", new XmlEscape());
        configurer.setFreemarkerVariables(variables);
        return configurer;
    }

    @Bean
    public FreeMarkerViewResolver freeMarkerViewResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
        resolver.setViewClass(FreeMarkerView.class);
        resolver.setViewNames(new String[]{"*.ftl"});
        resolver.setContentType("text/html; charset=UTF-8");
        resolver.setExposeRequestAttributes(true);
        resolver.setExposeSessionAttributes(true);
        resolver.setExposeSpringMacroHelpers(true);
        resolver.setRequestContextAttribute("request");
        resolver.setOrder(1);
        return resolver;
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(freeMarkerViewResolver());
        // 若同時支援 JSP
        // registry.jsp("/WEB-INF/jsp/", ".jsp").order(2);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
}

步驟 4:Controller 與模板

Controller

@Controller
@RequestMapping("/hello")
public class HelloController {
    @GetMapping("/world")
    public String helloWorld(Model model) {
        model.addAttribute("word0", "Hello ");
        model.addAttribute("word1", "World!");
        model.addAttribute("users", List.of("Alice", "Bob", "Charlie"));
        return "helloWorld"; // 對應 /WEB-INF/ftl/helloWorld.ftl
    }
}

模板 (/WEB-INF/ftl/helloWorld.ftl)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>FreeMarker Demo</title>
</head>
<body>
    <h2>${word0}${word1}</h2>
    
    <h3>用戶列表 (list 指令)</h3>
    <ul>
    <#list users as user>
        <li>${user_index}: ${user}</li>
    </#list>
    </ul>
    
    <h3>條件判斷 (if/else)</h3>
    <#if users?size > 2>
        <p>用戶超過 2 人</p>
    <#else>
        <p>用戶不足 2 人</p>
    </#if>
</body>
</html>

步驟 5:常見問題與優化

問題解決方案
模板修改不生效開發環境設 template_update_delay=0;生產設 -1 (不檢查) 或大於 0 秒
中文亂碼確保 default_encoding=UTF-8、output_encoding=UTF-8、ViewResolver contentType 含 charset、模板檔案以 UTF-8 儲存
靜態資源 404配置 <mvc:resources> 或 addResourceHandlers
共用佈局/片段使用 <#include>、<#import>、<@layout> 宏
Spring 表單標籤引入 <#import "/spring.ftl" as spring/> 使用 <@spring.formInput> 等

進階:自定義指令/共享變數

@Bean
public FreeMarkerConfigurer freemarkerConfig() {
    FreeMarkerConfigurer c = new FreeMarkerConfigurer();
    // ...
    Map<String, Object> vars = new HashMap<>();
    vars.put("appName", "MyApp");
    vars.put("formatMoney", (TemplateMethodModelEx) args -> {
        Number n = (Number) args.get(0);
        return NumberFormat.getCurrencyInstance(Locale.TAIWAN).format(n);
    });
    c.setFreemarkerVariables(vars);
    return c;
}

模板中直接使用:${appName}、${formatMoney(1234.5)}。

結語

Spring MVC + FreeMarker 是經典且穩定的視圖層組合。掌握 **Configurer → ViewResolver → Controller → Template** 四層配置鏈路,並善用「開發熱更、生產緩存」、「共享變數/宏/佈局」等進階特性,即可構建高效可維護的渲染層。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved