Tomcat源码阅读之过滤器

过滤器是web开发中常用的组件,可以通过web.xml中的filterfilter-mapping标签来配置过滤器的相关信息。过滤器的功能有点类似Servlet,但是使用起来更加灵活。在Tomcat中,跟过滤器相关的接口主要有三个:Filter,FilterChain和FilterConfig。
其中Filter接口是web开发中比较常用的一个接口,只要通过实现这个接口,就可以实现自定义的过滤器。Filter接口中定义了三个方法:

public interface Filter {


    public void init(FilterConfig filterConfig) throws ServletException;

    public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;

    public void destroy();


}

init方法用于初始化自定义过滤器,类似Servlet的init方法,FilterConfig 与ServletConfig也类似,除了能取到容器的环境类ServletContext对象之外,还能获取在filter 标签下配置的init-param 参数值。
每个请求进来都会调用doFilter方法,并在Servlet的service方法之前被调用。FilterChain 代表当前的整个请求链,所以通过FilterChain 的doFilter方法可以将请求继续传递下去,直到定义的过滤器都被执行到。如果想在某一步拦截这个请求,那么就不调用doFilter方法,也就是不让请求传递给下一个过滤器。
destroy方法在过滤器对象销毁时会被调用。
FilterChain接口表示过滤器链,接口中只定义了doFilter一个方法。

public interface FilterChain {


    public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;

}

doFilter 方法的作用就是在过滤器之间传递请求。
FilterConfig接口中定义了获取Filter相关信息的方法,实现类是ApplicationFilterConfig。

public interface FilterConfig {

    public String getFilterName();

    public ServletContext getServletContext();

    public String getInitParameter(String name);

    public Enumeration getInitParameterNames();

}

为了让自定义的每个过滤器都能够执行,就需要调用ApplicationFilterChain的doFilter 方法,因为ApplicationFilterChain的类修饰符是final,因此这个类的所有方法及属性都是不可继承的,doFilter 方法不能被重写,只能使用Tomcat中提供的。doFilter 方法中调用internalDoFilter方法传递请求。

private void internalDoFilter(ServletRequest request, 
                                  ServletResponse response)
        throws IOException, ServletException {

        // Call the next filter if there is one
        if (pos < n) {
            ApplicationFilterConfig filterConfig = filters[pos++];
            Filter filter = null;
            try {
                filter = filterConfig.getFilter();
                support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
                                          filter, request, response);

                if( Globals.IS_SECURITY_ENABLED ) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal = 
                        ((HttpServletRequest) req).getUserPrincipal();

                    Object[] args = new Object[]{req, res, this};
                    SecurityUtil.doAsPrivilege
                        ("doFilter", filter, classType, args, principal);

                    args = null;
                } else {  
                    filter.doFilter(request, response, this);
                }
              }

           }
           略
           servlet.service(request, response);


    }

ApplicationFilterChain类中定义了一个ApplicationFilterConfig类型的数组,用于存放Servlet对象的所有过滤器。数组中的过滤器是在创建ApplicationFilterChain对象时添加的,根据所有定义的Filter的url-pattern 的值与当前请求的URL进行匹配,如果匹配成功则保存到filters数组中。internalDoFilter方法中的pos表示当前计数器,也就是当前执行到第几个过滤器了,n表示过滤器的总数。如果pos小于n,表示过滤器还没执行完,那么接着获取下一个过滤器,当前计数器的值会加1,直到值等于n。
当过滤器链中的所有过滤器都执行完了之后,就会执行Servlet的service方法。通过使用过滤器,可以使我们能更加灵活地控制请求流转。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值