基於SpringBoot的後臺管理系統(異常、註解、node、page)(二)

common.exception、annotation、node、page

說明

若是您有幸能看到,請認閱讀如下內容;php

  • 一、本項目臨摹自abel533的Guns,他的項目 fork 自 stylefengGuns!開源的世界真好,能夠學到不少知識。java

  • 二、版權歸原做者全部,本身只是學習使用。跟着大佬的思路,但願本身也能變成大佬。gogogo》。。node

  • 三、目前只是一個後臺模塊,但願本身技能加強到必定時,能夠把stylefeng 的 [Guns]融合進來。jquery

  • 四、note裏面是本身的學習過程,菜鳥寫的,不是大佬寫的。內容都是大佬的。git

異常

一、首先來看全部業務異常的枚舉類,看異常大概就能知道這個系統主要完成那些業務邏輯。github

/** * 全部業務異常的枚舉 */
public enum BizExceptionEnum {

    /** * 字典 */
    DICT_EXISTED(400,"字典已經存在"),
    ERROR_CREATE_DICT(500,"建立字典失敗"),
    ERROR_WRAPPER_FIELD(500,"包裝字典屬性失敗"),

    /** * 文件上傳 */
    FILE_READING_ERROR(400,"FILE_READING_ERROR!"),
    FILE_NOT_FOUND(400,"FILE_NOT_FOUND!"),
    UPLOAD_ERROR(500,"上傳圖片出錯"),

    /** * 權限和數據問題 */
    DB_RESOURCE_NULL(400,"數據庫中沒有該資源"),
    NO_PERMITION(405, "權限異常"),
    REQUEST_INVALIDATE(400,"請求數據格式不正確"),
    INVALID_KAPTCHA(400,"驗證碼不正確"),
    CANT_DELETE_ADMIN(600,"不能刪除超級管理員"),
    CANT_FREEZE_ADMIN(600,"不能凍結超級管理員"),
    CANT_CHANGE_ADMIN(600,"不能修改超級管理員角色"),

    /** * 帳戶問題 */
    USER_ALREADY_REG(401,"該用戶已經註冊"),
    NO_THIS_USER(400,"沒有此用戶"),
    USER_NOT_EXISTED(400, "沒有此用戶"),
    ACCOUNT_FREEZED(401, "帳號被凍結"),
    OLD_PWD_NOT_RIGHT(402, "原密碼不正確"),
    TWO_PWD_NOT_MATCH(405, "兩次輸入密碼不一致"),

    /** * 錯誤的請求 */
    MENU_PCODE_COINCIDENCE(400,"菜單編號和副編號不能一致"),
    EXISTED_THE_MENU(400,"菜單編號重複,不能添加"),
    DICT_MUST_BE_NUMBER(400,"字典的值必須爲數字"),
    REQUEST_NULL(400, "請求有錯誤"),
    SESSION_TIMEOUT(400, "會話超時"),
    SERVER_ERROR(500, "服務器異常");

    BizExceptionEnum(int code, String message) {
        this.friendlyCode = code;
        this.friendlyMsg = message;
    }

    private int friendlyCode;
    private String friendlyMsg;
    private String urlPath;
    //Setter,Getter,Constractor略
    BizExceptionEnum(int code, String message) {
        this.friendlyCode = code;
        this.friendlyMsg = message;
    }
}
複製代碼

二、對業務異常的封裝,首先須要注意的是繼承自RuntimeException,以前講過了點這裏數據庫

/** * 業務異常的封裝 */
public class BussinessException extends RuntimeException {

    //友好提示的code碼
    private int friendlyCode;

    //友好提示
    private String friendlyMsg;

    //業務異常調整頁面
    private String urlPath;

    public BussinessException(BizExceptionEnum bizExceptionEnum) {
        this.friendlyCode = bizExceptionEnum.getCode();
        this.friendlyMsg = bizExceptionEnum.getMessage();
        this.urlPath = bizExceptionEnum.getUrlPath();
    }
}
複製代碼

