Spring+Freemarker遇NonHashException,无法访问对象属性怎么解决?
解决FreeMarker中
previousSearch被识别为字符串无法访问属性的问题 问题原因
出现NonHashException的核心原因是Spring往Model中传递的previousSearch不是TicketSearchForm对象,而是一个字符串。可能的触发场景:
- Controller中误将
TicketSearchForm的toString()结果(或其他字符串值)存入了previousSearch这个Model键; - 请求参数中存在同名的
previousSearch字符串参数,Spring自动将其绑定到Model,覆盖了你原本存入的对象; - 代码中错误地将字符串类型赋值给了
previousSearch对应的Model属性。
解决步骤
1. 检查Controller的Model赋值逻辑
确保你往Model中存入的是TicketSearchForm实例,而非字符串。正确示例如下:
@GetMapping("/ticket/search") public String showSearchPage(Model model) { TicketSearchForm previousSearch = new TicketSearchForm(); // 可从会话/数据库加载历史搜索数据 model.addAttribute("previousSearch", previousSearch); // 存入对象而非字符串 return "ticket/search"; }
排查是否存在model.addAttribute("previousSearch", "some-string-value")这类错误代码,或赋值前是否意外将对象转为了字符串。
2. 排查同名请求参数覆盖问题
如果请求URL/表单中存在名为previousSearch的参数,Spring会自动将其作为字符串存入Model,覆盖你手动添加的对象。可以通过以下方式验证:
- 暂时移除请求中所有
previousSearch相关参数,测试模板是否正常运行; - 在Controller中打印
model.getAttribute("previousSearch")的类型,确认其是否为TicketSearchForm实例。
3. 优化FreeMarker模板写法
FreeMarker可直接通过属性名访问对象的getter(Lombok的@Data已生成getStatus()),无需手动调用get方法,同时用==做字符串对比更简洁:
<select name="status" id="status" class="form-control select2"> <option value="ALL" <#if previousSearch.status == "ALL">selected</#if>>Alle anzeigen</option> <option value="OPEN" <#if previousSearch.status == "OPEN">selected</#if>>Offen</option> <option value="DONE" <#if previousSearch.status == "DONE">selected</#if>>Geschlossen</option> </select>
内容的提问来源于stack exchange,提问作者monamona
相关产品推荐
相关产品推荐

