Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
Apache FreeMarker自定义指令与方法:使用Java代码处理模板参数_创想鸟

Apache FreeMarker自定义指令与方法:使用Java代码处理模板参数

apache freemarker自定义指令与方法:使用java代码处理模板参数

本文深入探讨如何在Apache FreeMarker模板中,通过实现Java的`TemplateDirectiveModel`或`TemplateMethodModelEx`接口,创建自定义逻辑来处理模板参数。我们将详细介绍如何从Java代码中获取模板变量的值,并根据业务需求(例如数值比较和默认值设置)进行处理,从而扩展FreeMarker的动态渲染能力,实现模板与业务逻辑的有效分离。

1. 引言:扩展FreeMarker的Java能力

Apache FreeMarker作为一款强大的模板引擎,以其简洁的模板语言和高效的数据绑定能力广受欢迎。在多数情况下,模板语言自身足以处理数据的展示逻辑。然而,当面对更复杂的业务规则、数据验证、格式化或需要与后端Java服务深度交互的场景时,直接在模板中实现这些逻辑可能导致模板变得臃肿、难以维护。

为了解决这一问题,FreeMarker提供了两种强大的扩展机制:自定义指令(Custom Directives)和自定义方法模型(Custom Method Models)。它们允许开发者将复杂的Java业务逻辑封装起来,并在模板中以简洁、声明式的方式调用。本文将以一个具体的场景为例:判断一个账户号参数accNo是否大于0,若不满足条件(例如小于等于0、为空或非数字),则将其设置为默认值“0000”。

2. 使用自定义指令 TemplateDirectiveModel

2.1 概念与应用场景

TemplateDirectiveModel接口允许开发者创建自定义的FreeMarker指令。这些指令可以像FreeMarker内置指令(如、)一样,控制模板的渲染流程,或者像一个带有副作用的函数一样处理参数并输出内容。它们通常用于生成HTML片段、执行复杂的条件渲染或在模板中触发特定的Java逻辑。

立即学习“Java免费学习笔记(深入)”;

2.2 参数传递与获取

在FreeMarker模板中,自定义指令可以像XML/HTML标签一样使用,并接受命名参数。例如:。

在Java实现中,TemplateDirectiveModel接口的execute方法会接收到一个Map类型的params参数,其中包含了所有传递给指令的命名参数。参数的值是TemplateModel类型,需要根据实际数据类型进行相应的转换。

STORYD STORYD

帮你写出让领导满意的精美文稿

STORYD 137 查看详情 STORYD

示例场景: 我们希望在模板中通过 来处理一个名为accountNumber的模板变量。

2.3 实现步骤与代码示例

创建Java类并实现 TemplateDirectiveModel 接口:在execute方法中,从params获取名为accNo的参数。对获取到的TemplateModel进行类型检查和转换(预期为TemplateNumberModel)。执行业务逻辑:判断数值是否大于0。将处理后的结果通过env.getOut().write()方法写入到模板的输出流中。

import freemarker.core.Environment;import freemarker.template.*;import java.io.IOException;import java.util.Map;/** * 自定义FreeMarker指令,用于处理账户号: * 如果账户号大于0,则输出其值;否则输出"0000"。 */public class AccountNumberDirective implements TemplateDirectiveModel {    @Override    public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)            throws TemplateException, IOException {        // 1. 从params中获取名为"accNo"的参数        TemplateModel accNoModel = (TemplateModel) params.get("accNo");        String processedAccNo = "0000"; // 默认值        // 2. 检查参数类型并执行业务逻辑        if (accNoModel instanceof TemplateNumberModel) {            Number accNo = ((TemplateNumberModel) accNoModel).getAsNumber();            if (accNo != null && accNo.doubleValue() > 0) {                // 如果是有效数字且大于0,则使用其长整型字符串表示                processedAccNo = String.valueOf(accNo.longValue());            }        } else if (accNoModel instanceof TemplateScalarModel) {            // 考虑accNo可能作为字符串传入的情况            String accNoStr = ((TemplateScalarModel) accNoModel).getAsString();            try {                double accNoDouble = Double.parseDouble(accNoStr);                if (accNoDouble > 0) {                    processedAccNo = accNoStr; // 如果字符串是有效数字且大于0,则保留原字符串                }            } catch (NumberFormatException e) {                // 字符串无法解析为数字,保持默认值"0000"            }        }        // 如果accNoModel为null或非数字类型,则保持默认值"0000"        // 3. 将处理结果写入模板输出流        env.getOut().write(processedAccNo);    }}

2.4 FreeMarker模板使用示例

使用自定义指令处理账户号:

  • 账户号1 (12345):
  • 账户号2 (0):
  • 账户号3 (-10):
  • 账户号4 (null):
  • 账户号5 ("abc"):

2.5 注意事项

指令主要用于输出内容或控制渲染流程,不直接返回一个值供模板进行进一步的表达式计算。如果指令不接受参数,但仍需访问模板变量,可以使用env.getVariable(“variableName”)。但这会增加指令与模板数据模型的耦合度,通常不推荐。

3. 使用自定义方法模型 TemplateMethodModelEx

3.1 概念与应用场景

TemplateMethodModelEx接口允许开发者创建自定义的FreeMarker方法。这些方法可以像FreeMarker内置函数(如size()、substring())一样被调用,并返回一个值供模板进一步使用。对于需要计算一个值并将其返回给模板进行后续处理的场景,TemplateMethodModelEx通常是更典型和推荐的选择。

3.2 参数传递与获取

在FreeMarker模板中,自定义方法以函数调用的形式使用,例如 ${myMethod(param1, param2)}。

在Java实现中,TemplateMethodModelEx接口的exec方法会接收到一个List类型的arguments参数,其中包含了所有传递给方法的参数(按顺序)。与指令类似,参数的值也是TemplateModel类型,需要进行相应的类型转换。

示例场景: 我们希望在模板中通过 ${formatAccNo(accountNumber)} 来获取处理后的账户号。

3.3 实现步骤与代码示例

创建Java类并实现 TemplateMethodModelEx 接口:在exec方法中,从arguments列表获取参数(通常是第一个)。执行业务逻辑,判断数值是否大于0。返回一个TemplateModel(如SimpleScalar、SimpleNumber等)作为结果。

import freemarker.template.*;import java.util.List;/** * 自定义FreeMarker方法,用于格式化账户号: * 如果账户号大于0,则返回其字符串值;否则返回"0000"。 */public class AccountNumberMethod implements TemplateMethodModelEx {    @Override    public Object exec(List arguments) throws TemplateModelException {        // 1. 检查参数数量        if (arguments.isEmpty()) {            throw new TemplateModelException("AccountNumberMethod expects at least one argument (accNo).");        }        // 2. 获取第一个参数        TemplateModel accNoModel = (TemplateModel) arguments.get(0);        String processedAccNo = "0000"; // 默认值        // 3. 检查参数类型并执行业务逻辑        if (accNoModel instanceof TemplateNumberModel) {            Number accNo = ((TemplateNumberModel) accNoModel).getAsNumber();            if (accNo != null && accNo.doubleValue() > 0) {                processedAccNo = String.valueOf(accNo.longValue());            }        } else if (accNoModel instanceof TemplateScalarModel) {            // 考虑accNo可能作为字符串传入的情况            String accNoStr = ((TemplateScalarModel) accNoModel).getAsString();            try {                double accNoDouble = Double.parseDouble(accNoStr);                if (accNoDouble > 0) {                    processedAccNo = accNoStr; // 如果字符串是有效数字且大于0,则保留原字符串                }            } catch (NumberFormatException e) {                // 字符串无法解析为数字,保持默认值"0000"            }        }        // 如果accNoModel为null或非数字类型,则保持默认值"0000"        // 4. 返回处理结果,通常是SimpleScalar或SimpleNumber        return new SimpleScalar(processedAccNo);    }}

3.4 FreeMarker模板使用示例

使用自定义方法模型处理账户号:

  • 账户号1 (54321): ${formatAccNo(accNoVar)}
  • 账户号2 (0): ${formatAccNo(zeroAccNoVar)}
  • 账户号3 (-10): ${formatAccNo(negativeAccNoVar)}
  • 账户号4 (null): ${formatAccNo(nullAccNoVar)}
  • 账户号5 ("abc"): ${formatAccNo(stringAccNoVar)}

4. 注册自定义指令/方法到FreeMarker配置

无论是自定义指令还是自定义方法模型

以上就是Apache FreeMarker自定义指令与方法:使用Java代码处理模板参数的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/864803.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
CPU能效比是什么意思_CPU能效比概念与选购参考价值分析
上一篇 2025年11月28日 01:37:49
《魔兽世界》新资料片“至暗之夜”定档2026年3月2日
下一篇 2025年11月28日 01:37:49

相关推荐

  • 谷歌浏览器官网直接进入 Chrome浏览器官方登录入口

    谷歌浏览器官网直接进入方式为访问https://www.google.com/chrome/,该网站是Chrome官方登录入口,提供跨平台同步、V8引擎加速、地址栏集成搜索、自动填充表单等核心功能,支持极简界面、深色模式、自定义新标签页及侧边栏服务,具备安全浏览、隐私沙盒、密码检查和无痕模式等安全机…

    2026年9月22日
    100
  • MySQL跨数据库查询技巧_实现不同数据库间的数据联动操作

    MySQL跨数据库查询技巧_实现不同数据库间的数据联动操作MySQL跨数据库查询技巧_实现不同数据库间的数据联动操作MySQL跨数据库查询技巧_实现不同数据库间的数据联动操作MySQL跨数据库查询技巧_实现不同数据库间的数据联动操作

    mysql跨数据库查询的核心方法是在sql语句中通过“数据库名.表名”方式指定不同数据库的表,实现数据联动。1.在同一个mysql实例内,直接使用数据库名加表名进行关联查询,如db_user.users和db_order.orders,前提是用户需具备相应权限且建议对关联字段建立索引以提升性能;2.…

    2026年9月22日 用户投稿
    400
  • unix怎么安装php_unix系统安装php环境指南

    首先确认系统环境并检查是否已安装相关软件,然后选择包管理器或源码编译方式安装PHP;推荐使用包管理器快速安装,如Debian/Ubuntu用apt,CentOS/RHEL/Fedora用yum或dnf,FreeBSD用pkg;安装后配置Web服务器,Apache需加载mod_php或集成PHP-FP…

    2026年9月22日
    300
  • itextpdf freemarker渲染

    关于打印pdf操作的需求,经过研究,发现以下两种方法: 在现有的模板上进行编辑,这种方法操作难度较大。而通过FreeMarker生成静态页面,然后转换为HTML,操作更为顺畅。动态生成PDF的方法在网上参考较多,经过对比,我认为使用FreeMarker结合IText生成PDF最为简单。参考链接为ht…

    2026年9月22日
    300
  • Java多线程并发控制:告别线程优先级,拥抱锁机制

    本文深入探讨了在Java多线程环境中如何有效解决并发操作中断问题,特别是当多个线程尝试同时执行非原子性操作(如打印)时。文章指出,单纯依赖线程优先级并不可靠,并详细介绍了使用synchronized关键字配合共享锁对象实现互斥访问的关键技术,确保关键代码块的原子性执行,从而避免数据混乱和逻辑错误。 …

    2026年9月22日
    700
  • 设计VSCode三维图形编程界面与WebGL实时预览模块

    VSCode通过集成WebGL预览插件实现三维图形编程的实时反馈,利用扩展架构提供GLSL语法支持、文件关联及命令注册,并通过Webview嵌入渲染窗口,结合消息通信与动态编译技术实现实时预览,配合保存自动刷新、错误定位与多视图布局优化交互体验,构建高效闭环开发环境。 在使用 VSCode 进行三维…

    2026年9月22日
    100
  • Apache Pulsar 主题分区创建与管理指南

    本文深入探讨Apache Pulsar主题分区的创建与管理。Pulsar主题分区是实现高吞吐量和可伸缩性的关键,但必须在主题创建时进行配置。文章详细介绍了两种主要的分区主题创建方法:通过Broker配置实现自动分区,以及利用Pulsar Admin API进行显式创建,并强调了分区主题一旦创建后不可…

    2026年9月22日
    100
  • 使用 Spring Boot Test @Sql 注解通过掩码描述文件的方法

    在 Spring Boot 测试中,我们经常使用 @Sql 注解来执行 SQL 脚本,以便在测试前准备数据或在测试后清理数据。 通常的用法如下: @Sql(scripts = “/folder/my_favourite_script.sql”)@Testpublic void myTest() { …

    2026年9月22日
    100
  • Spring Boot集成MongoDB Atlas:正确配置与故障排除

    本教程详细指导如何在Spring Boot应用中正确配置与连接MongoDB Atlas集群。我们将重点讲解如何获取并使用正确的Atlas连接URI,安全地处理用户认证信息,以及准确指定目标数据库。通过实例代码和常见错误排查,帮助开发者避免连接失败,确保应用与MongoDB Atlas的顺畅集成。 …

    2026年9月22日
    600
  • Prestashop分页隐藏分类描述的SEO考量与处理

    本文探讨了Prestashop商店中分类描述在分页后消失的问题。我们解释了这种现象通常并非SEO问题,因为搜索引擎主要关注第一页的描述内容。教程将深入分析此行为背后的SEO逻辑,并提供确保网站SEO友好的最佳实践,强调第一页描述的重要性及规范使用Canonical标签。 Prestashop分类描述…

    2026年9月22日
    100
  • 如何利用 JavaScript 实现一个支持拖放排序的交互界面?

    答案是利用HTML5拖放API实现拖拽排序,通过设置draggable属性和监听dragstart、dragover、drop事件控制元素移动,结合CSS提升交互反馈。 要实现一个支持拖放排序的交互界面,核心是利用 HTML5 的拖放 API(Drag and Drop API)结合 JavaScr…

    2026年9月22日
    100
  • Apache POI生成带水印DOCX文件时的XML内容错误解析与应对

    本文深入探讨了使用Apache POI生成带有水印的DOCX文件时,可能遇到的“XML声明只能出现在输入开头”错误。该错误通常指向DOCX内部XML文件(如header4.xml)的格式问题,导致文件在Microsoft Word中无法打开。文章分析了错误原因,并提供了包括升级POI版本、手动检查D…

    2026年9月22日
    100
  • 配置PHP多线程的性能监控_通过监控优化php多线程怎么实现的效率

    PHP虽不支持传统多线程,但可通过pthreads扩展在CLI模式下实现;合理设置线程数、使用线程池、集成性能监控工具并优化任务分配可显著提升执行效率。 PHP 本身并不支持传统意义上的多线程,因为它默认运行在 Web 服务器(如 Apache 或 Nginx)的 CGI/FPM 模式下,每个请求是…

    2026年9月22日
    300
  • Java并发编程中Runnable接口使用方法

    Runnable接口用于定义线程任务,通过实现run()方法封装执行逻辑,不返回结果且不能抛出受检异常;可直接传给Thread实例启动线程,也可用Lambda表达式简化代码;推荐结合ExecutorService线程池使用,提升资源利用率;需注意无返回值、异常处理在内部完成、共享变量线程安全等问题。…

    2026年9月22日
    200
  • PHP 表单验证:确保 HTML select 下拉菜单已正确选择非默认选项

    本文将详细介绍如何在 PHP 后端对 HTML select 下拉菜单进行有效验证,确保用户选择了非默认选项。我们将探讨常见的验证误区,并提供一个简洁高效的解决方案,通过检查 $_POST 数据来判断用户是否已做出有效选择,从而避免表单提交无效数据,提升用户体验和数据准确性。 在构建 web 表单时…

    2026年9月22日
    300
  • 360浏览器怎么禁止网页自动刷新_360浏览器阻止页面定时刷新设置方法

    1、通过360浏览器开发者工具删除含http-equiv=”refresh”的meta标签可临时阻止刷新;2、启用弹窗拦截功能可屏蔽由脚本触发的自动刷新;3、使用无痕模式浏览可限制脚本运行,避免页面刷新;4、安装“Tampermonkey”等扩展并添加屏蔽规则可实现长期有效阻…

    2026年9月22日
    400
  • 在Java中如何通过Stream实现交集与差集

    交集可通过filter结合contains获取两集合共有元素,差集则保留一个集合中不在另一集合的元素,示例使用list1.stream().filter(list2::contains)得[3,4],filter(e->!list2.contains(e))得[1,2],建议将list2转为H…

    2026年9月22日
    100
  • Java Swing中按钮与文本框事件处理的实践指南

    本文将深入探讨Java Swing中ActionListener的正确使用方法,指导开发者如何为GUI按钮和文本框实现事件监听,从而处理用户输入、执行计算并实时更新界面。文章将重点讲解如何在actionPerformed方法中获取用户输入、进行类型转换、处理潜在异常,并提供一个完整的计算器示例来演示…

    2026年9月22日
    200
  • 使用MockWebServer对FeignClient进行单元测试

    本文详细阐述了如何利用Spring Cloud LoadBalancer和MockWebServer对FeignClient进行高效单元测试。通过在测试配置中动态注册MockWebServer实例,并将其作为FeignClient的服务发现目标,开发者可以精确模拟后端API的行为,包括各种HTTP响…

    2026年9月22日
    100
  • Java中异常处理与方法返回值结合

    异常发生时不应返回默认值,而应通过抛出异常或使用Optional、自定义结果类等方式明确传递错误信息,确保调用方能正确处理失败情况,提升代码健壮性与可读性。 在Java中,异常处理与方法返回值的结合是一个常见的编程问题。理解它们之间的关系有助于写出更健壮、可读性更强的代码。当一个方法可能发生异常时,…

    2026年9月22日
    100

发表回复

登录后才能评论
关注微信