springboot实现过滤器

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

一 过滤器简介

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

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

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

过滤器执行流程

img

  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——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现

FilterInterceptor
实现方式过滤器是基于函数回调基于Java的反射机制的,通常通过动态代理的方式来执行
规范依赖于Servlet容器,属于Servlet规范的一部分,生命周期由Servlet容器管理Spring规范 ,独立存在的,通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
作用范围对几乎所有的请求起作用只对action请求起作用
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值