freemarker 通过 URL 获取模板文件导出

发布时间 2023-08-10 13:19:02作者: colin220

通过远程模板文件导出 word 或其他格式文件。
示例是 Spring Boot 整合 freemarker。

添加 freemarker 依赖

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>

继承 URLTemplateLoader

创建一个名为 MyURLTemplateLoader 的类,继承 freemarker.cache.URLTemplateLoader 类。用于从远程获取模板文件的信息。

public class MyURLTemplateLoader extends URLTemplateLoader {

    private String remotePath;

    @Override
    protected URL getURL(String name) {
        URL url = null;
        try {
            url = new URL(remotePath + name);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return url;
    }

    public String getRemotePath() {
        return remotePath;
    }

    public void setRemotePath(String remotePath) {
        this.remotePath = remotePath;
    }

}

输出文件

通过模板文件输出到文件流。

@Component
public class FreemarkerHeplerImpl {

    private Configuration configuration = null;

    @PostConstruct
    void init() {
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        MyURLTemplateLoader templateLoader = new MyURLTemplateLoader();
        templateLoader.setRemotePath("http://www.aaa.com/");
        configuration.setTemplateLoader(templateLoader);
    }

    /**
     * 生成文档到相应流
     * 
     * @param dataModel    数据模型
     * @param out          输出流
     * @param templateName 模板名称
     */
    public void generate(Object dataModel, OutputStream out, String templateName) {
        Template template = null;
        try {
            template = configuration.getTemplate(templateName, Locale.CHINA, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
            template.process(dataModel, writer);
        } catch (TemplateException | IOException e) {
            e.printStackTrace();
        }
    }

}

通过这种方式生成文档时,freemarker 会在模板文件名上加上国际化信息,例如传参 templateName(模板名)为 aaa.ftl,但是 freemarker 会在查找时变成 aaa_zh.ftl。在命名模板名时主要加上国际化后缀。

生成文件示例

调用上面的方法生成 word 文件到输出流。

// 生成 word 文件
String templateName = "t1.ftl";
ServletOutputStream out = null;
try {
    out = response.getOutputStream();
} catch (IOException e) {
    e.printStackTrace();
}

String fileName = "t1.docx";
try {
    fileName = URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    
}
response.setContentType("application/msword");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

freemarkerHepler.generate(dataModel, out, templateName);

部分内容参考网上文章。