如何将Thymeleaf页面的authRequest modelAttribute回传至目标Controller?
问题描述
我已经在控制器中将modelAttribute "authRequest"传递到了dashboard.html页面,页面能正常显示${authRequest.userName}的值。现在希望点击“View Cards”按钮提交表单时,把"authRequest"回传给viewCards控制器,这样就能在viewCards.html里获取它的值。但尝试用th:href和form-action传递后,在viewCards控制器和对应页面里都拿到了null。
我尝试过的代码如下:
dashboard.html(可正常获取${authRequest.userName})
<form action="#" th:action="@{/viewCards}" th:object="${authRequest}" method="post"> <input type="submit" value="View cards" /> </form> <p th:text="'User Name: ' + ${authRequest.userName}" />
viewCards.html(无法获取${authRequest.userName})
<script type="text/javascript" th:src="@{/webjars/jquery/1.9.1/jquery.min.js/}"></script> <script th:inline="javascript"> var user= [[${authRequest.userName}]]; </script> <script type="text/javascript" th:src="@{/vCards.js}"></script> <p th:text="'User Name: ' + ${authRequest.userName}" />
控制器代码
@RequestMapping(value= "/virtualWallet/login" , method= RequestMethod.POST) public String getAuthResponse( @ModelAttribute AuthRequest authRequest, Model model ){ String resp = authService.getAuthResponse(authRequest); if(resp.equals("Success")) { return "dashboard"; } return null; } @RequestMapping(value= "/viewCards" , method = RequestMethod.POST) public String viewCards( @ModelAttribute AuthRequest authRequest ) { return "viewCards"; }
我预期在viewCards.html中获取"authRequest"的值,但实际为null,求正确传递方法。
问题分析
你遇到的问题主要有两个核心原因:
- 表单未绑定属性字段:虽然表单声明了
th:object="${authRequest}",但没有任何输入字段来绑定authRequest的具体属性。Spring MVC无法凭空构建完整的AuthRequest对象,导致控制器接收到的是null。 - 控制器未将对象存入Model:即使表单成功传递了数据,你的
viewCards控制器也没有把接收到的authRequest添加到Model中,页面自然无法从Model里获取该对象的值。
解决方案
方案一:通过表单隐藏字段传递属性(适合单次页面跳转)
这个方案通过在表单中添加隐藏字段,把authRequest的属性值传递给服务器,再由控制器将对象存入Model供页面使用。
修改dashboard.html的表单:
添加隐藏字段绑定authRequest的属性,Thymeleaf的th:field会自动生成对应的name和value属性:<form action="#" th:action="@{/viewCards}" th:object="${authRequest}" method="post"> <!-- 绑定userName属性的隐藏字段 --> <input type="hidden" th:field="*{userName}" /> <!-- 如果AuthRequest还有其他需要传递的属性,同样添加隐藏字段 --> <!-- <input type="hidden" th:field="*{password}" /> --> <input type="submit" value="View cards" /> </form> <p th:text="'User Name: ' + ${authRequest.userName}" />修改viewCards控制器:
接收authRequest后,将它添加到Model中:@RequestMapping(value= "/viewCards" , method = RequestMethod.POST) public String viewCards( @ModelAttribute AuthRequest authRequest, Model model ) { // 将authRequest存入Model,供页面渲染使用 model.addAttribute("authRequest", authRequest); return "viewCards"; }调整viewCards.html的jQuery路径:
原代码中jquery.min.js后面多了个斜杠,可能导致路径错误,建议去掉:<script type="text/javascript" th:src="@{/webjars/jquery/1.9.1/jquery.min.js}"></script>
方案二:使用Session存储对象(适合多页面共享数据)
如果authRequest需要在多个页面中复用,每次通过表单传递字段会很繁琐,这时可以用Session来存储对象。
修改登录控制器,将authRequest存入Session:
@RequestMapping(value= "/virtualWallet/login" , method= RequestMethod.POST) public String getAuthResponse( @ModelAttribute AuthRequest authRequest, Model model, HttpSession session ){ String resp = authService.getAuthResponse(authRequest); if(resp.equals("Success")) { // 将authRequest存入Session,后续页面可直接获取 session.setAttribute("authRequest", authRequest); return "dashboard"; } return null; }修改viewCards控制器,从Session获取对象:
@RequestMapping(value= "/viewCards" , method = RequestMethod.POST) public String viewCards( HttpSession session, Model model ) { // 从Session中取出authRequest AuthRequest authRequest = (AuthRequest) session.getAttribute("authRequest"); // 存入Model供页面使用 model.addAttribute("authRequest", authRequest); return "viewCards"; }简化dashboard.html的表单:
不需要再添加隐藏字段,直接提交表单即可:<form action="#" th:action="@{/viewCards}" method="post"> <input type="submit" value="View cards" /> </form>
内容的提问来源于stack exchange,提问作者ArthanaPS

