先设计数据库,数据库设计如下:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for jrbac_menu
-- ----------------------------
DROP TABLE IF EXISTS `jrbac_menu`;
CREATE TABLE `jrbac_menu` (
`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id,uuid32位',
`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '登录用户名',
`parent_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父菜单id',
`url` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '访问地址',
`icon` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '菜单图标',
`m_order` tinyint(4) DEFAULT 0 COMMENT '菜单顺序',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of jrbac_menu
-- ----------------------------
INSERT INTO `jrbac_menu` VALUES ('1', 'Forms', NULL, 'forms.html', 'fa fa-edit', 0);
INSERT INTO `jrbac_menu` VALUES ('2', 'UI Elements', NULL, '', 'fa fa-wrench', 1);
INSERT INTO `jrbac_menu` VALUES ('3', 'Buttons', '2', 'buttons.html', '', 0);
INSERT INTO `jrbac_menu` VALUES ('4', 'Icons', '2', 'icons.html', NULL, 1);
INSERT INTO `jrbac_menu` VALUES ('5', 'Multi-Level Dropdown', '', '', 'fa fa-sitemap', 2);
INSERT INTO `jrbac_menu` VALUES ('6', 'Second Level Item', '5', 'second.html', NULL, 0);
INSERT INTO `jrbac_menu` VALUES ('7', 'Third Level', '5', NULL, '', 1);
INSERT INTO `jrbac_menu` VALUES ('8', 'Third Level Item', '7', 'third.html', NULL, 0);
SET FOREIGN_KEY_CHECKS = 1;
菜单表字段分别有主键id、登录用户名、父菜单id、点击后的访问地址、菜单图标以及菜单顺序(优先级),并插入了一些数据,最顶级菜单的父菜单id为空
在java springboot中先在xml配置文件创建一个查询的mapperxml:
<?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">
<mapper namespace="com.example.demo.mapper.MenuMapper">
<select id="menuList" resultType="com.example.demo.entity.Menu">
select * from jrbac_menu order by m_order;
</select>
</mapper>
数据库交互使用的是mybatis-plus可以自动转驼峰。
mapper层:
public interface MenuMapper extends BaseMapper<Menu> {
List<Menu> menuList();
}
service层:
public interface MenuService extends IService<Menu> {
List<Menu> menuList();
}
service层的impl层:
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
@Override
public List<Menu> menuList() {
return this.baseMapper.menuList();
}
}
菜单pojo(javabean实体类):
@Data //注解自动生成set、get、tostring方法
public class Menu {
private String id;
private String name;
private String parentId;
private String url;
private String icon;
private Long mOrder;
//存放子菜单的列表
private List<Menu> childMenus;
}
controller层:
@Controller
@RequestMapping("menu")
public class MenuController {
@Autowired
private MenuService menuService;
@RequestMapping("menuJson")
@ResponseBody
public List<Menu> jsonMenu(){
//获取全部菜单
List<Menu> pmenu = menuService.menuList();
List<Menu> jsonMenu=new ArrayList<>();
//遍历菜单,判断是一级菜单的添加到要返回的json数据
for(Menu menu:pmenu){
if(StringUtils.isEmpty(menu.getParentId())){
jsonMenu.add(menu);
}
}
//给一级菜单添加子菜单,调用下面的递归方法加入进去
for(Menu menu:jsonMenu){
menu.setChildMenus(getChild(menu.getId(),pmenu));
}
return jsonMenu;
}
//添加子菜单的递归方法
private List<Menu> getChild(String id, List<Menu> pmenu) {
List<Menu> jsonMenu=new ArrayList<>();
//遍历全部菜单,是否有符合即不是一级菜单又父菜单id等于参数id的,添加到list中
for(Menu menu:pmenu){
if(!StringUtils.isEmpty(menu.getParentId())) {
if (menu.getParentId().equals(id)) {
jsonMenu.add(menu);
}
}
}
//遍历子菜单,看子菜单是否有点击路径,没有说明还有子菜单下还有子菜单继续递归添加子菜单
for(Menu menu:jsonMenu){
if(StringUtils.isEmpty(menu.getUrl())){
menu.setChildMenus(getChild(menu.getId(), pmenu));
}
}
//递归出口,若返回的子菜单list是空,就结束
if(jsonMenu.size()==0){
return null;
}
return jsonMenu;
}
}
使用postman测试结果:
[
{
"id": "1",
"name": "Forms",
"parentId": null,
"url": "forms.html",
"icon": "fa fa-edit",
"childMenus": null,
"morder": 0
},
{
"id": "2",
"name": "UI Elements",
"parentId": null,
"url": "",
"icon": "fa fa-wrench",
"childMenus": [
{
"id": "3",
"name": "Buttons",
"parentId": "2",
"url": "buttons.html",
"icon": "",
"childMenus": null,
"morder": 0
},
{
"id": "4",
"name": "Icons",
"parentId": "2",
"url": "icons.html",
"icon": null,
"childMenus": null,
"morder": 1
}
],
"morder": 1
},
{
"id": "5",
"name": "Multi-Level Dropdown",
"parentId": "",
"url": "",
"icon": "fa fa-sitemap",
"childMenus": [
{
"id": "6",
"name": "Second Level Item",
"parentId": "5",
"url": "second.html",
"icon": null,
"childMenus": null,
"morder": 0
},
{
"id": "7",
"name": "Third Level",
"parentId": "5",
"url": null,
"icon": "",
"childMenus": [
{
"id": "8",
"name": "Third Level Item",
"parentId": "7",
"url": "third.html",
"icon": null,
"childMenus": null,
"morder": 0
}
],
"morder": 1
}
],
"morder": 2
}
]