java責任鏈模式及項目實際運用

来源:http://www.cnblogs.com/shsxt/archive/2017/11/18/7858015.html
-Advertisement-
Play Games

1.前言 上次我們認識了java責任鏈模式的設計,那麼接下來將給大家展示責任鏈模式項目中的實際運用。如何快速搭建責任鏈模式的項目中運用。 2.簡單技術準備 我們要在項目中使用藉助這樣的幾個知識的組合運用,才能更好的詮釋。必備技能:簡單註解的定義;Spring攔截器的使用;簡答的責任鏈模式的定義;擁有 ...


1.前言

上次我們認識了java責任鏈模式的設計,那麼接下來將給大家展示責任鏈模式項目中的實際運用。如何快速搭建責任鏈模式的項目中運用。

 

2.簡單技術準備

我們要在項目中使用藉助這樣的幾個知識的組合運用,才能更好的詮釋。

必備技能:
簡單註解的定義;
Spring攔截器的使用;
簡答的責任鏈模式的定義;

擁有以前的準備的知識點的,我們就可以快速搭建責任鏈來做安全校驗了。

3. 場景模擬

場景: 系統中我們需要一些安全校驗結構,如登陸校驗與角色校驗。接下來我們使用責任鏈模式來開發這個流程化校驗。
 

4. 設計模式

我們將設計一個web項目,採用springmvc 框架。開發語言使用JAVA。
執行過程執行過程:

SpringMVC攔截器  --- > 攔截指定註解 --- > 進入責任鏈處理 
 

5編碼實戰

5.1 註解定義

定義一個Permission註解

/**
 *  許可權 攔截
 * @author MR.YongGan.Zhang
 *
 */
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Permission {
   
    VerifyType verifyType() default VerifyType.LOGIN;
   
    String[] verifyValue () default "";
   
}
 

 
其中 是枚舉類型的校驗類型
 

/**
 * 校驗的種類
 *
 * NONE   不校驗
 * LOGIN  登陸校驗
 * ROLE   角色校驗
 *
 * @author MR.YongGan.Zhang
 *
 */
public enum VerifyType {
 
    NONE, LOGIN, ROLE;
   
}
 

 

5.2攔截器定義

我們定義攔截器PermissionInterceptor,實際上也是註解解析器。我們將藉助於springMVC來做攔截器。
 
我們使用springMVC 攔截器可以實現 org.springframework.web.servlet.HandlerInterceptor 重寫介面的三個方法即可。
我們一起看看是如何實現的。
 

import java.lang.reflect.Method;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
import com.shsxt.framework.Permission.Permission;
import com.shsxt.framework.Permission.handlerchain.PermissionHandlerChainStaticFactory;
import com.shsxt.framework.Permission.handlerchain.PermissionWithNone;
import com.shsxt.framework.constant.VerifyType;
/**
 * 安全校驗
 *
 *     1. 攔截 用戶是否登陸
 *     2. 許可權攔截
 *
 *
 * @author MR.YongGan.Zhang
 * @version 1.0.1
 *
 *          備註: 1.0.0 實現用戶登陸攔截 1.0.1 增加實現許可權
 *
 */
 
