过滤器

过滤器(Filter)介绍

Filter可以认为是Servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。Filter也可以对用户请求生成响应,这一点与Servlet相同,但实际上很少会使用Filter向用户请求生成响应。使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行预处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter有如下几个用处。

  • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。

  • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。

  • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。

  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

Filter有如下几个种类。

  • 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。

  • 日志Filter:详细记录某些特殊的用户请求。

  • 负责解码的Filter:包括对非标准编码的请求解码。

  • 能改变XML内容的XSLT Filter等。

  • Filter可以负责拦截多个请求或响应;一个请求或响应也可以被多个Filter拦截。

创建一个Filter只需两个步骤

  • 创建Filter处理类

  • web.xml文件中配置Filter

创建Filter必须实现javax.servlet.Filter接口,在该接口中定义了如下三个方法。

  • void init(FilterConfig config):用于完成Filter的初始化。

  • void destory():用于Filter销毁前,完成某些资源的回收。

  • void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。该方法可以实现对用户请求进行预处理(ServletRequest request),也可实现对服务器响应进行后处理(ServletResponse response)—它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。

 

过滤器的配置

  现在我们通过过滤器来实现记录请求执行时间的功能,其实现如下:

public class LogCostFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        long start = System.currentTimeMillis();
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("Execute cost="+(System.currentTimeMillis()-start));
    }
 
    @Override
    public void destroy() {
 
    }
}

 

 

  这段代码的逻辑比较简单,就是在方法执行前先记录时间戳,然后通过过滤器链完成请求的执行,在返回结果之间计算执行的时间。这里需要主要,这个类必须继承Filter类,这个是Servlet的规范,这个跟以前的Web项目没区别。但是,有了过滤器类以后,以前的web项目可以在web.xml中进行配置,但是spring boot项目并没有web.xml这个文件,那怎么配置?在Spring boot中,我们需要FilterRegistrationBean来完成配置。其实现过程如下:

@Configuration
public class FilterConfig {
 
    @Bean
    public FilterRegistrationBean registFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new LogCostFilter());
        registration.addUrlPatterns("/*");
        registration.setName("LogCostFilter");
        registration.setOrder(1);
        return registration;
    }
 
}

 

  这样配置就完成了,需要配置的选项主要包括实例化Filter类,然后指定url的匹配模式,设置过滤器名称和执行顺序,这个过程和在web.xml中配置其实没什么区别,只是形式不同而已。现在我们可以启动服务器访问任意URL:

  大家可以看到上面的配置已经生效了。除了通过 FilterRegistrationBean 来配置以外,还有一种

@WebFilter(urlPatterns = {"/getbotlist","/EXAMPLE12"}, filterName = "logFilter2")//配置请求匹配规则匹配,使能到具体的API
public class Filter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override//预处理函数
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException, IOException {
        long start = System.currentTimeMillis();
        System.out.println("-----------------------过滤器开始------------------------");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("-----------------------过滤器结束------------------------");
    }

    @Override
    public void destroy() {
    }
}

 

  这里直接用@WebFilter就可以进行配置,同样,可以设置url匹配模式,过滤器名称等。这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在配置类中加另外一个注解:@ServletComponetScan,指定扫描的包。

@SpringBootApplication
@MapperScan("com.pandy.blog.dao")
@ServletComponentScan("com.pandy.blog.filters")
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}

 

 

  现在,我们再来访问一下任意URL:

  可以看到,我们配置的两个过滤器都生效了。细心的读者会发现,第二个Filter我们并没有指定执行的顺序,但是却在第一个Filter之前执行。这里需要解释一下,@WebFilter这个注解并没有指定执行顺序的属性,其执行顺序依赖于Filter的名称,是根据Filter类名(注意不是配置的filter的名字)的字母顺序倒序排列,并且@WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器。有兴趣的朋友可以自己实验一下。

posted @ 2021-09-24 16:27  忙碌了一整天的L师傅  阅读(82)  评论(0编辑  收藏  举报