SpringBoot整合FreeMarker&&FreeMarkerAutoConfiguration 自动装配相关源码跟踪分析

时间:2024-10-12 20:40:47

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

在这里插入图片描述

  1. @Configuration这是个配置类

  2. @ConditionalOnClass({ , })
    当 classpath 下存在 以及 FreeMarkerConfigurationFactory 时,配置才会生效,也就是说当我们引入了 Freemarker 之后,配置就会生效。你也可以理解为加了相关依赖。

  3. @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

在这里插入图片描述

  1. @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
  1. @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 帮我们完成了。