- 数据库表
- 实体类
- service层逻辑
- 效果
id为该课程唯一id,title为目录名称,parent_id为父目录id,父id为0代表为一级目录
EduSubject 为mp逆向工程生成实体类,用于查表封装数据
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "EduSubject对象", description = "课程科目")
public class EduSubject implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "课程类别ID")
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;
@ApiModelProperty(value = "类别名称")
private String title;
@ApiModelProperty(value = "父ID")
private String parentId;
@ApiModelProperty(value = "排序字段")
private Integer sort;
@ApiModelProperty(value = "创建时间")
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@ApiModelProperty(value = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
}
EduSubjectTree 用于将数据封装为树形结构,children为该目录的子目录
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EduSubjectTree {
private String id;
private String title;
private List children;
}
service层逻辑
思路是将数据库中课程分类的所有数据一次查出,然后再用popSubjectById方法筛选出一级目录,再让所有一级目录进入队列,再依次出队查询一级目录对应的二级目录,再让二级目录分别进队,再分别出队查对应三级目录,后面三级四级同理
准备popSubjectById方法,用于将list中pid为指定pid的分类删除并封装为一个EduSubjectTree类的list
private ListpopSubjectById(List list, String pid) { List listTree = new ArrayList<>(); if (pid == null) { pid = "0"; } for (int i = 0; i < list.size(); i++) { if (pid.equals(list.get(i).getParentId())) { listTree.add(new EduSubjectTree(list.get(i).getId(), list.get(i).getTitle(), null)); list.remove(i); i--; } } return listTree; }
getSubjectTree方法为返回封装好的树形分类列表
public ListgetSubjectTree() { // 获取数据库所有课程分类 List list = baseMapper.selectList(null); // 队列用于查每个元素的子菜单 LinkedList queue = new LinkedList<>(); // context为最后返回的目录 List context = new ArrayList<>(); // 将list中的一级目录(pid为“0”的分类菜单)删除并进队 queue.addAll(popSubjectById(list, "0")); // 将一级目录放入context context.addAll(queue); // 队列为空或者list长度不为0,则还有未处理的菜单 // 如果出现list中pid出错也不会导致死循环,因为队列会出队至空 // 如果list为空说明已经没有课程分类,也不需要再处理 while (!queue.isEmpty() || list.size() == 0) { // 队首元素出队 EduSubjectTree pop = queue.pop(); // 调用popSubjectById()方法获取list中队首元素的所有子菜单,并且popSubjectById方法会将这些子菜单从list中删除 List children = popSubjectById(list, pop.getId()); // 将查出来的子菜单赋值给pop.children pop.setChildren(children); // 再将这个子元素全部进队 // 如是二级菜单,则在查询完所有一级菜单的子菜单,这些二级菜单会出队用于查询他们的子菜单(即三级菜单) queue.addAll(children); } return context; }
可以看到前端开发三级目录封装完成
前端开发–vue–router
{
"success": true,
"code": 20000,
"message": "成功",
"data": {
"context": [
{
"id": "1522577148796497922",
"title": "前端开发",
"children": [
{
"id": "1522577149379506177",
"title": "vue",
"children": [
{
"id": "1522577153909351238",
"title": "router",
"children": []
}
]
},
{
"id": "1522577150042206209",
"title": "javascript",
"children": []
},
{
"id": "1522577150839123969",
"title": "jquery",
"children": []
}
]
},
{
"id": "1522577151422132226",
"title": "后端开发",
"children": [
{
"id": "1522577152009334785",
"title": "java",
"children": []
},
{
"id": "1522577152667840514",
"title": "c++",
"children": []
}
]
},
{
"id": "1522577153317957634",
"title": "数据库开发",
"children": [
{
"id": "1522577153909354497",
"title": "mysql",
"children": []
}
]
}
]
}
}
这个service逻辑是第一次用到了java的值传递实现两个方法同时操作一个对象,即在popSubjectById()方法中删除list中元素,同时也删除了getSubjectTree()方法中查询出所有课程分类的list,不知道这样会不会有别的问题,后续发现问题再更。
效果


