common.exception、annotation、node、page
說明
如果您有幸能看到,請認閱讀以下內容;
-
1、本專案臨摹自abel533的Guns,他的專案 fork 自 stylefeng 的 Guns!開源的世界真好,可以學到很多知識。
-
2、版權歸原作者所有,自己只是學習使用。跟著大佬的思路,希望自己也能變成大佬。gogogo》。。
-
3、目前只是一個後臺模組,希望自己技能增強到一定時,可以把stylefeng 的 [Guns]融合進來。
-
4、note裡面是自己的學習過程,菜鳥寫的,不是大佬寫的。內容都是大佬的。
異常
1、首先來看所有業務異常的列舉類,看異常大概就能知道這個系統主要完成那些業務邏輯。
/**
* 所有業務異常的列舉
*/
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;
}
}
複製程式碼
2、對業務異常的封裝,首先需要注意的是繼承自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();
}
}
複製程式碼
3、接下來是工具類初始化異常,需要注意serialVersionUID的作用:
- 1、serialVersionUID 是 Java 為每個序列化類產生的版本標識,可用來保證在反序列時,傳送方傳送的和接受方接收的是可相容的物件。
- 2、如果接收方接收的類的 serialVersionUID 與傳送方傳送的 serialVersionUID 不一致,進行反序列時會丟擲 InvalidClassException。
- 3、序列化的類可顯式宣告 serialVersionUID 的值,
這個中定義異常和PayMap中定義方式幾乎一樣。
/**
* 工具類初始化
*/
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 {
}
複製程式碼
自定義註解
4、最後在看下自定義註解
元註解:
元註解的作用就是負責註解其他註解。Java5.0定義了4個標準的meta-annotation型別,它們被用提供對其他annotation型別的說明。
- 1、@Target
- 2、@Retention
- 3、@Documented
- 4、@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";
}
複製程式碼
5、先來看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);
複製程式碼
6、接下來,我們看看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)1、查出第一頁的資料,每頁5條:
PageHelper.offsetPage(0, 5);
複製程式碼
(2)、獲取總數:
PageInfo pageInfo = new PageInfo<>(cs);
System.out.println("總數:"+pageInfo.getTotal());
System.out.println(pageInfo);
複製程式碼