在网站开发的时候我们会对网站的栏目进行分类,一个栏目可以有多个子分类,一个子分类又可以有分裂,例如:新闻栏目下有每日早报和每日晚报两个栏目,其中每日早报下面又分为上海早报,北京早报,杭州早报,下面是京东首页的分类图。

 

数据库设计
我们在设计数据库的时候仅仅使用一张表就可以把上面的关系给捋清楚,就是通过一个parentid字段,让我们开看一下这张表的表结构
 

各位看官可以看一下建表语句
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键递增',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '分类名称',
`parentid` int(11) NULL DEFAULT NULL COMMENT '父节点id',
`url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '分类链接',
`icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '分类图标',
`order` int(11) NULL DEFAULT NULL COMMENT '分类排序权重',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

再让我们来插入一点测试数据

INSERT INTO `menu` VALUES (1, '新闻', 0, '/www/xinwen', 'xxx', 1);
INSERT INTO `menu` VALUES (2, '每日日报', 1, '/www/meiriribao', 'xxx', 2);
INSERT INTO `menu` VALUES (3, '每日晚报', 1, '/www/zaobao', 'xxx', 1);
INSERT INTO `menu` VALUES (4, '河南日报', 2, '/www/henan', 'xxx', 2);
INSERT INTO `menu` VALUES (5, '上海日报', 2, '/www/shanghai', 'xxx', 1);
INSERT INTO `menu` VALUES (6, '南京日报', 2, '/www/nanjing', 'xxx', 3);
INSERT INTO `menu` VALUES (7, '开封日报', 4, '/www/zhoukou', 'xxx', 2);
INSERT INTO `menu` VALUES (8, '郑州日报', 4, '/www/zhenghzou', 'xxx', 3);
 现在我们来看一下Java程序中该如何从数据库中读取数据这样的数据返回页面。在下在项目中用的是SSM框架因为并不是SSM框架教程,这里仅仅贴出Dao层,简单至极
List<Menu> findAll();
 <select id="findAll" resultMap="BaseResultMap">
select * from menu;
</select>
看一下菜单对应的实体

package com.sys.domain;

import java.util.List;

public class Menu implements Comparable<Menu> {
private Integer id; private String name; private Integer parentid; private String url; private String icon; private Integer order; //子菜单列表
private List<Menu> children; public List<Menu> getChildren() {
return children;
}
public void setChildren(List<Menu> children) {
this.children = children;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name == null ? null : name.trim();
} public Integer getParentid() {
return parentid;
} public void setParentid(Integer parentid) {
this.parentid = parentid;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url == null ? null : url.trim();
} public String getIcon() {
return icon;
} public void setIcon(String icon) {
this.icon = icon == null ? null : icon.trim();
} public Integer getOrder() {
return order;
} public void setOrder(Integer order) {
this.order = order;
} @Override
public int compareTo(Menu o) {
if (this.order != o.order) {
return this.order - o.order;
}
return 0;
}
}

实体关键点1:实体Menu实现了Comparable接口并实现了compareTo方法

这样就可以直接使用Collections.sort()方法进行List排序

实体关键点2:实体中新增一个属性List<Menu> children,用于存储返回页面的子节点

 

实体较介绍完了,我们就可以直接看代码啦,都加上注释了很简单

package com.sys.menutree;

