`

Freemarker源码解析

 
阅读更多
FreeMarker 自定义模版文件加载器

       模版文件加载器用来告诉 FreeMarker 引擎到什么地方去加载模版文件。 FreeMarker 自带了三种文件加载器,分别是:文件目录加载器、类路径加载器以及 Web 上下文加载器。当在 Web 环境中使用 FreemarkerServlet 来加载模版文件时,默认使用第三种加载器,并通过 Servlet 的配置 TemplatePath 来指定模版文件所存放的路径,该路径是相对于 Web 的根目录的。

       在某种情况下,我们可能会希望把模版文件的源码进行加密处理,例如我们使用 DES 加密方式将模版源文件加密后进行存储,然后我们通过自行实现一个加密的模版文件加载器来读取这些模版文件,解密后交给 FreeMarker 引擎解释执行并得到执行的结果。 FreeMarker 为模版文件加载器定义了一个统一的接口 —— TemplateLoader ,该接口有以下四个方法:closeTemplateSource 关闭模版资源
findTemplateSource 根据名称返回指定的模版资源
getLastModified 返回模版资源最后一次修改的时间
getReader 返回读取模版资源的 Reader

      为了简单起见,我们可以在 FreeMarker 自带的加载器上进行扩展,重写 getReader 方法对读取到的模版文件内容进行解密后生成一个新的 Reader 实例并返回(详细过程不再叙述)。

FreeMarker 自带的几个 TemplateLoader 分别是:
//ClassTemplateLoader :基于类路径的模版加载器
//FileTemplateLoader :基于文件目录的模版加载器
//MultiTemplateLoader :多种加载器的混合
//StringTemplateLoader :基于字符串的模版加载器
//URLTemplateLoader :基于 URL 的模版加载器
//WebappTemplateLoader :基于 Web 上下文的模版加载器

//重载模版加载器后通过下面代码使之生效:cfg.setTemplateLoader(loader)

FreeMarker 缓存处理

FreeMarker 的缓存处理主要用于模版文件的缓存,一般来讲,模版文件改动不会很频繁,在一个流量非常大的网站中,如果频繁的读取模版文件对系统的负担还是很重的,因此 FreeMarker 通过将模版文件的内容进行缓存,来降低模版文件读取的频次,降低系统的负载。

当处理某个模版时,FreeMarker 直接从缓存中返回对应的 Template 对象,并有一个默认的机制来保证该模版对象是跟模版文件同步的。如果使用的时候 FreemarkerServlet 时,有一个配置项 template_update_delay 用来指定更新模版文件的间隔时间,相当于多长时间检测一下是否有必要重新加载模版文件,0 表示每次都重新加载,否则为多少毫秒钟检测一下模版是否更改。

FreeMarker 定义了一个统一的缓存处理接口 CacheStorage ,默认的实现是 MruCacheStorage 最近最少使用的缓存策略。一般情况下,很少需要对缓存进行扩展处理。您可以通过下面的代码指定最大缓存的模版数:cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250))

其中第一个参数是最大的强引用对象数,第二个为最大的弱引用对象数。这两个值 FreeMarker 默认的是 0 和 Integer.MAX_VALUE,表明模版缓存数是无限的



freemarker页面数据

基本思路为:利用Struts2对自定义result type的支持,自定义能够生成静态页面的result type,结合模板引擎Freemarker可以实现大批量静态页面的生成。
参看org.apache.struts2.views.freemarker.FreemarkerResult的代码实现,自定义了自己的生成静态页面的result type。

源代码:
 package com.mobilesoft.esales.webapp.action; 
public class FreemarkerResult extends StrutsResultSupport { 
    private static final long serialVersionUID = -3778230771704661631L; 
    protected ActionInvocation invocation;
    protected Configuration configuration;
    protected ObjectWrapper wrapper;
    protected FreemarkerManager freemarkerManager;
    private Writer writer;
    protected String location;
    private String pContentType = “text/html”; 
    protected String fileName; // 要生成的静态页面名称
    protected String filePath; // 要生成的静态页面的路径
    protected String staticTemplate; // 用于生成静态页面Freemarker模板的路径 
    public FreemarkerResult() {
        super();
    } 
    public FreemarkerResult(String location) {
        super(location);
    } 
    @Inject
    public void setFreemarkerManager(FreemarkerManager mgr) {
        this.freemarkerManager = mgr;
    } 
    public void setContentType(String aContentType) {
        pContentType = aContentType;
    } 
    public String getContentType() {
        return pContentType;
    } 
    public void doExecute(String location, ActionInvocation invocation)
            throws IOException, TemplateException {
        this.location = location;
        this.invocation = invocation;
        this.configuration = getConfiguration();
        this.wrapper = getObjectWrapper(); 
        this.fileName = (String) conditionalParse(fileName, invocation);
        this.staticTemplate = (String) conditionalParse(staticTemplate, invocation);
        this.filePath = ((String) conditionalParse(filePath, invocation)) == null ? “”
                : ((String) conditionalParse(filePath, invocation)); 
        if (!location.startsWith(”/”)) {
            ActionContext ctx = invocation.getInvocationContext();
            HttpServletRequest req = (HttpServletRequest) ctx
                    .get(ServletActionContext.HTTP_REQUEST);
            String base = ResourceUtil.getResourceBase(req);
            location = base + “/” + location;
        } 
        //生成html页面的模板类
        Template template = configuration.getTemplate(location, deduceLocale());
        // 生成静态页面的的模板类
        Template staticTemplate = configuration.getTemplate(this.staticTemplate,
                deduceLocale()); 
        TemplateModel model = createModel();
        String path = ServletActionContext.getServletContext().getRealPath(
                filePath)
                + File.separator;
        Writer out = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(path + fileName))); 
        if (preTemplateProcess(template, model)) {
            try {
                staticTemplate.process(model, out);
                template.process(model, getWriter());
            } finally {
                postTemplateProcess(template, model);
                postTemplateProcess(staticTemplate, model);
            }
        }
    } 
    protected Configuration getConfiguration() throws TemplateException {
        return freemarkerManager.getConfiguration(ServletActionContext
                .getServletContext());
    } 
    protected ObjectWrapper getObjectWrapper() {
        return configuration.getObjectWrapper();
    } 
    public void setWriter(Writer writer) {
        this.writer = writer;
    } 
    protected Writer getWriter() throws IOException {
        if (writer != null) {
            return writer;
        }
        return ServletActionContext.getResponse().getWriter();
    } 
    protected TemplateModel createModel() throws TemplateModelException {
        ServletContext servletContext = ServletActionContext
                .getServletContext();
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        ValueStack stack = ServletActionContext.getContext().getValueStack(); 
        Object action = null;
        if (invocation != null)
            action = invocation.getAction(); // Added for NullPointException
        return freemarkerManager.buildTemplateModel(stack, action,
                servletContext, request, response, wrapper);
    } 
    protected Locale deduceLocale() {
        if (invocation.getAction() instanceof LocaleProvider) {
            return ((LocaleProvider) invocation.getAction()).getLocale();
        } else {
            return configuration.getLocale();
        }
    } 
    protected void postTemplateProcess(Template template, TemplateModel data)
            throws IOException {
    } 
    protected boolean preTemplateProcess(Template template, TemplateModel model)
            throws IOException {
        Object attrContentType = template.getCustomAttribute(”content_type”); 
        if (attrContentType != null) {
            ServletActionContext.getResponse().setContentType(
                    attrContentType.toString());
        } else {
            String contentType = getContentType(); 
            if (contentType == null) {
                contentType = “text/html”;
            } 
            String encoding = template.getEncoding(); 
            if (encoding != null) {
                contentType = contentType + “; charset=” + encoding;
            } 
            ServletActionContext.getResponse().setContentType(contentType);
        } 
        return true;
    } 
    public String getFileName() {
        return fileName;
    } 
    public void setFileName(String fileName) {
        this.fileName = fileName;
    } 
    public String getFilePath() {
        return filePath;
    } 
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    } 
    public String getStaticTemplate() {
        return staticTemplate;
    } 
    public void setStaticTemplate(String staticTemplate) {
        this.staticTemplate = staticTemplate;
    }
}

2、struts.xml
源代码
 <action name=”staticViewAction” class=”com.mobilesoft.esales.webapp.action.StaticViewtAction”>
            <result name=”success” type=”staticview”>
                <param name=”location”>test/freemarkertest.ftl</param>
                <param name=”contentType”>text/html</param>
                 <param name=”fileName”>${filename}</param>
                <param name=”staticTemplate”>test/freemarkertest.ftl</param>
                <param name=”filePath”>static</param>
            </result>                    
 </action>

分享到:
评论

相关推荐

    Freemarker原理解析

    3. **创建FreeMarker模板文件解析器类**: 如`FreeMarkerUtil.java`,这是一个工具类,用于处理模板解析和数据合并。这个类会加载配置,指定模板文件的路径,加载模板,设置编码,然后调用`process()`方法将数据...

    SpringDataJpa整合FreeMarker源码样例

    《SpringDataJpa整合FreeMarker源码解析》 在当今的软件开发中,Spring Boot、Spring Data JPA和FreeMarker的整合已经成为了构建高效、简洁Web应用的常见选择。本篇将深入探讨如何将这三个强大的工具结合在一起,...

    Freemarker原理解析.rar_FreeMarker 源码_freamarker原理_freemarker_freemar

    本资料主要对Freemarker的实现原理进行了深入的源码解析。 在理解Freemarker的工作原理前,首先要明确其基本概念。Freemarker是一个基于模板的语言(Template Language),模板是纯文本文件,其中包含了静态文本和...

    freemarker源码.rar

    这个"freemarker源码.rar"文件包含了Freemarker的源代码,对于想要深入了解其内部工作原理或者进行二次开发的开发者来说,是一份宝贵的资料。 源码分析通常包括以下几个方面: 1. **模板语言解析**:Freemarker...

    freemarker 源码、中文API、 freemarker Myeclipse 编辑器

    通过阅读源码,开发者可以深入理解Freemarker内部的工作机制,比如模板解析、变量替换、数据模型绑定等过程。这对于想要定制或者优化Freemarker功能的高级开发者来说尤其有用。同时,源码也是学习软件设计模式和最佳...

    freemarker java解析依赖工具类.zip

    Freemarker是一个强大的模板引擎,它在Java世界中被广泛用于生成动态HTML、XML或其他文本格式...通过学习和使用这些源码和工具类,你可以更深入地掌握Freemarker的工作方式,从而更好地利用它为你的项目生成动态内容。

    struts+freemarker 源码例

    在"struts+freemarker 源码例"这个项目中,我们可能看到的是一个实际运行的示例,它展示了如何在Struts框架中集成并使用FreeMarker作为视图层技术。下面我们将深入探讨这两个技术以及它们之间的协作。 首先,Struts...

    freemarker 源码及文档

    通过阅读源码,开发者可以了解到Freemarker如何解析模板、执行表达式、处理变量和指令、以及如何与Java对象模型交互等核心机制。例如,`freemarker.template`包下的`Template`类是处理模板的核心,`Configuration`类...

    freemarker-2.3.8源码

    5. **模板解析(Template Parsing)**:源码中会包含Freemarker如何解析模板文件,将其转化为抽象语法树(AST)的过程。 6. **模板执行(Template Execution)**:Freemarker通过`Template`类来执行模板,将数据...

    FreeMarker 解析后缀名文件

    在本篇文章中,我们将深入探讨FreeMarker的工作原理、使用方法以及它在解析后缀名文件时的角色。 1. **FreeMarker的基本概念** - **模板**: FreeMarker的工作核心是模板文件,通常以`.ftl`(FreeMarker Template ...

    基于Java语言的freeMarker模板引擎设计源码解析与优化

    该项目深入解析并优化了基于Java语言的FreeMarker模板引擎,源码包含24个文件,其中包括12个Java源文件、4个FTL模板文件、3个XML配置文件、2个属性文件以及其他类型文件。项目结构清晰,旨在提升模板引擎的性能与...

    struts2sitemesh-freemarker 源码

    FreeMarker变量通常是从Action传递过来的数据,通过${}表达式在模板中被解析和渲染。 4. **整合与配置**:在源码中,你会看到`struts-plugin.xml`文件,这是Struts2的插件配置,用于集成Sitemesh。同时,Sitemesh的...

    spring mvc、hibernate、freemarker开源项目源码下载

    FreeMarker 的源码则会揭示模板引擎如何解析模板,如何处理数据模型,以及生成最终输出的过程。 此外,通过分析源码,还可以了解到这三者之间如何协同工作,例如 Spring MVC 如何与 Hibernate 集成,实现数据的持久...

    freemarker 自定义freeMarker标签

    FreeMarker提供了详细的日志输出,通过调整日志级别,你可以查看模板解析、执行的详细信息,这对于查找问题非常有用。 最后,关于标签的性能考虑,应避免在自定义标签中执行耗时操作,因为这会影响模板的渲染速度。...

    spring与freemarker整合 示例源码

    在IT行业中,Spring框架是Java应用开发中的一个核心组件,它提供了一个全面的编程...通过这个示例源码,你可以了解到Spring与Freemarker整合的具体实现,以及在实际项目中如何运用这一组合来构建高效、灵活的Web应用。

    jforum说明文档 源码解析 单点登录 jforum缓存

    在深入理解Jforum的过程中,源码解析是至关重要的一步。 **源码解析** Jforum的源码结构清晰,采用MVC(模型-视图-控制器)设计模式,使得代码维护和扩展变得容易。主要的组成部分包括: 1. **模型层(Model)**:...

    freemarker导出word

    本话题主要探讨如何借助Freemarker技术来实现Word文档的导出,并结合生成二维码图片以及批量生成Word文档的方法。 首先,让我们深入理解Freemarker的工作原理。Freemarker是一个基于模板的语言,它与Java代码分离,...

    freemarker 2.3.13 源码

    5. **模板解析与编译**:源码会展示Freemarker如何解析模板文件,将其转换为抽象语法树(AST),然后编译成Java字节码。这个过程是Freemarker性能的关键,理解这一部分能帮助优化模板执行效率。 6. **指令与宏**:...

    freemarker2.3源码以及build之后的(包含build所需jar包)

    源代码是学习任何软件内部工作原理的最佳资源,通过对源码的阅读和分析,我们可以了解Freemarker如何处理模板,如何生成动态内容,以及其内部的数据模型和模板语言机制。 Freemarker 2.3是该模板引擎的一个早期版本...

Global site tag (gtag.js) - Google Analytics