freemark获取context方法(spring3.0)

设置ftl的目录/WEB-INF/ftl

 

新建文件taglibs.ftl内容

<#macro basePath><#if springMacroRequestContext.getContextPath()=="/"><#else>${springMacroRequestContext.getContextPath()}</#if></#macro>
<#global contextPath><@basePath/></#global>

这句就是精华

 

在你的ftl文件中引入

<#import "/spring.ftl" as spring />
<#include "/common/taglibs.ftl" />

 

注意: <#macro basePath> 这段判断了没有项目跟目录的情况,  例如只有个  /  这种场景,

只要在其它文件里   ${contextPath}     就可以获取根目录了。  跟重要的是taglibs.ftl里可以引入更多的 tag   例如struts    tld  样式公用jquery.js等东西。

网上说了很多方式在ftl里用  ${request.conextPath}   ${Request.conextPath} 之类的我试了都没有作用

我觉得应该用springMacroRequestContext来读取request的方法, 不是获取属性值哦。

除此之外还可以定义宏   用import的方式导入文件

另外我附上spring.ftl    希望可以对您理解在freemark里使用spring标签有所帮助

 

 


 

 <#ftl strip_whitespace=true>
<#--
 * spring.ftl
 *
 * This file consists of a collection of FreeMarker macros aimed at easing
 * some of the common requirements of web applications - in particular
 * handling of forms.
 *
 * Spring's FreeMarker support will automatically make this file and therefore
 * all macros within it available to any application using Spring's
 * FreeMarkerConfigurer.
 *
 * To take advantage of these macros, the "exposeSpringMacroHelpers" property
 * of the FreeMarker class needs to be set to "true". This will expose a
 * RequestContext under the name "springMacroRequestContext", as needed by
 * the macros in this library.
 *
 * @author Darren Davison
 * @author Juergen Hoeller
 * @since 1.1
 -->

<#--
 * message
 *
 * Macro to translate a message code into a message.
 -->
<#macro message code>${springMacroRequestContext.getMessage(code)}</#macro>

<#--
 * messageText
 *
 * Macro to translate a message code into a message,
 * using the given default text if no message found.
 -->
<#macro messageText code, text>${springMacroRequestContext.getMessage(code, text)}</#macro>

<#--
 * messageArgs
 *
 * Macro to translate a message code with arguments into a message.
 -->
<#macro messageArgs code, args>${springMacroRequestContext.getMessage(code, args)}</#macro>

<#--
 * messageArgsText
 *
 * Macro to translate a message code with arguments into a message,
 * using the given default text if no message found.
 -->
<#macro messageArgsText code, args, text>${springMacroRequestContext.getMessage(code, args, text)}</#macro>

<#--
 * theme
 *
 * Macro to translate a theme message code into a message.
 -->
<#macro theme code>${springMacroRequestContext.getThemeMessage(code)}</#macro>

<#--
 * themeText
 *
 * Macro to translate a theme message code into a message,
 * using the given default text if no message found.
 -->
<#macro themeText code, text>${springMacroRequestContext.getThemeMessage(code, text)}</#macro>

<#--
 * themeArgs
 *
 * Macro to translate a theme message code with arguments into a message.
 -->
<#macro themeArgs code, args>${springMacroRequestContext.getThemeMessage(code, args)}</#macro>

<#--
 * themeArgsText
 *
 * Macro to translate a theme message code with arguments into a message,
 * using the given default text if no message found.
 -->
<#macro themeArgsText code, args, text>${springMacroRequestContext.getThemeMessage(code, args, text)}</#macro>

<#--
 * url
 *
 * Takes a relative URL and makes it absolute from the server root by
 * adding the context root for the web application.
 -->
<#macro url relativeUrl>${springMacroRequestContext.getContextUrl(relativeUrl)}</#macro>

<#--
 * bind
 *
 * Exposes a BindStatus object for the given bind path, which can be
 * a bean (e.g. "person") to get global errors, or a bean property
 * (e.g. "person.name") to get field errors. Can be called multiple times
 * within a form to bind to multiple command objects and/or field names.
 *
 * This macro will participate in the default HTML escape setting for the given
 * RequestContext. This can be customized by calling "setDefaultHtmlEscape"
 * on the "springMacroRequestContext" context variable, or via the
 * "defaultHtmlEscape" context-param in web.xml (same as for the JSP bind tag).
 * Also regards a "htmlEscape" variable in the namespace of this library.
 *
 * Producing no output, the following context variable will be available
 * each time this macro is referenced (assuming you import this library in
 * your templates with the namespace 'spring'):
 *
 *   spring.status : a BindStatus instance holding the command object name,
 *   expression, value, and error messages and codes for the path supplied
 *
 * @param path : the path (string value) of the value required to bind to.
 *   Spring defaults to a command name of "command" but this can be overridden
 *   by user config.
 -->
