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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...