PAYATHON 2026

FreeMarker 2.3.34 是否兼容 Jakarta EE 11?

数据阿明

兼容性结论

FreeMarker 2.3.34 是否兼容 Jakarta EE 11,取决于应用使用了哪些功能。应分别判断核心模板渲染以及 Servlet、JSP 集成的兼容性。特别是 JSP 标签库集成,仅凭支持 jakarta.* 命名空间无法确认兼容。

FreeMarker 从 2.3.33 起提供了 freemarker.ext.jakarta.servlet 和 freemarker.ext.jakarta.jsp,所以 2.3.34 并非只支持旧的 javax.* API。Jakarta 集成类与旧版集成类位于同一个 FreeMarker JAR 中。参见 FreeMarker 2.3.33 发布说明。

原问题没有提供异常堆栈、服务器版本和具体集成方式,目前无法确定升级失败是否由 FreeMarker 引起。

为什么支持 Jakarta 仍可能报错?

Jakarta EE 11 中的 Jakarta Pages 4.0 删除了一批已弃用的 API,包括 jakarta.servlet.jsp.el 包中的旧表达式接口。依赖这些接口的 JSP 集成代码在升级后可能出现类加载错误。参见 Jakarta Pages 4.0 规范附录 C。

FreeMarker 的问题跟踪记录中有一份报告,描述了使用 JspTaglibs 后找不到 jakarta.servlet.jsp.el.VariableResolver 的情况。报告涉及的是 2.3.35 环境,不能据此得出 2.3.34 的测试结论,但 JSP 标签库集成值得重点验证。参见 FREEMARKER-236。

如何排查升级问题?

1. 确认实际使用的集成类

如果应用直接配置了 FreemarkerServlet,检查 web.xml 中使用的类名。Jakarta 环境对应的类是:

<servlet-class>freemarker.ext.jakarta.servlet.FreemarkerServlet</servlet-class>

如果代码直接从 ServletContext 加载模板,Jakarta 版本的导入应为:

import freemarker.ext.jakarta.servlet.WebappTemplateLoader;

这些类名及其与旧版类的对应关系见 FreeMarker Jakarta Servlet API 文档。如果由框架负责集成,还要检查框架实际创建的是哪套类;单独修改 web.xml 未必会影响框架行为。

2. 根据异常中的缺失类判断方向

  • 缺少 javax.servlet.* 或 javax.servlet.jsp.*:检查是否仍有旧版集成类或依赖被加载。
  • 缺少 jakarta.servlet.jsp.el.VariableResolver:重点检查 JSP 标签库桥接是否调用了 Pages 4.0 已移除的 API。
  • 出现 NoSuchMethodError 或 AbstractMethodError:检查编译时 API、运行时容器 API 和第三方依赖是否一致。
  • 如果错误只涉及模板语法、变量或模板路径:先按模板配置问题处理,不宜直接归因于 Jakarta EE 11。

如果使用 Maven,可以查看依赖的解析结果:

mvn dependency:tree

同时检查最终 WAR 包中的 WEB-INF/lib,确认没有意外打包旧版 Servlet、JSP 或 EL API。部署到由容器提供这些 API 的环境时,相应 API 依赖通常应使用 provided。

3. 将普通模板渲染和 JSP 标签调用分开验证

先用不调用 JSP 标签的简单模板测试渲染,再测试原有的 JspTaglibs 调用。如果前者成功、后者失败,可以重点排查 JSP 桥接、标签库及相关 API。这种方法只能帮助定位故障,不能替代对整个应用的兼容性验证。

遇到 JSP API 不兼容时如何处理?

如果异常确认来自已移除的 JSP API,应查找明确修复该调用路径的 FreeMarker 版本或补丁,并在目标容器中验证。不能假定升级到任意更高版本就一定能解决问题。

无法立即完成适配时,可以评估将相关 JSP 标签改写为 FreeMarker 指令,或暂时使用项目已验证可运行的容器版本。不要混入旧版 JSP API JAR 来掩盖缺失类问题,这可能进一步造成方法签名和类加载冲突。

确定本次升级的具体修复方法,还需要完整异常堆栈、服务器与 JDK 版本、FreeMarker 集成配置,以及是否使用 JspTaglibs。

备注:内容仅供参考。