Spring Boot 纯FreeMarker模板引擎使用


placeholder image
admin 发布于:2022-05-09 10:20:48
阅读:loading

基本介绍

在Spring Boot项目的页面技术选型可以是JSP,也可以是前面说过的Thymeleaf,同样也可以是FreeMarker等其它模板技术,由于前面的页面编写已经应用了Thymeleaf,所以在页面这一块毫不犹豫的会考虑使用了多年的JSP或Thymeleaf,但是绝不会使用FreeMarker作为页面显示层,只是多年来也算是多次使用FreeMarker作为一些模板去实际应用(作为doc格式的word导出;作为Email邮件发送的富文本等),本站系统功能后期也使用到了邮件发送,所以考虑使用FreeMarker来作为模板动态生成待发送邮件的html文本。

为何在使用Thymeleaf页面模板后,还要使用FreeMarker作为模板技术呢,这点就源于个人对Thymeleaf掌握的深度不够导致,主要是并未掌握在无框架整合的项目环境中使用纯Thymeleaf如何去实现模板页面的访问以及传递数据后模板的数据渲染,强行实现也并非不可能实现,只是需要发送http请求访问Controller转向至页面得到最终的响应页面结果,只不过这种实现还会要考虑一些其它的并发症,所以只是说说而已,还是拿可以被纯Java环境去应用的模板技术FreeMarker来实现。

注意了,由于以及使用Thymeleaf作为页面的模板来使用了,也就是说在pom.xml中导入的时候通过starter的方式来导入了spring-boot-starter-thymeleaf,再导入FreeMarker的时候并不能直接导入通过starter的方式导入spring-boot-starter-freemarker,因为同时导入了两个页面模板的starter可能会存在一些深层次的问题,比如会存在两个自动注入的配置类,如果通过starter导出后个人认为还需要将FreeMarkerAutoConfiguration的自动配置组件排除掉。本次集成FreeMarker只是为普通编程式的Api应用,详细集成过程参考如下:

pom.xml

<!--freemarker-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

FreemarkerConfiguration.java

package cn.chendd.configuration;

import ...;

/**
 * Freemarker配置类
 *
 * @author chendd
 * @date 2022/4/15 22:10
 */
@Configuration
public class FreemarkerConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setDefaultEncoding(StandardCharsets.UTF_8.name());
        configurer.setTemplateLoaderPaths("classpath:/templates/freemarker");
        return configurer;
    }

}

controller定义

package cn.chendd.modules.freemarker.controller;

import ...;

/**
 * Api FreeMarker 启动类排除了FreeMarkerAutoConfiguration
 *
 * @author chendd
 * @date 2022/4/13 11:17
 */
@RestController
@RequestMapping("/freemarker")
@Api(value = "测试 FreeMarker 接口" , tags = {"测试 FreeMarker 接口"})
@ApiSort(10)
public class FreemarkerController {

    @GetMapping("/configurer")
    @ApiOperation(value = "获取freemarker模板路径" , consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperationSupport(order = 10)
    public String[] templateLoaderPaths() throws IllegalAccessException {
        FreeMarkerConfigurer configurer = SpringBeanFactory.getBean(FreeMarkerConfigurer.class);
        Field field = FieldUtils.getField(configurer.getClass(), "templateLoaderPaths", true);
        return (String[]) field.get(configurer);
    }

    @GetMapping("/template")
    @ApiOperation(value = "测试响应 hello 模板" , consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @ApiOperationSupport(order = 20)
    public Map<String , String> template() throws Exception {
        FreeMarkerConfigurer configurer = SpringBeanFactory.getBean(FreeMarkerConfigurer.class);
        Template template = configurer.getConfiguration().getTemplate("hello.html");
        HashMap<String, String> param = Maps.newHashMap();
        param.put("name" , "chendd");
        Map<String , String> result = Maps.newHashMap();
        result.put("template" , template.toString());
        result.put("value" , FreeMarkerTemplateUtils.processTemplateIntoString(template, param));
        return result;
    }

}

swagger输出

image.png

(输出模板路径)

image.png

(输出原始模板内容和解析后的内容)

知识点

(1)源码示例中包含swagger在线访问的简单运行和基于Spring Boot test的Junit运行;

(2)从启动类中排除自带的FreeMarkerAutoConfiguration自动装配,除去自带FreeMarker的各种默认配置,采用自定义FreeMarkerConfigurer配置,设置模板路径(覆盖application.yaml中的配置);

(3)项目源码为在Spring Boot项目环境下,使用Thymeleaf作为视图层页面输出,同时使用FreeMarker做为某些功能的模板输出(纯Java环境代码的简单使用);

(4)特别提醒,部分类使用到了spring-context-support包下的freemarker的view包,本站博客系统由于使用spring-boot-starter-cache中依赖了,当前example系统由core模块单独增加的依赖;

源码下载

源码工程下载可转至https://gitee.com/88911006/chendd-blog-examples项目的Thymeleaf分支;


 点赞


 发表评论

当前回复:作者

 评论列表


留言区