freemarker模板加载器

来源:互联网 发布:淘宝店店主的工作经验 编辑:程序博客网 时间:2024/05/15 16:53


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

在某种情况下,我们可能会希望把模版文件的源码进行加密处理,例如我们使用 DES 加密方式将模版源文件加密后进行存储,然后我们通过自行实现一个加密的模版文件加载器来读取这些模版文件,解密后交给 FreeMarker 引擎解释执行并得到执行的结果。 FreeMarker 为模版文件加载器定义了一个统一的接口 —— TemplateLoader ,该接口有以下四个方法:

closeTemplateSource关闭模版资源findTemplateSource根据名称返回指定的模版资源getLastModified返回模版资源最后一次修改的时间getReader返回读取模版资源的 Reader

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

FreeMarker 自带的几个 TemplateLoader 分别是:

  1. ClassTemplateLoader :基于类路径的模版加载器
  2. FileTemplateLoader :基于文件目录的模版加载器
  3. MultiTemplateLoader :多种加载器的混合
  4. StringTemplateLoader :基于字符串的模版加载器
  5. URLTemplateLoader :基于 URL 的模版加载器
  6. WebappTemplateLoader :基于 Web 上下文的模版加载器

重载模版加载器后通过下面代码使之生效:

cfg.setTemplateLoader(loader)

模板加载器:模板加载器是加载基于抽象模板路径下,比如"index.ftl"或"products/catalog.ftl"的原生文本数据对象。这由具体的模板加载器对象来确定它们取得请求数据时使用了什么样的数据来源(文件夹中的文件,数据等等)。当调用cfg.getTemplate(这里的cfg就是Configuration实例)时,FreeMarker询问模板加载器是否已经为cfg建立返回给定模板路径的文本,之后FreeMarker解析文本生成模板。

4.1、内建模板加载器

在Configuration中可以使用下面的方法来方便建立三种模板加载。(每种方法都会在其内部新建一个模板加载器对象,然后创建Configuration实例来使用它。)

void setDirectoryForTemplateLoading(File dir);

void setClassForTemplateLoading(Class cl, String prefix);

void setServletContextForTemplateLoading(Object servletContext, String path);

上述的第一种方法在磁盘的文件系统上设置了一个明确的目录,它确定了从哪里加载模板。不要说可能,File参数肯定是一个存在的目录。否则,将会抛出异常。 第二种调用方法使用了一个Class类型的参数和一个前缀。这是让你来指定什么时候通过相同的机制来加载模板,不过是用Java的ClassLoader来加载类。这就意味着传入的Class参数会被用来调用Class.getResource()方法来找到模板。参数prefix是给模板的名称来加前缀的。在实际运行的环境中,类加载机制是首选用来加载模板的方法,因为通常情况下,从类路径下加载文件的这种机制,要比从文件系统的特定目录位置加载安全而且简单。在最终的应用程序中,所有代码都使用.jar文件打包也是不错的,这样用户就可以直接执行包含所有资源的.jar文件了。 第三种调用方式需要Web应用的上下文和一个基路径作为参数,这个基路径是Web应用根路径(WEB-INF目录的上级目录)的相对路径。那么加载器将会从Web应用目录开始加载模板。尽管加载方法对没有打包的.war文件起作用,因为它使用了ServletContext.getResource()方法来访问模板,注意这里我们指的是“目录”。如果忽略了第二个参数(或使用了””),那么就可以混合存储静态文件(.html,.jpg等)和.ftl文件,只是.ftl文件可以被送到客户端执行。当然必须在WEB-INF/web.xml中配置一个Servlet来处理URI格式为*.ftl的用户请求,否则客户端无法获取到模板,因此你将会看到Web服务器给出的秘密提示内容。在站点中不能使用空路径,这将成为一个问题,你应该在WEB-INF目录下的某个位置存储模板文件,这样模板源文件就不会偶然地被执行到,这种机制对servlet应用程序来加载模板来说,是非常好用的方式,而且模板可以自动更新而不需重启Web应用程序,但是对于类加载机制,这样就行不通了。

4.2、从多个位置加载模板

如果需要从多个位置加载模板,那就不得不为每个位置都实例化模板加载器对象,将它们包装到一个被称为MultiTemplateLoader的特殊模板加载器,最终将这个加载器传递给Configuration对象的setTemplateLoader(TemplateLoader loader)方法。下面给出一个使用类加载器从两个不同位置加载模板的示例:

import freemarker.cache.*; // 模板加载器在这个包下...FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates")); FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates")); ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), ""); TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl }; MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); cfg.setTemplateLoader(mtl);

现在,FreeMarker将会尝试从/tmp/templates目录加载模板,如果在这个目录下没有发现请求的模板,它就会继续尝试从/usr/data/templates目录下加载,如果还是没有发现请求的模板,那么它就会使用类加载器来加载模板。

4.3、从其他资源加载模板

如果内建的类加载器都不适合使用,那么就需要来编写自己的类加载器了,这个类需要实现freemarker.cache.TemplateLoader接口,然后将它传递给Configuration对象的setTemplateLoader(TemplateLoader loader)方法。

如果你的模板需要通过URL访问其他模板,那么就不需要实现TemplateLoader接口了,可以选择子接口freemarker.cache.URLTemplateLoader来替代,只需实现URL getURL(String templateName)方法即可。

1 0
原创粉丝点击