Apache FreeMarker 是一个模板引擎,用于生成从 HTML 到电子邮件和其他任何类型的文本输出。Spring 框架有内置的集成,可以使用 Spring MVC 和 FreeMarker 模板。

视图配置

首先需要先添加依赖

  1. // org.springframework.ui.freemarker.FreeMarkerConfigurationFactory 在 spring-context-support 中被支持
  2. implementation group: 'org.springframework', name: 'spring-context-support', version: '5.3.15'
  3. implementation group: 'org.freemarker', name: 'freemarker', version: '2.3.31'

下面的例子显示了如何将 FreeMarker 配置为一种视图技术:

  1. @Configuration
  2. @EnableWebMvc
  3. public class WebConfig implements WebMvcConfigurer {
  4. @Override
  5. public void configureViewResolvers(ViewResolverRegistry registry) {
  6. // 使用空的默认视图名称前缀和默认后缀 .ftl 注册 FreeMarker 视图解析器。
  7. // 请注意,您还必须通过添加 FreeMarkerConfigurer bean 来配置 FreeMarker
  8. registry.freeMarker();
  9. }
  10. // 配置 FreeMarker...
  11. @Bean
  12. public FreeMarkerConfigurer freeMarkerConfigurer() {
  13. FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
  14. configurer.setTemplateLoaderPath("/WEB-INF/freemarker");
  15. return configurer;
  16. }
  17. }

下面的例子显示了如何在 XML 中进行同样的配置:

  1. <mvc:annotation-driven/>
  2. <mvc:view-resolvers>
  3. <mvc:freemarker/>
  4. </mvc:view-resolvers>
  5. <!-- Configure FreeMarker... -->
  6. <mvc:freemarker-configurer>
  7. <mvc:template-loader-path location="/WEB-INF/freemarker"/>
  8. </mvc:freemarker-configurer>

另外,你也可以声明 FreeMarkerConfigurer bean 来完全控制所有的属性,如下例所示:

  1. <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  2. <property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
  3. </bean>

你的模板需要存储在前面的例子中所示的 FreeMarkerConfigurer 指定的目录中。鉴于前面的配置,如果你的控制器返回的视图名称是 welcome,解析器会寻找 /WEB-INF/freemarker/welcome.ftl模板。

FreeMarker 配置

你可以通过在 FreeMarkerConfigurer Bean 上设置适当的 bean 属性,将 FreeMarker 「Settings」和 「SharedVariables」直接传递给 FreeMarker 配置对象(它由 Spring 管理)。freemarkerSettings 属性需要一个 java.util.Properties 对象,而 freemarkerVariables 属性需要一个java.util.Map。下面的例子显示了如何使用 FreeMarkerConfigurer:

  1. <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  2. <property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
  3. <property name="freemarkerVariables">
  4. <map>
  5. <entry key="xml_escape" value-ref="fmXmlEscape"/>
  6. </map>
  7. </property>
  8. </bean>
  9. <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>

关于适用于 Configuration 对象的设置和变量的细节,请参见 FreeMarker 文档。

表单处理

Spring 提供了一个标签库供 JSP 使用,其中包含 <spring:bind/>元素。这个元素主要让表单显示来自表单支持对象的值,并显示来自 Web 或业务层中验证器的失败验证结果。Spring 在 FreeMarker 中也支持同样的功能,还有额外的方便宏用于生成表单输入元素本身。

绑定宏(Macros)

在 FreeMarker 的 spring-webmvc.jar 文件中维护了一套标准的宏,所以它们总是可以被适当配置的应用程序使用。

在 Spring 模板库中定义的一些宏被认为是内部的(私有的),但在宏定义中不存在这样的范围,使所有的宏对调用代码和用户模板是可见的。下面的章节只集中讨论你需要从模板中直接调用的宏。如果你想直接查看宏代码,文件名为 spring.ftl,位于org.springframework.web.servlet.view.freemarker 包中。

简单的绑定

在你基于 FreeMarker 模板的 HTML 表单中,作为 Spring MVC 控制器的表单视图,你可以使用类似于下一个例子的代码来绑定字段的值,并以类似于 JSP 的方式为每个输入字段显示错误信息。下面的例子显示了一个 personForm 视图:

  1. <!-- FreeMarker 宏必须被导入到一个命名空间。
  2. 我们强烈建议坚持使用 "spring"。 -->
  3. <#import "/spring.ftl" as spring/>
  4. <html>
  5. ...
  6. <form action="" method="POST">
  7. Name:
  8. <@spring.bind "personForm.name"/>
  9. <input type="text"
  10. name="${spring.status.expression}"
  11. value="${spring.status.value?html}"/><br />
  12. <#list spring.status.errorMessages as error> <b>${error}</b> <br /> </#list>
  13. <br />
  14. ...
  15. <input type="submit" value="submit"/>
  16. </form>
  17. ...
  18. </html>

<@spring.bind>需要一个 ‘path’ 参数,它由你的命令对象的名字组成(它是 ‘command’,除非你在控制器配置中改变了它),后面是一个 . 和你想绑定的命令对象上的字段名。你也可以使用嵌套字段,如 command.address.street。绑定宏假定默认的 HTML 转义行为由 web.xml 中的 ServletContext 参数 defaultHtmlEscape 指定。

该宏的另一种形式叫做 <@spring.bindEscaped>,它需要第二个参数,明确指定是否应该在状态错误信息或值中使用 HTML 转义。你可以根据需要将其设置为真或假。附加的表单处理宏简化了 HTML 转义的使用,你应该尽可能地使用这些宏。它们将在下一节中解释。

输入宏

FreeMarker 的附加便利宏简化了绑定和表单生成(包括验证错误显示)。从来没有必要使用这些宏来生成表单输入字段,你可以将它们与简单的HTML 或直接调用我们之前强调的 Spring 绑定宏进行混合和匹配。

下面的可用宏表显示了 FreeMarker 模板(FTL)的定义和每个宏的参数列表。

:::tips 后面的内容还挺多的,就不记录了,暂时没有打算使用这个视图,请参考 官方文档 :::

一个 Hello Word 例子

image.png
这个例子架子在 Spring Web MVC 中 内嵌 Tomcat 笔记中有说明,这里针对配置和写法进行搭建。

  1. package cn.mrcode.study;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  6. import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
  7. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  8. import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
  9. /**
  10. * @author mrcode
  11. */
  12. @EnableWebMvc
  13. @ComponentScan("cn.mrcode.study.springdocsread")
  14. @Configuration
  15. public class AppConfig implements WebMvcConfigurer {
  16. @Override
  17. public void configureViewResolvers(ViewResolverRegistry registry) {
  18. registry.freeMarker();
  19. }
  20. // 配置 FreeMarker...
  21. @Bean
  22. public FreeMarkerConfigurer freeMarkerConfigurer() {
  23. FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
  24. // 对应的是模板存放地址
  25. configurer.setTemplateLoaderPath("/WEB-INF/freemarker");
  26. return configurer;
  27. }
  28. }

hello-word.ftl

  1. 您好:${username}

controller

  1. package cn.mrcode.study.springdocsread.web;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.ui.Model;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. /**
  7. * @author mrcode
  8. */
  9. @Controller
  10. @RequestMapping("/demo2")
  11. public class Demo2Controller {
  12. @GetMapping("/freemarker")
  13. public String freemarker(Model model) {
  14. // 添加一个响应参数
  15. model.addAttribute("username", "Hello Word");
  16. return "hello-word";
  17. }
  18. }

然后访问 http://localhost:8080/demo2/freemarker 就能看到渲染的 html 页面了