三、接下來是工具類初始化異常,須要注意serialVersionUID的做用:服務器

  • 一、serialVersionUID 是 Java 爲每一個序列化類產生的版本標識,可用來保證在反序列時,發送方發送的和接受方接收的是可兼容的對象。
  • 二、若是接收方接收的類的 serialVersionUID 與發送方發送的 serialVersionUID 不一致,進行反序列時會拋出 InvalidClassException。
  • 三、序列化的類可顯式聲明 serialVersionUID 的值,

這個中定義異常和PayMap中定義方式幾乎同樣。async

/** * 工具類初始化 */
public class ToolBoxException extends RuntimeException {
    //serialVersionUID 是 Java 爲每一個序列化類產生的版本標識,可用來保證在反序列時,發送方發送的和接受方接收的是可兼容的對象。
    // 若是接收方接收的類的 serialVersionUID 與發送方發送的 serialVersionUID 不一致,進行反序列時會拋出 InvalidClassException。序列化的類可顯式聲明 serialVersionUID 的值,
    private static final long serialVersionUID = 8247610319171014183L;

    public ToolBoxException(Throwable e) {
        super(e.getMessage(),e);
    }

    public ToolBoxException(String message) {
        super(message);
    }

    public ToolBoxException(String message, Throwable throwable) {
        super(message,throwable);
    }
    public ToolBoxException(String messageTemplate, Object...params) {
        super(StrKit.format(messageTemplate,params));
    }
}
--------------------------------------------------------------------------------
/** * 驗證碼錯誤異常 * * @Author guo //這個模板不錯 * @Date 2018-03-04 12:04. */
public class InvalidKaptchaException extends RuntimeException {
}
複製代碼

自定義註解

四、最後在看下自定義註解ide

元註解:

元註解的做用就是負責註解其餘註解。Java5.0定義了4個標準的meta-annotation類型,它們被用提供對其餘annotation類型的說明。

  • 一、@Target
  • 二、@Retention
  • 三、@Documented
  • 四、@Inherited

@Target

做用:用於描述註解的使用範圍(即:被描述的註解能夠用在什麼地方)

取值(ElementType)有:

  • 1.CONSTRUCTOR:用於描述構造器
  • 2.FIELD:用於描述域
  • 3.LOCAL_VARIABLE:用於描述局部變量
  • 4.METHOD:用於描述方法
  • 5.PACKAGE:用於描述包
  • 6.PARAMETER:用於描述參數
  • 7.TYPE:用於描述類、接口(包括註解類型) 或enum聲明

@Retention

做用:表示須要在什麼級別保存該註釋信息,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效)

取值(RetentionPoicy)有:

  • 1.SOURCE:在源文件中有效(即源文件保留)
  • 2.CLASS:在class文件中有效(即class保留)
  • 3.RUNTIME:在運行時有效(即運行時保留)

@Documented

做用:用於描述其它類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化。

@Inherited

@Inherited元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。

接下來,咱們在看自定義註解

/** * 權限註解,用於檢查權限 規定訪問權限 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)   //運行時有效
@Target({ElementType.METHOD})         //方法範圍
public @interface Permission {
    String[] value() default {};
}
-------------------------------------------------------
/** * 多數據源標識 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface DataSource {
}
---------------------------------------------------------
/** * 標記須要作業務日誌的方法 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface BussinessLog {

    /** * 業務的名稱,例如:"修改菜單" */
    String value() default "";

    /** * 被修改的實體的惟一標識,例如:菜單實體的惟一標識爲"id" */
    String key() default "id";

    /** * 字典(用於查找key的中文名稱和字段的中文名稱) */
    String dict() default "SystemDict";
}



複製代碼

五、先來看Node類的定義吧,

ZTree is an advanced jQuery 'tree plug-in'. The performance is excellent, it is easy to configurw (with a full set of options), and has many advanced features (that usually only come with paid software).

