模拟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的FilterChian

public 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

初始化 secondFilter

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

过滤器已处理完毕,现在由Servlet来处理请求。。。

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

firstFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

secondFilter: http://localhost:8080/filter/hello...?name=zhangsan&age=23&address=xxxxx

过滤器已处理完毕,现在由Servlet来处理请求。。。

过滤器已处理完毕,现在由Servlet来处理请求。。。

过滤器已处理完毕,现在由Servlet来处理请求。。。  

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

 

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

 

模拟JavaEE的Filter,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。