模拟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;

    }

}

上面的几个类模拟了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.

    }

}

模拟客户端发送请求:

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

时间: 2024-11-13 22:21:41

模拟JavaEE的Filter的相关文章

JavaEE中Filter实现用户登录拦截

实现思路是编写过滤器,如果用户登录之后session中会存一个user.如果未登录就为null,就可以通过过滤器将用户重定向到登陆页面,让用户进行登陆,当然过滤器得判断用户访问的如果是登陆请求需要放行,如果不是就需要进行拦截并进行验证.登陆成功再session存存入user,这样过滤器每次都会通过. 1.首先编写验证登陆的过滤器 package danger.filter; import java.io.IOException; import javax.servlet.Filter; impo

Spring源码阅读系列总结

最近一段时间,粗略的查看了一下Spring源码,对Spring的两大核心和Spring的组件有了更深入的了解.同时在学习Spring源码时,得了解一些设计模式,不然阅读源码还是有一定难度的,所以一些重要的设计模式简单的做了阐述.同时还会简单的加入一些GOF中提到的设计原则.Spring的源码阅读系列,也暂告一段落.下面是就带你走进Spring世界: Spring系列的引子 1)Spring WebApplicationContext初始化与消亡 这一节帮我们了解Spring是如何初始化WebAp

java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast

严重: Exception starting filter encodingFilterjava.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast to javax.servlet.Filterat org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConf

Spring boot下添加filter

出自:http://www.jb51.net/article/113389.htm 前言 传统的javaEE增加Filter是在web.xml中配置,如以下代码: <filter> <filter-name>TestFilter</filter-name> <filter-class>com.cppba.filter.TestFilter</filter-class> </filter> <filter-mapping>

设计模式-责任链设计

看了一下设计模式中的责任链设计模式,主要实现类似拦截器的功能,记下来方便自己以后复习. 1.应用场景 假设要处理爬虫趴下来的内容,你就需要发这些内容进行去噪,例如:取格式化html标签,去页面脚本,去敏感信息等等,如果将这些过滤内容都写在一个方法中,那么势必造成代码耦合性强,如果以后不断的添加内容,将造成很大的维护成本. 所以,我们需要把变化的内容抽取出来定义为接口,需要使用时我们只需实现其对应的操作. 2.实例应用 1. 内容去噪过滤 先定义过滤接口 package org.andy.filt

Java实现责任链模式

责任链模式: 将接受者对象连成一条链,并在该链上传递请求,直到一个几首这对象处理它.通过让更多对象有机会处理请求,避免了请求发送者和接受者之间的耦合. 责任链模式的优缺点: 优点:高内聚,低耦合.业务变更,新增一级处理时,只需要新增一个类即可.符合我们开闭原则(扩展开发,变更关闭). 缺点:时间,内存的效果相对较大.java的AWT对责任链模式的抛弃,去拥抱了观察者模式. 应用: Java异常处理机制 JavaScript事件模型 JavaEE的Filter拦截器 SpringSecurity 

python代码练习(每天一小时)

1 # Single line comments start with a hash. 2 # 单行注释由一个井号开头. 3 """ Multiline strings can be written 4 using three "'s, and are often used 5 as comments 6 三个双引号(或单引号)之间可以写多行字符串, 7 通常用来写注释. 8 """ 9 10 #####################

责任链(ChainOfResponsibility)模式

在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出请求的客户端并不知道链上的哪一个对象,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任. 1.  从击鼓传花谈起 击鼓传花是一种热闹而紧张的游戏.在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传花的地方是分开的,以示公正.开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在某人手中,则该人就得饮酒. 比如说,贾母.贾赦.贾政.贾宝玉和贾环是五个参加

JavaEE学习之Spring Security3.x——模拟数据库实现用户,权限,资源的管理

一.引言 因项目需要最近研究了下Spring Security3.x,并模拟数据库实现用户,权限,资源的管理. 二.准备 1.了解一些Spring MVC相关知识: 2.了解一些AOP相关知识: 3.了解Spring: 4.了解Maven,并安装. 三.实现步骤 本示例中使用的版本是Spring Security3.2.2.通过数据库实现Spring Security认证授权大致需要以下几个步骤: 1.新建maven web project(因为本示例使用的是maven来构建的),项目结构如下,