import com.sys.dao.MenuMapper;
import com.sys.domain.Menu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import java.util.*; /**
* @Author:jimisun
* @Description:
* @Date:Created in 18:02 2018/8/8
* @Modified By:
*/
@Controller
@RequestMapping("/menu")
public class MenuController { @Autowired
private MenuMapper menuMapper; @RequestMapping(value = "/findTree", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> findTree(@RequestBody(required = false) Menu menu) {
//构建返回数据
Map<String, Object> data = new HashMap<String, Object>(); try {
//查询到的所有菜单
List<Menu> allMenu = menuMapper.findAll();
//根节点
List<Menu> rootMenu = new ArrayList<Menu>(); //根据传递的参数设置根节点
if (menu != null && menu.getId() != null) {
//父节点为传递的id为根节点
for (Menu nav : allMenu) {
if (nav.getParentid().equals(menu.getId())) {
rootMenu.add(nav);
}
}
} else {
//父节点是0的,为根节点。
for (Menu nav : allMenu) {
if (nav.getParentid().equals(0)) {
rootMenu.add(nav);
}
}
} // 根据Menu类的order排序
Collections.sort(rootMenu); //为根菜单设置子菜单,getClild是递归调用的
for (Menu nav : rootMenu) {
//获取根节点下的所有子节点 使用getChild方法
List<Menu> childList = getChild(nav.getId(), allMenu);
//给根节点设置子节点
nav.setChildren(childList);
} data.put("success", "true");
data.put("list", rootMenu);
return data;
} catch (Exception e) {
data.put("success", "false");
data.put("list", new ArrayList());
return data;
} } /**
* 递归设置栏目的子节点
*
* @param id 父节点id
* @param allMenu 节点列表
* @return
*/
private List<Menu> getChild(Integer id, List<Menu> allMenu) {
//子菜单
List<Menu> childList = new ArrayList<Menu>();
for (Menu nav : allMenu) {
// 遍历所有节点,将所有菜单的父id与传过来的根节点的id比较
//相等说明:为该根节点的子节点。
if (nav.getParentid().equals(id)) {
childList.add(nav);
}
}
//递归设置子节点
for (Menu nav : childList) {
nav.setChildren(getChild(nav.getId(), allMenu));
}
//排序
Collections.sort(childList);
//如果节点下没有子节点,返回一个空List(递归退出)
if (childList.size() == 0) {
return new ArrayList<Menu>();
}
return childList;
} }

最后我们来看一下功能演示

直接发送直接请求接口,获取的是所有分类

请求结果

{
"success": "true",
"list": [
{
"id": 5,
"name": "上海日报",
"parentid": 2,
"url": "/www/shanghai",
"icon": "xxx",
"order": 1,
"children": []
},
{
"id": 4,
"name": "河南日报",
"parentid": 2,
"url": "/www/henan",
"icon": "xxx",
"order": 2,
"children": [
{
"id": 7,
"name": "开封日报",
"parentid": 4,
"url": "/www/zhoukou",
"icon": "xxx",
"order": 2,
"children": []
},
{
"id": 8,
"name": "郑州日报",
"parentid": 4,
"url": "/www/zhenghzou",
"icon": "xxx",
"order": 3,
"children": []
}
]
},
{
"id": 6,
"name": "南京日报",
"parentid": 2,
"url": "/www/nanjing",
"icon": "xxx",
"order": 3,
"children": []
}
]
}

发送请求接口,并附带要查询的分类id

结果如下

{
"success": "true",
"list": [
{
"id": 5,
"name": "上海日报",
"parentid": 2,
"url": "/www/shanghai",
"icon": "xxx",
"order": 1,
"children": []
},
{
"id": 4,
"name": "河南日报",
"parentid": 2,
"url": "/www/henan",
"icon": "xxx",
"order": 2,
"children": [
{
"id": 7,
"name": "开封日报",
"parentid": 4,
"url": "/www/zhoukou",
"icon": "xxx",
"order": 2,
"children": []
},
{
"id": 8,
"name": "郑州日报",
"parentid": 4,
"url": "/www/zhenghzou",
"icon": "xxx",
"order": 3,
"children": []
}
]
},
{
"id": 6,
"name": "南京日报",
"parentid": 2,
"url": "/www/nanjing",
"icon": "xxx",
"order": 3,
"children": []
}
]
}

Java构建网站多级菜单功能解决方案的更多相关文章

  1. java实现网站paypal支付功能并且异步修改订单的状态

    java实现网站paypal支付功能并且异步修改订单的状态:步骤如下 第一步:去paypal的官网https://www.paypal.com注册一个个人账号,在创建沙箱测试账号时需要用到 第二步:p ...

  2. java生成多级菜单树

