在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示。本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结构的问题。如有不正之处,欢迎大家批评指正。
编程模型

我们以北京行政区划为例,讲解整个模型。

北京市:市辖区 县

市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区

县:密云县 延庆县

UML类图如下:

Tree结构

TreeNode:定义树的节点对象

nodeId:树节点Id。
    nodeName:树节点名称。
    parentNodeId:树节点父Id。
    orderNum:节点在树中的排序号,在同一节点下进行排序。
    level:当前树节点所在的层级,根节点为第一层。
    parent:当前树节点的父节点。
    children:当前树节点的儿子节点。
    allChildren:当前树节点的子孙节点。

ITree:定义树对象要实现的方法。

getTree():以 List 形式返回树的所有的 TreeNode 对象。
    getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
    getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。

Tree:实现 ITree 接口,提供树的完整功能。

getTree():以 List 形式返回树的所有的 TreeNode 对象。
    getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
    getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。

ITreeNode:定义模板方法,构造树形结构的类要实现该接口,Tree 通过调用该接口中的方法获取 nodeId nodeName parentNodeId orderNum 数据。

getNodeId():获取树节点Id。
    getNodeName():获取树节点名称。
    getParentNodeId():获取树节点父Id。
    getOrderNum():获取节点在树中的排序号,在同一节点下进行排序。

Org:定义行政区划类,实现 ItreeNode 接口。
---------------------

在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示。本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结构的问题。如有不正之处,欢迎大家批评指正。
编程模型

我们以北京行政区划为例,讲解整个模型。

北京市:市辖区 县

市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区

县:密云县 延庆县

UML类图如下:

Tree结构

TreeNode:定义树的节点对象

nodeId:树节点Id。
    nodeName:树节点名称。
    parentNodeId:树节点父Id。
    orderNum:节点在树中的排序号,在同一节点下进行排序。
    level:当前树节点所在的层级,根节点为第一层。
    parent:当前树节点的父节点。
    children:当前树节点的儿子节点。
    allChildren:当前树节点的子孙节点。

ITree:定义树对象要实现的方法。

getTree():以 List 形式返回树的所有的 TreeNode 对象。
    getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
    getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。

Tree:实现 ITree 接口,提供树的完整功能。

getTree():以 List 形式返回树的所有的 TreeNode 对象。
    getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
    getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。

ITreeNode:定义模板方法,构造树形结构的类要实现该接口,Tree 通过调用该接口中的方法获取 nodeId nodeName parentNodeId orderNum 数据。

getNodeId():获取树节点Id。
    getNodeName():获取树节点名称。
    getParentNodeId():获取树节点父Id。
    getOrderNum():获取节点在树中的排序号,在同一节点下进行排序。

Org:定义行政区划类,实现 ItreeNode 接口。
实现代码

TreeNode类:

package com.ips.tree;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.annotation.JSONField;

/**
 * <p>Title: 树节点</p>
 * <p>Description:一棵树由许多包含父子关系的节点组成 </p>
 * @author  liuzhibo
 * @date    2017年1月18日
 */
public class TreeNode {
    //树节点ID
    @JSONField(ordinal=1)
    private String nodeId;
    //树节点名称
    @JSONField(ordinal=2)
    private String nodeName;
    //父节点ID
    @JSONField(ordinal=3)
    private String parentNodeId;
    //节点在树中的排序号
    @JSONField(ordinal=4)
    private int orderNum;
    //节点所在的层级
    @JSONField(ordinal=5)
    private int level;
    private TreeNode parent;
    //当前节点的二子节点
    @JSONField(ordinal=6)
    private List<TreeNode> children = new ArrayList<TreeNode>();
    //当前节点的子孙节点
    private List<TreeNode> allChildren = new ArrayList<TreeNode>();

public TreeNode(ITreeNode obj){
        this.nodeId = obj.getNodeId();
        this.nodeName = obj.getNodeName();
        this.parentNodeId = obj.getNodeParentId();
        this.orderNum = obj.getOrderNum();
    }
    public void addChild(TreeNode treeNode){
        this.children.add(treeNode);
    }
    public void removeChild(TreeNode treeNode){
        this.children.remove(treeNode);
    }
    public String getNodeId() {
        return nodeId;
    }
    public void setNodeId(String nodeId) {
        this.nodeId = nodeId;
    }
    public String getNodeName() {
        return nodeName;
    }
    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }
    public String getParentNodeId() {
        return parentNodeId;
    }
    public void setParentNodeId(String parentNodeId) {
        this.parentNodeId = parentNodeId;
    }
    public int getLevel() {
        return level;
    }
    public void setLevel(int level) {
        this.level = level;
    }
    public TreeNode getParent() {
        return parent;
    }
    public void setParent(TreeNode parent) {
        this.parent = parent;
    }
    public List<TreeNode> getChildren() {
        return children;
    }
    public void setChildren(List<TreeNode> children) {
        this.children = children;
    }
    public int getOrderNum() {
        return orderNum;
    }
    public void setOrderNum(int orderNum) {
        this.orderNum = orderNum;
    }

