1. 程式人生 > 實用技巧 >springboot 動吧專案選單模組

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所示: