You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:26:03