FreeMarker 生成静态文件(写在磁盘当中)

在 Spring Boot 中使用 FreeMarker 生成静态文件(如 HTML、XML 等)的核心思路是:通过 FreeMarker 模板引擎渲染动态内容后,将结果写入物理文件。以下是完整实现步骤:


在这里插入图片描述

1. 添加依赖 & 基础配置

确保已添加 FreeMarker 依赖(与常规 Web 渲染配置相同):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

application.yml 配置:

spring:
  freemarker:
    template-loader-path: classpath:/templates/
    cache: false  # 开发时关闭缓存
    suffix: .ftl // 指定文件格式 需要以.ftl文件结尾
    charset: UTF-8

2. 核心工具类:生成静态文件

创建一个工具类 StaticFileGenerator,用于封装生成逻辑:

import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import java.io.FileWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

@Component
public class StaticFileGenerator {
	
	// 引入Configuration来操作  FreeMarker 生成静态文件
    private final Configuration freemarkerConfig;

    public StaticFileGenerator(Configuration freemarkerConfig) {
        this.freemarkerConfig = freemarkerConfig;
    }

    /**
     * 生成静态文件
     * @param templateName 模板文件名(如 "post.ftl")
     * @param dataModel    数据模型
     * @param outputPath   输出文件路径(如 "/var/www/html/post-123.html")
     */
    public void generate(String templateName, Map<String, Object> dataModel, String outputPath) {
        try {
            // 获取模板
            Template template = freemarkerConfig.getTemplate(templateName);
            
            // 渲染内容
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, dataModel);
            
            // 写入文件
            Path path = Paths.get(outputPath);
            path.toFile().getParentFile().mkdirs(); // 确保目录存在
            try (FileWriter writer = new FileWriter(path.toFile())) {
                writer.write(content);
            }
            
        } catch (Exception e) {
            throw new RuntimeException("生成静态文件失败: " + e.getMessage(), e);
        }
    }
}

3. 使用场景示例:生成博客文章静态页

场景描述

当用户发布一篇博客时,自动生成对应的静态 HTML 文件(如 post-123.html)。


步骤 1:定义数据模型
// 示例实体类
@Data // Lombok 注解
public class BlogPost {
    private Long id;
    private String title;
    private String content;
    private LocalDateTime createTime;
}

步骤 2:创建 FreeMarker 模板

模板文件 src/main/resources/templates/post.ftl

<!DOCTYPE html>
<html>
<head>
    <title>${post.title}</title>
    <meta charset="UTF-8">
</head>
<body>
    <h1>${post.title}</h1>
    <div class="time">发布时间:${post.createTime?string("yyyy-MM-dd HH:mm")}</div>
    <div class="content">${post.content}</div>
</body>
</html>

步骤 3:在 Service 中调用生成逻辑
@Service
public class BlogService {

    private final StaticFileGenerator staticFileGenerator;

    public BlogService(StaticFileGenerator staticFileGenerator) {
        this.staticFileGenerator = staticFileGenerator;
    }

    public void publishPost(BlogPost post) {
        // 保存到数据库的逻辑(此处省略)...

        // 构建数据模型
        Map<String, Object> dataModel = new HashMap<>();
        dataModel.put("post", post);

        // 生成静态文件(假设输出到项目的 static/posts 目录) 指定的文件目录
        String outputPath = "src/main/resources/static/posts/post-" + post.getId() + ".html";
        staticFileGenerator.generate("post.ftl", dataModel, outputPath);
    }
}

4. 触发生成

通过 Controller 或定时任务触发生成逻辑:

@RestController
@RequestMapping("/posts")
public class BlogController {

    private final BlogService blogService;

    public BlogController(BlogService blogService) {
        this.blogService = blogService;
    }

    @PostMapping
    public ResponseEntity<String> createPost(@RequestBody BlogPost post) {
        blogService.publishPost(post);
        return ResponseEntity.ok("文章发布成功,静态页已生成!");
    }
}

5. 访问静态文件

生成的静态文件默认会被 Spring Boot 识别为静态资源(因为放在 src/main/resources/static 目录下)。
访问地址示例:

http://localhost:8080/posts/post-123.html

关键注意事项

1. 路径配置
  • 输出路径:建议将静态文件生成到独立目录(如 /var/www/html),而非项目资源目录,避免打包后路径混乱。
  • 权限问题:确保应用有权限写入目标目录。
2. 动态更新
  • 模板修改:若修改了模板文件,需重新生成静态文件才能生效。
  • 数据更新:如果数据变更,需重新生成关联的静态文件(或设置版本号机制)。
3. 性能优化
  • 批量生成:对大量文件生成时,可结合线程池提高效率。
  • 缓存控制:生产环境开启 FreeMarker 缓存(spring.freemarker.cache=true)。

高级用法

1. 结合定时任务

使用 @Scheduled 定期生成静态文件(如每日凌晨更新排行榜):

@Scheduled(cron = "0 0 0 * * ?") // 每天凌晨执行
public void generateDailyReport() {
    Map<String, Object> data = reportService.getDailyData();
    staticFileGenerator.generate("report.ftl", data, "/reports/daily-report.html");
}
2. 事件驱动生成

通过 Spring 事件机制,在数据变更时触发生成:

// 定义事件
public class PostPublishedEvent extends ApplicationEvent {
    private final BlogPost post;
    public PostPublishedEvent(Object source, BlogPost post) {
        super(source);
        this.post = post;
    }
    // getter
}

// 发布事件(在 Service 中)
applicationEventPublisher.publishEvent(new PostPublishedEvent(this, post));

// 监听事件
@Component
public class StaticFileGeneratorListener {
    @EventListener
    public void handlePostPublished(PostPublishedEvent event) {
        staticFileGenerator.generate(...);
    }
}

总结

通过 FreeMarker 生成静态文件的核心步骤:

  1. 模板设计:编写 .ftl 模板文件,定义动态占位符和逻辑。
  2. 数据准备:构建与模板匹配的数据模型(Map 或 Java 对象)。
  3. 渲染写入:调用 FreeMarker 渲染模板,将结果写入物理文件。
  4. 访问管理:通过 HTTP 直接访问静态文件或集成到 CDN。

此方案适用于需要预生成静态内容以提高性能的场景(如 SEO 优化、高并发页面)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值