    使用java实现一个多级菜单树结构 先上数据库 ps_pid字段很重要,是父级菜单的id Menu类 Menu类要新增一个字段,用来存放子菜单 /** * 子菜单列表 */ private List& ...

  3. Python简单实现多级菜单

    # -*- coding: utf-8 -*- # @Time : 2018-06-01 13:40 # @Author : 超人 # @Email : huxiaojiu111@gmail.com ...

  4. Atitit.excel导出 功能解决方案 php java C#.net版总集合.doc

    Atitit.excel导出 功能解决方案 php java C#.net版总集合.docx 1.1. Excel的保存格式office2003 office2007/2010格式1 1.2. 类库选 ...

  5. java 24 - 7 GUI之 创建多级菜单窗体

    需求: 创建多级菜单 步骤: A:创建窗体对象(并设置属性和布局) B:创建菜单栏 C:创建菜单和子菜单 D:逐步添加菜单(子菜单添加到菜单中,菜单添加到菜单栏中) E:窗体中设置菜单栏(菜单栏并不是 ...

  6. Vue2 实现树形菜单(多级菜单)功能模块

    结构示意图 ├── index.html ├── main.js ├── router │ └── index.js # 路由配置文件 ├── components # 组件目录 │ ├── App. ...

  7. 网站开发---js与java实现的一些小功能

    记录一下网站开发过程中的一些小功能 1.js获取当前年份: <span>Copyright © 2017-<script>document.write( new Date(). ...

  8. 使用Java语言开发微信公众平台(八)——自定义菜单功能

    随着上一篇文章的结束,我们已经实现了所有消息的类型的回复功能.今天,我们来学习更加高大上,也更加重要的自定义菜单功能. 一.了解自定义菜单 自定义菜单是微信公众平台最常用也是最重要的功能之一.根据微信 ...

  9. Java中各类Cache机制实现解决方案[来自CSDN]

    摘要:在Java中,不同的类都有自己单独的Cache机制,实现的方法也可能有所不同,文章列举了Java中常见的各类Cache机制的实现方法,同时进行了综合的比较. 在Java中,不同的类都有自己单独的 ...

随机推荐

  1. autoHotKey 一些脚本积累

    新建test.ahk,然后运行即可. #InstallKeybdHook #Persistent Hotstring("EndChars", "`n") ; 设 ...

  2. MySQL中多表删除方法

    如果您是才接触MySQL数据库的新人,那么MySQL中多表删除是您一定需要掌握的,下面就将为详细介绍MySQL中多表删除的方法,供您参考,希望对你学习掌握MySQL中多表删除能有所帮助. 1.从MyS ...

  3. [Jobdu] 题目1373:整数中1出现的次数(从1到n整数中1出现的次数)

    题目描述: 亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他.问题是:求出1~13的整数中1出现的次数,并算出100~130 ...

  4. spring boot文件上传、下载

    主题:Spring boot 文件上传(多文件上传)[从零开始学Spring Boot]http://www.iteye.com/topic/1143595 Spring MVC实现文件下载http: ...

  5. spring-boot 中application.properties的各种配置

    ###########################################################datasource connect mysql################# ...

  6. jquery 取第一个兄弟节点

    1.HTML <table> <tr> <td>1</td> <td>abc</td> <td>def</td ...

  7. linux用户空间和内核空间(内核高端内存)_转

    转自:Linux用户空间与内核空间(理解高端内存) 参考: 1. 进程内核栈.用户栈 2. 解惑-Linux内核空间 3. linux kernel学习笔记-5 内存管理   Linux 操作系统和驱 ...

  8. Dom监听组合按键

    JS监听组合按键   有些时候,我们需要在网页上,增加一些快捷按键,方便用户使用一些常用的操作,比如:保存,撤销,复制.粘贴等等. 下面简单梳理一下思路: 我们所熟悉的按键有这么集中类型: 单独的按键 ...

  9. 打开palette控制面板

    (2)

  10. yii2 输出json的方法

    public function actionAjax() { if(isset(Yii::$app->request->post('test'))){ $test = "Ajax ...