SpringBoot 整合 Freemarker
通过 Freemarker 模版,我们可以将数据渲染成 HTML 网页、电子邮件、配置文件以及源代码等。
Freemarker 不是面向最终用户的,而是一个 Java 类库,我们可以将之作为一个普通的组件嵌入到我们的产品中。
Freemarker 模版后缀为 .ftl(FreeMarker Template Language)
Freemarker 的自动化配置类org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration
- 当 classpath 下存在 freemarker.template.Configuration 以及 FreeMarkerConfigurationFactory 时,配置才会生效,也就是说当我们引入了 Freemarker 之后,配置就会生效。
@Configuration
@ConditionalOnClass({ freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class })
@EnableConfigurationProperties(FreeMarkerProperties.class)
@Import({ FreeMarkerServletWebConfiguration.class, FreeMarkerReactiveWebConfiguration.class,
FreeMarkerNonWebConfiguration.class })
public class FreeMarkerAutoConfiguration {
}
导入的 FreeMarkerServletWebConfiguration 配置中
- @ConditionalOnWebApplication 表示当前配置在 web 环境下才会生效
- ConditionalOnClass 表示当前配置在存在 Servlet 和 FreeMarkerConfigurer 时才会生效
- @AutoConfigureAfter 表示当前自动化配置在 WebMvcAutoConfiguration 之后完成
- FreeMarkerConfigurer 是Freemarker 的一些基本配置,例如 templateLoaderPath、defaultEncoding 等
- FreeMarkerViewResolver是视图解析器的基本配置,包含了viewClass、suffix、allowRequestOverride、allowSessionOverride 等属性
在 SSM 的 XML 文件中自己配置 Freemarker ,也不过就是配置这些东西。现在,这些配置由 FreeMarkerServletWebConfiguration 帮我们完成了
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({ Servlet.class, FreeMarkerConfigurer.class })
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
class FreeMarkerServletWebConfiguration extends AbstractFreeMarkerConfiguration {
protected FreeMarkerServletWebConfiguration(FreeMarkerProperties properties) {
super(properties);
}
@Bean
@ConditionalOnMissingBean(FreeMarkerConfig.class)
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
applyProperties(configurer);
return configurer;
}
@Bean
@ConditionalOnMissingBean(name = "freeMarkerViewResolver")
@ConditionalOnProperty(name = "spring.freemarker.enabled", matchIfMissing = true)
public FreeMarkerViewResolver freeMarkerViewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
getProperties().applyToMvcViewResolver(resolver);
return resolver;
}
}
FreeMarkerProperties
配置了 Freemarker 的基本信息,例如模板位置在 classpath:/templates/ ,再例如模板后缀为 .ftl,那么这些配置我们以后都可以在 application.properties 中进行修改
@ConfigurationProperties(prefix = "spring.freemarker")
public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties {
publicstaticfinal String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/";
publicstaticfinal String DEFAULT_PREFIX = "";
publicstaticfinal String DEFAULT_SUFFIX = ".ftl";
/**
* Well-known FreeMarker keys which are passed to FreeMarker's Configuration.
*/
private Map<String, String> settings = new HashMap<>();
}
一、创建工程
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Controller
@Controller
public class UserController {
@GetMapping("/index")
public String index(Model model) {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.setId((long) i);
user.setUsername("javaboy>>>>" + i);
user.setAddress("www.javaboy.org>>>>" + i);
users.add(user);
}
model.addAttribute("users", users);
return"index";
}
}
在 freemarker 中渲染数据users
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>用户编号</td>
<td>用户名称</td>
<td>用户地址</td>
</tr>
<#list users as user>
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.address}</td>
</tr>
</#list>
</table>
</body>
</html>
二、其他配置
要修改模版文件位置等,可以在 application.properties 中进行配置:
# HttpServletRequest的属性是否可以覆盖controller中model的同名项
spring.freemarker.allow-request-override=false
# HttpSession的属性是否可以覆盖controller中model的同名项
spring.freemarker.allow-session-override=false
# 是否开启缓存
spring.freemarker.cache=false
# 模板文件编码
spring.freemarker.charset=UTF-8
# 是否检查模板位置
spring.freemarker.check-template-location=true
# Content-Type的值
spring.freemarker.content-type=text/html
# 是否将HttpServletRequest中的属性添加到Model中
spring.freemarker.expose-request-attributes=false
# 是否将HttpSession中的属性添加到Model中
spring.freemarker.expose-session-attributes=false
# 模板文件后缀
spring.freemarker.suffix=.ftl
#模板文件位置
spring.freemarker.template-loader-path=classpath:/templates/
【注意】
Freemarker 中,还有两个后缀,一个叫做 ftlh,这个用在 HTML 模板中,另一个叫做 ftlx,这个用在 XML 模板中。
Spring Boot2.2.0 之前,Freemarker 模板默认采用的后缀就是 ftl
//FreeMarkerProperties 类的部分源码(Spring Boot2.2.0 之前的版本):
@ConfigurationProperties(
prefix = "spring.freemarker"
)
public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties {
public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/";
public static final String DEFAULT_PREFIX = "";
public static final String DEFAULT_SUFFIX = ".ftl"; //默认的后缀还是 .ftl
private Map<String, String> settings = new HashMap();
private String[] templateLoaderPath = new String[]{"classpath:/templates/"};
private boolean preferFileSystemAccess = true;
Spring Boot2.2.0 开始,FreeMarkerProperties 文件内容就发生了变化
@ConfigurationProperties(
prefix = "spring.freemarker"
)
public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties {
public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/";
public static final String DEFAULT_PREFIX = "";
public static final String DEFAULT_SUFFIX = ".ftlh"; //.ftlh
private Map<String, String> settings = new HashMap();
private String[] templateLoaderPath = new String[]{"classpath:/templates/"};
private boolean preferFileSystemAccess = true;
所以当访问不到页面资源:两种方案
- 将 Freemarker 模板的后缀改为 .ftlh,推荐这种方式
- 在 application.properties 中修改默认配置
# 强行把 Freemarker 模板的后缀又改回 .ftl
spring.freemarker.suffix=.ftl