zTree is open source and uses the MIT license.

  • Supports JSON data.
  • Supports both static and asynchronous (Ajax) data loading.
  • Supports multiple instances of zTree in one page.
  • zTree3.0 can use lazy loading for large data, it can easily load tens of thousands of nodes in seconds even in the IE6 browser.
  • ...

The most important is the official document to the very full(English is very important, important and important.)

ZTreeNode定義:

/** * jquery ztree 插件的節點 */
public class ZTreeNode {
    /** * 節點id */
    private Integer id;
    /** * 父節點id */
    private Integer pId;
    /** * 節點名稱 */
    private String name;
    /** * 是否打開節點 */
    private Boolean open;
    /** * 是否被選中 */
    private Boolean checked;
    //Setter、Getter、Constructor、toString忽略
}
複製代碼

MenuNode實現了Compareable接口,重寫了compareTo()方法完整代碼在這

@Override
public int compareTo(Object o) {
    MenuNode menuNode = (MenuNode) o;
    Integer num = menuNode.getNum();
    if (num == null) {
        num = 0;
    }
    return this.num.compareTo(num);
}
複製代碼
/** * * 菜單的節點 */
public class MenuNode implements Comparable {
    /** * 節點id */
    private Integer id;
    /** * 父節點 */
    private Integer parentId;
    /** * 節點名稱 */
    private String name;
    /** * 按鈕級別 */
    private Integer levels;
    /** * 按鈕級別 */
    private Integer ismenu;
    /** * 按鈕的排序 */
    private Integer num;
    /** * 節點的url */
    private String url;
    /** * 節點圖標 */
    private String icon;
    /** * 子節點的集合 */
    private List<MenuNode> children;
    /** * 查詢子節點時候的臨時集合 */
    private List<MenuNode> linkedList = new ArrayList<MenuNode>();
}
複製代碼

爲了方便之後查看,方法單獨提出來。

/** * 構建整個菜單樹 */
    public void buildNodeTree(List<MenuNode> nodeList) {
        for (MenuNode treeNode : nodeList) {
            List<MenuNode> linkedList = treeNode.findChildNodes(nodeList, treeNode.getId());
            if (linkedList.size() > 0) {
                treeNode.setChildren(linkedList);
            }
        }
    }
    /** * 查詢子節點的集合 */
    public List<MenuNode> findChildNodes(List<MenuNode> nodeList, Integer parentId) {
        if (nodeList == null && parentId == null)
            return null;
        for (Iterator<MenuNode> iterator = nodeList.iterator(); iterator.hasNext(); ) {
            MenuNode node = (MenuNode) iterator.next();
            // 根據傳入的某個父節點ID,遍歷該父節點的全部子節點
            if (node.getParentId() != 0 && parentId.equals(node.getParentId())) {
                recursionFn(nodeList, node, parentId);
            }
        }
        return linkedList;
    }
--------------------------------------------------------------------------------
    /** * 遍歷一個節點的子節點 */
    public void recursionFn(List<MenuNode> nodeList, MenuNode node, Integer pId) {
        List<MenuNode> childList = getChildList(nodeList, node);// 獲得子節點列表
        if (childList.size() > 0) {// 判斷是否有子節點
            if (node.getParentId().equals(pId)) {
                linkedList.add(node);
            }
            Iterator<MenuNode> it = childList.iterator();
            while (it.hasNext()) {
                MenuNode n = (MenuNode) it.next();
                recursionFn(nodeList, n, pId);
            }
        } else {
            if (node.getParentId().equals(pId)) {
                linkedList.add(node);
            }
        }
    }

    /** * 獲得子節點列表 */
    private List<MenuNode> getChildList(List<MenuNode> list, MenuNode node) {
        List<MenuNode> nodeList = new ArrayList<MenuNode>();
        Iterator<MenuNode> it = list.iterator();
        while (it.hasNext()) {
            MenuNode n = (MenuNode) it.next();
            if (n.getParentId().equals(node.getId())) {
                nodeList.add(n);
            }
        }
        return nodeList;
    }
