Spring MVC中如何实现ModelAndView嵌套,将panel.jsp嵌入layout.jsp
问题描述
需求
要在layout.jsp里展示panel.jsp的面板列表,复用layout.jsp的样式和功能,不用在panel.jsp里单独实现这些内容。
当前问题
控制器的loadLayout()方法中,当panelData不为空时,会返回editPanel()生成的指向dashboard/panel的ModelAndView,直接替换了原本指向dashboard/layout的视图,导致layout.jsp加载失败,没法在其中嵌入panel.jsp并执行相关脚本。
相关代码
视图定义
- 主页面视图:
ModelAndView mav = new ModelAndView("dashboard/layout"); - 面板页面视图:
ModelAndView mav = new ModelAndView("dashboard/panel");
layout.jsp代码
<style>.....</style> <!-- Panel display --> <div class="container row" id="container"></div> <script>.....</script>
panel.jsp代码
<c:forEach var="panel" items='${panelData}'> <div class="panel-container col-lg-${panel.size}"> ..samplecontent... </div> </c:forEach>
控制器代码
@RequestMapping("DashboardController/loadLayout") public ModelAndView loadLayout() { System.out.println("====Inside DashboardController#loadLayout===="); //list of dashboards List<Dashboard> dashboards = dashboardManagerService.findAllActive(); ModelAndView mav = new ModelAndView("dashboard/layout"); Set<Panel> panelData = new HashSet<>(); for (Dashboard dashboard : dashboards) { //panelData from the dashboard panelData.addAll(dashboard.getLayoutPanels()); } if (!panelData.isEmpty()) { System.out.println("inside the else part " + panelData); return editPanel(panelData); } else { System.out.println("inside the if part " + panelData); } return mav; } public ModelAndView editPanel(Set<Panel> panelData) { System.out.println("====Inside DashboardController#editPanel===="); ModelAndView mav = new ModelAndView("dashboard/panel"); mav.addObject("panelData", panelData); mav.setViewName("dashboard/panel"); return mav; }
解决方案
方法一:修改控制器逻辑,始终返回layout视图
直接在loadLayout()里处理数据,不用调用editPanel()返回单独的panel视图,把panelData放到layout的ModelAndView中:
修改后的控制器代码:
@RequestMapping("DashboardController/loadLayout") public ModelAndView loadLayout() { System.out.println("====Inside DashboardController#loadLayout===="); List<Dashboard> dashboards = dashboardManagerService.findAllActive(); ModelAndView mav = new ModelAndView("dashboard/layout"); Set<Panel> panelData = new HashSet<>(); for (Dashboard dashboard : dashboards) { panelData.addAll(dashboard.getLayoutPanels()); } // 不管数据是否为空,都将panelData传入model mav.addObject("panelData", panelData); System.out.println(panelData.isEmpty() ? "inside the if part " + panelData : "inside the else part " + panelData); return mav; } // 若editPanel需单独调用,可保留但修改为返回layout视图 public ModelAndView editPanel(Set<Panel> panelData) { System.out.println("====Inside DashboardController#editPanel===="); ModelAndView mav = new ModelAndView("dashboard/layout"); mav.addObject("panelData", panelData); return mav; }
然后修改layout.jsp,在容器中引入panel.jsp:
<style>.....</style> <!-- Panel display --> <div class="container row" id="container"> <%@ include file="panel.jsp" %> </div> <script>.....</script>
这样不管panelData是否为空,都会加载layout.jsp,同时把panel.jsp的内容嵌入容器,复用layout的样式和脚本。
方法二:使用视图模板框架(如Thymeleaf)
如果项目用Thymeleaf这类模板框架,可通过片段引用实现布局复用:
修改layout.jsp:
<style>.....</style> <!-- Panel display --> <div class="container row" id="container"> <div th:replace="dashboard/panel :: panel-fragment"></div> </div> <script>.....</script>
修改panel.jsp定义片段:
<div th:fragment="panel-fragment"> <c:forEach var="panel" items='${panelData}'> <div class="panel-container col-lg-${panel.size}"> ..samplecontent... </div> </c:forEach> </div>
控制器依旧返回dashboard/layout并传递panelData即可。
内容的提问来源于stack exchange,提问作者CypherBee
相关产品推荐
相关产品推荐

