| <!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'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">"index.ftl"</code> or |
| <code class="inline-code">"products/catalog.ftl"</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'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 "directory" 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">""</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'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'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("/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);</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'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''. 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'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, "strong:20, soft:250");</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> |