精华内容
下载资源
问答
  • 具有动态责任链的调解员。 确定此程序包是否要混合使用和。 简而言之-具有通配符的动态通道,并确保侦听器的执行顺序。 特征: 同步,异步,基于承诺和生成器的侦听器 野人 排除 安装 npm install event-wire --...
  • java动态链模式和责任链模式

    千次阅读 2018-08-06 17:53:05
    java动态链模式和责任链模式 很多框架的技术原理都涉及到java动态链模式和责任链模式,比如spring和mybatis。 动态代理模式 代理,顾名思义,代为处理。先来看看名词解释: 代理就是定义一个行为和某类(class...

    java动态链模式和责任链模式

    很多框架的技术原理都涉及到java动态链模式和责任链模式,比如spring和mybatis。

    动态代理模式

    代理,顾名思义,代为处理。先来看看名词解释:
    代理就是定义一个行为和某类(class)的对象相似,而又潜在地表示了所有继承自该类的对象的东西,我们把这种类的对象叫做代理(surrogate)
    来源代理(百度百科)。
    来看一下最常用的代理技术:

    • JDK代理技术(JDK自带代理技术)
    • CGLIB代理技术(第三方代理技术)

    JDK代理技术

    jdk代理技术是java.lang.reflect包提供的方式,它必须通过一个接口才能产生代理对象,所以必须先创建对象,所以先对接口进行定义。

        public interface HelloWorld{
            void sayHelloWorld();
        }
    

    然后我们来创建一个是实现类:

        public class HelloWorldImpl implements HelloWorld{
            @override
            public void sayHelloWorld(){
                System.out.println("Hello World!");
            }
        }
    

    实现动态代理,分成两步走,第一步,实现接口java.lang.reflect.InvocationHandler,它有一个invoke方法,用于提供接口数组用于下挂代理对象

        public class JdkProxyExample implements InvocationHandler{
        //真实对象
        private object target = null;
        /**
        *建立代理对象和真实对象的代理关系,并返回对象
        *@param target 真实对象
        *@return 代理对象
        */
        public object bind(Object target){
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterface(),this);
        /**
        *代理对象逻辑
        *@param proxy 代理对象
        *@param method 当前调度方法
        *@param args 当前方法参数
        *@return 代理结果返回
        *@throws Throwable 异常
        */
        @override
        public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
            System.out.println("进入代理逻辑方法");
            System.out.println("在调度真实对象之前的服务");
            Object object = method.invoke(target,args);
            System.out.println("在调度真实对象之后的服务");
            return object;
        }
        }
    

    第一步建立对象和代理对象之间的联系,也就是使用了bind方法用如下语句
    Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterface(),this);
    生成代理对象,通过目标类的类加载器,和目标类的挂在接口。用当前对象this作为代理逻辑方法的现实方法,它必须实现InvocationHandler接口的invoke方法。
    第二步实现代理逻辑方法。invoke方法可以实现代理逻辑。

    这样我们进行HelloWorld proxy= (HelloWorld)jdk . bind(new HelloWorldImpl());
    生成的就是proxy代理对象,调用方法proxy . sayHelloWorld();就会输出:

        进入代理逻辑方法
        在调度真实对象之前的服务
        Hello World
        在调度真实对象之后的服务
    

    这样通过代理,我们做到了什么事情呢?
    你可以看到,我们并没有修改HelloWorldImpl类的sayHello()方法,但是执行出来的代理方法增添了新的内容!如果把目标对象比喻成棒棒糖,那么,代理操作就是在糖外面再裹了一层糖浆!

    CGLIB代理技术

    下面来讲代理的另一种实现方式。
    上面讲的JDK代理,必须要有挂在的接口,也就是说目标的被代理对象必须要有实现的接口。
    如果目标对象没有接口,是一个普通类怎么办呢?
    我们可以用CGLB技术。CGLB使用抽象类来实现代理。来个简单的例子:

        public class SampleClass {
            public void test(){
                System.out.println("hello world");
            }
    
            public static void main(String[] args) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(SampleClass.class);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                        System.out.println("before method run...");
                        Object result = proxy.invokeSuper(obj, args);
                        System.out.println("after method run...");
                        return result;
                    }
                });
                SampleClass sample = (SampleClass) enhancer.create();
                sample.test();
            }
        }
    

    如果把两个类实现同一个接口的这种行为,看作是当兄弟,那么一个类继承另一个类的行为可以被看作当儿子所以JDK的代理和CGLB的差别就是当兄弟和当儿子的区别(都是针对目标对象而言)。
    CGLB的代理实际上是用Enhance对象调用setSuperclass()设置目标类为父类,setCallback()为实际执行的逻辑方法,然后返回代理对象。

    拦截器

    动态代理比较难理解,所以设计者设计了一个拦截器,实现代理,这样开发人员就不需要关心动态代理是怎么实现的。
    一般来说,拦截器是这样的

        public interfa ce Interceptor {
        public boolean before (Obje ct pr , oxy , Object target , Method method , Object []
        args) ;
        public void around(Object proxy , Object target , Method method , Object[]
        args) ;
        public void after(Object proxy, Object target, Method method , Object []
        args) ;
        }
    

    拦截器的作用就是他的名字,拦截。把代理看作一种拦截行为。
    回头看代理的逻辑实现,可以分为,原方法执行前,原方法执行,原方法执行后。三个部分。当然原方法实际上是可以不执行的。
    而拦截器实际上就是把这几个部分拿出来并且加工了一下。
    before()在原方法执行前执行,返回boolean,为true是调用原方法,false调用around()方法,之后调用after()方法。

    Created with Raphaël 2.1.2before() 是否为true原方法after()around() yesno

    这样依赖,我们就只能看见拦截器,而看不见内部的动态代理了。
    也就是说设计者提供了接口,封装了内部原理,而开发人员负责实现接口,提供实际逻辑

    责任链模式

    上面说到,设计者会用拦截器去替换动态代理,提供对应的接口给开发者,从而降低开发难度。
    但是拦截器可以有很多个,比如生病报销,需要将材料一层层的上报。也像是捕鱼,有的鱼篓有好几节长。
    当一个对象在一条链上被多个拦截器拦截处理(当然也可以存在拦截器,而不做任何处理)时,我们把这样的设计模式称之为责任链模式
    内部也就会有多个代理对象。
    这时候你可能就知道了,联想到之前的,我们说代理就是在棒棒糖(原对象方法)上裹了一层糖,那么责任链就是按照顺序裹了一层有一层。类比请假:
    拦截器模式
    而拦截的方法执行就像是从中穿过的一条线的顺序:拦截器的执行
    这样看是不是像穿过了一个裹了一层有一层的糖衣的棒棒糖呢?

    总结

    意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
    优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
    缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

    展开全文
  • JDK动态代理+责任链设计模式 Mybatis 的插件机制,运用的就是该设计模式 ; 文章转自大牛: 雨点的名字 JDK动态代理案例 public class MyProxy { /** * 一个接口 */ public interface HelloService{ void ...

    JDK动态代理+责任链设计模式

    Mybatis 的插件机制,运用的就是该设计模式 ;

    文章转自大牛: 雨点的名字

    • JDK动态代理案例
    public class MyProxy {
        /**
         * 一个接口
         */
        public interface HelloService{
            void sayHello();
        }
        /**
         * 目标类实现接口
         */
        static class HelloServiceImpl implements HelloService{
    
            @Override
            public void sayHello() {
                System.out.println("sayHello......");
            }
        }
        /**
         * 自定义代理类需要实现InvocationHandler接口
         */
        static  class HWInvocationHandler implements InvocationHandler {
            /**
             * 目标对象
             */
            private Object target;
    
            public HWInvocationHandler(Object target){
                this.target = target;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("------插入前置通知代码-------------");
                //执行相应的目标方法
                Object rs = method.invoke(target,args);
                System.out.println("------插入后置处理代码-------------");
                return rs;
            }
    
            public static Object wrap(Object target) {
                return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                        target.getClass().getInterfaces(),new HWInvocationHandler(target));
            }
        }
        public static void main(String[] args)  {
            HelloService proxyService = (HelloService) HWInvocationHandler.wrap(new HelloServiceImpl());
            proxyService.sayHello();
        }
    }
    

    运行结果

    ------插入前置通知代码-------------
    sayHello......
    ------插入后置处理代码-------------
    
    • 优化

      上面代理的功能是实现了,但是有个很明显的缺陷,就是 HWInvocationHandler 是动态代理类,也可以理解成是个工具类,我们不可能会把业务代码写到写到到invoke方法里,
      不符合面向对象的思想,可以抽象一下处理。可以设计一个Interceptor接口,需要做什么拦截处理实现接口就行了。

    public interface Interceptor {
        /**
         * 具体拦截处理
         */
        void intercept();
    }
    

    intercept() 方法就可以处理各种前期准备了

    public class LogInterceptor implements Interceptor {
        @Override
        public void intercept() {
            System.out.println("------插入前置通知代码-------------");
        }
    }
    
    public class TransactionInterceptor implements Interceptor {
        @Override
        public void intercept() {
            System.out.println("------插入后置处理代码-------------");
        }
    }
    
    • 代理对象也做一下修改
    public class HWInvocationHandler implements InvocationHandler {
    
        private Object target;
    
        private List<Interceptor> interceptorList = new ArrayList<>();
    
        public TargetProxy(Object target,List<Interceptor> interceptorList) {
            this.target = target;
            this.interceptorList = interceptorList;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
           //处理多个拦截器
            for (Interceptor interceptor : interceptorList) {
                interceptor.intercept();
            }
            return method.invoke(target, args);
        }
    
        public static Object wrap(Object target,List<Interceptor> interceptorList) {
            HWInvocationHandler targetProxy = new HWInvocationHandler(target, interceptorList);
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                                          target.getClass().getInterfaces(),targetProxy);
        }
    }
    

    现在可以根据需要动态的添加拦截器了,在每次执行业务代码sayHello()之前都会拦截一下,看起来高级一点,来测试一下

    public class Test {
        public static void main(String[] args) {
            List<Interceptor> interceptorList = new ArrayList<>();
            interceptorList.add(new LogInterceptor());
            interceptorList.add(new TransactionInterceptor());
    
            HelloService target = new HelloServiceImpl();
            Target targetProxy = (Target) TargetProxy.wrap(target,interceptorList);
            targetProxy.sayHello();
        }
    }
    

    运行结果

    ------插入前置通知代码-------------
    ------插入后置处理代码-------------
    sayHello......
    
    • 再优化
      上面的动态代理确实可以把代理类中的业务逻辑抽离出来,但是我们注意到,
      只有前置代理,无法做到前后代理,那么我们还需要再优化。
      思路:
      ① 我们可以做进一步的抽象,把拦截对象信息进行封装一下,
      作为拦截器拦截方法的参数

      ② 把拦截目标对象真正的执行方法放到 Interceptor中完成,
      这样就可以实现前后拦截,并且还能对拦截对象的参数等做修改。

    设计一个Invocation 对象。

    public class Invocation {
    
        /**
         * 目标对象
         */
        private Object target;
        /**
         * 执行的方法
         */
        private Method method;
        /**
         * 方法的参数
         */
        private Object[] args;
        
        //省略getset
        public Invocation(Object target, Method method, Object[] args) {
            this.target = target;
            this.method = method;
            this.args = args;
        }
    
        /**
         * 执行目标对象的方法
         */
        public Object process() throws Exception{
           return method.invoke(target,args);
        }
    }
    

    Interceptor拦截接口做修改

    public interface Interceptor {
        /**
         * 具体拦截处理
         */
        Object intercept(Invocation invocation) throws Exception;
    }
    

    Interceptor实现类

    public class TransactionInterceptor implements Interceptor {
    
        @Override
        public Object intercept(Invocation invocation) throws Exception{
            System.out.println("------插入前置通知代码-------------");
            Object result = invocation.process();
            System.out.println("------插入后置处理代码-------------");
            return result;
        }
    }
    

    Invocation 类就是被代理对象的封装,也就是要拦截的真正对象。HWInvocationHandler修改如下:

    public class HWInvocationHandler implements InvocationHandler {
    
        private Object target;
    
        private Interceptor interceptor;
    
        public TargetProxy(Object target,Interceptor interceptor) {
            this.target = target;
            this.interceptor = interceptor;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Invocation invocation = new Invocation(target,method,args);
            return interceptor.intercept(invocation);
        }
    
        public static Object wrap(Object target,Interceptor interceptor) {
            HWInvocationHandler targetProxy = new HWInvocationHandler(target, interceptor);
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),targetProxy);
        }
    }
    

    测试类

    public class Test {
        public static void main(String[] args) {
            HelloService target = new HelloServiceImpl();
            Interceptor transactionInterceptor = new TransactionInterceptor();
            HelloService targetProxy = (Target) TargetProxy.wrap(target,transactionInterceptor);
            targetProxy.sayHello();
        }
    }
    

    运行结果

    ------插入前置通知代码-------------
    sayHello......
    ------插入后置处理代码-------------
    
    • 再再优化

      上面这样就能实现前后拦截,并且拦截器能获取拦截对象信息。
      但是测试代码的这样调用看着别扭,对应目标类来说,只需要了解对他
      插入了什么拦截就好。

    再修改一下,在拦截器增加一个插入目标类的方法。

    public interface Interceptor {
        /**
         * 具体拦截处理
         */
        Object intercept(Invocation invocation) throws Exception;
    
        /**
         *  插入目标类
         */
        Object plugin(Object target);
    
    }
    
    public class TransactionInterceptor implements Interceptor {
    
        @Override
        public Object intercept(Invocation invocation) throws Exception{
            System.out.println("------插入前置通知代码-------------");
            Object result = invocation.process();
            System.out.println("------插入后置处理代码-------------");
            return result;
        }
    
        @Override
        public Object plugin(Object target) {
            return TargetProxy.wrap(target,this);
        }
    }
    

    这样目标类仅仅需要在执行前,插入需要的拦截器就好了,测试代码:

    public class Test {
        public static void main(String[] args) {
            HelloService target = new HelloServiceImpl();
            Interceptor transactionInterceptor = new TransactionInterceptor();
            //把事务拦截器插入到目标类中
            target = (HelloService) transactionInterceptor.plugin(target);
            target.sayHello();
        }
    }
    

    运行结果

    ------插入前置通知代码-------------
    sayHello......
    ------插入后置处理代码-------------
    
    • 多个拦截器如何处理
      到这里就差不多完成了,那我们再来思考如果要添加多个拦截器呢,怎么搞?
    public class Test {
        public static void main(String[] args) {
            HelloService target = new HelloServiceImpl();
            Interceptor transactionInterceptor = new TransactionInterceptor();
            target = (HelloService) transactionInterceptor.plugin(target);
            LogInterceptor logInterceptor = new LogInterceptor();
            target = (HelloService)logInterceptor.plugin(target);
            target.sayHello();
        }
    }
    

    运行结果

    ------插入前置通知代码-------------
    ------插入前置通知代码-------------
    sayHello......
    ------插入后置处理代码-------------
    ------插入后置处理代码------------
    
    • 责任链设计模式
      其实上面已经实现的没问题了,只是还差那么一点点,添加多个拦截器的时候不太美观,让我们再次利用面向对象思想封装一下。我们设计一个InterceptorChain 拦截器链类
    public class InterceptorChain {
    
        private List<Interceptor> interceptorList = new ArrayList<>();
    
        /** 
         * 插入所有拦截器
         */
        public Object pluginAll(Object target) {
            for (Interceptor interceptor : interceptorList) {
                target = interceptor.plugin(target);
            }
            return target;
        }
    
        public void addInterceptor(Interceptor interceptor) {
            interceptorList.add(interceptor);
        }
        /**
         * 返回一个不可修改集合,只能通过addInterceptor方法添加
         * 这样控制权就在自己手里
         */
        public List<Interceptor> getInterceptorList() {
            return Collections.unmodifiableList(interceptorList);
        }
    }
    

    其实就是通过pluginAll() 方法包一层把所有的拦截器插入到目标类去而已。测试代码:

    public class Test {
    
        public static void main(String[] args) {
            HelloService target = new HelloServiceImpl();
            Interceptor transactionInterceptor = new TransactionInterceptor();
            LogInterceptor logInterceptor = new LogInterceptor();
            InterceptorChain interceptorChain = new InterceptorChain();
            interceptorChain.addInterceptor(transactionInterceptor);
            interceptorChain.addInterceptor(logInterceptor);
            target = (Target) interceptorChain.pluginAll(target);
            target.sayHello();
        }
    }
    

    这里展示的是JDK动态代理+责任链设计模式,那么Mybatis拦截器就是基于该组合进行开发。

    展开全文
  • 当一个对象在一条链上被多个拦截器拦截处理(拦截器也可以选择不拦截它)时,把这种设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景。 依据上一篇文章中创建的拦截器接口,创建三个拦截器对象 ...

    当一个对象在一条链上被多个拦截器拦截处理(拦截器也可以选择不拦截它)时,把这种设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景。

    依据上一篇文章中创建的拦截器接口,创建三个拦截器对象

    public class Interceptor1 implements Interceptor{
    
    	@Override
    	public boolean before(Object proxy, Object target, Method method, Object[] args) {
    		System.out.println("拦截器1的before方法");
    		return true;
    	}
    
    	@Override
    	public void around(Object proxy, Object target, Method method, Object[] args) {
    		
    	}
    
    	@Override
    	public void after(Object proxy, Object target, Method method, Object[] args) {
    		System.out.println("拦截器1的after方法");
    	}
    
    }
    
    public class Interceptor2 implements Interceptor {
    
    	/* (non-Javadoc)
    	 * @see interceptor.Interceptor#before(java.lang.Object, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    	 */
    	@Override
    	public boolean before(Object proxy, Object target, Method method, Object[] args) {
    		System.out.println("拦截器2的before方法");
    		return true;
    	}
    
    	/* (non-Javadoc)
    	 * @see interceptor.Interceptor#around(java.lang.Object, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    	 */
    	@Override
    	public void around(Object proxy, Object target, Method method, Object[] args) {
    	}
    
    	/* (non-Javadoc)
    	 * @see interceptor.Interceptor#after(java.lang.Object, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    	 */
    	@Override
    	public void after(Object proxy, Object target, Method method, Object[] args) {
    		System.out.println("拦截器2的after方法");
    	}
    
    }
    
    public class Interceptor3 implements Interceptor{
    
    	/* (non-Javadoc)
    	 * @see interceptor.Interceptor#before(java.lang.Object, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    	 */
    	@Override
    	public boolean before(Object proxy, Object target, Method method, Object[] args) {
    		System.out.println("拦截器3的before方法");
    		return true;
    	}
    
    	/* (non-Javadoc)
    	 * @see interceptor.Interceptor#around(java.lang.Object, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    	 */
    	@Override
    	public void around(Object proxy, Object target, Method method, Object[] args) {
    	}
    
    	/* (non-Javadoc)
    	 * @see interceptor.Interceptor#after(java.lang.Object, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    	 */
    	@Override
    	public void after(Object proxy, Object target, Method method, Object[] args) {
    		System.out.println("拦截器3的after方法");
    	}
    
    }
    

    实现责任链模式的逻辑

    public class InterceptorJdkProxy implements InvocationHandler {
    
    	private Object target;//真实对象
    	private String interceptorClass = null;//拦截器全限定类名
    	
    	public InterceptorJdkProxy(Object target, String interceptorClass) {
    		this.target = target;
    		this.interceptorClass = interceptorClass;
    	}
    	
    	public static Object bind(Object target,String interceptorClass) {
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass));
    	}
    
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		if(interceptorClass == null) {
    			return method.invoke(proxy, args);
    		}else {
    			Object result = null;
    			Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
    			if(interceptor.before(proxy, target, method, args)) {
    				result = method.invoke(target, args);
    			}else {
    				interceptor.around(proxy, target, method, args);
    			}
    			//调用后置方法
    			interceptor.after(proxy, target, method, args);
    			return result;
    		}
    	}
    	
    	public static void main(String[] args) {
    		HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(), "interceptor.Interceptor1");
    		HelloWorld proxy2 = (HelloWorld) InterceptorJdkProxy.bind(proxy1, "interceptor.Interceptor2");
    		HelloWorld proxy3 = (HelloWorld) InterceptorJdkProxy.bind(proxy2, "interceptor.Interceptor3");
    		proxy3.sayHelloWorld();
    	}
    
    }
    

    执行结果如下:

    拦截器3的before方法
    拦截器2的before方法
    拦截器1的before方法
    Hello World!
    拦截器1的after方法
    拦截器2的after方法
    拦截器3的after方法

    可以看到拦截器中的方法执行顺序:before方法按照从最后一个拦截器到第一个拦截器的顺序运行,而after则按照拦截器调用的顺序运行。

    展开全文
  • 有一个DNS服务器项目(其实是最近在做的一个智能DNS项目)的过滤模块,现有如下需求:1.能准确判断出用户IP地址是否合法,及用户...由于前一段时间了解了一下责任链模式,所以决定用责任链模式实现该模块。类结构图...

    有一个DNS服务器项目(其实是最近在做的一个智能DNS项目)的过滤模块,现有如下需求:1.能准确判断出用户IP地址是否合法,及用户IP是否位于黑名单中;2.用户请求查询的主机名是否合法,机主机名是否位于黑名单中。要实现对以上用户请求过滤。后期可能还要实现对ddos攻击请求的过滤。由于前一段时间了解了一下责任链模式,所以决定用责任链模式实现该模块。类结构图如下所示(图画的不一定准确,凑合着看吧):

    clip_image002[7]

    图中有一个抽象类Filter,他有一个抽象方法Validate(),用于实现对请求的过滤。其他类均继承自Filter类。其中IPFilter实现对IP过滤,DomainNameFilter实现对主机名的过滤。DDOsFilter实现对DDOs请求过滤,暂时未使用。FilterChain中有一个List<Filter> 类型对象filterChain用于存放各个过滤器。还有一个Add()方法用来向filterChain中添加过滤器。

    现在由于没有新的需求,采用的是静态的去初始化filterChain。方法如下:

    public FilterChain Add(Filter filter) 

    { 
        filterChain.Add(filter); 
        return this; 
    } 
    7

    然后,可以像下面一样去调用这个方法:

    FilterChain fc = new FilterChain(); 
    fc.Add(new IPFilter()).Add(new DomainNameFilter()).Add(new DDosFilter()); 
    3

    OK,现在只需调用fc.Validate(),就可以实现对IP和主机名的过滤。

    似乎,我们已经实现该模块的功能了,而且用着也挺简单,调用时完全不需要知道过滤具体是怎么实现的。很完美,所以经测试之后我们将系统发布到服务器上开始工作。

    但是,我们似乎忽略了一点。假如现在我们发现有用户发送恶意请求企图攻击我们的服务器,导致我们的服务器不能正常的为其他用户提供服务。我们当然不能容忍这种行为,更不能让攻击者得逞。所以我们要将DDosFilter也投入使用来时我们的系统更加强壮。

    What should we do?

    我们需要修改代码。如上面的fc.Add().Add().Add(),我们可以再在后面加一个Add().

    OK,问题解决了。

    假如,现在又有新的需求,主机名过滤不在那么重要了,要将其去掉。

    怎么做?

    正如上面我们需要修改代码来完成工作。但是慢慢的我们会发现,我们每次都需要修改代码,而且每次只是需要修改一丁点儿的代码。但是我们的系统已经正式发布了,每次只为这么一点小事就修改代码,会显示出我们的系统不够强壮。而且每次的一丁点的修改,也使我们的工作看起来似乎没什么意义。

    我们寻求更加简便的方法来完成对系统的更改。于是我们想到了配置文件。我们可以将要使用的过滤器写入配置文件中,这样只需修改配置文件就可以完成对系统的更改,而无需修改代码。

    最近,看了看反射(虽然课堂上老师说只是了解即可,可我的直觉告诉我这个东西可以多了解一些,它很有用),它完全可胜任这一工作。当然还会有其他方法。但本文只探讨用反射机制实现。于是产生了如下面的代码:

    1  private FilterChain DynamicAdd() 
    2  
    3  { 
    4      string fileContent = File.ReadAllText("Filter.config");

     


    5      string[] filters = fileContent.Trim().Split(';');

     


    6      Assembly ass = Assembly.GetExecutingAssembly();

     


    7      Type[] types = ass.GetTypes();

     


    8      object obj = null;

    9      foreach (var item in filters) 
    10         {

     


    11         try 
    12             {

     


    13                 obj = ass.CreateInstance(item.Trim());

     


    14             }

     


    15         catch (Exception) 
    16             {

     


    17                  continue;

     


    18             } 
    19             if (obj != null)
                        {

     


    20                        filterChain.Add((Filter)obj); 
    21                 }
                }

    22                 return this; 
    23     } 
    24

    其中,需要加载的过滤器放在filter.config这个文件中。格式如下:

    Filter.IPFilter;Filter.DomainNameFilter;Filter.DDosFilter

          从配置文件中可以读出过滤器的名称,然后通过反射构造出对应过滤器的对象,然后将对象加入filterChain中,从而实现filterChain的动态初始化。

          对于过滤规则,一个系统有一组就够了,所以可以进一步将filterChain声明为 private static List<Filter> 类型,然后在类构造器而不是实例构造器中去动态初始化它。这样在过滤时就完全不需要去考虑初始化过滤链的事儿了。当过滤需求放生变化时,只需修改配置文件,然后重启一下服务即可。进而摆脱频繁修改代码的烦恼。


    本文转自HDDevTeam 51CTO博客,原文链接:http://blog.51cto.com/hddev/622944,如需转载请自行联系原作者

    展开全文
  • 动态代理模式和责任链模式 动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问。 先来谈谈什么是代理模式。假设这样一个场景,你的公司是一家软件公司,你是以为软件工程师...
  • JDK动态代理在添加前、后置处理时存在的缺陷? 一 在JDK动态代理模式中代理类通过实现InvocationHandler接口,在invoke方法可以调用目标类的方法,并在调用目标方法时实现前、后置处理。jdk动态代理是基于接口实现...
  • SpringAOP之探秘(动态代理、责任链模式、注解使用)- 详情:https://blog.csdn.net/Dream_Weave/article/details/85008674
  • 002:责任链模式1 责任链模式的应用场景2 责任链底层实现原理与类图3 使用工厂模式实现责任链模式014 使用工厂模式实现责任链模式...5、基于数据库实现动态责任链 6、Java过滤器责任链模式源码分析 什么是责任链模式 客
  • jdk动态代理 被代理接口:  package com.mzs.test; public interface DemoService { void speak(String str); void jump(String str); } 被代理类:  package com.mzs.test; public class ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,155
精华内容 462
关键字:

动态责任链