欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot实现过滤器

程序员文章站 2022-05-23 10:12:40
...

过滤器的英文名称为 Filter, 是 Servlet 技术中最实用的技术。如同它的名字一样,过滤器是处于客户端和服务器资源文件之间的一道过滤网,帮助我们过滤掉一些不符合要求的请求,通常用作 Session 校验,判断用户权限,如果不符合设定条件,则会被拦截到特殊的地址或者基于特殊的响应。

一 过滤器简介

过滤器是对数据进行过滤,预处理过程,当我们访问网站时,有时候会发布一些敏感信息,发完以后有的会用*替代,还有就是登陆权限控制等,一个资源,没有经过授权,肯定是不能让用户随便访问的,这个时候,也可以用到过滤器。

过滤器的功能还有很多,例如实现URL级别的权限控制、压缩响应信息、编码格式等等。拦截掉我们不需要的接口请求,修改请求(request)和响应(response)内容,完成CORS跨域请求等等。

  • 过滤器依赖Servlet容器,属于Servlet规范的一部分。
  • 在实现上基于Servlet容器的函数回调,可以对几乎所有请求进行过滤。
  • Filter的生命周期由Servlet容器管理。

过滤器执行流程

springboot实现过滤器

  1. SpringBoot启动默认加载的Filter
    ​ characterEncodingFilter
    ​ hiddenHttpMethodFilter
    ​ httpPutFormContentFilter
    ​ requestContextFilter

  2. Filter优先级

@Order(1):表示过滤器的顺序,假设我们有多个过滤器,你如何确定过滤器的执行顺序?这个注解就是规定过滤器的顺序。

​ Ordered.HIGHEST_PRECEDENCE
​ Ordered.LOWEST_PRECEDENCE

​ 低位值意味着更高的优先级 Higher values are interpreted as lower priority
​ 自定义Filter,避免和默认的Filter优先级一样,不然会冲突

​ 注册Filter的bean FilterRegistrationBean
​ 同模块里面有相关默认Filter
​ web->servlet->filter

二 过滤器配置使用方式 自定义Filter

过滤器里面的三个方法

init : filter对象只会创建一次,init方法也只会执行一次。

doFilter : 主要的业务代码编写方法,可以多次重复调用

destroy : 在销毁Filter时自动调用(程序关闭或者主动销毁Filter)。

过滤器配置使用方式一:通过注解方式注入过滤器

  1. 引入spring-boot-starter-web

在pom.xml 中引入spring-boot-starter-web包。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

  1. 建立过滤器程序
//@Component
@Order(1) // 指定过滤器的执行顺序@Order(1)
@WebFilter(filterName = "loginFilter", urlPatterns = "/*" , initParams = {
        @WebInitParam(name = "URL", value = "http://localhost:8081")})
public class LoginFilter implements Filter {

    /**
     * 容器加载的时候调用
     *
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        System.out.println("初始化 init loginFilter");
    }

    /**
     * 请求被拦截的时候进行调用
     *
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println(" doFilter loginFilter");

        HttpServletRequest request = (HttpServletRequest) servletRequest;

        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String username = request.getParameter("username");

        if ("admin".equals(username)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            System.out.println("非admin,返回主页");
            response.sendRedirect("/index.html");
            return;

        }
    }

    /**
     * 容器被销毁的时候调用
     */
    @Override
    public void destroy() {

        System.out.println("销毁 destroy loginFilter");
    }
}

1) 注解:

  1. @Component就是把这个类注入到IOC容器中 可以不用在SpringBootApplication上使用@ServletComponentScan

  2. @WebFilter:标记一个类为filter,被spring进行扫描,表示这个class是过滤器。@WebFilter是spring3.0的一个注解。

2)参数:

  • filterName 为过滤器名字,
  • urlPatterns 为过滤器的范围,拦截规则,支持正则
  • initParams 为过滤器初始化参数。

3)例如:

@WebFilter(urlPatterns = “/api”,filterName = “myFilter”)说明这是一个web过滤器,它拦截的url为/api,过滤器名字为myFilter

4)官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners

  1. 建立Contoller类
    @RequestMapping("/api/testFilter")
    public Object testFilter() {

        Map map = new HashMap();
        map.put("test","我的过滤器");

        return map;

    }
  1. 启动类中增加注解,自动注册Filter

在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。

@SpringBootApplication
@MapperScan({"com.beiluo.demo.dao","com.beiluo.demo.mapper"})
@ServletComponentScan // 扫描 Servlet 相关的组件
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

过滤器配置使用方式二 : 通过代码方式注入过滤器

  1. 通过过滤器来实现记录请求执行时间的功能
public class TestFilter implements Filter {
    
    private String url;
    /**
     * filter对象只会创建一次,init方法也只会执行一次。
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.url = filterConfig.getInitParameter("URL");
        System.out.println("Filter init...");
    }

    /**
     * 主要的业务代码编写方法
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        long start = System.currentTimeMillis();
        System.out.println(start + " Filter doFilter before...");
        filterChain.doFilter(servletRequest, servletResponse);
        long end = System.currentTimeMillis();
        System.out.println(end + "Filter doFilter after...");
    }

    /**
     * 在销毁Filter时自动调用。
     */
    @Override
    public void destroy() {
        System.out.println("Filter destroy...");
    }
}

  1. 注册第三方过滤器 功能与spring mvc中通过配置web.xml相同
@Configuration
public class FilterConfig {
    
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new TestFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setName("testFilter");
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;

    }
}

三 过滤器和拦截器的区别

AOP不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。 但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现

Filter Interceptor
实现方式 过滤器是基于函数回调 基于Java的反射机制的,通常通过动态代理的方式来执行
规范 依赖于Servlet容器,属于Servlet规范的一部分,生命周期由Servlet容器管理 Spring规范 ,独立存在的,通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
作用范围 对几乎所有的请求起作用 只对action请求起作用
相关标签: springboot