以此之长,补彼之短----AOP(Filter)

 

AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP利用封装、继承和多态把一切事物打造成对象结构,但是对于所有对象中都存在的一些公共行为,OOP就显得无能为力,抽象和接口虽好,但对所有不相干的对象建立共同的接口或父类未免有些生硬,例如日志功能,日志代码几乎散布在所有的对象层次中,而它和散布到对象的核心功能毫无关系,对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。因此,为减少这种大量的重复代码,面向切面技术诞生了,AOP和OOP的关系好似JSP和Servlet的关系,以此之长,补彼之短。

 

Java中常见的AOP技术有两个,分别是Filter和代理模式,代理模式又分为静态代理和动态代理。他们各自实现的功能不同,原理如出一辙。如下图,以添加用户为例,采用Module1架构模式,从图中可以看出无论程序从左向右或者从右向左执行都必须经过Filter,Filter在Request到达JSP(Servlet)前截获Request并进行预处理,也可以在Response离开JSP(Servlet)时处理Response,然后对Request进行统一的设置后继续向后传递,比如可以在Filter完成字符集的设置,用户身份的识别,敏感词汇的过滤等等,配置Filter个数不限。

下面就以设置字符集为例,首先创建一个Class文件,并让他实现Filter接口,覆写init和doFilter,代码如下:

[java] view plain copy print ?
  1. package com.snail.drp.util.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11.   
  12. public class CharsetEncodingFilter implements Filter {  
  13.     private String endcoding;  
  14.       
  15.     @Override  
  16.     public void destroy() {  
  17.         // TODO Auto-generated method stub   
  18.     }  
  19.   
  20.     @Override  
  21.     public void doFilter(ServletRequest request, ServletResponse response,  
  22.             FilterChain chain) throws IOException, ServletException {  
  23.         request.setCharacterEncoding(endcoding);  
  24.           
  25.         //继续执行   
  26.         chain.doFilter(request, response);    
  27.     }  
  28.   
  29.     @Override  
  30.     public void init(FilterConfig filterConfig) throws ServletException {  
  31.         this.endcoding = filterConfig.getInitParameter("encoding");  
  32.     }  
  33. }  
package com.snail.drp.util.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class CharsetEncodingFilter implements Filter { private String endcoding; @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(endcoding); //继续执行 chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { this.endcoding = filterConfig.getInitParameter("encoding"); } }

Filter虽不是一个Servlet,但它需要在web.xml文件中配置之后才能使用,具体解释看代码中的注释,如下:

[html] view plain copy print ?
  1. <filter>        
  2.     <filter-name>CharsetEncodingFilterfilter-name>  
  3.     <filter-class>com.snail.drp.util.filter.CharsetEncodingFilterfilter-class>  
  4.       
  5.     <init-param>  
  6.         <param-name>encodingparam-name>  
  7.         <param-value>GB18030param-value>  
  8.     init-param>  
  9. filter>  
  10.   
  11. <filter-mapping>  
  12.     <filter-name>CharsetEncodingFilterfilter-name>  
  13.     <url-pattern>*.jspurl-pattern>  
  14. filter-mapping>  
  15. <filter-mapping>  
  16.     <filter-name>CharsetEncodingFilterfilter-name>  
  17.     <url-pattern>/servlet/*url-pattern>  
  18. filter-mapping>  
CharsetEncodingFilter com.snail.drp.util.filter.CharsetEncodingFilter encoding GB18030 CharsetEncodingFilter *.jsp CharsetEncodingFilter /servlet/*

Filter是职责链模式的经典应用,从上面示例代码可以看出,实现了Filter接口的doFilter方法主要用于截获Request对象,把截获的请求处理后(设置字符集),调用FilterChain 接口的chain.doFilter(request,response)方法,把处理权传递给下一个filter。

 

其中,FilterChain维护了一个链表,链表中存放着配置对象的链条,每次用户调用 一次chain.doFilter(request, response),链表就去取下一个配置对象,再通过配置对象 得到下一个filter,然后调用该filter,接着在filter里写的逻辑就被执行了。

 

http://blog.csdn.net/stubbornpotatoes/article/details/7347663

你可能感兴趣的:(spring)