--------------------------------------------------------------------------------
    /** * 清除掉按鈕級別的資源 * * @param nodes * @return */
    public static List<MenuNode> clearBtn(List<MenuNode> nodes) {
        ArrayList<MenuNode> noBtns = new ArrayList<MenuNode>();
        for (MenuNode node : nodes) {
            if(node.getIsmenu() == IsMenu.YES.getCode()){
                noBtns.add(node);
            }
        }
        return noBtns;
    }

    /** * 清除全部二級菜單 * * @param nodes * @return */
    public static List<MenuNode> clearLevelTwo(List<MenuNode> nodes) {
        ArrayList<MenuNode> results = new ArrayList<MenuNode>();
        for (MenuNode node : nodes) {
            Integer levels = node.getLevels();
            if (levels.equals(1)) {
                results.add(node);
            }
        }
        return results;
    }
--------------------------------------------------------------------------------
    /** * 構建菜單列表 */
    public static List<MenuNode> buildTitle(List<MenuNode> nodes) {

        List<MenuNode> clearBtn = clearBtn(nodes);

        new MenuNode().buildNodeTree(clearBtn);

        List<MenuNode> menuNodes = clearLevelTwo(clearBtn);

        //對菜單排序
        Collections.sort(menuNodes);

        //對菜單的子菜單進行排序
        for (MenuNode menuNode : menuNodes) {
            if (menuNode.getChildren() != null && menuNode.getChildren().size() > 0) {
                Collections.sort(menuNode.getChildren());
            }
        }

        //若是關閉了接口文檔,則不顯示接口文檔菜單
        GunsProperties gunsProperties = SpringContextHolder.getBean(GunsProperties.class);
        if (!gunsProperties.getSwaggerOpen()) {
            List<MenuNode> menuNodesCopy = new ArrayList<>();
            for (MenuNode menuNode : menuNodes) {
                if (Const.API_MENU_NAME.equals(menuNode.getName())) {
                    continue;
                } else {
                    menuNodesCopy.add(menuNode);
                }
            }
            menuNodes = menuNodesCopy;
        }

        return menuNodes;
    }
複製代碼

zTree簡單使用

獲取全部的選擇節點、獲取子節點

// 經過id號來獲取這個樹
var treeObj2 = $.fn.zTree.getZTreeObj("treeDemo");
// 獲取全部已經選擇了的節點,得到一個node列表
var nodes2 = treeObj2.getCheckedNodes(true);
// 若是是葉子節點就把id拿出來
var idlist = [];
$.each(nodes2, function (i, item) {
    if (!item.isParent) {
        //alert(item.id + "," + item.name);
        idlist.push(item.id);
    }
});
console.log(idlist);
複製代碼

六、接下來,咱們看看pagehelper,Mybatis通用分頁插件這個插件也是本項目大佬寫的。若是非要本身封裝也能夠,可是你用過的話就不會在本身封裝了。主要是PageInfo類。

package com.guo.guns.common.page;

import com.github.pagehelper.Page;

import java.util.List;

/** * 分頁結果的封裝(for Bootstrap Table) * * @Author guo * @Date 2018-03-04 13:47 */
public class PageInfoBT<T> {

    /** * 結果集 */
    private List<T> rows;

    /** * 總數 */
    private long total;

    public PageInfoBT(List<T> page) {
        this.rows = page;
        if (page instanceof Page) {
            this.total = ((Page) page).getTotal();
        } else {
            this.total = page.size();
        }
    }
  //Setter、Getter略
}

複製代碼

PageHelper簡單使用

(1)一、查出第一頁的數據,每頁5條:

PageHelper.offsetPage(0, 5);
複製代碼

(2)、獲取總數:

PageInfo pageInfo = new PageInfo<>(cs);
System.out.println("總數:"+pageInfo.getTotal());
System.out.println(pageInfo);
複製代碼
相關文章
相關標籤/搜索