blob: b6829f2a6589471f0c99012477c6301c61596c79 [file] [log] [blame]
<!doctype html>
<!-- Generated by FreeMarker/Docgen from DocBook -->
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>Template loading - FreeMarker Manual</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="FreeMarker Manual">
<meta property="og:title" content="Template loading">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="http://example.com/pgui_config_templateloading.html">
<link rel="canonical" href="http://example.com/pgui_config_templateloading.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1594338517553">
</head>
<body itemscope itemtype="https://schema.org/Code">
<meta itemprop="url" content="http://example.com/">
<meta itemprop="name" content="FreeMarker Manual">
<!--[if lte IE 9]>
<div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please use a modern browser to view this website.</div>
<![endif]--><div class="header-top-bg"><div class="site-width header-top"><a class="logo" href="http://example.com" role="banner"> <img itemprop="image" src="logo.png" alt="My Logo">
</a></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">FreeMarker Manual</a><div class="navigation-header"></div></div><div class="site-width breadcrumb-row"><ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui.html"><span itemprop="name">Programmer&#39;s Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_config.html"><span itemprop="name">The Configuration</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_config_templateloading.html"><span itemprop="name">Template loading</span></a></li></ul><div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul class="bookmark-list"><li><a href="alphaidx.html">Index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="ref.html">Reference</a></li><li><a href="app_faq.html">FAQ</a></li><li><a href="preface.html#test_target">Bőregér</a></li></ul></div></div></div> <div class="main-content site-width">
<div class="content-wrapper no-toc">
<div id="table-of-contents-wrapper" class="col-left">
</div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="pgui_config_settings.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_config_errorhandling.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="pgui_config_templateloading" itemprop="headline">Template loading</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_38" data-menu-target="autoid_38">Template loaders</a><ul><li><a class="page-menu-link" href="#autoid_39" data-menu-target="autoid_39">Built-in template loaders</a></li><li><a class="page-menu-link" href="#autoid_40" data-menu-target="autoid_40">Loading templates from multiple locations</a></li><li><a class="page-menu-link" href="#autoid_41" data-menu-target="autoid_41">Loading templates from other sources</a></li><li><a class="page-menu-link" href="#autoid_42" data-menu-target="autoid_42">The template path</a></li></ul></li><li><a class="page-menu-link" href="#pgui_config_templateloading_caching" data-menu-target="pgui_config_templateloading_caching">Template caching</a></li></ul> </div>
<h2 class="content-header header-section2" id="autoid_38">Template loaders</h2>
<p>Template loaders are objects that load raw textual data based
on abstract template paths like <code class="inline-code">&quot;index.ftl&quot;</code> or
<code class="inline-code">&quot;products/catalog.ftl&quot;</code>. It is up to the concrete
template loader object what source does it use to fetch the
requested data (files in a directory, data base, etc.). When you
call <code class="inline-code">cfg.getTemplate</code> (where
<code class="inline-code">cfg</code> is a <code class="inline-code">Configuration</code>
instance), FreeMarker ask the template loader you have set up for
the <code class="inline-code">cfg</code> to return the text for the given template
path, and then FreeMarker parses that text as template.</p>
<h3 class="content-header header-section3" id="autoid_39">Built-in template loaders</h3>
<p>You can set up three template loading methods in the
<code class="inline-code">Configuration</code> using the following convenience
methods. (Each method will create a template loader object
internally and set up the <code class="inline-code">Configuration</code>
instance to use that.)</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">void setDirectoryForTemplateLoading(File dir);</pre></div>
<p>or</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">void setClassForTemplateLoading(Class cl, String prefix);</pre></div>
<p>or</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">void setServletContextForTemplateLoading(Object servletContext, String path);</pre></div>
<p>The first method above sets an explicit directory on the
file system from which to load templates. Needless to say perhaps,
the <code class="inline-code">File</code> parameter must be an existing
directory. Otherwise, an exception will be thrown.</p>
<p>The second call takes a <code class="inline-code">Class</code> as a
parameter and a prefix. This is for when you want to load
templates via the same mechanism that a java
<code class="inline-code">ClassLoader</code> uses to load classes. This means
that the class you pass in will be used to call
<code class="inline-code">Class.getResource()</code> to find the templates. The
<code class="inline-code">prefix</code> parameter is prepended to the name of
the template. The classloading mechanism will very likely be the
preferred means of loading templates for production code, since
loading from the classpath mechanism is usually more foolproof
than specifying an explicit directory location on the file system.
It is also nicer in a final application to keep everything in a
<code class="inline-code">.jar</code> file that the user can simply execute
directly and have all the icons and text and everything else
inside the <code class="inline-code">.jar</code> file.</p>
<p>The third call takes the context of your web application,
and a base path, which is interpreted relative to the web
application root directory (that&#39;s the parent of the
<code class="inline-code">WEB-INF</code> directory). This loader will load the
templates from the web application directory. Note that we refer
to &quot;directory&quot; here although this loading method works even for
unpacked <code class="inline-code">.war</code> files since it uses
<code class="inline-code">ServletContext.getResource()</code> to access the
templates. If you omit the second parameter (or use
<code class="inline-code">&quot;&quot;</code>), you can simply store the static files
(<code class="inline-code">.html</code>, <code class="inline-code">.jpg</code>, etc.) mixed
with the <code class="inline-code">.ftl</code> files, just
<code class="inline-code">.ftl</code> files will be sent to the client
processed. Of course, you must set up a Servlet for the
<code class="inline-code">*.ftl</code> uri-pattern in
<code class="inline-code">WEB-INF/web.xml</code> for this, otherwise the client
will get the templates as is, and thus may see confidential
content! You should not use empty path if this is a problem for
your site, rather you should store the templates somewhere inside
the <code class="inline-code">WEB-INF</code> directory, so the raw templates are
never served accidentally. This mechanism will very likely be the
preferred means of loading templates for servlet applications,
since the templates can be updated without restarting the web
application, while this often doesn&#39;t work with the class-loader
mechanism.</p>
<h3 class="content-header header-section3" id="autoid_40">Loading templates from multiple locations</h3>
<p>If you need to load templates from multiple locations, you
have to instantiate the template loader objects for every
location, wrap them into a special template loader named
<code class="inline-code">MultiTemplateLoader</code> and finally pass that
loader to the <code class="inline-code">setTemplateLoader(TemplateLoader
loader)</code> method of <code class="inline-code">Configuration</code>.
Here&#39;s an example for loading templates from two distinct
directories and with the class-loader:</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">import freemarker.cache.*; // template loaders live in this package
<em>...</em>
FileTemplateLoader ftl1 = new FileTemplateLoader(new File(&quot;/tmp/templates&quot;));
FileTemplateLoader ftl2 = new FileTemplateLoader(new File(&quot;/usr/data/templates&quot;));
ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), &quot;&quot;);
TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl };
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
cfg.setTemplateLoader(mtl);</pre></div>
<p>Now FreeMarker will try to load templates from
<code class="inline-code">/tmp/templates</code> directory, and if it does not
find the requested template there, it will try to load that from
<code class="inline-code">/usr/data/templates</code>, and if it still does not
find the requested template, then it tries to load that with the
class-loader.</p>
<h3 class="content-header header-section3" id="autoid_41">Loading templates from other sources</h3>
<p>If none of the built-in class loaders are good for you, you
will have to write your own class that implements the
<code class="inline-code">freemarker.cache.TemplateLoader</code> interface and
pass it to the <code class="inline-code">setTemplateLoader(TemplateLoader
loader)</code> method of <code class="inline-code">Configuration</code>.
Please read the API JavaDoc for more information.</p>
<p>If your template source accesses the templates through an
URL, you needn&#39;t implement a <code class="inline-code">TemplateLoader</code>
from scratch; you can choose to subclass
<code class="inline-code">freemarker.cache.URLTemplateLoader</code> instead and
just implement the <code class="inline-code">URL getURL(String
templateName)</code> method.</p>
<h3 class="content-header header-section3" id="autoid_42">The template path</h3>
<p>It is up to the template loader how it interprets template
paths. But to work together with other components there are
restrictions regarding the format of the path. In general, it is
strongly recommended that template loaders use URL-style paths.
The path must not use <code class="inline-code">/</code>, <code class="inline-code">./</code>
and <code class="inline-code">../</code> and <code class="inline-code">://</code> with other
meaning as they have in URL paths (or in UN*X paths). The
characters <code class="inline-code">*</code> and <code class="inline-code">?</code> are
reserved. Also, the template loader must not want paths starting
with <code class="inline-code">/</code>; FreeMarker will never call template
loader with such path. Note that FreeMarker always normalizes the
paths before passing them to the template loader, so the paths do
not contain <code class="inline-code">/../</code> and such, and are relative to
the imaginary template root directory.</p>
<p>Note that FreeMarker template loading always uses slash (not
backslash) regardless of the host OS.</p>
<h2 class="content-header header-section2" id="pgui_config_templateloading_caching">Template caching</h2>
<p>FreeMarker caches templates (assuming you use the
<code class="inline-code">Configuration</code> methods to create
<code class="inline-code">Template</code> objects). This means that when you call
<code class="inline-code">getTemplate</code>, FreeMarker not only returns the
resulting <code class="inline-code">Template</code> object, but stores it in a
cache, so when next time you call <code class="inline-code">getTemplate</code>
with the same (or equivalent) path, it just returns the cached
<code class="inline-code">Template</code> instance, and will not load and parse
the template file again.</p>
<p>If you change the template file, then FreeMarker will re-load
and re-parse the template automatically when you get the template
next time. However, since checking if the file has been changed can
be time consuming, there is a <code class="inline-code">Configuration</code> level
setting called ``update delay&#39;&#39;. This is the time that must elapse
since the last checking for a newer version of a certain template
before FreeMarker will check that again. This is set to 5 seconds by
default. If you want to see the changes of templates immediately,
set it to 0. Note that some template loaders may have problems with
template updating. For example, class-loader based template loaders
typically do not notice that you have changed the template
file.</p>
<p>A template will be removed from the cache if you call
<code class="inline-code">getTemplate</code> and FreeMarker realizes that the
template file has been removed meanwhile. Also, if the JVM thinks
that it begins to run out of memory, by default it can arbitrarily
drop templates from the cache. Furthermore, you can empty the cache
manually with the <code class="inline-code">clearTemplateCache</code> method of
<code class="inline-code">Configuration</code>.</p>
<p>The actual strategy of when a cached template should be thrown
away is pluggable with the <code class="inline-code">cache_storage</code> setting,
by which you can plug any <code class="inline-code">CacheStorage</code>
implementation. For most users
<code class="inline-code">freemarker.cache.MruCacheStorage</code> will be
sufficient. This cache storage implements a two-level Most Recently
Used cache. In the first level, items are strongly referenced up to
the specified maximum (strongly referenced items can&#39;t be dropped by
the JVM, as opposed to softly referenced items). When the maximum is
exceeded, the least recently used item is moved into the second
level cache, where they are softly referenced, up to another
specified maximum. The size of the strong and soft parts can be
specified with the constructor. For example, set the size of the
strong part to 20, and the size of soft part to 250:</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250))</pre></div>
<p>Or, since <code class="inline-code">MruCacheStorage</code> is the default
cache storage implementation:</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">cfg.setSetting(Configuration.CACHE_STORAGE_KEY, &quot;strong:20, soft:250&quot;);</pre></div>
<p>When you create a new <code class="inline-code">Configuration</code> object,
initially it uses an <code class="inline-code">MruCacheStorage</code> where
<code class="inline-code">maxStrongSize</code> is 0, and
<code class="inline-code">maxSoftSize</code> is
<code class="inline-code">Integer.MAX_VALUE</code> (that is, in practice,
infinite). But using non-0 <code class="inline-code">maxStrongSize</code> is maybe
a better strategy for high load servers, since it seems that, with
only softly referenced items, JVM tends to cause just higher
resource consumption if the resource consumption was already high,
because it constantly throws frequently used templates from the
cache, which then have to be re-loaded and and re-parsed.</p>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="pgui_config_settings.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_config_errorhandling.html"><span>Next</span></a></div></div></div></div> </div>
</div>
<div class="site-footer"><div class="site-width"><div class="footer-bottom"> <p class="last-generated">
Last generated:
<time itemprop="dateModified" datetime="2020-07-09T23:48:37Z" title="Thursday, July 9, 2020 11:48:37 PM GMT">2020-07-09 23:48:37 GMT</time> </p>
<p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2020
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a> </p>
</div></div></div></body>
</html>