Thymeleaf遍历枚举读取属性触发OGNL Exception问题排查
问题根因
这个异常是OGNL库的已知类型识别bug,和你枚举类的getter写法、List构造逻辑没有关系:
- OGNL解析对象属性时,会先判断目标对象是否实现
Map接口,命中就走Map专属的属性读写逻辑 - 3.0.12版本之前的Thymeleaf集成的OGNL版本存在判定缺陷,会错误地把枚举实例识别为Map实例
- OGNL读取属性前会尝试往它识别出的"Map"里写入属性访问缓存标记,而枚举本身没有实现Map的put方法,最终调用到
AbstractMap.put的默认实现,直接抛出UnsupportedOperationException
不用浪费时间排查枚举的getter命名、上下文传值逻辑,这些环节都没有问题。
解决方案
按改造成本从低到高选择即可:
- 首选方案:直接将Thymeleaf依赖升级到3.0.12及以上版本,官方已经在这个版本修复了枚举类型的误识别问题,不需要修改任何业务代码、模板代码,改完直接生效。
- 无法升级版本的兼容方案:在后端做一层数据转换,不要直接传递枚举实例的List给模板。新建一个普通POJO类,只保留模板渲染需要的
anchor、title字段,遍历枚举集合把对应属性值拷贝到POJO实例中,再传递POJO的List给前端遍历即可,完全绕开OGNL对枚举的解析逻辑。 - 临时调试方案:关闭OGNL的属性访问缓存,在Thymeleaf模板引擎初始化时注入自定义OGNL上下文配置:
这个方案会小幅降低模板渲染性能,生产环境不推荐使用。OgnlContext context = new OgnlContext(null, null, new DefaultMemberAccess(true)); context.setCacheAcessors(false);
注意:不要尝试通过给枚举类实现Map接口的方式绕过异常,会破坏枚举的单例、序列化特性,引入更难排查的隐性问题。
内容的提问来源于stack exchange,提问作者Gauthier
相关产品推荐
相关产品推荐

