简单的递归遍历层级菜单生成封装数据

/ 默认分类 / 0 条评论 / 871浏览

遍历设计的层级菜单

一般我们都会有这样一种需求,在数据库中设计好了菜单的级别的数据,这样的每一个菜单都会设计一个父菜单的编号,然后我们需要遍历出所有的菜单,并且还是封装好的,(这样的问题我大学时期第一次参加实习就是遇到这样的需求需要解决,并且再后期的面试过程中也是遇到过这样的问题)

最终显示出的json格式的数据就是下面这样的

详细的输出菜单的代码如下所示:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("permission")
public class Permission implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    private String pid;

    private String name;

    private Integer type;

    private String permissionValue;

    private String path;

    private String component;

    private String icon;

    private Integer status;

    @TableField(exist = false)
    private Integer level;

    @TableField(exist = false)
    private List<Permission> children;

    @TableField(exist = false)
    private boolean isSelect;

    private Boolean isDeleted;

    private Date gmtCreate;

    private Date gmtModified;


}
@RestController
public class MyController {

    @Autowired
    MyService service;

    @GetMapping("/menu")
    public Permission getAllMenu()
    {
        Permission menu = service.getAllMenu();
        return menu;
    }

}
/**
 * @author CodeManZuo
 * @date 2020/5/6 - 15:07
 */
@Service
public class MyService {

    @Autowired
    PermissionMapper mapper;

    /**
     * TODO 获取封装好的显示菜单数据
     * Created by zuohui
     **/
    public Permission getAllMenu() {
        List<Permission> allPermissionList = mapper.selectList(null);
        Permission topParentPermission = findTopParentPermission(allPermissionList);
        topParentPermission = setChildenPermission(topParentPermission,allPermissionList);
        return topParentPermission;
    }

    /**
     * TODO 寻找最顶端父菜单
     * Created by zuohui
     **/
    private Permission findTopParentPermission(List<Permission> allPermissionList) {
        for (Permission permission : allPermissionList) {
            if(permission.getPid().equals("0"))
            {
                permission.setLevel(1);
                return permission;
            }
        }
        return null;
    }

    /**
     * TODO 递归封装菜单核心方法-设置子菜单
     * Created by zuohui
     **/
    private Permission setChildenPermission(Permission parentPermission, List<Permission> allPermissionList) {
        parentPermission.setChildren(new ArrayList<Permission>());
        for (Permission permission : allPermissionList) {
            if(permission.getPid().equals(parentPermission.getId()))
            {
                permission.setLevel(parentPermission.getLevel()+1);
                parentPermission.getChildren().add(setChildenPermission(permission,allPermissionList));
            }
        }
        return parentPermission;
    }
}

public interface PermissionMapper extends BaseMapper<Permission> {

}

分析

这里主要的业务逻辑代码就是service中的setChildenPermission()这个方法

  1. 第一步需要查询出所有的菜单对象
  2. 第二步需要在所有的菜单对象中查询出最顶端的菜单对象,其实这个菜单是不会显示出来的,知识一个作为封装子菜单的一个工具壳,所有的数据都是作为这个菜单的子菜单
  3. 第一次进入setChildrenPermission()方法参数就是最高的父级菜单对象和所有菜单数据集合对象
  4. 在setChildrenPermission中我们会遍历所有的菜单,找到当前setChildrenPermission方法的第一个参数parentPermission的子菜单,并且将遍历到的设置进来,在这里因为子菜单可能也是一个父菜单,所以设置的时候就是直接再次调用setChildenPermission,因为这个方法返回的值就是方法的第一个参数parentPermission,并且这个参数就是当前需要设置子菜单的父菜单;

每一个递归都会有一个入口和出口,很多时候我们的出口是一个if判断,如果符合条件就返回,这里我们的出口是for循环遍历结束