zoukankan      html  css  js  c++  java
  • 过滤器 简单飞扬

    tt用spring写的过滤器

    Spring 是一个非常优秀的轻量级框架,通过Spring的IoC容器,我们的关注点便放到了需要实现的业务逻辑上。对AOP的支持则能让我们动 态增强业务方法。编写普通的业务逻辑Bean是非常容易而且易于测试的,因为它能脱离J2EE容器(如Servlet,JSP环境)单独进行单元测试。最 后的一步便是在Spring框架中将这些业务Bean以XML配置文件的方式组织起来,它们就按照我们预定的目标正常工作了!非常容易!

    本文将给出一个基本的Spring入门示例,并演示如何使用Spring的AOP将复杂的业务逻辑分离到每个方面中。

    1.开发环境配置
    2.编写Bean接口及其实现
    3.在Spring中配置Bean并获得Bean的实例
    4.编写Advisor以增强ServiceBean
    5.总结

    1.开发环境配置

    首先,需要正确配置Java环境。推荐安装JDK1.4.2,并正确配置环境变量:

    JAVA_HOME=<JDK安装目录>
    CLASSPATH=.
    Path=%JAVA_HOME%"bin;……

    我 们将使用免费的Eclipse 3.1作为IDE。新建一个Java Project,将Spring的发布包spring.jar以及commons-logging-1.0.4.jar复制到Project目录下,并在 Project > Properties中配置好Java Build Path:

    2.编写Bean接口及其实现

    我们实现一个管理用户的业务Bean。首先定义一个ServiceBean接口,声明一些业务方法:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    /**
     * Interface of service facade.
     *
     * @author Xuefeng
     */
    public interface ServiceBean {
        void addUser(String username, String password);
        void deleteUser(String username);
        boolean findUser(String username);
        String getPassword(String username);
    }

    然后在MyServiceBean中实现接口:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     *
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    import java.util.*;
    public class MyServiceBean implements ServiceBean {
        private String dir;
        private Map map = new HashMap();
        public void setUserDir(String dir) {
            this.dir = dir;
            System.out.println("Set user dir to: " + dir);
        }
        public void addUser(String username, String password) {
            if(!map.containsKey(username))
                map.put(username, password);
            else
                throw new RuntimeException("User already exist.");
        }
        public void deleteUser(String username) {
            if(map.remove(username)==null)
                throw new RuntimeException("User not exist.");
        }
        public boolean findUser(String username) {
            return map.containsKey(username);
        }
        public String getPassword(String username) {
            return (String)map.get(username);
        }
    }

    为了简化逻辑,我们使用一个Map保存用户名和口令。

    现在,我们已经有了一个业务Bean。要测试它非常容易,因为到目前为止,我们还没有涉及到Spring容器,也没有涉及到任何Web容器(假定这是一个Web应用程序关于用户管理的业务Bean)。完全可以直接进行Unit测试,或者,简单地写个main方法测试:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    public class Main {
        public static void main(String[] args) throws Exception {
            ServiceBean service = new MyServiceBean();
            service.addUser("bill", "hello");
            service.addUser("tom", "goodbye");
            service.addUser("tracy", "morning");
            System.out.println("tom's password is: " + service.getPassword("tom"));
            if(service.findUser("tom")) {
                service.deleteUser("tom");
            }
        }
    }

    执行结果:

    3.在Spring中配置Bean并获得Bean的实例

    我们已经在一个main方法中实现了业务,不过,将对象的生命周期交给容器管理是更好的办法,我们就不必为初始化对象和销毁对象进行硬编码,从而获得更大的灵活性和可测试性。

    想要把ServiceBean交给Spring来管理,我们需要一个XML配置文件。新建一个beans.xml,放到src目录下,确保在classpath中能找到此配置文件,输入以下内容:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean id="service" class="com.crackj2ee.example.spring.MyServiceBean" />
    </beans>

    以上XML声明了一个id为service的Bean,默认地,Spring为每个声明的Bean仅创建一个实例,并通过id来引用这个Bean。下面,我们修改main方法,让Spring来管理业务Bean:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    public class Main {
        public static void main(String[] args) throws Exception {
            // init factory:
            XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
            // use service bean:
            ServiceBean service = (ServiceBean)factory.getBean("service");
            service.addUser("bill", "hello");
            service.addUser("tom", "goodbye");
            service.addUser("tracy", "morning");
            System.out.println("tom's password is """ + service.getPassword("tom") + """");
            if(service.findUser("tom")) {
                service.deleteUser("tom");
            }
            // close factory:
            factory.destroySingletons();
        }
    }

    执行结果:
     

    由于我们要通过main方法启动Spring环境,因此,首先需要初始化一个BeanFactory。红色部分是初始化Spring的BeanFactory的典型代码,只需要保证beans.xml文件位于classpath中。

    然后,在BeanFactory中通过id查找,即可获得相应的Bean的实例,并将其适当转型为合适的接口。

    接着,实现一系列业务操作,在应用程序结束前,让Spring销毁所有的Bean实例。

    对比上一个版本的Main,可以看出,最大的变化是不需要自己管理Bean的生命周期。另一个好处是在不更改实现类的前提下,动态地为应用程序增加功能。

    4.编写Advisor以增强ServiceBean

    所 谓AOP即是将分散在各个方法处的公共代码提取到一处,并通过类似拦截器的机制实现代码的动态织入。可以简单地想象成,在某个方法的调用前、返回 前、调用后和抛出异常时,动态插入自己的代码。在弄清楚Pointcut、Advice之类的术语前,不如编写一个最简单的AOP应用来体验一下。

    考虑一下通常的Web应用程序都会有日志记录,我们来编写一个LogAdvisor,对每个业务方法调用前都作一个记录:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;
    public class LogAdvisor implements MethodBeforeAdvice {
        public void before(Method m, Object[] args, Object target) throws Throwable {
            System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");
        }
    }

    然后,修改beans.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
        <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
        <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
            <property name="target"><ref local="serviceTarget"/></property>
            <property name="interceptorNames">
                <list>
                    <value>logAdvisor</value>
                </list>
            </property>
        </bean>
    </beans>

    注 意观察修改后的配置文件,我们使用了一个ProxyFactoryBean作为service来与客户端打交道,而真正的业务Bean即 MyServiceBean被声明为serviceTarget并作为参数对象传递给ProxyFactoryBean,proxyInterfaces 指定了返回的接口类型。对于客户端而言,将感觉不出任何变化,但却动态加入了LogAdvisor,关系如下:
     

    运行结果如下,可以很容易看到调用了哪些方法:
     

    要截获指定的某些方法也是可以的。下面的例子将修改getPassword()方法的返回值:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    public class PasswordAdvisor implements MethodInterceptor {
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Object ret = invocation.proceed();
            if(ret==null)
                return null;
            String password = (String)ret;
            StringBuffer encrypt = new StringBuffer(password.length());
            for(int i=0; i<password.length(); i++)
                encrypt.append('*');
            return encrypt.toString();
        }
    }

    这个PasswordAdvisor将截获ServiceBean的getPassword()方法的返回值,并将其改为"***"。继续修改beans.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
        <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
        <bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" />
        <bean id="passwordAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice">
                <ref local="passwordAdvisorTarget"/>
            </property>
            <property name="patterns">
                <list>
                    <value>.*getPassword</value>
                </list>
            </property>
        </bean>
        <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
            <property name="target"><ref local="serviceTarget"/></property>
            <property name="interceptorNames">
                <list>
                    <value>logAdvisor</value>
                    <value>passwordAdvisor</value>
                </list>
            </property>
        </bean>
    </beans>

    利用Spring提供的一个RegexMethodPointcutAdvisor可以非常容易地指定要截获的方法。运行结果如下,可以看到返回结果变为"******":
     

    还需要继续增强ServiceBean?我们编写一个ExceptionAdvisor,在业务方法抛出异常时能做一些处理:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit:
    http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;
    import org.springframework.aop.ThrowsAdvice;
    public class ExceptionAdvisor implements ThrowsAdvice {
        public void afterThrowing(RuntimeException re) throws Throwable {
            System.out.println("[Exception] " + re.getMessage());
        }
    }

    将此Advice添加到beans.xml中,然后在业务Bean中删除一个不存在的用户,故意抛出异常:

    service.deleteUser("not-exist");

    再次运行,注意到ExceptionAdvisor记录下了异常:
     

    5.总结

    利用Spring非常强大的IoC容器和AOP功能,我们能实现非常灵活的应用,让Spring容器管理业务对象的生命周期,利用AOP增强功能,却不影响业务接口,从而避免更改客户端代码。

    为了实现这一目标,必须始终牢记:面向接口编程。而Spring默认的AOP代理也是通过Java的代理接口实现的。虽然Spring也可以用CGLIB实现对普通类的代理,但是,业务对象只要没有接口,就会变得难以扩展、维护和测试。

    欢迎来信与作者交流:asklxf@163.com

    附完整源码:

    注:本例需要commons-logging-1.0.4.jar和spring.jar

     ServiceBean.java

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     *
     * For more information, please visit: http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;

    /**
     * Interface of service facade.
     *
     * @author Xuefeng
     */
    public interface ServiceBean {

        void addUser(String username, String password);

        void deleteUser(String username);

        boolean findUser(String username);

        String getPassword(String username);
    }

    MyServiceBean.java:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     *
     * For more information, please visit: http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;

    import java.util.*;

    public class MyServiceBean implements ServiceBean {

        private String dir;
        private Map map = new HashMap();

        public void setUserDir(String dir) {
            this.dir = dir;
            System.out.println("Set user dir to: " + dir);
        }

        public void addUser(String username, String password) {
            if(!map.containsKey(username))
                map.put(username, password);
            else
                throw new RuntimeException("User already exist.");
        }

        public void deleteUser(String username) {
            if(map.remove(username)==null)
                throw new RuntimeException("User not exist.");
        }

        public boolean findUser(String username) {
            return map.containsKey(username);
        }

        public String getPassword(String username) {
            return (String)map.get(username);
        }
    }

    Main.java:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit: http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;

    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;

    public class Main {

        public static void main(String[] args) throws Exception {
            // init factory:
            XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
            // use service bean:
            ServiceBean service = (ServiceBean)factory.getBean("service");
            service.addUser("bill", "hello");
            service.addUser("tom", "goodbye");
            service.addUser("tracy", "morning");
            System.out.println("tom's password is """ + service.getPassword("tom") + """");
            if(service.findUser("tom")) {
                service.deleteUser("tom");
            }
            service.deleteUser("not-exist");
            // close factory:
            factory.destroySingletons();
        }
    }

    beans.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
        <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />

        <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />

        <bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" />

        <bean id="passwordAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice">
                <ref local="passwordAdvisorTarget"/>
            </property>
            <property name="patterns">
                <list>
                    <value>.*getPassword</value>
                </list>
            </property>
        </bean>

        <bean id="exceptionAdvisor" class="com.crackj2ee.example.spring.ExceptionAdvisor" />

        <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
            <property name="target"><ref local="serviceTarget"/></property>
            <property name="interceptorNames">
                <list>
                    <value>logAdvisor</value>
                    <value>passwordAdvisor</value>
                    <value>exceptionAdvisor</value>
                </list>
            </property>
        </bean>
    </beans>

    LogAdvisor.java:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit: http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;

    import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;

    public class LogAdvisor implements MethodBeforeAdvice {

        public void before(Method m, Object[] args, Object target) throws Throwable {
            System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");
        }

    }

    PasswordAdvisor.java:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit: http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;

    public class PasswordAdvisor implements MethodInterceptor {

        public Object invoke(MethodInvocation invocation) throws Throwable {
            Object ret = invocation.proceed();
            if(ret==null)
                return null;
            String password = (String)ret;
            StringBuffer encrypt = new StringBuffer(password.length());
            for(int i=0; i<password.length(); i++)
                encrypt.append('*');
            return encrypt.toString();
        }

    }

    ExceptionAdvisor.java:

    /**
     * Copyright_2006, Liao Xuefeng
     * Created on 2006-3-9
     * For more information, please visit: http://www.crackj2ee.com
     */
    package com.crackj2ee.example.spring;

    import org.springframework.aop.ThrowsAdvice;

    public class ExceptionAdvisor implements ThrowsAdvice {
        public void afterThrowing(RuntimeException re) throws Throwable {
            System.out.println("[Exception] " + re.getMessage());
        }
    }

    转自网络
  • 相关阅读:
    matab plot指令和低通滤波器的响应图
    matlab中hold指令、figure指令及subplot指令的使用
    matlab中axis的使用
    matlab switch case 和 try catch用法示例
    matlab中使用elseif和if嵌套的对比
    matlab中运用项目思维分析问题并解决问题
    matlab图像显示程序模板
    matlab最简单程序模板
    第06篇 MyEclipse 2016 安装/破解
    第05篇. Tomcat和JDK的内存配置
  • 原文地址:https://www.cnblogs.com/jiandanfy/p/1068158.html
Copyright © 2011-2022 走看看