public List<TreeNode> getAllChildren() {
        if(this.allChildren.isEmpty()){
            for(TreeNode treeNode : this.children){
                this.allChildren.add(treeNode);
                this.allChildren.addAll(treeNode.getAllChildren());
            }
        }
        return this.allChildren;
    }   
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101

ITree接口:

package com.ips.tree;

import java.util.List;

public interface ITree {
    public List<TreeNode> getTree();
    public List<TreeNode> getRoot();
    public TreeNode getTreeNode(String nodeId);
}

1
    2
    3
    4
    5
    6
    7
    8
    9

Tree类:

package com.ips.tree;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class Tree implements ITree {
    private HashMap<String, TreeNode> treeNodesMap = new HashMap<String, TreeNode>();
    private List<TreeNode> treeNodesList = new ArrayList<TreeNode>();

public Tree(List<ITreeNode> list){
        initTreeNodeMap(list);
        initTreeNodeList();
    }

private void initTreeNodeMap(List<ITreeNode> list){
        TreeNode treeNode = null;
        for(ITreeNode item : list){
            treeNode = new TreeNode(item);
            treeNodesMap.put(treeNode.getNodeId(), treeNode);
        }

Iterator<TreeNode> iter = treeNodesMap.values().iterator();
        TreeNode parentTreeNode = null;
        while(iter.hasNext()){
            treeNode = iter.next();
            if(treeNode.getParentNodeId() == null || treeNode.getParentNodeId() == ""){
                continue;
            }

parentTreeNode = treeNodesMap.get(treeNode.getParentNodeId());
            if(parentTreeNode != null){
                treeNode.setParent(parentTreeNode);
                parentTreeNode.addChild(treeNode);
            }
        }
    }

private void initTreeNodeList(){
        if(treeNodesList.size() > 0){
            return;
        }
        if(treeNodesMap.size() == 0){
            return;
        }
        Iterator<TreeNode> iter = treeNodesMap.values().iterator();
        TreeNode treeNode = null;
        while(iter.hasNext()){
            treeNode = iter.next();
            if(treeNode.getParent() == null){
                this.treeNodesList.add(treeNode);
                this.treeNodesList.addAll(treeNode.getAllChildren());
            }
        }
    }

@Override
    public List<TreeNode> getTree() {
        return this.treeNodesList;
    }

@Override
    public List<TreeNode> getRoot() {
        List<TreeNode> rootList = new ArrayList<TreeNode>();
        if (this.treeNodesList.size() > 0) {
            for (TreeNode node : treeNodesList) {
                if (node.getParent() == null)
                    rootList.add(node);
            }
        }
        return rootList;
    }

@Override
    public TreeNode getTreeNode(String nodeId) {
        return this.treeNodesMap.get(nodeId);
    }

}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80

ITreeNode 接口:

package com.ips.tree;

public interface ITreeNode {
    public String getNodeId();
    public String getNodeName();
    public String getNodeParentId();
    public Integer getOrderNum();
}

1
    2
    3
    4
    5
    6
    7
    8

Org 类:

package com.ips.tree;

public class Org implements ITreeNode {
    private String uuid;
    private String parentId;
    private String name;
    private Integer orderNum;
    private String code;
    private String type;

public Org(){

}
    public Org(String uuid, String parentId, String name, Integer orderNum, String code, String type){
        this.uuid = uuid;
        this.parentId = parentId;
        this.name = name;
        this.orderNum = orderNum;
        this.code = code;
        this.type = type;
    }
    @Override
    public String getNodeId() {
        return this.uuid;
    }

@Override
    public String getNodeName() {
        return this.name;
    }

@Override
    public String getNodeParentId() {
        return this.parentId;
    }

@Override
    public Integer getOrderNum() {
        return this.orderNum;
    }

public String getUuid() {
        return uuid;
    }

public void setUuid(String uuid) {
        this.uuid = uuid;
    }

public String getParentId() {
        return parentId;
    }

public void setParentId(String parentId) {
        this.parentId = parentId;
    }

public String getName() {
        return name;
    }

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

public String getCode() {
        return code;
    }

public void setCode(String code) {
        this.code = code;
    }

public String getType() {
        return type;
    }

public void setType(String type) {
        this.type = type;
    }
    public void setOrderNum(Integer orderNum) {
        this.orderNum = orderNum;
    }

}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85