<#macro bind path>
    <#if htmlEscape?exists>
        <#assign status = springMacroRequestContext.getBindStatus(path, htmlEscape)>
    <#else>
        <#assign status = springMacroRequestContext.getBindStatus(path)>
    </#if>
    <#-- assign a temporary value, forcing a string representation for any
    kind of variable. This temp value is only used in this macro lib -->
    <#if status.value?exists && status.value?is_boolean>
        <#assign stringStatusValue=status.value?string>
    <#else>
        <#assign stringStatusValue=status.value?default("")>
    </#if>
</#macro>

<#--
 * bindEscaped
 *
 * Similar to spring:bind, but takes an explicit HTML escape flag rather
 * than relying on the default HTML escape setting.
 -->
<#macro bindEscaped path, htmlEscape>
    <#assign status = springMacroRequestContext.getBindStatus(path, htmlEscape)>
    <#-- assign a temporary value, forcing a string representation for any
    kind of variable. This temp value is only used in this macro lib -->
    <#if status.value?exists && status.value?is_boolean>
        <#assign stringStatusValue=status.value?string>
    <#else>
        <#assign stringStatusValue=status.value?default("")>
    </#if>
</#macro>

<#--
 * formInput
 *
 * Display a form input field of type 'text' and bind it to an attribute
 * of a command or bean.
 *
 * @param path the name of the field to bind to
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
 -->
<#macro formInput path attributes="" fieldType="text">
    <@bind path/>
    <input type="${fieldType}" id="${status.expression}" name="${status.expression}" value="<#if fieldType!="password">${stringStatusValue}</#if>" ${attributes}<@closeTag/>
</#macro>

<#--
 * formPasswordInput
 *
 * Display a form input field of type 'password' and bind it to an attribute
 * of a command or bean. No value will ever be displayed. This functionality
 * can also be obtained by calling the formInput macro with a 'type' parameter
 * of 'password'.
 *
 * @param path the name of the field to bind to
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
 -->
<#macro formPasswordInput path attributes="">
    <@formInput path, attributes, "password"/>
</#macro>

<#--
 * formHiddenInput
 *
 * Generate a form input field of type 'hidden' and bind it to an attribute
 * of a command or bean. This functionality can also be obtained by calling
 * the formInput macro with a 'type' parameter of 'hidden'.
 *
 * @param path the name of the field to bind to
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
 -->
<#macro formHiddenInput path attributes="">
    <@formInput path, attributes, "hidden"/>
</#macro>

<#--
 * formTextarea
 *
 * Display a text area and bind it to an attribute of a command or bean.
 *
 * @param path the name of the field to bind to
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
 -->
<#macro formTextarea path attributes="">
    <@bind path/>
    <textarea id="${status.expression}" name="${status.expression}" ${attributes}>${stringStatusValue}</textarea>
</#macro>

<#--
 * formSingleSelect
 *
 * Show a selectbox (dropdown) input element allowing a single value to be chosen
 * from a list of options.
 *
 * @param path the name of the field to bind to
 * @param options a map (value=label) of all the available options
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
-->
<#macro formSingleSelect path options attributes="">
    <@bind path/>
    <select id="${status.expression}" name="${status.expression}" ${attributes}>
        <#if options?is_hash>
            <#list options?keys as value>
            <option value="${value?html}"<@checkSelected value/>>${options[value]?html}</option>
            </#list>
        <#else>
            <#list options as value>
            <option value="${value?html}"<@checkSelected value/>>${value?html}</option>
            </#list>
        </#if>
    </select>
</#macro>

<#--
 * formMultiSelect
 *
 * Show a listbox of options allowing the user to make 0 or more choices from
 * the list of options.
 *
 * @param path the name of the field to bind to
 * @param options a map (value=label) of all the available options
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
-->
<#macro formMultiSelect path options attributes="">
    <@bind path/>
    <select multiple="multiple" id="${status.expression}" name="${status.expression}" ${attributes}>
        <#list options?keys as value>
        <#assign isSelected = contains(status.value?default([""]), value)>
        <option value="${value?html}"<#if isSelected> selected="selected"</#if>>${options[value]?html}</option>
        </#list>
    </select>
</#macro>

