zoukankan      html  css  js  c++  java
  • java责任链模式及项目实际运用

    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
     
    这就是我们在设计时候,所需要学习的地方。利用注解将我们与业务代码进行解耦合,在使用责任链模式更加具有水平拓展性,以后随着业务的发展,可以添加黑名单或者白天校验,以及添加风控系统的对接。

  • 相关阅读:
    神奇的JavaScript之正则
    神奇的JavaScript之Function
    实现img包含在容量居中显示
    《JavaScript patterns》读书笔记
    多线程下的单例模式你真的了解吗?
    分享一个很不错的编程学习网站:https://www.lidihuo.com
    史上最全使用Nexus搭建Maven服务器详细配置
    SqlServer内存释放
    JS对url编码
    未能加载文件或程序集 XX 或它的某一个依赖项
  • 原文地址:https://www.cnblogs.com/shsxt/p/7858015.html
Copyright © 2011-2022 走看看