TreeDemo 类:执行该类的 main 方法,查看效果。

package com.ips.tree;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;

public class TreeDemo {

public static void main(String[] args) {
        Tree tree = new Tree(genOrgList());
        TreeNode treeNode = tree.getTreeNode("2");

SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); // 构造方法里,也可以直接传需要序列化的属性名字
        filter.getExcludes().add("parent");
        filter.getExcludes().add("allChildren");
        String data = JSONObject.toJSONString(treeNode, filter);
        System.out.println(data);
    }

public static List<ITreeNode> genOrgList(){
        List<ITreeNode> list = new ArrayList<ITreeNode>();

Org org = new Org("2", "1", "北京市", 2, "110000", "2");
        list.add(org);
        org = new Org("3", "2", "市辖区", 3, "110100", "3");
        list.add(org);
        org = new Org("4", "3", "东城区", 4, "110101", "4");
        list.add(org);
        org = new Org("5", "3", "东城区", 5, "110102", "4");
        list.add(org);
        org = new Org("6", "3", "东城区", 6, "110105", "4");
        list.add(org);
        org = new Org("7", "3", "东城区", 7, "110106", "4");
        list.add(org);
        org = new Org("8", "3", "东城区", 8, "110107", "4");
        list.add(org);
        org = new Org("9", "3", "东城区", 9, "110108", "4");
        list.add(org);
        org = new Org("10", "3", "东城区", 10, "110109", "4");
        list.add(org);
        org = new Org("11", "3", "东城区", 11, "110111", "4");
        list.add(org);
        org = new Org("12", "3", "东城区", 12, "110112", "4");
        list.add(org);
        org = new Org("13", "3", "东城区", 13, "110113", "4");
        list.add(org);
        org = new Org("14", "3", "东城区", 14, "110114", "4");
        list.add(org);
        org = new Org("15", "3", "东城区", 15, "110115", "4");
        list.add(org);
        org = new Org("16", "3", "东城区", 16, "110116", "4");
        list.add(org);
        org = new Org("17", "3", "东城区", 17, "110117", "4");
        list.add(org);
        org = new Org("18", "2", "县", 3, "110200", "3");
        list.add(org);
        org = new Org("19", "18", "密云县", 19, "110228", "4");
        list.add(org);
        org = new Org("20", "18", "延庆县", 20, "110229", "4");
        list.add(org);
        return list;
    }

}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66

执行结果如下:

{
    "nodeId": "2",
    "nodeName": "北京市",
    "parentNodeId": "1",
    "orderNum": 2,
    "level": 0,
    "children": [{
        "nodeId": "18",
        "nodeName": "县",
        "parentNodeId": "2",
        "orderNum": 3,
        "level": 0,
        "children": [{
            "nodeId": "19",
            "nodeName": "密云县",
            "parentNodeId": "18",
            "orderNum": 19,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "20",
            "nodeName": "延庆县",
            "parentNodeId": "18",
            "orderNum": 20,
            "level": 0,
            "children": []
        }]
    },
    {
        "nodeId": "3",
        "nodeName": "市辖区",
        "parentNodeId": "2",
        "orderNum": 3,
        "level": 0,
        "children": [{
            "nodeId": "17",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 17,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "15",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 15,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "16",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 16,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "13",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 13,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "14",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 14,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "11",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 11,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "12",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 12,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "10",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 10,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "7",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 7,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "6",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 6,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "5",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 5,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "4",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 4,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "9",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 9,
            "level": 0,
            "children": []
        },
        {
            "nodeId": "8",
            "nodeName": "东城区",
            "parentNodeId": "3",
            "orderNum": 8,
            "level": 0,
            "children": []
        }]
    }]
}

1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149

