• Java Web之路一:过滤器(Filter)


    一、过滤器(Filter)简介

    过滤器是对web资源进行拦截,做一些处理后再交给下一个过滤器或Servlet处理,主要可以拦截request和response
    过滤器是以一种组件的形式与web程序绑定,采用链式进行工作。
     
    过滤器的好处:
    可以拦截请求和响应,以便查看或者获取客户端与服务器之间的交互数据,实现过滤的功能。另外过滤器可以动态的添加或删除而不需要修改web程序的逻辑。
     
    过滤器的初始化和销毁都是通过Web容器来实现的,Web容器初始化Filter对象之后会执行init方法,销毁Filter对象之前会执行destory方法。
     
    二、过滤器的使用
    2.1、Filter基本使用
    Servlet中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方法是在Filter初始化时会被调用、destroy方法是Filter被销毁时调用,而doFilter方法是过滤器的工作时执行的方法,doFilter至少需要保护两块逻辑,一个是当前过滤器需要处理的过滤逻辑,一个是跳转到下一个过滤器中。

    如下自定义的过滤器:

    public class LogFilter implements Filter {
    
        /**初始化过滤器时调用*/
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("初始化过滤器");
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("执行过滤器逻辑");
            //跳转到过滤器链路到下一个链路
            chain.doFilter(request, response);
        }
    
        public void destroy() {
            System.out.println("销毁过滤器");
        }
    }
    本文采用SpringBoot方式,Filter的配置类如下:
        @Bean
        public FilterRegistrationBean initLogFilter(){
            FilterRegistrationBean bean = new FilterRegistrationBean();
            LogFilter filter = new LogFilter();
            bean.setFilter(filter);
            //需要过滤的URL路径
            List<String> urls = new ArrayList<String>();
            urls.add("/manage/*");//只过滤 /manage/*的路径
            bean.setUrlPatterns(urls);
            return bean;
        }
    
        @Bean
        public FilterRegistrationBean initTimeFilter(){
            FilterRegistrationBean bean = new FilterRegistrationBean();
            TimeFilter filter = new TimeFilter();
            bean.setFilter(filter);
            //需要过滤的URL路径
            List<String> urls = new ArrayList<String>();
            urls.add("/*");//过滤所有路径
            bean.setUrlPatterns(urls);
            return bean;
        } 
    自定义过滤器需要实现Filter接口,重写Filter接口的三个方法,然后配置Filter即可,项目启动时会执行init方法,项目关闭时会执行destory方法,客户端每次发起请求都会执行一次doFilter方法,doFilter必须执行chain.doFilter方法将请求转发到下一个过滤器,
    否则最终的请求就无法达到业务层逻辑,多个Filter的执行顺序和配置的执行顺序一样,先配置的就先执行,也可以手动设置不同的Filter的执行顺序,理论上各个Filter直接是相互独立的。 
     
    2.2、Filter的进阶使用
    实战情况下不同的Filter需要过滤的路径可能不一样,可以通过设置不同的Filter过滤不同的路径,如上例中LogFilter只拦截 /manage/* 路径的请求,而TimeFilter会过滤所有的请求;
    另外除了过滤的路径,不同的Filter也可以手动设置不同的执行顺序,可以通过@Order注解来设置,而且Spring还提供了@WebFilter注解可以直接定义Filter,而不需要单独再用@Bean注解来定义,用法如下:
    @WebFilter(urlPatterns = "/*")
    @Order(1)
    public class LogFilter implements Filter {
       
        //...............
    
    }
    @WebFilter(urlPatterns = "/manage/*")
    @Order(2)
    public class TimeFilter implements Filter {
    
       //......
     
    }
    定义了两个Filter,其中LogFilter执行顺序为第一个,并且过滤所有请求;TimeFilter执行顺序为第二个,过滤 /manage/* 路径的请求
    而@WebFilter注解是Servlet的注解,所以需要在启动类中加上Servlet注解的扫描注解 @ServletComponentScan,如下示:
    @SpringBootApplication
    @ServletComponentScan
    public class Bootstrap
    {
        public static void main( String[] args )
        {
            SpringApplication.run(Bootstrap.class);
        }
    }

    三、Filter的实现原理

     Filter和Servlet一样都是通过Web容器实现的,Web容器分别存了Servlet和Filter的两个Map,key是对应配置的路径url-parttern,value分别就是Servlet和Filter的实例

    在web容器启动时就会初始化所有的Filter,并且将所有的Filter存入Map中,每次当有客户端请求来时,web容器都会先获取请求的url,然后遍历所有的Filter,如果Filter满足URL的条件,就将Filter加入到过滤器数组中。

    然后将过滤器数组中的所有过滤器组成过滤器链,挨个执行过滤器的逻辑。

     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    new和base的语法
    js常用代码
    无法识别connectionStrings
    DataTable
    字符串的操作时间格式化
    Facade外观模式(转载cnblogs)
    ArrayList下的循环绑定和循环删除
    自定义属性与事件委托相结合的实例
    泛型 开放类型和构造类型(基础学习)
    C#策略模式 摘自jspcool
  • 原文地址:https://www.cnblogs.com/jackion5/p/11990858.html
Copyright © 2020-2023  润新知