首页 > 代码库 > 模拟JavaEE的Filter

模拟JavaEE的Filter

做JavaEE开发几年了,只是知道Filter、Servlet的执行流程,但是一直对Filter是如何实现的并不了解。

    Filter的处理中的FilterChain是J2ee的接口,并没有提供实现,具体的实现有各个Servlet容器来实现的。今天就找了个时间,简单的看了一下Tomcat的FilterChain的内部实现,做了一个大致的了解,下面就来模拟了一下。

    以我对Tomcat中Filter简单实现,设计了下面的类图:

 

 

Filter接口、FilterChain,是完全按照J2EE中的Filter接口、FilterChain来设计的。

FilterContext是Filter的执行上下文。

DefaultFilterChain用于调配各个过滤器的执行。

Request是封装的简易请求。

FirstFilter、SecondFilter用于模拟我们开发时自定义的Filter。

Client用于测试。

 

 

下面附上代码:

// J2EE的Filter/** * Created with IntelliJ IDEA. * User: Administrator * Date: 14-7-28 * To change this template use File | Settings | File Templates. */public interface Filter {    public void init(FilterConfig cfg);    public void doFilter(Request request, Object response, FilterChain chain);    public void destroy();} // J2EE的FilterChianpublic interface FilterChain {   void doFilter(Request request, Object response);} // Filter配置信息,用于Filter初始化public class FilterConfig {    private String name;    public FilterConfig(){}    public FilterConfig(String name){        this.name=name;    }     public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }} // 模拟Filter执行的上下文public class FilterContext {    List<Filter> filters=new ArrayList<Filter>();    public FilterContext(){     }    public void addFilter(Filter filter, FilterConfig cfg){        this.filters.add(filter);        filter.init(cfg);    }     public void remvoeFilter(Filter filter){        this.filters.remove(filter);        filter.destroy();    }     public Filter getFilter(int index){        return filters.get(index);    }} // 自定义请求public class Request {    private String url;    private String param;     public String getUrl() {        return url;    }     public void setUrl(String url) {        this.url = url;    }     public String getParam() {        return param;    }     public void setParam(String param) {        this.param = param;    }     @Override    public String toString() {        return this.url+"?"+this.getParam();    }}   // 模拟FilterChain的内部实现public class DefaultFilterChain implements FilterChain {    private FilterContext context;    private int i=0;     public void doFilter(Request request, Object response) {         if(i<context.filters.size()){            context.getFilter(i++).doFilter(request, response, this);        }        else {            System.out.println("过滤器已处理完毕,现在由Servlet来处理请求。。。");        }    }     public void setContext(FilterContext context) {        this.context = context;    }}  
View Code

 

上面的几个类模拟了J2EE对于FIlter的设计。

 

接下来,自定义两个Filter:

public class FirstFilter implements Filter {    private String name;    public void init(FilterConfig cfg) {        this.name=cfg.getName();        System.out.println("初始化 "+cfg.getName());    }     public void doFilter(Request request, Object response, FilterChain chain) {        System.out.println(this.name+": "+request);        if (request.getUrl()!=null){            chain.doFilter(request,response);        }    }     public void destroy() {        //To change body of implemented methods use File | Settings | File Templates.    }}  public class SecondFilter implements Filter {    private String name;    public void init(FilterConfig cfg) {        this.name=cfg.getName();        System.out.println("初始化 "+cfg.getName());    }     public void doFilter(Request request, Object response, FilterChain chain) {        System.out.println(this.name+": "+request);        if (request.getUrl()!=null){            chain.doFilter(request,response);        }    }     public void destroy() {        //To change body of implemented methods use File | Settings | File Templates.    }}
View Code

模拟客户端发送请求: 

 

public class Client {     public static void main(String[] args) throws InterruptedException {        final FilterContext context=init();          final int poolsize=10;// 模拟多个请求        ExecutorService pool=Executors.newFixedThreadPool(poolsize);        List<Callable<Object>> tasks=new ArrayList<Callable<Object>>(poolsize);        for (int i=0; i<poolsize;i++){            tasks.add(new Callable<Object>() {                public Object call() throws Exception {                    //客户端请求                    Request request=new Request();                    request.setUrl("http://localhost:8080/filter/hello...");                    request.setParam("name=zhangsan&age=23&address=xxxxx");                     Object response=new Object();                    // 这里是模拟过滤器对请求过滤                    DefaultFilterChain chain=new DefaultFilterChain();                    chain.setContext(context);                    chain.doFilter(request,response);                    return response;                }            });        }        pool.invokeAll(tasks);    } // 初始化FilterContext    static FilterContext init(){        // 初始化FilterContext并添加自定义Filter ,这个过程是模拟Web Server启动        FilterContext context=new FilterContext();        Filter filter=new FirstFilter();        context.addFilter(filter, new FilterConfig("firstFilter"));        filter=new SecondFilter();        context.addFilter(filter, new FilterConfig("secondFilter"));        return context;    }}

 这个模拟过程,只是模拟了发送请求,过滤器对请求过滤的过程。并没有对响应信息处理。

上面的模拟的执行结果:

初始化 firstFilter初始化 secondFilterfirstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxfirstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。过滤器已处理完毕,现在由Servlet来处理请求。。。firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxfirstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxfirstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxxsecondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx过滤器已处理完毕,现在由Servlet来处理请求。。。过滤器已处理完毕,现在由Servlet来处理请求。。。过滤器已处理完毕,现在由Servlet来处理请求。。。  

上面的是对Filter的模拟,具体是怎样一个过程,还需要认真的研究源码才可知晓。尽管如此,通过这个模拟至少对Filter的处理有一个简单的了解。

 

Filter的设计其实是按照AOP的思想设计的。为什么这么说,下一篇博客将揭晓。