注:该示例中使用了 alibaba 的 fastjson 实现类对象序列化,maven 依赖如下:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.20</version>
</dependency>
---------------------
作者:zhiboer
来源:CSDN
原文:https://blog.csdn.net/claram/article/details/54616485
版权声明:本文为博主原创文章,转载请附上博文链接!

Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级的更多相关文章

  1. mssql sqlserver 使用sql脚本 清空所有数据库表数据的方法分享

    摘要: 下文讲述清空数据库中所有表信息的方法分享,如下所示: 实验环境:sql server 2008 实现思路: 1.禁用所有约束,外键 2.禁用所有触发器 3.删除表数据 4.开启触发器 5.开启 ...

  2. jmeter 获取数据库表数据作为参数

    jmeter - 获取数据库表数据作为参数 在jmeter中使用数据库表数据首先需要设置数据库连接,然后在创建JDBC取样器 1.创建配置元件 JDBC Connection Configuratio ...

  3. Atitit.数据库表的物理存储结构原理与架构设计与实践

    Atitit.数据库表的物理存储结构原理与架构设计与实践 1. Oracle和DB2数据库的存储模型如图: 1 1.1. 2. 表数据在块中的存储以及RowId信息3 2. 数据表的物理存储结构 自然 ...

  4. MSSQL 删除数据库表数据

    --删除数据库表数据 慎用 create PROCEDURE sp_DeleteAllData AS ) ) ) ) ) ) begin try begin tran -- 失效索引,触发器 open ...

  5. 【Java/JDBC】借助ResultSetMetaData,从数据库表中抽取字段信息存成Excel文件

    本例工程下载:https://files.cnblogs.com/files/xiandedanteng/FindNotnullColumns20191102-3.rar 工作中曾有个为42张表建立测 ...

  6. EasyUI_tree根据数据库数据生成树形结构JSON格式

    @Entitypublic class PubComp { @Id private String aguid; // 菜单ID private String pguid; // 父菜单 private ...

  7. SQL2008将服务器的数据库表数据插入到本地数据库

    一,配置参数 exec sp_configure reconfigure exec sp_configure RECONFIGURE 若不配置参数会出现,提示这个错误: SQL Server 阻止了对 ...

  8. 使用python将mysql数据库的数据转换为json数据

    由于产品运营部需要采用第三方个推平台,来推送消息.如果手动一个个键入字段和字段值,容易出错,且非常繁琐,需要将mysql的数据转换为json数据,直接复制即可. 本文将涉及到如何使用Python访问M ...

  9. 定时器中实现数据库表数据移动的功能,Exception in thread "Timer-0" isExist java.lang.NullPointerException定时器中线程报错。

    package com.shawnway.trade.marketdata.constants; import java.sql.SQLException; import java.util.Cale ...

随机推荐

  1. java生成webservice

    使用Eclipse生成一个WebService应用 1.创建一个Dynamic web project 2.创建一个对外提供服务的类.比如: package com.guorui.services; ...

  2. Mybatis Batch 批量操作

    Mybatis Batch 批量操作 http://www.blogjava.net/diggbag/articles/mybatis.html

  3. TensorFlow基础笔记(5) VGGnet_test

    参考 http://blog.csdn.net/jsond/article/details/72667829 资源: 1.相关的vgg模型下载网址 http://www.vlfeat.org/matc ...

  4. imx6 18bit display

    imx6 kernel中使用18bit的lcd,uboot中bootargs参数bpp=32,lcd才能够正常显示. "bootargs=console=ttymxc0,115200 ini ...

  5. HashMap与HashCode有关,用Sort对象排序

    遍历Map,使用keySet()可以返回set值,用keySet()得到key值,使用迭代器遍历,然后使用put()得到value值. 上面这个算法的关键语句: Set s=m.keySet(); I ...

  6. 【BZOJ】1699: [Usaco2007 Jan]Balanced Lineup排队(rmq/树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1699 我是用树状数组做的..rmq的st的话我就不敲了.. #include <cstdio& ...

  7. css字体属性相关。

    出处:CSS 参考手册    http://www.w3school.com.cn/cssref/index.asp text-decoration 属性 说明:这个属性允许对文本设置某种效果,如加下 ...

  8. @Override错误

    导入一个项目,项目所有类报  @Override 有错误,去掉就不报错了,原因?在 Java Compiler 将 Enable project specific setting 选中  然后再选择1 ...

  9. 盘点:七大.NET著名开源项目

    尽管过了相当长的时间,花费了不少资源,微软和.NET社区还是在最近几年加入到了开源运动的阵营中来了,这令人相当惊讶,因为两大阵营一直都是经常对立的.然而,事实是依靠开源,微软社区中的开源开发工具日益发 ...

  10. 导出数据到Excel方法总结

    一,问题的提出 近来在网上经常有人问怎样把数据导出到Excel中?针对这个问题网上也有很多资料.大都比较的琐碎.本人当前从事的项目中,刚好涉及到这些内容.就顺便做了一些归纳整理.共享给大家.避免大家再 ...