public class PermissionInterceptor implements HandlerInterceptor {
   
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
           throws Exception {
      
       System.err.println(" 進入  PermissionInterceptor  。。。 ");
       System.err.println(handler.getClass().getName());
      
       if (handler instanceof HandlerMethod) {
 
           HandlerMethod hm = (HandlerMethod) handler;
 
           Method method = hm.getMethod();
          
           // 如果包含了 Permission 註解
           if (method.isAnnotationPresent(Permission.class)) { //
 
              Permission permission = method.getAnnotation(Permission.class);
              // 獲取 註解 中的屬性
              VerifyType verifyType = permission.verifyType();
             
              // 獲取許可權校驗值
              String[] verifyValue = permission.verifyValue();
             
                // 責任鏈模式  校驗
              PermissionWithNone permissionWithNone = PermissionHandlerChainStaticFactory.createPermissionWithNone();
              // 執行結果
              boolean bool = permissionWithNone.handleChain(verifyType,request,verifyValue);
              System.err.println(bool);
              return bool;
           }
       }
       return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
           ModelAndView modelAndView) throws Exception {
      
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
           throws Exception {
      
    }
 
}

 
我們定義好了攔截器,下一步需要將我們攔截器配置給我們springMVC容器中管理



在servlet-context.xml 上配置定義好的攔截器。
 

<mvc:interceptors>
       <mvc:interceptor>
           <mvc:mapping path="/**" />
           <mvc:exclude-mapping path="/user/userLogin" />
           <mvc:exclude-mapping path="/index" />
           <mvc:exclude-mapping path="/css/**" />
           <mvc:exclude-mapping path="/images/**" />
           <mvc:exclude-mapping path="/jquery-easyui-1.3.3/**" />
           <mvc:exclude-mapping path="/js/**" />
           <mvc:exclude-mapping path="/zTree_v3/**" />
           <bean class="com.shsxt.framework.interceptor.PermissionInterceptor" />
       </mvc:interceptor>
    </mvc:interceptors>

 
這樣我們就將攔截器配置給springMVC容器了。

5.3 責任鏈的設計

5.3.1 抽象責任鏈

PermissionAbstractHandlerChain:定義責任鏈處理規則。
 

/**
 * 許可權控制 責任鏈
 * @author MR.YongGan.Zhang
 *
 */
public abstract class PermissionAbstractHandlerChain {
   
    // 控制鏈
    protected PermissionAbstractHandlerChain  successor;
   
    public abstract boolean handleChain(VerifyType verifyType, HttpServletRequest request, String[] verifyValue );
   
    public PermissionAbstractHandlerChain getHandlerChain () {
       return this.successor;
    }
   
   
    public void setSuccessor (PermissionAbstractHandlerChain successor) {
      
       this.successor = successor;
      
    }
   
}

 

5.3.2 具體業務處理對象

PermissionWithNone  PermissionWithLogin PermissionWithRole 都需要繼承抽象處理鏈。
 

5.3.2.1. PermissionWithNone  不做校驗

/**
 *
 * @author MR.YongGan.Zhang
 *
 */
public class PermissionWithNone extends PermissionAbstractHandlerChain {
 
    @Override
    public boolean handleChain(VerifyType verifyType ,HttpServletRequest request ,String[] verifyValue ) {
 
       if (verifyType == VerifyType.NONE) {
           return true;
       } else {
           setSuccessor(PermissionHandlerChainStaticFactory.createPermissionWithLogin());
           return getHandlerChain().handleChain(verifyType,request,verifyValue);
       }
    }
 
}
 

 

5.3.2.2. PermissionWithLogin 登陸校驗

/**
 *
 * @author MR.YongGan.Zhang
 *
 */
public class PermissionWithLogin  extends PermissionAbstractHandlerChain {
 
    @Override
    public boolean handleChain(VerifyType verifyType ,HttpServletRequest request,String[] verifyValue) {
      
       if (verifyType == VerifyType.LOGIN) {
           /**
            * 實現登陸攔截校驗
            */
           boolean status = VerificationLoginUtil.isLoginedStatus(request);
           return status;
       }else {
           setSuccessor(PermissionHandlerChainStaticFactory.createPermissionWithRole());
           return getHandlerChain().handleChain(verifyType, request, verifyValue);
       }
    }
}
 

 

備註 boolean status = VerificationLoginUtil.isLoginedStatus(request);
此處的登陸校驗需要結合實際的業務來做。

5.3.2.3.PermissionWithRole 許可權校驗

/**
 * @author MR.YongGan.Zhang
 */
public class PermissionWithRole extends PermissionAbstractHandlerChain {
 
