FreeMarker获取Java对象数据配置及空值渲染报错解决
将Java对象传入FreeMarker模板不需要添加额外的特殊配置,你遇到的报错和对象传值配置无关,核心原因是FreeMarker默认规则下,直接访问值为null的对象/属性会直接抛出InvalidReferenceException,和字段是否为public修饰没有关系——哪怕是public字段,只要所属对象是null,访问时一样会报错,和Java里调用null对象的属性报空指针是同一个逻辑。
你当前场景下初始加载时searchForm或frm_searchType为null,直接读取searchForm.frm_searchType就触发了这个异常,以下三种方案都可以实现初始加载正常渲染,按需选择即可:
方案1:模板层添加空值安全处理(最推荐,改动最小)
直接修改if判断的取值逻辑,使用FreeMarker内置的空值安全语法,给可能为null的属性设置默认值:
<#if (searchForm.frm_searchType)!"" == "Non-Member"> <#assign isMember = true> <#assign isNonMember = false> <#else> <#assign isMember = false> <#assign isNonMember = true> </#if>
语法说明:(表达式)!默认值表示如果括号内的链式取值任意一步返回null/missing,就直接使用后面的默认值,这里设置为空字符串后,初始加载时空值会走else分支,符合业务逻辑。
如果需要更严谨的存在性判断,也可以写成:
<#if (searchForm.frm_searchType)?? && searchForm.frm_searchType == "Non-Member"> <#assign isMember = true> <#assign isNonMember = false> <#else> <#assign isMember = false> <#assign isNonMember = true> </#if>
??运算符用来判断前面的表达式是否存在、不为null。
方案2:全局配置FreeMarker兼容null值
如果不想在每个模板取值时都写空判断,可以开启FreeMarker的经典兼容模式,该模式下null值会被自动当做空字符串处理,不会抛出异常。
如果是Spring Boot项目,直接在配置文件中添加如下配置即可:
spring.freemarker.settings.classic-compatible=true
如果是XML形式配置FreeMarker,给FreeMarkerConfigurer的freemarkerSettings属性添加classic_compatible=true的配置项即可。
注意:该配置是全局生效的,会改变所有模板的null值处理逻辑,确认符合业务预期后再使用。
方案3:后端初始化传参对象
在后端将searchForm对象放入模型传给模板之前,先完成对象初始化:直接new出SearchForm实例,给frm_searchType属性设置默认值(比如空字符串、默认的会员类型枚举值),从根源上避免null值传入模板。
内容的提问来源于stack exchange,提问作者Hemanth

