树型结构

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树型结构相关的知识,希望对你有一定的参考价值。

  想实现一下“树型结构”,提供一种实现思路,实践方法为先主干后细节,此处只写主干思路。

1、先看效果图:

技术分享

实现框架为:mybatis + spring + zTree + zDialog;

2、根据页面元素,及zTree前台框架,抽象出树型结构对象,用于接收后台的数据库数据,方便使用java对象,传输数据信息到前台页面。

注:面向对象编程的思想,多用几次就有了。

技术分享
package com.dyl.dto;

import java.io.Serializable;

/**
 * 树查询结果类
 * 
 * @author duyaolin
 * @date 2016-6-1 下午04:26:21
 */
public class TreeModel implements Serializable {
    private static final long serialVersionUID = -3975150427085854588L;
    private String id;// 节点id
    private String pId;// 父节点pId,I必须大写
    private String name;// 节点名称
    private boolean open = false;// 是否展开树节点,默认不展开
    private String url;// 节点链接的目标URL
    private String icon;// 节点自定义图标的URL路径
    private String title;// 节点提示信息

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getpId() {
        return pId;
    }

    public void setpId(String pId) {
        this.pId = pId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        this.open = open;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}
View Code

 3、配置web.xml、jdbc.properties、springContext-*.xml、mybatis-config.xml。

技术分享
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- 加载Spring容器配置 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 设置Spring容器加载配置文件路径 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:context/springContext-*.xml</param-value>
    </context-param>

    <!-- Spring请求分发servlet -->
    <servlet>
        <servlet-name>SpringServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:context/dispatcher_servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>SpringServlet</servlet-name>
        <url-pattern>*.doo</url-pattern>
    </servlet-mapping>

    <!-- 解决工程编码过滤器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
View Code
技术分享
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:ORCL
jdbc.username=dyl
jdbc.password=dyl
View Code
技术分享
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/tx 
                        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
    <!-- 读取属性文件 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
            </list>
        </property>
    </bean>
    
   <!-- 配置DataSource数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="initialSize" value="1" />
        <property name="maxActive" value="5" />
        <property name="maxIdle" value="2" />
        <property name="minIdle" value="1" />
        <property name="maxWait" value="-1" />
        <property name="timeBetweenEvictionRunsMillis" value="20000" />
        <property name="minEvictableIdleTimeMillis" value="10000" />
        <property name="defaultAutoCommit" value="false" />
    </bean>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:sqlmap/mybatis-config.xml" />
    </bean>
    
    <!-- SESSION模板 -->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
      <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
</beans>
View Code
技术分享
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
   <settings>
      <!-- changes from the defaults -->  
      <setting name="lazyLoadingEnabled" value="false" />
   </settings>

    <!-- Register Alias -->
    <typeAliases>
        <typeAlias alias="org" type="com.dyl.dto.OrgDto" />
        <typeAlias alias="emp" type="com.dyl.dto.EmpDto" />
        <typeAlias alias="tree" type="com.dyl.dto.TreeModel" />
    </typeAliases>

    <!-- Register Mapper -->
    <mappers>
        <mapper resource="com/dyl/dao/EmpDaoMapper.xml" />
        <mapper resource="com/dyl/dao/OrgDaoMapper.xml" />
    </mappers>

</configuration>
View Code

4、编写数据层。

技术分享
package com.dyl.dao;

import java.util.List;

import com.dyl.dto.TreeModel;

public interface IOrgDao {
    public List<TreeModel> getTreeList(String org);
}
View Code
技术分享
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace和定义的Mapper接口对应,并实现其中的方法 -->
<mapper namespace="com.dyl.dao.IOrgDao">