<#--
 * formRadioButtons
 *
 * Show radio buttons.
 *
 * @param path the name of the field to bind to
 * @param options a map (value=label) of all the available options
 * @param separator the html tag or other character list that should be used to
 *    separate each option. Typically '&nbsp;' or '<br>'
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
-->
<#macro formRadioButtons path options separator attributes="">
    <@bind path/>
    <#list options?keys as value>
    <#assign id="${status.expression}${value_index}">
    <input type="radio" id="${id}" name="${status.expression}" value="${value?html}"<#if stringStatusValue == value> checked="checked"</#if> ${attributes}<@closeTag/>
    <label for="${id}">${options[value]?html}</label>${separator}
    </#list>
</#macro>

<#--
 * formCheckboxes
 *
 * Show checkboxes.
 *
 * @param path the name of the field to bind to
 * @param options a map (value=label) of all the available options
 * @param separator the html tag or other character list that should be used to
 *    separate each option. Typically '&nbsp;' or '<br>'
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
-->
<#macro formCheckboxes path options separator attributes="">
    <@bind path/>
    <#list options?keys as value>
    <#assign id="${status.expression}${value_index}">
    <#assign isSelected = contains(status.value?default([""]), value)>
    <input type="checkbox" id="${id}" name="${status.expression}" value="${value?html}"<#if isSelected> checked="checked"</#if> ${attributes}<@closeTag/>
    <label for="${id}">${options[value]?html}</label>${separator}
    </#list>
    <input type="hidden" name="_${status.expression}" value="on"/>
</#macro>

