springboot 動吧項目菜單模塊


  1.  

    菜單管理設計說明

    1. 業務設計說明

菜單管理又稱為資源管理,是系統資源對外的表現形式。本模塊主要是實現對菜單進行添加、修改、查詢、刪除等操作,其表設計語句如下:

CREATE TABLE `sys_menus` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '資源名稱',
  `url` varchar(200) DEFAULT NULL COMMENT '資源URL',
  `type` int(11) DEFAULT NULL COMMENT '類型     1:菜單   2:按鈕',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  `note` varchar(100) DEFAULT NULL COMMENT '備注',
  `parentId` int(11) DEFAULT NULL COMMENT '父菜單ID,一級菜單為0',
  `permission` varchar(500) DEFAULT NULL COMMENT '授權(如:sys:user:create)',
  `createdTime` datetime DEFAULT NULL COMMENT '創建時間',
  `modifiedTime` datetime DEFAULT NULL COMMENT '修改時間',
  `createdUser` varchar(20) DEFAULT NULL COMMENT '創建用戶',
  `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改用戶',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='資源管理';

菜單表與角色表是多對多的關系,在表設計時,多對多關系通常由中間表(關系表)進行維護,如圖-1所示:

 

 

 

基於角色菜單表的設計,其角色和菜單對應的關系數據要存儲到關系表中,其具體存

儲形式,如圖-2所示:

 

 

 

 

菜單與角色的關系表腳本設計如下:

 

CREATE TABLE `sys_role_menus` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) DEFAULT NULL COMMENT '角色ID',
  `menu_id` int(11) DEFAULT NULL COMMENT 'ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='角色與菜單對應關系';
  1. 原型設計說明

基於用戶需求,實現菜單靜態頁面(html/css/js),通過靜態頁面為用戶呈現菜單模塊的基本需求實現。

當在主頁左側菜單欄,點擊菜單管理時,在主頁內容呈現區,呈現菜單列表頁面,如

圖-3所示。

 

 

 

 

當在菜單列表頁面點擊添加按鈕時,異步加載菜單編輯頁面,並在列表內容呈現區,

呈現菜單編輯頁面,如圖-4所示。

 

 

 

在菜單編輯頁面選擇上級菜單時,異步加載菜單信息,並以樹結構的形式呈現上級菜

單,如圖-5所示。

 

 

 

 

  1. API設計說明

菜單管理業務后台API分層架構及調用關系如圖-6所示:

 

 

 

 

 

  1. 菜單管理列表頁面呈現

    1. 業務時序分析

菜單管理頁面的加載過程,其時序分析如圖-7所示:

 

 

 

 

  1. Controller實現

  • 業務描述與設計實現

基於菜單管理的請求業務,在PageController中添加doMenuUI方法,用於返回菜單列表頁面。

  • 關鍵代碼設計與實現

第一步:在PageController中定義返回菜單列表的方法。代碼如下:

 

@RequestMapping("menu/menu_list")
public String doMenuUI() {
    return "sys/menu_list";
}
 

第二步:在PageController中基於rest風格的url方式優化返回UI頁面的方法。找出共性進行提取,例如:

 

@RequestMapping("{module}/{moduleUI}")
public String doModuleUI(@PathVariable String moduleUI) {
        return "sys/"+moduleUI;
}
  1. 客戶端實現

    1. 首頁菜單事件處理

  • 業務描述與設計實現

首先准備菜單列表頁面(/templates/pages/sys/menu_list.html),然后在starter.html頁面中點擊菜單管理時異步加載菜單列表頁面。

  • 關鍵代碼設計與實現

找到項目中的starter.html頁面,頁面加載完成以后,注冊菜單管理項的點擊事件,當點擊菜單管理時,執行事件處理函數。關鍵代碼如下:

 

$(function(){
     …
     doLoadUI("load-menu-id","menu/menu_list")
})

說明:對於doLoadUI函數,假如在starter.html中已經定義,則無需再次定義.

 

 
function doLoadUI(id,url){
     $("#"+id).click(function(){
            $("#mainContentId").load(url);
   });
}

菜單管理列表數據呈現

  1. 數據架構分析

菜單列表頁面加載完成,啟動菜單數據異步加載操作,本次菜單列表頁面要呈現菜單以及2息,其數據查詢時,數據的封裝及傳遞過程,如圖-8所示。

 

 

 

 說明:本模塊將從數據庫查詢到的菜單數據封裝到map對象,一行記錄一個map對象,其中key為表中的字段(列)名,值為字段(列)對應的值。時序圖如下

 

 

 

  1. 服務端關鍵業務及代碼實現

    1. Dao接口實現

  • 業務描述及設計實現

通過數據層對象,基於業務層參數,查詢菜單以及上級菜單信息(要查詢上級菜單名)。 

  • 關鍵代碼分析及實現

第一步:定義數據層接口對象,通過此對象實現數據庫中菜單數據的訪問操作。關鍵代碼如下:

 

@Mapper
public interface SysMenuDao {
}

第二步:在SysMenuDao接口中添加findObjects方法,基於此方法實現菜單數據的查詢操作。代碼如下:

List<Map<String,Object>> findObjects();
  1. Mapper文件實現

  • 業務描述及設計實現

基於Dao接口創建映射文件,在此文件中通過相關元素(例如select)描述要執行的數據操作。

  • 關鍵代碼設計及實現

第一步:在映射文件的設計目錄中添加SysMenuMapper.xml映射文件,代碼如下:

 

<?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>

第二步:在映射文件中添加id為findObjects的元素,實現菜單記錄查詢。我們要查詢所有菜單以及菜單對應的上級菜單名稱。關鍵代碼如下:

 

<select id="findObjects" resultType="map">
         
          <!-- 方案1
          select c.*,p.name parentName
          from sys_menus c left join sys_menus p
          on c.parentId=p.id 
          -->
          <!-- 方案2 -->
          select c.*,(
                    select p.name 
                    from sys_menus p
                    where c.parentId=p.id
                    ) parentName
          from sys_menus c
         
 </select>

說明:自關聯查詢分析,如圖-10所示:

 

 

 

 

  1. Service接口及實現類

  • 業務描述與設計實現

在菜單查詢中,業務層對象主要是借助數據層對象完成菜單數據的查詢。后續還可以基於AOP對數據進行緩存,記錄訪問日志等。

  • 關鍵代碼設計及實現

第一步:定義菜單業務接口及方法,暴露外界對菜單業務數據的訪問,其代碼參考如下:

 

package com.cy.pj.sys.service;
public interface SysMenuService {
     List<Map<String,Object>> findObjects();
}

 第二步:定義菜單業務接口實現類,並添加菜單業務數據對應的查詢操作實現,其代碼參考如下:

 

package com.cy.pj.sys.service.impl;
@Service
public class SysMenuServiceImpl implements SysMenuService{
      @Autowired
      private SysMenuDao sysMenuDao;
      @Override
      public List<Map<String, Object>> findObjects() {
        List<Map<String,Object>> list=
            sysMenuDao.findObjects();
        if(list==null||list.size()==0)
        throw new ServiceException("沒有對應的菜單信息");
        return list;
}
  1. Controller類實現

  • 業務描述與設計實現

控制層對象主要負責請求和響應數據的處理,例如,本模塊通過業務層對象執行業務邏輯,再通過VO對象封裝響應結果(主要對業務層數據添加狀態信息),最后將響應結果轉換為JSON格式的字符串響應到客戶端。

  • 關鍵代碼設計與實現

定義Controller類,並將此類對象使用Spring框架中的@Controller注解進行標識,表示此類對象要交給Spring管理。然后基於@RequestMapping注解為此類定義根路徑映射。代碼參考如下:

 

package com.cy.pj.sys.controller;
@RequestMapping("/menu/")
@RestController
public class SysMenuController {
}

說明:這里的@RestController注解等效於在類上同時添加了@Controller和  @ResponseBody注解.

在Controller類中添加菜單查詢處理方法,代碼參考如下:

 

@RequestMapping("doFindObjects")
public JsonResult doFindObjects() {
    return new  JsonResult(sysMenuService.findObjects());
}
  1. 客戶端關鍵業務及代碼實現

    1. 菜單列表信息呈現

  • 業務描述與設計實現

菜單頁面加載完成以后,向服務端發起異步請求加載菜單信息,當菜單信息加載完成需要將菜單信息呈現到列表頁面上。

  • 關鍵代碼設計與實現

第一步:在菜單列表頁面引入treeGrid插件相關的JS。

 

<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>

第二步:在菜單列表頁面,定義菜單列表配置信息,關鍵代碼如下:

 

var columns = [
{
    field : 'selectItem',
    radio : true
},
{
    title : '菜單ID',
    field : 'id',
    align : 'center',
    valign : 'middle',
    width : '80px'
},
{
    title : '菜單名稱',
    field : 'name',
    align : 'center',
    valign : 'middle',
    width : '130px'
},
{
    title : '上級菜單',
    field : 'parentName',
    align : 'center',
    valign : 'middle',
    sortable : true,
    width : '100px'
},
{
    title : '類型',
    field : 'type',
    align : 'center',
    valign : 'middle',
    width : '70px',
    formatter : function(item, index) {
        if (item.type == 1) {
            return '<span class="label label-success">菜單</span>';
        }
        if (item.type == 2) {
            return '<span class="label label-warning">按鈕</span>';
        }
    }
}, 
{
    title : '排序號',
    field : 'sort',
    align : 'center',
    valign : 'middle',
    sortable : true,
    width : '70px'
}, 
{
    title : '菜單URL',
    field : 'url',
    align : 'center',
    valign : 'middle',
 
    width : '160px'
}, 
{
    title : '授權標識',//要顯示的標題名稱
    field : 'permission',//json串中的key
    align : 'center',//水平居中
    valign : 'middle',//垂直居中
    sortable : false //是否排序
} ];//格式來自官方demos -->treeGrid(jquery擴展的一個網格樹插件)

第三步:定義異步請求處理函數,代碼參考如下:

 

function doGetObjects(){//treeGrid
    //1.構建table對象(bootstrap框架中treeGrid插件提供)
    var treeTable=new TreeTable(
            "menuTable",//tableId
            "menu/doFindObjects",//url
             columns);
    //設置從哪一列開始展開(默認是第一列)
    //treeTable.setExpandColumn(2);
    //2.初始化table對象(底層發送ajax請求獲取數據)
    treeTable.init();//getJSON,get(),...
}

第四步:頁面加載完成,調用菜單查詢對應的異步請求處理函數,關鍵代碼如下:

$(function(){
    doGetObjects();
})
  1. 菜單管理刪除操作實現

    1. 業務時序分析

    基於用戶在列表頁面上選擇的的菜單記錄ID,執行刪除操作,本次刪除業務實現中,首先要基於id判斷當前菜單是否有子菜單,假如有子菜單則不允許刪除,沒有則先刪除菜單角色關系數據,然后再刪除菜單自身信息。其時序分析如圖-11所示:

     

     

     

    1. 服務端關鍵業務及代碼實現

      1. Dao接口實現

      • 業務描述及設計實現

      數據層基於業務層提交的菜單記錄id,刪除菜單角色關系以及菜單數據,菜單自身記錄信息。

      • 關鍵代碼設計及實現

      第一步:創建SysRoleMenuDao並定義基於菜單id刪除關系數據的方法,關鍵代碼如下:

       

      @Mapper
      public interface SysRoleMenuDao {
          int deleteObjectsByMenuId(Integer menuId);
      }

      第二步:在SysMenuDao中添加基於菜單id查詢子菜單記錄的方法。代碼參考如下:

      int getChildCount(Integer id);

      第三步:在SysMenuDao中添加基於菜單id刪除菜單記錄的方法。代碼參考如下:

      int deleteObject(Integer id);
      1. Mapper文件實現

      • 業務描述及設計實現

      在SysRoleMenuDao,SysMenuDao接口對應的映射文件中添加用於執行刪除業務的delete元素,然后在元素內部定義具體的SQL實現。

      • 關鍵代碼設計與實現

      第一步:創建SysRoleMenuMapper.xml文件並添加基於菜單id刪除關系數據的元素,關鍵代碼如下:

       

      <?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>

      第二步:在SysMenuMapper.xml文件中添加基於id統計子菜單數量的元素,關鍵代碼如下:

      <select id="getChildCount"
                   parameterType="int"
                   resultType="int">
                select count(*)
                from sys_menus
                where parentId=#{id}        
       </select>

      第三步:在SysMenuMapper.xml文件添加delete元素,基於帶單id刪除菜單自身記錄信息,關鍵代碼如下:

       

      <delete id="deleteObject">
             delete from sys_menus
             where id =#{id}
             
          </delete
      1. Service接口及實現類

      • 業務描述與設計實現

      在菜單業務層定義用於執行菜單刪除業務的方法,首先通過方法參數接收控制層傳遞的菜單id,並對參數id進行校驗。然后基於菜單id統計子菜單個數,假如有子菜單則拋出異常,提示不允許刪除。假如沒有子菜單,則先刪除角色菜單關系數據。最后刪除菜單自身記錄信息后並返回業務執行結果。

      • 關鍵代碼設計與實現

      第一步:在SysMenuService接口中,添加基於id進行菜單刪除的方法。關鍵代碼如下:

       

      int deleteObject(Integer id);

      第二步:在SysMenuServiceImpl實現類中注入SysRoleMenuDao相關對象。關鍵代碼如下:

      @Autowired
      private SysRoleMenuDao sysRoleMenuDao;

      第三步:在SysMenuServiceImpl實現類中添加刪除業務的具體實現。關鍵代碼如下

      @Override
          public int deleteObject(Integer id) {
              //1.驗證數據的合法性
              if(id==null||id<=0)
              throw new IllegalArgumentException("請先選擇");
              //2.基於id進行子元素查詢
              int count=sysMenuDao.getChildCount(id);
              if(count>0)
              throw new ServiceException("請先刪除子菜單");
              //3.刪除角色,菜單關系數據
              sysRoleMenuDao.deleteObjectsByMenuId(id);
              //4.刪除菜單元素
              int rows=sysMenuDao.deleteObject(id);
              if(rows==0)
              throw new ServiceException("此菜單可能已經不存在");
              //5.返回結果
              return rows;
          }
      1. Controller類實現

      • 業務描述與設計實現

      在菜單控制層對象中,添加用於處理菜單刪除請求的方法。首先在此方法中通過形參接收客戶端提交的數據,然后調用業務層對象執行刪除操作,最后封裝執行結果,並在運行時將響應對象轉換為JSON格式的字符串,響應到客戶端。

      • 關鍵代碼設計與實現

      第一步:在SysMenuController中添加用於執行刪除業務的方法。代碼如下:

       

       @RequestMapping("doDeleteObject")
            public JsonResult doDeleteObject(Integer id){
                sysMenuService.deleteObject(id);
                return new JsonResult("delete ok");
            }

      第二步:啟動tomcat進行訪問測試,打開瀏覽器輸入如下網址:http://localhost/menu/doDeleteObject?id=10

      1. 客戶端關鍵業務及代碼實現

        1. 菜單列表頁面事件處理

      • 業務描述及設計實現

      用戶在頁面上首先選擇要刪除的元素,然后點擊刪除按鈕,將用戶選擇的記錄id異步提交到服務端,最后在服務端執行菜單的刪除動作。

      • 關鍵代碼設計與實現

      第一步:頁面加載完成以后,在刪除按鈕上進行點擊事件注冊。關鍵代碼如下:

       

      $(".input-group-btn")
             .on("click",".btn-delete",doDeleteObject)

      第二步:定義刪除操作對應的事件處理函數。關鍵代碼如下:

      function doDeleteObject(){
          //1.獲取選中的記錄id
          var id=doGetCheckedId();
          if(!id){
            alert("請先選擇");
            return;
          }
         //2.給出提示是否確認刪除
        if(!confirm("確認刪除嗎"))return;
          //3.異步提交請求刪除數據
          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);
              }
          });
      }

      第三步:定義獲取用戶選中的記錄id的函數。關鍵代碼如下:

       

      function doGetCheckedId(){
          //1.獲取選中的記錄
          var selections=$("#menuTable")
          //bootstrapTreeTable是treeGrid插件內部定義的jquery擴展函數
          //getSelections為擴展函數內部要調用的一個方法
          .bootstrapTreeTable("getSelections");
          //2.對記錄進行判定
          if(selections.length==1)
          return selections[0].id;
      }
      1. 菜單添加頁面呈現

        1. 業務時序分析

      添加頁面加載時序分析,如圖-12所示:

       

       

       

       

      1. 准備菜單編輯頁面

      首先准備菜單列表頁面(/templates/pages/sys/menu_edit.html),然后在menu_list.html頁面中點擊菜單添加時異步加載菜單編輯頁面。

       

      1. 菜單編輯頁面呈現

      • 業務描述與設計實現

      菜單列表頁面點擊添加按鈕時,異步加載菜單編輯頁面。

      • 關鍵代碼設計與實現

      第一步:菜單列表頁面上,對添加按鈕進行事件注冊,關鍵代碼如下:

       在menu_edit.html頁面中定義用於呈現樹結構的DIV組件

      <div class="layui-layer layui-layer-page layui-layer-molv layer-anim" id="menuLayer" type="page" times="2" showtime="0" contype="object"
              style="z-index:59891016; width: 300px; height: 450px; top: 100px; left: 500px; display:none">
              <div class="layui-layer-title" style="cursor: move;">選擇菜單</div>
              <div class="layui-layer-content" style="height: 358px;">
                  <div style="padding: 10px;" class="layui-layer-wrap">
                      <ul id="menuTree" class="ztree"></ul>    <!-- 動態加載樹 -->
                  </div>
              </div>
              <span class="layui-layer-setwin"> <a class="layui-layer-ico layui-layer-close layui-layer-close1 btn-cancel" ></a></span>
              <div class="layui-layer-btn layui-layer-btn-">
                  <a class="layui-layer-btn0 btn-confirm">確定</a>
                  <a class="layui-layer-btn1 btn-cancel">取消</a>
               </div>
            </div>
      1. ZTree數據呈現

      • 業務描述與設計實現

      引入zTree需要的JS,並,並基於JS中的定義的API初始化zTree中的菜單信息。

      • 關鍵代碼設計與實現

      第一步:引入js文件

       

        <script type="text/javascript" src="bower_components/ztree/jquery.ztree.all.min.js"></script>
        <script type="text/javascript" src="bower_components/layer/layer.js">
        </script>

      第二步:在menu_edit.html中定義zTree配置信息(初始化zTree時使用)

       

      var zTree; 
      var setting = {
            data : {
                simpleData : {
                    enable : true,
                    idKey : "id",  //節點數據中保存唯一標識的屬性名稱
                    pIdKey : "parentId",  //節點數據中保存其父節點唯一標識的屬性名稱
                    rootPId : null  //根節點id
                }
            }
        }

      第二步:定義異步加載zTree信息的函數,關鍵代碼如下:

        function doLoadZtreeNodes(){
            
            var url="menu/doFindZtreeMenuNodes";
            //異步加載數據,並初始化數據
            $.getJSON(url,function(result){
                if(result.state==1){
                    //使用init函數需要先引入ztree對應的js文件
                    zTree=$.fn.zTree.init(
                            $("#menuTree"),
                            setting,
                            result.data);
                     $("#menuLayer").css("display","block");
                }else{
                    alert(result.message);
                }
            })
        }

      第三步:定義zTree中取消按鈕事件處理函數,點擊取消隱藏zTree。關鍵代碼如下:

       

      function doHideTree(){
           $("#menuLayer").css("display","none");
        }

      第四步:定義zTree中確定按鈕對應的事件處理處理函數。關鍵代碼如下:

      function doSetSelectNode(){
            //1.獲取選中的節點對象
            var nodes=zTree.getSelectedNodes();
            if(nodes.length==1){      
      var node=nodes[0];
            console.log(node);
            //2.將對象中內容,填充到表單
            $("#parentId").data("parentId",node.id);
            $("#parentId").val(node.name);
      }
            //3.隱藏樹對象
            doHideTree();
        }

       第五步:定義頁面加載完成以后的事件處理函數:

       $(document).ready(function(){
            $("#mainContentId")
            .on("click",".load-sys-menu",doLoadZtreeNodes)
            $("#menuLayer")
            .on("click",".btn-confirm",doSetSelectNode)
            .on("click",".btn-cancel",doHideTree)
        });
      1. 菜單數據添加實現

        1. 數據基本架構分析

      用戶在菜單編輯頁面輸入數據,然后異步提交到服務端,其簡易數據傳遞基本架構,如圖-14所示:

       

       

       

      用戶在菜單添加頁面中填寫好菜單數據,然后點擊保存按鈕,將用戶填寫的數據添加

      到數據庫。其時序分析,如圖-15所示:

       

       

       

      1. 服務端關鍵業務及代碼實現

        1. Entity類定義

      • 業務描述與設計實現

      定義持久化對象,封裝客戶端請求數據,並將數據傳遞到數據層進行持久化。

      • 關鍵代碼設計與實現

      菜單持久層對象類型定義,關鍵代碼如下:

       

      import lombok.Data;
      @Data
      public class SysMenu implements Serializable{ private static final long serialVersionUID = -8805983256624854549L; private Integer id; /**菜單名稱*/ private String name; /**菜單url: log/doFindPageObjects*/ private String url; /**菜單類型(兩種:按鈕,普通菜單)*/ private Integer type=1; /**排序(序號)*/ private Integer sort; /**備注*/ private String note; /**上級菜單id*/ private Integer parentId; /**菜單對應的權限標識(sys:log:delete)*/ private String permission; /**創建用戶*/ private String createdUser; /**修改用戶*/ private String modifiedUser; private Date createdTime; private Date modifiedTime;
      1. DAO接口定義

      • 業務描述與設計實現

      負責將用戶提交的菜單數據,持久化到數據庫。

      • 關鍵代碼設計與實現

      在SysMenuDao接口中定義數據持久化方法:

       

      int insertObject(SysMenu entity);
      1. Mapper映射文件定義

      • 業務描述與設計實現

      基於SysMenuDao中方法的定義,編寫用於實現菜單添加的SQL元素。

      • 關鍵代碼設計與實現

      在SysMenuMapper.xml中添加insertObject元素,用於寫入菜單信息。關鍵代碼如下:

       

      <insert id="insertObject"
                  parameterType="com.cy.pj.sys.entity.SysMenu">
                insert into sys_menus
                (name,url,type,sort,note,parentId,permission,
      createdTime,modifiedTime,createdUser,modifiedUser)
                values
                (#{name},#{url},#{type},#{sort},#{note},#{parentId},
      #{permission},now(),now(),#{createdUser},#{modifiedUser})
       </insert>
      1. Service接口定義及實現

      • 業務描述與設計實現

      基於控制層請求,調用數據層對象將菜單信息寫入到數據庫中。

      • 關鍵代碼設計與實現

      第一步:在SysMenuService接口中,添加用於保存菜單對象的方法。關鍵代碼如下

       

      int saveObject(SysMenu entity);

      第二步:在SysMenuServiceImpl類中,實現菜單保存操作。關鍵代碼如下:

       

      @Override
      public int saveObject(SysMenu entity) {
              //1.合法驗證
              if(entity==null)
              throw new IllegalArgumentException("保存對象不能為空");
              if(StringUtils.isEmpty(entity.getName()))
              throw new IllegalArgumentException("菜單名不能為空");
              //2.保存數據
              int  rows=sysMenuDao.insertObject(entity);
              //3.返回數據
              return rows;
          }
      1. Controller類定義

      • 業務描述與設計實現

      接收客戶端提交的菜單數據,並對其進行封裝,然后調用業務層對象進行業務處理,最后將業務層處理結果響應到客戶端。

      • 關鍵代碼設計與實現

      定義Controller方法,借助此方法處理保存菜單數據請求和響應邏輯。關鍵代碼如下:

       

          @RequestMapping("doSaveObject")
          public JsonResult doSaveObject(SysMenu entity){
              sysMenuService.saveObject(entity);
              return new JsonRehlt("save ok");
          }
      1. 客戶端關鍵業務及代碼實現

        1. 頁面cancel按鈕事件處理

      • 業務描述與設計實現

      點擊頁面cancel按鈕時,加載菜單那列表頁面。

      • 關鍵代碼設計與實現

      第一步:事件注冊(頁面加載完成以后)

       

        $(".box-footer")
            .on("click",".btn-cancel",doCancel)

      第二步:事件處理函數定義

       function doCancel(){
          var url="menu/menu_list";
          $("#mainContentId").load(url);  
        }
      1. 頁面Save按鈕事件處理

      • 業務描述與設計實現

      點擊頁面save按鈕時,將頁面上輸入的菜單信息異步提交到服務端。

      • 關鍵代碼設計與實現

      第一步:事件注冊(頁面加載完成以后)

       

       $(".box-footer")
            .on("click",".btn-save",doSaveOrUpdate)

      第二步:Save按鈕事件處理函數定義。關鍵代碼如下:

       

       function doSaveOrUpdate(){
            //1.獲取表單數據
            var params=doGetEditFormData();
            //2.定義url
            var url="menu/doSaveObject";
            //3.異步提交數據
            $.post(url,params,function(result){
                if(result.state==1){
                    alert(result.message);
                    doCancel();
                }else{
                    alert(result.message);
                }
            });
        }

      第三步:表單數據獲取及封裝函數定義。關鍵代碼如下:

      function doGetEditFormData(){
            var params={
                type:$("form input[name='typeId']:checked").val(),
              name:$("#nameId").val(),
              url:$("#urlId").val(),
              sort:$("#sortId").val(),
              permission:$("#permissionId").val(),
              parentId:$("#parentId").data("parentId")
            }
            return params;
        }
      1. 菜單修改頁面數據呈現

        1. 業務時序分析

      當在菜單列表頁面中選中某條記錄,然后點擊修改按鈕時,其業務時序分析如圖-16所示:

       

       

       

      1. 客戶端關鍵業務及代碼實現

        1. 列表頁面修改按鈕事件處理

      • 業務描述與設計實現

      點擊頁面修改按鈕時,獲取選中菜單記錄,並異步加載編輯頁面。

      • 關鍵代碼設計與實現

      第一步:列表頁面修改按鈕事件注冊,關鍵代碼如下:

       

      $(".input-group-btn")
      .on("click",".btn-update",doLoadEditUI);

       

      第二步:修改按鈕事件處理函數定義或修改,關鍵代碼如下:

       

      function doLoadEditUI(){
          var title;
          if($(this).hasClass("btn-add")){
              title="添加菜單"
          }else if($(this).hasClass("btn-update")){
              title="修改菜單"
              //獲取選中的記錄數據
              var rowData=doGetCheckedItem();
              if(!rowData){
                  alert("請選擇一個");
                  return;
              }
              $("#mainContentId").data("rowData",rowData);
          }
          var url="menu/menu_edit";
          $("#mainContentId").load(url,function(){
              $(".box-title").html(title);
          })
      }

      第三步:獲取用戶選中記錄的函數定義。關鍵代碼如下:

      function doGetCheckedItem(){
          var tr=$("tbody input[type='radio']:checked")
                 .parents("tr");
          return tr.data("rowData");
      }
      1. 編輯頁面菜單數據呈現

      • 業務描述與設計實現

      頁面加載完成,在頁面指定位置呈現要修改的數據。

      • 關鍵代碼設計與實現

      第一步:頁面加載完成以后,獲取頁面div中綁定的數據。關鍵代碼如下:

       

      $(function(){
            …
            //假如是修改
            var data=$("#mainContentId").data("rowData");
            if(data)doInitEditFormData(data);
        });

      第二步:定義編輯頁面數據初始化方法。關鍵代碼如下:

       

      function doInitEditFormData(data){
          /*   $("input[type='radio']").each(function(){
                if($(this).val()==data.type){
                    $(this).prop("checked",true);
                }
            }) */
            $(".typeRadio input[value='"+data.type+"']").prop("checked",true);
            $("#nameId").val(data.name);
            $("#sortId").val(data.sort);
            $("#urlId").val(data.url);
            $("#permissionId").val(data.permission);
            $("#parentId").val(data.parentName);
            $("#parentId").data("parentId",data.parentId);
        }
      1. 菜單數據更新實現

        1. 業務時序分析

      當點擊編輯頁面更新按鈕時,其時序分析如圖-17所示:

       

       

       

      1. 服務端關鍵業務及代碼實現

        1. DAO接口實現

      • 業務描述與設計實現

      負責將用戶編輯頁面提交到服務端的菜單數據,更新到數據庫進行持久性存儲。

      • 關鍵代碼設計與實現

      在SysMenuDao接口中添加數據更新方法,關鍵代碼如下:

       

      int updateObject(SysMenu entity);
      1. Mapper映射文件定義

      • 業務描述與設計實現

      基於SysMenuDao中updateObject方法的定義,編寫用於實現菜單更新的SQL元素。

      • 關鍵代碼設計與實現

      在SysMenuMapper.xml中添加updateObject元素,用於更新菜單信息。關鍵代碼如下:

       

      <update id="updateObject"
                  parameterType="com.cy.pj.sys.entity.SysMenu">
               update sys_menus
               set
                 name=#{name},
                 type=#{type},
                 sort=#{sort},
                 url=#{url},
                 parentId=#{parentId},
                 permission=#{permission},
                 modifiedUser=#{modifiedUser},
                 modifiedTime=now()
              where id=#{id}
          </update>
      1. Service接口及實現

      • 業務描述與設計實現

      基於控制層請求,對數據進行校驗並調用數據層對象將菜單信息更新到數據庫中。

      • 關鍵代碼設計與實現

      第一步:在SysMenuService接口中,添加用於更新菜單對象的方法。關鍵代碼如下

       

      int updateObject(SysMenu entity);

      第二步:在SysMenuServiceImpl類中,實現菜單保存操作。關鍵代碼如下:

      @Override
      public int updateObject(SysMenu entity) {
              //1.合法驗證
              if(entity==null)
              throw new ServiceException("保存對象不能為空");
              if(StringUtils.isEmpty(entity.getName()))
              throw new ServiceException("菜單名不能為空");
              
              //2.更新數據
              int rows=sysMenuDao.updateObject(entity);
              if(rows==0)
              throw new ServiceException("記錄可能已經不存在");
              //3.返回數據
              return rows;
      }
      1. Controller類定義

      • 業務描述與設計實現

      接收客戶端提交的菜單數據,並對其進行封裝,然后調用業務層對象進行業務處理,最后將業務層處理結果響應到客戶端。

      • 關鍵代碼設計與實現

      定義Controller方法,借助此方法處理保存菜單數據請求和響應邏輯。關鍵代碼如下

       

      @RequestMapping("doUpdateObject")
          public JsonResult doUpdateObject(
      SysMenu entity){
              sysMenuService.updateObject(entity);
              return new JsonResult("update ok");
          }
      1. 客戶端關鍵業務及代碼實現

        1. 編輯頁面更新按鈕事件處理

      • 業務描述與設計實現

      點擊頁面save按鈕時,將頁面上輸入的菜單編輯信息提交到服務端。

      • 關鍵代碼設計與實現

      編輯Save按鈕對應的事件處理函數。關鍵代碼如下:

       

       function doSaveOrUpdate(){
            //1.獲取表單數據
            var params=doGetEditFormData();
      var rowData=$("#mainContentId").data("rowData");
            //2.定義url
            var insertUrl="menu/doSaveObject";
            var updateUrl="menu/doUpdateObject";
            var url=rowData?updateUrl:insertUrl;
            if(rowData)params.id=rowData.id;
            //3.異步提交數據
            $.post(url,params,function(result){
                if(result.state==1){
                    alert(result.message);
                    doCancel();
                }else{
                    alert(result.message);
                }
            });
        }
      1. 重難點分析

      • 菜單管理在整個系統中的定位(資源管理)。

      • 菜單數據的自關聯查詢實現(查詢當前菜單以及這個菜單的上級菜單)。

      • 菜單管理中數據的封裝過程(請求數據,響應數據)。

      • 菜單數據在客戶端的呈現。(treeGrid,zTree)

        1. FAQ分析

        • 菜單表是如何設計的,都有哪些字段?

        • 菜單列表數據在客戶端是如何展示的?(TreeGrid)

        • 菜單刪除業務是如何處理的?

        • 菜單編輯頁面中上級菜單數據的呈現方式?(zTree)

        • 常用表連接方式,如圖-18所示:

        •  

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM