渲染父子视图会导致StackOverflow异常

时间:2017-10-18 11:04:24

标签: java jsp recursion jstl

我无法在jsp页面中呈现嵌套的父子树结构。由于

引起的堆栈流错误
 <code><jsp:include page=""/></code>

我的数据库:

 Id ||  Name  ||  Parentid  ||
 1  ||  animal||  0         ||  
 2  ||  Dog   ||  1         ||    etc.

模特课:

public class Node {
    private int id;
    private String name;
    private int parentId;
    private List<Node> children;

    public Node() {
    }

    public Node(String name, int parentId, List<Node> children) {
        this.name = name;
        this.parentId = parentId;
        this.children = children;
    }

DAO班级:

 @Override
    public List<Node> nodelist() {

         String sql = "select * from tree";
      List<Node> listNode = jdbcTemplate.query(sql, new RowMapper<Node>() {

            @Override
            public Node mapRow(ResultSet rs, int rowNum) throws SQLException {
               Node node = new Node();
                    node.setId(rs.getInt("id"));
                node.setName(rs.getString("name"));
                node.setParentId(rs.getInt("parent_id"));

                return node;


            }

        });

        return listNode;
    }

在控制器中,我按如下方式绑定对象:

List<Node> rootNodes;

@Autowired
    TreeDao treeDao;


    @RequestMapping(value = "/node", method = RequestMethod.GET)
    public ModelAndView getallnodes(ModelAndView model) throws IOException {

        //menuObj = menuDao.listCategory();
        List<Node> listnode = treeDao.nodelist();

        getInfiniteTree(listnode);
        model.addObject("rootNodes",rootNodes);
        model.setViewName("tree");

        return model;
    }

    public List<Node> getInfiniteTree(List<Node> nodes) {
        return findRootNodes(nodes);
    }

    private List<Node> findRootNodes(List<Node> nodes) {
        rootNodes = new ArrayList<Node>();
        for (Node node : nodes) {
            if (node.getParentId() == 0) {
                rootNodes.add(node);
                findChildNodes(node, nodes);
            }
        }



System.out.println("rootnodes "+rootNodes);


    Gson gson = new Gson();
    System.out.println(gson.toJson(rootNodes));
     //I got the correct json format data here.
        //Collections.sort(rootNodes);
        return rootNodes;
    }



    private  void findChildNodes(Node parentNode, List<Node> nodes) {
        List<Node> children = new ArrayList<Node>();
        parentNode.setChildren(children);
        for (Node node : nodes) {
            if (node.getParentId() == parentNode.getId()) {
                children.add(node);
                findChildNodes(node, nodes);
            }
        }

        //Collections.sort(children);
    }

在另一个java swing项目中,我测试了类似的代码并获得了以下字符串结果:

nodes [Node{id=1, name=供应链部, parentId=0, sort=3, children=[Node{id=5, name=物流部, parentId=1, sort=1, children=[]}, Node{id=6, name=采购部, parentId=1, sort=2, children=[]}]}, Node{id=2, name=技术部, parentId=0, sort=1, children=[Node{id=7, name=开发部, parentId=2, sort=2, children=[Node{id=12, name=后端部, parentId=7, sort=2, children=[]}, Node{id=13, name=前端部, parentId=7, sort=2, children=[Node{id=14, name=diee, parentId=13, sort=2, children=[]}, Node{id=15, name=diee, parentId=13, sort=2, children=[]}]}]}, Node{id=8, name=测试部, parentId=2, sort=1, children=[]}, Node{id=9, name=运维部, parentId=2, sort=3, children=[]}]}, Node{id=3, name=行政部, parentId=0, sort=2, children=[Node{id=10, name=招聘部, parentId=3, sort=1, children=[]}, Node{id=11, name=人事部, parentId=3, sort=2, children=[]}]}, Node{id=4, name=公关部, parentId=0, sort=4, children=[]}]

问题是我无法使用jsp递归显示它,我尝试下面的代码:

tree.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

    </head>
    <body>
        <c:set var="menuitem" value="${rootNodes}" scope="request" />
        <jsp:include page="menuitem.jsp" />
    </body>
</html> 

menuitem.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<ul>
    <c:forEach var ="menuitems" items="${menuitem}">
        <li><a href="#">${menuitems.name}</a></li>
        <ul>
   <c:if test="${fn:length(menuitems.children) gt 0}">
      <li class="droprightMenu">
          <c:out value="Has children"></c:out>
         <c:forEach var="menuitemc" items="${menuitems.children}">
           <c:set var="menuitem" value="${menuitemc}" scope="request" />
           <%--<jsp:include page="menuitem.jsp" />--%>
         </c:forEach>
      </li>
   </c:if>
      </ul>
      </c:forEach>
</ul>

它不包括通过无限子项的页面,因为我是JSP递归的新手,请忽略我的错误。我在这里呆了好几天。 例外:

Don't know how to iterate over supplied "items" in &lt;forEach&gt;
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/views/menuitem.jsp at line 14

11: 
12: 
13: <ul>
14:     <c:forEach var ="menuitems" items="${menuitem}">
15:         <li><a href="#">${menuitems.name}</a></li>
16:         <ul>
17:    <c:if test="${fn:length(menuitems.children) gt 0}">

2 个答案:

答案 0 :(得分:1)

<强> menuitem.jsp

 <c:forEach var="menuitem" items="${menuitem.children}">
    <li><a href="#" id="${menuitem.id}"><i class="fa fa-circle-o"></i>  <span>${menuitem.name} </span></a></li>
    <c:set var="menuitem" value="${menuitem}" scope="request" />
    <jsp:include page="/WEB-INF/views/menuitem.jsp" />
 </c:forEach>

我认为问题出在这里。尝试将var="menuitem"重命名为var="childmenuitem。 我相信你目前不断将同一个对象传递到子菜单,导致无限循环。

答案 1 :(得分:0)

最后我以这种方式解决了它:

tree.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

    </head>
    <body>



        <c:set var="menuitem" value="${rootNodes}" scope="request" />
        <jsp:include page="menuitem.jsp" />
    </body>
</html> 

在menuitem.jsp中:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>




<ul>
    <c:forEach var ="menuitems" items="${menuitem}">
        <li><a href="#">${menuitems.name}</a></li>
        <ul>
   <c:if test="${fn:length(menuitems.children) gt 0}">
      <li class="droprightMenu">
          <c:out value="Has children"></c:out>
         <%--<c:forEach var="menuitemc" items="${menuitems.children}">--%>
           <c:set var="menuitem" value="${menuitems.children}" scope="request" />
           <jsp:include page="menuitem.jsp" />
         <%--</c:forEach>--%>
      </li>
   </c:if>
      </ul>
      </c:forEach>
</ul>

希望它会对某人有所帮助。