    <select id="getTreeList" parameterType="java.lang.String" resultType="tree">
        select distinct comcode id, comcname name, uppercomcode pId, (comcode || ‘-‘ || comcname) title, comlevel from org 
        start with comcode like concat(#{org}, ‘%‘) connect by nocycle uppercomcode = prior comcode order by comlevel        
    </select>

</mapper>
View Code

5、编写业务层。

技术分享
package com.dyl.service;

import java.util.List;

import com.dyl.dto.TreeModel;

public interface IOrgService {
    // 获取机构树信息
    public List<TreeModel> getTreeList(String org) throws Exception;
}
View Code
技术分享
package com.dyl.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dyl.dao.IOrgDao;
import com.dyl.dto.TreeModel;
import com.dyl.service.IOrgService;

@Transactional
@Service("orgServiceImpl")
public class OrgServiceImpl implements IOrgService{
    @Resource(name="sqlSessionTemplate")
    private SqlSessionTemplate session;

    public List<TreeModel> getTreeList(String org) throws Exception {
        IOrgDao orgDao = session.getMapper(IOrgDao.class);
        List<TreeModel> list = orgDao.getTreeList(org);
        return list;
    }

}
View Code

6、编写控制器。

技术分享
package com.dyl.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.dyl.dto.TreeModel;
import com.dyl.service.IOrgService;

@Controller
@RequestMapping("org.do")
public class OrgController {
    Logger logger = Logger.getLogger(this.getClass());

    @Resource(name = "orgServiceImpl")
    private IOrgService orgService;

    // 选择机构
    @RequestMapping(params = "method=queryOrg")
    public void queryOrg(HttpServletRequest request,
            HttpServletResponse response, ModelMap model) throws IOException {
        String data = "";// 返回标识到客户端,"0"-后台处理失败(系统异常)
        response.setContentType("text/html;charset=GBK");// 让浏览器用GBK来解析返回的数据
        PrintWriter printWriter = response.getWriter();
        try {
            List<TreeModel> treeList = orgService.getTreeList(request.getParameter("org"));
            if (treeList.size() == 0) {
                data = "2";// 没有数据
            } else {
                data = JSONArray.fromObject(treeList).toString();
            }
        } catch (Exception e) {
            data = "0";
            logger.error("获取机构树信息出现异常", e);
        }
        printWriter.write(data);
        printWriter.close();
    }
}
View Code

7、父页面核心代码。

技术分享
<input name="org" type="text" ondblclick="selectOrg();">

function selectOrg() {
 var org = fm.org.value;
 var url = ‘/WebRoot/jsp/invoicemanage/invoiceOrgTree.jsp?org=‘ + org;
 var diag = new Dialog();
 diag.Width = 400;
 diag.Height = 400;
 diag.Title = "请选择机构";
 diag.ShowButtonRow = true;
 diag.OKEvent = function() {
  var orgOfTree = diag.innerFrame.contentWindow.document.getElementById(‘orgOfTree‘).value;
  if (orgOfTree && orgOfTree != ‘‘) {
   fm.org.value = orgOfTree;
   diag.close();
  } else {
   Dialog.alert(‘<span style="color:red;"><b>受票机构</b></span>不允许为空‘);
  }
 };
 diag.URL = url;
 diag.show();
 diag.okButton.value = "确 定";
 diag.cancelButton.value = "取 消";
}
View Code

8、编写树型结构页面。

技术分享
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
    String org = request.getParameter("org");
%>

<html>
<head>
  <title>机构树</title>
  <link rel="stylesheet" type="text/css" href="/WebRoot/css/standard.css">
</head>
<body onload="init(‘rLike‘)" background="/WebRoot/images/bgCommon.gif">
  <form name="fm" method="POST" action="">
    <table cellpadding="5" cellspacing="1">
      <tr>
        <td>机构:</td>
        <td>
          <input type="text" id="orgOfTree" name="orgOfTree" class="codecode" maxLength="10" 
            style="width: 100px;" value="<%=org %>" ondblclick="init(‘rLike‘);">
        </td>
      </tr>    
    </table>
    <ul id="orgTree" class="ztree">
    </ul><br/>
  </form>
</body>
  <script type="text/javascript" src="/WebRoot/js/jquery-1.9.1.min.js"></script>
  <script type="text/javascript" src="/WebRoot/js/zDialog/zDrag.js"></script>
  <script type="text/javascript" src="/WebRoot/js/zDialog/zDialog.js"></script>
  <script type="text/javascript" src="/WebRoot/js/mask.js"></script>
  <link rel="stylesheet" type="text/css" href="/WebRoot/js/zTree/zTreeStyle.css">
  <script type="text/javascript" src="/WebRoot/js/zTree/jquery.ztree.all.min.js"></script>
  <script type="text/javascript">
      var orgOfTree = fm.orgOfTree.value;
    function init(flag) {// flag为模糊查询标志
        $(function() {
             alert("jQuery oK!");
         });
        
        $.ajax( {
            type : "POST",
            url : ‘/WebRoot/org.do‘,
            data : {
                method : ‘queryOrg‘,
                org : fm.orgOfTree.value
            },
            dataType : "json",
            beforeSend : function() {
                $(document).mask(‘系统正在处理中,请稍后...‘); 
            },
            success : function(data) {
                if (‘0‘ == data) {
                    Dialog.alert(‘<span style="color:red;"><b>获取机构树异常,请联系管理员!</b></span>‘, function() {
                        Dialog.close();
                    });
                } else if (‘2‘ == data) {
                    Dialog.alert(‘<span style="color:red;"><b>没有找到机构,请重新输入!</b></span>‘);
                } else {
                    var setting = {
                        callback : {
                            onCheck: zTreeOnCheck,
                            onClick: zTreeOnClick
                        },
                        check : {
                            chkStyle : ‘radio‘,
                            //enable : true,
                            radioType : ‘all‘
                        },
                        data : {
                            key : {
                                name : ‘title‘
                            },
                            simpleData : {
                                enable : true
                            }
                        }
                    }; 
                    var treeNodes = data;// 把后台封装好的简单Json格式赋给treeNodes
                    $(function() {
                        $.fn.zTree.init($("#orgTree"), setting, treeNodes);
                     });
                    var treeObj = $.fn.zTree.getZTreeObj("orgTree");
                    var nodes = treeObj.getNodes();
                    if (nodes.length > 0) {
                        treeObj.selectNode(nodes[0]);
                        fm.orgOfTree.value = nodes[0].id;
                        //fm.orgNameOfTree.value = nodes[0].name;
                    }
                }
            },
            error : function(XMLResponse) {// 用于调试错误
                alert(XMLResponse.responseText);
            },
            complete : function() {
                $(document).unmask();
            }
        });
    }
    // 用于捕获checkbox/radio被勾选或取消勾选的事件回调函数
    function zTreeOnCheck(event, treeId, treeNode) {
        fm.orgOfTree.value = treeNode.id;
        //fm.orgNameOfTree.value = treeNode.name;
    }
    // 用于捕获节点被点击的事件回调函数
    function zTreeOnClick(event, treeId, treeNode) {
        fm.orgOfTree.value = treeNode.id;
        //fm.orgNameOfTree.value = treeNode.name;
    };
  </script>
</html>
View Code

9、最后,附上代码结构图。
技术分享

 

注:本次实践是常见工具库的调用,也花了两个半小时,想出来、做出来、说出来、写出来,是不一样的。完。

以上是关于树型结构的主要内容,如果未能解决你的问题,请参考以下文章

UVA536 Tree Recovery(树型结构基础)

树型结构

树型结构

用LINQ从树型数据结构中获取级别的最好方法是什么?

MFC 树型视图三个结构:TVINSERTSTRUCTTVITEMNMTREEVIEW

JS通过递归,处理树型结构数据