    @Override
    public boolean handleChain(VerifyType verifyType, HttpServletRequest request, String[] verifyValue) {
       // 角色校驗 實現登陸
       if (verifyType == VerifyType.ROLE) {
           boolean status = VerificationLoginUtil.isLoginedStatus(request);
           System.out.println(status);
           if (!status) {
              return false;
           }
 
           /**
            * 實現登陸攔截校驗
            */
           List<String> verify = Arrays.asList(verifyValue);
 
           // 用戶包含的許可權【結合實際業務來設計】
           List<String> userPermission = (List<String>) request.getSession()
                  .getAttribute(CrmConstant.USER_PERMISSIONS);
           if (verify != null && verify.size() > 0) {
              for (String cherck : verify) {
                  boolean flag = userPermission.contains(cherck);// 檢測許可權是否包含
                  if (!flag) {
                     return flag;// 不包含則返回 false
                  }
              }
           }
           return true;
 
       } else {
           throw new YgException("PS001", "安全校驗 未能識別");
       }
    }
}

 

5.3.3 處理鏈的靜態工廠設計

/**
 *  責任鏈 對象的靜態工廠 模式
 * @author MR.YongGan.Zhang
 */
public class PermissionHandlerChainStaticFactory {
   
    public static PermissionWithNone createPermissionWithNone(){
       return new PermissionWithNone();
    }
   
    public static PermissionWithLogin createPermissionWithLogin(){
       return new PermissionWithLogin();
    }
   
    public static PermissionWithRole createPermissionWithRole(){
       return new PermissionWithRole();
    }
}

 

5.4 如何使用



當我們設計的結構需要進行安全校驗時候,則添加註解
@Permission( verifyType = VerifyType.ROLE ,verifyValue = {"101011"} )
表示進行角色校驗 需要校驗的值為101011
 
這就是我們在設計時候,所需要學習的地方。利用註解將我們與業務代碼進行解耦合,在使用責任鏈模式更加具有水平拓展性,以後隨著業務的發展,可以添加黑名單或者白天校驗,以及添加風控系統的對接。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前面我們學習了numpy,現在我們來學習一下pandas。 Python Data Analysis Library 或 pandas 主要用於處理類似excel一樣的數據格式,其中有表頭、數據序列號以及實際的數據,而numpy就僅僅包含了實際的數據。 安裝 直接輸入: 最基本用法 輸出: 我們可以 ...
  • List<Map<String, Object>> queryData = configDao.queryConfig( expressions, conditions, expressions); Collections.sort(queryData, new Comparator<Map<Str ...
  • 一.生產者消費者問題? 1.生產者消費者問題(英語:Producer-consumer problem),也稱有限緩衝問題(英語:Bounded-buffer problem),是一個多線程同步問題的經典案例。該問題描述了兩個共用固定大小緩衝區的線程——即所謂的“生產者”和“消費者”——在實際運行時 ...
  • 作者:NiceCui 本文謝絕轉載,如需轉載需徵得作者本人同意,謝謝。 本文鏈接:http://www.cnblogs.com/NiceCui/p/7858473.html 郵箱:[email protected] 日期:2017-11-18 Python學習一:序列基礎詳解 一:序列介紹 Pyth ...
  • Step1.情景概要 Hello,小伙伴們,好久不見,之前跟大家分享了三層架構與MVC思想,相信大家對於這兩塊內容有了相對清晰的個人認識了,既然我們講到了MVC,這裡我們接著這塊內容繼續往下深入,今天我們來看看MVC 中的V-VIEW 即我們所說的視圖層。 Step2.視圖技術 對於我們WEB開發人 ...
  • static修飾的成員變數和成員方法獨立於該類的任何對象。也就是說,它不依賴類特定的實例,被類的所有實例共用。 只要這個類被載入,Java虛擬機就能根據類名在運行時數據區的方法區內定找到他們。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象。 1、static變數 按照是否靜態 ...
  • 題目描述: Reverse a singly linked list. 解題思路: 可用遞歸的方法對鏈表進行反轉。 代碼: 解題收穫: 溫習了基本的遞歸思想和鏈表的使用。但做的時候還是迷茫了很久,說明對鏈表的使用還是不太熟悉。 ...
  • 本文重點介紹使用Eclipse+pydev插件來寫Python代碼, 以及在Mac上配置Eclipse+Pydev 和Windows配置Eclipse+Pydev 轉載:https://www.cnblogs.com/Bonker/p/3584707.html 編輯器:Python 自帶的 IDLE ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...