3. Menu management list data presentation
3.1 data architecture analysis
After loading the menu list page, start the asynchronous loading operation of menu data. This menu list page should present the menu and superior menu information. During data query, the data encapsulation and transmission process is shown in figure-8.
Figure-8
Note: This module encapsulates the menu data queried from the database into a map object. One map object is recorded in one row, where key is the field (column) name in the table and value is the value corresponding to the field (column).
The timing analysis of data loading process is shown in figure-9:
Figure-9
3.2 key business and code implementation of server
3.2.1 Dao interface implementation
- Business description and design implementation
Through the data layer object, query the menu and parent menu information (to query the parent menu name) based on the business layer parameters.
- Key code analysis and Implementation
Step 1: define the data layer interface object, and access the menu data in the database through this object. The key codes are as follows:
@Mapper public interface SysMenuDao { }
Step 2: add the findObjects method in the SysMenuDao interface to realize the query operation of menu data based on this method. The code is as follows:
List<Map<String,Object>> findObjects();
Note: a row of records is mapped to a map object, and multiple rows are stored in the list.
Think: why use map to store data here? What are the advantages and disadvantages?
3.2.2 Mapper file implementation
- Business description and design implementation
Create a mapping file based on the Dao interface, in which the data operations to be performed are described by related elements (such as select).
- Key code design and Implementation
Step 1: add the SysMenuMapper.xml mapping file in the design directory of the mapping file. The code is as follows:
<?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.cy.pj.sys.dao.SysMenuDao"> </mapper>
Step 2: add the findObjects element with id in the mapping file to realize paging query. The key codes are as follows:
<select id="findObjects" resultType="map"> <!-- Option 1 select c.*,p.name parentName from sys_menus c left join sys_menus p on c.parentId=p.id --> <!-- Option 2 --> select c.*,( select p.name from sys_menus p where c.parentId=p.id ) parentName from sys_menus c </select>
Description: Auto Association query analysis, as shown in figure-10:
Figure-10
Test class:
package com.cy.pj.sys.dao; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class SysMenuDaoTests { @Autowired private SysMenuDao sysMenuDao; @Test public void testFindObjects() { List<Map<String,Object>> list= sysMenuDao.findObjects(); for(Map<String,Object> map:list) { System.out.println(map); } System.out.println(list.size()); } }
3.2.3 Service interface and implementation class
- Business description and design implementation
In menu query, the business layer object mainly completes the query of menu data with the help of data layer object. Later, you can cache data and record access logs based on AOP.
- Key code design and Implementation
Step 1: define the menu service interface and method to expose the external access to the menu service data. The code reference is as follows:
package com.cy.pj.sys.service; public interface SysMenuService { List<Map<String,Object>> findObjects(); }
Step 2: define the menu business interface implementation class and add the query operation implementation corresponding to the menu business data. The code reference is as follows:
package com.cy.pj.sys.service.impl; @Service public class SysMenuServiceImpl implements SysMenuService{ @Autowired private SysMenuDao sysMenuDao; @Override public List<Map<String, Object>> findObjects() { //... //... return sysMenuDao.findObjects(); } }
3.2.4 Controller class implementation
- Business description and design implementation
The control layer object is mainly responsible for the processing of request and response data. For example, this module executes business logic through the business layer object, encapsulates the response result through the VO object (mainly adds status information to the business layer data), and finally converts the response result into a character string in JSON format to respond to the client.
- Key code design and Implementation
Define the Controller class and identify such objects with the @ Controller annotation in the Spring framework, indicating that such objects are to be managed by Spring. Then define a root path mapping for this class based on the @ RequestMapping annotation.
The code reference is as follows:
package com.cy.pj.sys.controller; @RequestMapping("/menu/") @RestController public class SysMenuController { }
Note: the @ RestController annotation here is equivalent to adding @ Controller and @ ResponseBody annotations on the class at the same time, and adding menu query processing methods in the Controller class. The code reference is as follows:
@RequestMapping("doFindObjects") public JsonResult doFindObjects() { return new JsonResult(sysMenuService.findObjects()); }
3.3 client key business and code implementation
3.3.1 menu list information presentation
- Business description and design implementation
After the menu page is loaded, an asynchronous request is sent to the server to load the menu information. When the menu information is loaded, the menu information needs to be presented on the list page.
- Key code design and Implementation
Step 1: introduce JS related to treeGrid plug-in on the menu list page.
<script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.extension.js"></script> <script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.min.js"></script> <script type="text/javascript" src="bower_components/treegrid/tree.table.js"></script>
Step 2: on the menu list page, define the menu list configuration information. The key codes are as follows:
var columns = [ { field : 'selectItem', radio : true }, { title : 'menu ID', field : 'id', align : 'center', valign : 'middle', width : '80px' }, { title : 'Menu name', field : 'name', align : 'center', valign : 'middle', width : '130px' }, { title : 'Superior menu', field : 'parentName', align : 'center', valign : 'middle', sortable : true, width : '100px' }, { title : 'type', field : 'type', align : 'center', valign : 'middle', width : '70px', formatter : function(item, index) { if (item.type == 1) { return '<span class="label label-success">menu </span>'; } if (item.type == 2) { return '<span class="label label-warning">Button </span>'; } } }, { title : 'Sort number', field : 'sort', align : 'center', valign : 'middle', sortable : true, width : '70px' }, { title : 'menu URL', field : 'url', align : 'center', valign : 'middle', width : '160px' }, { title : 'Authorization ID',//Title name to display field : 'permission',//key in json string align : 'center',//horizontally valign : 'middle',//Vertical center sortable : false //Sort } ];//The format comes from the official demos -- > treegrid (a grid tree plug-in of jQuery extension)
Step 3: define the asynchronous request processing function. The code reference is as follows:
function doGetObjects(){//treeGrid //1. Build a table object (provided by treeGrid plug-in in bootstrap framework) var treeTable=new TreeTable( "menuTable",//tableId "menu/doFindObjects",//url columns); //Set which column to expand from (the default is the first column) //treeTable.setExpandColumn(2); //2. Initialize the table object (the bottom layer sends an ajax request to get data) treeTable.init();//getJSON,get(),... } Step 4: after the page is loaded, call the asynchronous request processing function corresponding to the menu query. The key codes are as follows: $(function(){ doGetObjects(); })
4. (extracurricular expansion) implementation of menu management deletion
4.1 business timing analysis
The deletion operation is performed based on the menu record id selected by the user on the list page. In this deletion business implementation, first judge whether the current menu has a submenu based on the id. if there is a submenu, it is not allowed to delete. If not, delete the menu role relationship data first, and then delete the menu information. The time sequence analysis is shown in figure-11:
As shown in figure-11
4.2 key business and code implementation of server
4.2.2 Dao interface implementation
- Business description and design implementation
The data layer deletes the menu role relationship and menu data based on the menu record id submitted by the business layer, and records the information of the menu itself.
- Key code design and Implementation
Step 1: create sysrolemeudao and define the method to delete relationship data based on menu id. the key codes are as follows:
@Mapper public interface SysRoleMenuDao { int deleteObjectsByMenuId(Integer menuId); }
Step 2: add a method to query submenu records based on menu id in SysMenuDao. The code reference is as follows:
int getChildCount(Integer id);
Step 3: add a method to delete menu records based on menu id in SysMenuDao. The code reference is as follows:
int deleteObject(Integer id);
4.2.3 Mapper file implementation
- Business description and design implementation
In the mapping file corresponding to the sysrolemendao and sysmenudao interfaces, add the delete element used to execute the deletion business, and then define the specific SQL implementation inside the element.
- Key code design and Implementation
Step 1: create a sysrolemenmapper.xml file and add an element to delete relational data based on menu id. the key code is as follows:
<?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.cy.pj.sys.dao.SysRoleMenuDao"> <delete id="deleteObjectsByMenuId" parameterType="int"> delete from sys_role_menus where menu_id=#{menuId} </delete> </mapper>
Step 2: add the element of counting the number of submenus based on id in SysMenuMapper.xml file. The key code is as follows:
<select id="getChildCount" parameterType="int" resultType="int"> select count(*) from sys_menus where parentId=#{id} </select>
Step 3: add the delete element in the SysMenuMapper.xml file to delete the recorded information of the menu based on the single id. the key codes are as follows:
<delete id="deleteObject"> delete from sys_menus where id =#{id} </delete>
4.2.4 Service interface and implementation class
- Business description and design implementation
The method for executing menu deletion service is defined in the menu service layer. Firstly, the menu id transmitted by the control layer is received through the method parameters, and the parameter id is verified. Then count the number of submenus based on the menu id. if there is a submenu, an exception will be thrown, indicating that deletion is not allowed. If there is no submenu, delete the role menu relationship data first. Finally, delete the recorded information of the menu itself and return the business execution result.
- Key code design and Implementation
Step 1: in the SysMenuService interface, add a method to delete a menu based on id. The key codes are as follows:
int deleteObject(Integer id);
Step 2: inject sysrolemendoao related objects into the SysMenuServiceImpl implementation class. The key codes are as follows:
@Autowired private SysRoleMenuDao sysRoleMenuDao;
Step 2: add and delete the specific implementation of the business in the SysMenuServiceImpl implementation class. The key codes are as follows:
@Override public int deleteObject(Integer id) { //1. Verify the legitimacy of the data if(id==null||id<=0) throw new IllegalArgumentException("Please select first"); //2. Query sub elements based on id int count=sysMenuDao.getChildCount(id); if(count>0) throw new ServiceException("Please delete the submenu first"); //3. Delete role and menu relation data sysRoleMenuDao.deleteObjectsByMenuId(id); //4. Delete menu elements int rows=sysMenuDao.deleteObject(id); if(rows==0) throw new ServiceException("This menu may no longer exist"); //5. Return results return rows; }
4.2.5 Controller class implementation
- Business description and design implementation
In the menu control layer object, add a method for processing menu deletion requests. First, in this method, the data submitted by the client is received through the formal parameters, then the business layer object is executed to perform the deletion operation, and finally the execution result is encapsulated, and the response object is converted to a JSON format string at runtime to respond to the client.
- Key code design and Implementation
Step 1: add a method for deleting business in SysMenuController. The code is as follows:
@RequestMapping("doDeleteObject") public JsonResult doDeleteObject(Integer id){ sysMenuService.deleteObjects(id); return new JsonResult("delete ok"); }
Step 2: start tomcat for access test, open the browser and enter the following website:
http://localhost/menu/doDeleteObject?id=10
4.3 client key business and code implementation
4.3.1 menu list page event handling
- Business description and design implementation
On the page, the user first selects the element to be deleted, then clicks the delete button to asynchronously submit the record id selected by the user to the server, and finally executes the menu deletion action on the server.
- Key code design and Implementation
Step 1: after the page is loaded, register the click event on the delete button. The key codes are as follows:
... $(".input-group-btn") .on("click",".btn-delete",doDeleteObject) ...
Step 2: define the event handling function corresponding to the deletion operation. The key codes are as follows:
function doDeleteObject(){ //1. Get the selected record id var id=doGetCheckedId(); if(!id){ alert("Please select first"); return; } //2. Give a prompt to confirm deletion if(!confirm("Are you sure to delete"))return; //3. Asynchronously submit request to delete data var url="menu/doDeleteObject"; var params={"id":id}; $.post(url,params,function(result){ if(result.state==1){ alert(result.message); $("tbody input[type='radio']:checked") .parents("tr").remove(); }else{ alert(result.message); } }); }
Step 3: define the function to obtain the record id selected by the user. The key codes are as follows:
function doGetCheckedId(){ //1. Get the selected record var selections=$("#menuTable") //Bootstrap treetable is a jquery extension function defined internally by the treeGrid plug-in //getSelections is a method to be called inside the extension function .bootstrapTreeTable("getSelections"); //2. Judge the records if(selections.length==1) return selections[0].id; }