<#--
 * formCheckbox
 *
 * Show a single checkbox.
 *
 * @param path the name of the field to bind to
 * @param attributes any additional attributes for the element (such as class
 *    or CSS styles or size
-->
<#macro formCheckbox path attributes="">
 <@bind path />
    <#assign id="${status.expression}">
    <#assign isSelected = status.value?? && status.value?string=="true">
 <input type="hidden" name="_${id}" value="on"/>
 <input type="checkbox" id="${id}" name="${id}"<#if isSelected> checked="checked"</#if> ${attributes}/>
</#macro>

<#--
 * showErrors
 *
 * Show validation errors for the currently bound field, with
 * optional style attributes.
 *
 * @param separator the html tag or other character list that should be used to
 *    separate each option. Typically '<br>'.
 * @param classOrStyle either the name of a CSS class element (which is defined in
 *    the template or an external CSS file) or an inline style. If the value passed in here
 *    contains a colon (:) then a 'style=' attribute will be used, else a 'class=' attribute
 *    will be used.
-->
<#macro showErrors separator classOrStyle="">
    <#list status.errorMessages as error>
    <#if classOrStyle == "">
        <b>${error}</b>
    <#else>
        <#if classOrStyle?index_of(":") == -1><#assign attr="class"><#else><#assign attr="style"></#if>
        <span ${attr}="${classOrStyle}">${error}</span>
    </#if>
    <#if error_has_next>${separator}</#if>
    </#list>
</#macro>

<#--
 * checkSelected
 *
 * Check a value in a list to see if it is the currently selected value.
 * If so, add the 'selected="selected"' text to the output.
 * Handles values of numeric and string types.
 * This function is used internally but can be accessed by user code if required.
 *
 * @param value the current value in a list iteration
-->
<#macro checkSelected value>
    <#if stringStatusValue?is_number && stringStatusValue == value?number>selected="selected"</#if>
    <#if stringStatusValue?is_string && stringStatusValue == value>selected="selected"</#if>
</#macro>

<#--
 * contains
 *
 * Macro to return true if the list contains the scalar, false if not.
 * Surprisingly not a FreeMarker builtin.
 * This function is used internally but can be accessed by user code if required.
 *
 * @param list the list to search for the item
 * @param item the item to search for in the list
 * @return true if item is found in the list, false otherwise
-->
<#function contains list item>
    <#list list as nextInList>
    <#if nextInList == item><#return true></#if>
    </#list>
    <#return false>
</#function>

<#--
 * closeTag
 *
 * Simple macro to close an HTML tag that has no body with '>' or '/>',
 * depending on the value of a 'xhtmlCompliant' variable in the namespace
 * of this library.
-->
<#macro closeTag>
    <#if xhtmlCompliant?exists && xhtmlCompliant>/><#else>></#if>
</#macro>

<think>嗯,用户想了解FreeMarker如何获取远程模板。首先,我需要回忆一下FreeMarker的基本知识。FreeMarker是一个模板引擎,主要用于生成文本输出,比如HTML网页、电子邮件或配置文件。通常,模板是存储在本地文件系统中的,但有时候可能需要从远程位置加载模板,比如HTTP服务器、数据库或者云存储。 接下来,我需要确认FreeMarker是否原生支持远程模板加载。根据记忆,FreeMarker默认的模板加载器是文件系统加载器,也就是从本地目录加载。不过,它的设计允许通过自定义TemplateLoader来扩展模板来源。所以,用户需要自己实现一个TemplateLoader来从远程获取模板。 然后,用户可能需要具体的步骤或示例代码。我应该分步骤说明如何实现自定义的TemplateLoader。首先,继承TemplateLoader接口,实现其中的findTemplateSource、getLastModified、getReader和close方法。在findTemplateSource中,使用HTTP客户端获取远程资源,比如用Java的HttpClient发送GET请求。如果响应成功,就将内容保存到字符串或字节数组中,并返回一个标识符。然后,在getReader方法中,将获取的内容转换为Reader对象,供FreeMarker处理。 此外,需要提到配置FreeMarker使用这个自定义的加载器。通过Configuration对象的setTemplateLoader方法,传入自定义的实例。这样,当调用configuration.getTemplate("远程模板URL")时,就会触发自定义加载器的逻辑。 还要考虑异常处理,比如网络连接失败、资源不存在等情况,应该在findTemplateSource中妥善处理,可能返回null或者抛出异常,具体根据FreeMarker的约定。另外,缓存机制,为了提高性能,可能需要缓存远程模板,避免频繁请求,但需要处理缓存失效的问题,比如根据Last-Modified头或ETag来验证更新。 用户可能会遇到的问题包括网络延迟、认证授权(比如需要API密钥或OAuth)、模板更新同步等。需要提醒用户注意这些方面,并根据实际需求调整实现。例如,在自定义TemplateLoader中添加请求头,处理身份验证,或者设置超时时间。 最后,给出一个简单的示例代码会有帮助。比如,使用Java的HttpClient实现一个HttpTemplateLoader,并在main方法中演示如何配置和使用。同时,说明需要处理的依赖,比如HttpClient的库,如果用户使用Maven,可能需要添加相应的依赖项。 总结一下,步骤应该是:1. 理解FreeMarker的TemplateLoader机制;2. 实现自定义的远程加载器;3. 配置FreeMarker使用该加载器;4. 处理异常和缓存;5. 提供示例代码和注意事项。这样用户就能逐步实现远程模板的获取了。</think>FreeMarker 获取远程模板的实现需要结合其模板加载机制,以下是逐步说明: 1. 核心原理 - FreeMarker 通过`TemplateLoader`接口实现模板加载 - 默认提供文件系统加载器(`FileTemplateLoader`) - 远程加载需要自定义实现该接口 2. 自定义模板加载器步骤 (1) 实现`TemplateLoader`接口 ```java public class RemoteTemplateLoader implements TemplateLoader { private final HttpClient httpClient = HttpClient.newHttpClient(); // 模板源标识方法 public Object findTemplateSource(String name) throws IOException { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(name)) // name即为远程URL .build(); HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); return response.statusCode() == 200 ? response.body() : null; } // 获取最后修改时间(根据远程服务器支持) public long getLastModified(Object templateSource) { return System.currentTimeMillis(); // 需要根据实际响应头处理 } // 获取模板内容读取器 public Reader getReader(Object templateSource, String encoding) { return new StringReader((String) templateSource); } public void closeTemplateSource(Object templateSource) { // 可在此处释放资源 } } ``` 3. 配置使用(需 Java 11+) ```java Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); cfg.setTemplateLoader(new RemoteTemplateLoader()); // 使用示例 Template template = cfg.getTemplate("https://example.com/templates/email.ftl"); ``` 4. 关键注意事项 - 网络超时处理:建议配置合理的连接/读取超时 - 缓存机制:推荐实现模板缓存避免频繁请求 - 错误处理:需处理HTTP 404/500等错误状态 - 认证支持:可扩展支持Basic Auth/OAuth等认证方式 - 编码处理:需正确处理响应字符编码 5. 优化建议 ```java // 可添加的优化项 class CachedRemoteLoader extends RemoteTemplateLoader { private final Cache<String, String> templateCache = CacheBuilder.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .build(); @Override public Object findTemplateSource(String name) throws IOException { String content = templateCache.getIfPresent(name); if(content == null){ content = super.loadFromRemote(name); templateCache.put(name, content); } return content; } } ``` 6. 安全建议 - 启用HTTPS保证传输安全 - 限制可访问的域名白名单 - 对模板内容进行安全扫描 - 设置合理的下载大小限制 实际应用中需要根据具体场景选择实现方式,例如对高频访问的模板建议配合CDN使用,对敏感模板建议增加访问鉴权机制。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值