This is the 17th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
The complete example code addresses are as follows: github.com/Dr-Water/sp…
First, the origin of the problem of permission tree
- In the development, it is inevitable to encounter a multi-level menu structure tree, or multi-level department structure tree, or multi-level province, district and county structure, data structure is similar to the following JSON data:
[{"id": "1"."name": "Main Menu 1"."pid": "0"."menuChildren": [{"id": "4"."name": "Submenu 1.1"."pid": "1"."menuChildren": [{"id": "6"."name": "Submenu 1.1.1"."pid": "4"."menuChildren": []}, {"id": "9"."name": "Submenu 1.1.2"."pid": "4"."menuChildren": []}]}, {"id": "5"."name": "Submenu 1.2"."pid": "1"."menuChildren": []}]}, {"id": "2"."name": "Main Menu 2"."pid": "0"."menuChildren": [{"id": "Seven"."name": "Submenu 2.1"."pid": "2"."menuChildren": []}, {"id": "8"."name": "Submenu 2.2"."pid": "2"."menuChildren": []}]}, {"id": "3"."name": "Main Menu 3"."pid": "0"."menuChildren": []}]Copy the code
Second, solutions
Current solutions mainly include the following two solutions:
- Scheme 1: The back end returns all the required data to the front end in a big list, and the front end performs operations to make the data into a tree structure
- There are two solutions to this problem: the backend makes the data into a hierarchical structure before the backend returns it
- Method 1: Secondary data query, in the Java program to build the tree structure
- Method two: the first time to query the highest level of data, and then repeatedly query the database to query the sub-data
Since the front-end level of the blogger is limited, only the back-end implementation method can be used at present, and the cost of each query database is relatively high, so this paper uses method 1 of scheme 2 for verification
Implementation steps
Take the structure tree of a menu
- Prepare basic data for the mysql database
2. Java entity classes
@Data
@NoArgsConstructor
public class Menu implements Serializable {
private String id;
private String name;
private String pid;
private List<Menu> menuChildren;
}
Copy the code
- Java dao layer
@Mapper
public interface MenuDao {
/** * Query subclass menu * by parent class ID@param pid
* @return* /
List<Menu> selectByPid(Integer pid);
/** * query all menus *@return* /
List<Menu> selectAll(a);
/** * query the menu except the first level menu *@return* /
List<Menu> selectAllNotBase(a);
}
Copy the code
- Mapper file
<! DOCTYPEmapper
PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ratel.shiro.dao.MenuDao">
<select id="selectByPid" resultType="com.ratel.shiro.entity.Menu">
SELECT * FROM menu WHERE pid=#{pid}
</select>
<select id="selectAll" resultType="com.ratel.shiro.entity.Menu">
SELECT * FROM menu
</select>
<select id="selectAllNotBase" resultType="com.ratel.shiro.entity.Menu">SELECT * FROM menu where pid! = 0</select>
</mapper>
Copy the code
- Controller layer (since it is query operation, and no complex operation, lazy not write service layer)
@RestController
@RequestMapping("mymenu")
public class MenuController {
@Autowired
private MenuDao menuDao;
@RequestMapping("/getMenuTree")
public List<Menu> getMenuTree(a){
List<Menu> menusBase = menuDao.selectByPid(0);
List<Menu> menuLNotBase = menuDao.selectAllNotBase();
for (Menu menu : menusBase) {
List<Menu> menus = iterateMenus(menuLNotBase, menu.getId());
menu.setMenuChildren(menus);
}
return menusBase;
}
/** * multilevel menu query method *@paramMenuVoList is a collection of menus that does not contain the highest level menus *@paramPid Parent class ID *@return* /
public List<Menu> iterateMenus(List<Menu> menuVoList,String pid){
List<Menu> result = new ArrayList<Menu>();
for (Menu menu : menuVoList) {
// Get the menu id
String menuid = menu.getId();
// Get the parent id of the menu
String parentid = menu.getPid();
if(StringUtils.isNotBlank(parentid)){
if(parentid.equals(pid)){
// Recursively queries submenus of the current submenuList<Menu> iterateMenu = iterateMenus(menuVoList,menuid); menu.setMenuChildren(iterateMenu); result.add(menu); }}}returnresult; }}Copy the code
- The launcher tests with Postman:
The json data returned is as follows:
[{"id": "1"."name": "Main Menu 1"."pid": "0"."menuChildren": [{"id": "4"."name": "Submenu 1.1"."pid": "1"."menuChildren": [{"id": "6"."name": "Submenu 1.1.1"."pid": "4"."menuChildren": []}, {"id": "9"."name": "Submenu 1.1.2"."pid": "4"."menuChildren": []}]}, {"id": "5"."name": "Submenu 1.2"."pid": "1"."menuChildren": []}]}, {"id": "2"."name": "Main Menu 2"."pid": "0"."menuChildren": [{"id": "Seven"."name": "Submenu 2.1"."pid": "2"."menuChildren": []}, {"id": "8"."name": "Submenu 2.2"."pid": "2"."menuChildren": []}]}, {"id": "3"."name": "Main Menu 3"."pid": "0"."menuChildren": []}]Copy the code
Reference links: Java recursive processing permission management menu tree or classification once done permission tree traversal ——– permission tree background traversal general solution (Java background) user permissions multi-level menu traversal method Java with recursive implementation of the ball upper and lower levels (involves the removal of the upper level) Java recursion gets a summary of the Java recursion algorithm for all child nodes below a parent node