Freemarker 简介
这是一个相当老牌的开源的免费的模版引擎。通过 Freemarker 模版,我们可以将数据渲染成 HTML 网页、电子邮件、配置文件以及源代码等。Freemarker 不是面向最终用户的,而是一个 Java 类库,我们可以将之作为一个普通的组件嵌入到我们的产品中。
Freemarker 模版后缀为 .ftl(FreeMarker Template Language)。FTL 是一种简单的、专用的语言,它不是像 Java 那样成熟的编程语言。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。
这里先把代码显示咯,再做分析解释
就不从新建项目讲起来了,这样废话就太多了,就是记得加上SpringBoot官方给的Freemarker的依赖。
结构
依赖
新建时,没加也问题不大,我们自己在中手动加上就好
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
UserController
/**
* @author ZSL
* @ClassName UserController
* @description
* @date 2019/8/6
*/
@Controller
public class UserController {
@GetMapping("/user")
public String getUser( Model model){
User user = new User();
("zid");
("zsl");
(18);
("user",user);
return "index";
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
在resources目录下的templates文件夹下新建.ftl的FreeMarker文件
这里你直接新建是没有.ftl文件的,你可以通过html文件改后缀也可以直接新定义新建.ftl文件的选项,.ftl和html文件差不多。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<tr>
<td>${}</td>
<td>${}</td>
<td>${}</td>
</tr>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
相信上面的代码不用注释你能看得懂,都是基础代码。
那么我们来分析一下,我们知道Starter中知道了有个自动装配类xxxAutoConfiguration
的,那么我们来看看在FreeMarker中的自动装配类。
我们从头慢慢来分析
启动类
@SpringBootApplication
是个组合注解
@EnableAutoConfiguration 表示启用 Spring 应用程序上下文的自动配置,该注解会自动导入一个名为 AutoConfigurationImportSelector 的类,而这个类会去读取一个名为 的文件, 中则定义需要加载的自动化配置类
没错是的,我们的FreeMarkerAutoConfiguration 自动装配类就是在这个文件中。
而这个的路径:
org\springframework\boot\spring-boot-autoconfigure\2.1.\spring-boot-autoconfigure-2.1.!\META-INF\
- 1
那么我们来看这个FreeMarkerAutoConfiguration
自动装配类
/**
* {@link EnableAutoConfiguration Auto-configuration} for FreeMarker.
*
* @author Andy Wilkinson
* @author Dave Syer
* @author Kazuki Shimizu
* @since 1.1.0
*/
@Configuration
@ConditionalOnClass({ , })
@EnableConfigurationProperties()
@Import({ , ,
})
public class FreeMarkerAutoConfiguration {
private static final Log logger = ();
private final ApplicationContext applicationContext;
private final FreeMarkerProperties properties;
public FreeMarkerAutoConfiguration(ApplicationContext applicationContext, FreeMarkerProperties properties) {
= applicationContext;
= properties;
}
@PostConstruct
public void checkTemplateLocationExists() {
if (() && ()) {
List<TemplateLocation> locations = getLocations();
if (().noneMatch(this::locationExists)) {
("Cannot find template location(s): " + locations + " (please add some templates, "
+ "check your FreeMarker configuration, or set "
+ "=false)");
}
}
}
private List<TemplateLocation> getLocations() {
List<TemplateLocation> locations = new ArrayList<>();
for (String templateLoaderPath : ()) {
TemplateLocation location = new TemplateLocation(templateLoaderPath);
(location);
}
return locations;
}
private boolean locationExists(TemplateLocation location) {
return ();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
-
@Configuration这是个配置类
-
@ConditionalOnClass({ , })
当 classpath 下存在 以及 FreeMarkerConfigurationFactory 时,配置才会生效,也就是说当我们引入了 Freemarker 之后,配置就会生效。你也可以理解为加了相关依赖。 -
@Import({ , , })
在web环境中,,不在web环境中,本地的。
但是这个FreeMarkerAutoConfiguration 自动化配置只做了模板位置检查。
因为这里不是在本地中使用FreeMarker,而是在Web环境中使用,所以配置是导入到了FreeMarkerServletWebConfiguration这个配置中
@Configuration
@ConditionalOnWebApplication(type = )
@ConditionalOnClass({ , })
@AutoConfigureAfter()
class FreeMarkerServletWebConfiguration extends AbstractFreeMarkerConfiguration {
protected FreeMarkerServletWebConfiguration(FreeMarkerProperties properties) {
super(properties);
}
@Bean
@ConditionalOnMissingBean()
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
applyProperties(configurer);
return configurer;
}
@Bean
public freeMarkerConfiguration(FreeMarkerConfig configurer) {
return ();
}
@Bean
@ConditionalOnMissingBean(name = "freeMarkerViewResolver")
@ConditionalOnProperty(name = "", matchIfMissing = true)
public FreeMarkerViewResolver freeMarkerViewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
getProperties().applyToMvcViewResolver(resolver);
return resolver;
}
@Bean
@ConditionalOnEnabledResourceChain
@ConditionalOnMissingFilterBean()
public FilterRegistrationBean<ResourceUrlEncodingFilter> resourceUrlEncodingFilter() {
FilterRegistrationBean<ResourceUrlEncodingFilter> registration = new FilterRegistrationBean<>(
new ResourceUrlEncodingFilter());
(, );
return registration;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- @Configuration这是个配置类
2.@ConditionalOnWebApplication 表示当前配置在 web 环境下才会生效。
表示当前配置在存在 Servlet 和 FreeMarkerConfigurer 时才会生效。
4.@AutoConfigureAfter 表示当前自动化配置在 WebMvcAutoConfiguration 之后完成。
freeMarkerConfigurer方法分析
那么我们来看这个applyProperties
protected void applyProperties(FreeMarkerConfigurationFactory factory) {
(());
(());
(());
Properties settings = new Properties();
(());
(settings);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这里的applyProperties的参数是一个FreeMarkerConfigurationFactory
而我们传过来的是FreeMarkerConfigurer,查看它们的继承关系
在applyProperties中,通过在FreeMarkerConfigurationFactory中,从配置文件中获取配置信息来进行装配的。
FreeMarkerConfigurer 是 Freemarker 的一些基本配置,例如 templateLoaderPath、defaultEncoding 等
freeMarkerViewResolver方法分析
@Bean
@ConditionalOnMissingBean(name = "freeMarkerViewResolver")
@ConditionalOnProperty(name = "", matchIfMissing = true)
public FreeMarkerViewResolver freeMarkerViewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
getProperties().applyToMvcViewResolver(resolver);
return resolver;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- @ConditionalOnMissingBean(name = “freeMarkerViewResolver”)
在不存在freeMarkerViewResolver这个对象时有效
2。@ConditionalOnProperty(prefix = “rest”, name = “auth-open”, havingValue = “true”, matchIfMissing = true)
prefix 配置的前缀
name 属性是从配置文件中读取属性值
havingValue 配置读取的属性值跟havingValue做比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效
matchIfMissing = true表示如果没有在设置该属性,则默认为条件符合
意思就是在等配置文件中如果没有配置视图解析器,就默认这个配置类生效
则是视图解析器的基本配置,包含了viewClass、suffix、allowRequestOverride、allowSessionOverride 等属性。
FreeMarkerServletWebConfiguration的构造方法
protected FreeMarkerServletWebConfiguration(FreeMarkerProperties properties) {
super(properties);
}
- 1
- 2
- 3
- 4
查看FreeMarkerProperties 这个类
@ConfigurationProperties(prefix = "")
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";
/**
* Well-known FreeMarker keys which are passed to FreeMarker's Configuration.
*/
private Map<String, String> settings = new HashMap<>();
/**
* Comma-separated list of template paths.
*/
private String[] templateLoaderPath = new String[] { DEFAULT_TEMPLATE_LOADER_PATH };
/**
* Whether to prefer file system access for template loading. File system access
* enables hot detection of template changes.
*/
private boolean preferFileSystemAccess = true;
public FreeMarkerProperties() {
super(DEFAULT_PREFIX, DEFAULT_SUFFIX);
}
public Map<String, String> getSettings() {
return ;
}
public void setSettings(Map<String, String> settings) {
= settings;
}
public String[] getTemplateLoaderPath() {
return ;
}
public boolean isPreferFileSystemAccess() {
return ;
}
public void setPreferFileSystemAccess(boolean preferFileSystemAccess) {
= preferFileSystemAccess;
}
public void setTemplateLoaderPath(String... templateLoaderPaths) {
= templateLoaderPaths;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
看到这个类的很多东西是不是很眼熟了?
这里的类名都是看到类名就知道它的作用的,就不一一去说了,太多废话了。
在 SSM 的 XML 文件中配置 Freemarker ,也是配置这些东西。只不过这些配置在SpringBoot中有自动装配类 FreeMarkerServletWebConfiguration 帮我们完成了。