所有分类
  • 所有分类
  • 未分类

SpringBoot-过滤器(Filter)的用法

简介 

说明

本文用示例介绍SpringBoot(SpringMVC)中的过滤器的用法。

Filter可以有多个。一个filter执行完之后会执行另外一个。

过滤器的使用场景

  1. 控制用户访问权限
  2. 记录日志
  3. 图像转换
  4. 数据压缩
  5. 加密
  6. Token校验
  7. 媒体类型过滤

实例1:单过滤器

两种方式注册filter(两种方式的本质都是一样的,都是去FilterRegistrationBean注册自定义Filter ):
1、使用Spring Boot提供的FilterRegistrationBean注册Filter
2、使用原生servlet注解(@WebFilter)定义Filter。缺点:无法指定过滤器顺序。

注册方式1:FilterRegistrationBean

定义Filter 

package com.example.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class MyFilter implements Filter {
    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter.init");
        System.out.println("  过滤器名:" + filterConfig.getFilterName());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // do something 处理request 或response
        System.out.println("MyFilter.doFilter");

        if (servletRequest instanceof HttpServletRequest) {
            System.out.println("  URL:" + ((HttpServletRequest)servletRequest).getRequestURL());
        }

        // 调用filter链中的下一个filter
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter.destroy");
    }
}

注册自定义Filter 

package com.example.filter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean registrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
}

注册方式2:@WebFilter

此法的缺点:无法指定过滤器顺序。

package com.example.filter;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Component
// 定义filterName 和过滤的url
@WebFilter(filterName = "myFilter" ,urlPatterns = "/*")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter.init");
        System.out.println("  过滤器名:" + filterConfig.getFilterName());
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // do something 处理request 或response
        System.out.println("MyFilter.doFilter");

        if (servletRequest instanceof HttpServletRequest) {
            System.out.println("  URL:" + ((HttpServletRequest)servletRequest).getRequestURL());
        }

        // 调用filter链中的下一个filter
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
        System.out.println("MyFilter.destroy");
    }
}

Controller

package com.example.controller;

import com.example.entity.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping("/test1")
    public User test1(User user) {
        System.out.println("HelloController.test1");
        return user;
    }
}

实体类 

package com.example.entity;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

测试

启动SpringBoot

2020-09-04 23:25:27.216  INFO 16948 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-09-04 23:25:27.216  INFO 16948 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 781 ms
MyFilter.init
  过滤器名:myFilter
2020-09-04 23:25:27.361  INFO 16948 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-09-04 23:25:27.493  INFO 16948 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-09-04 23:25:27.501  INFO 16948 --- [           main] com.example.DemoApplication              : Started DemoApplication in 1.44 seconds (JVM running for 2.276)
2020-09-04 23:25:40.252  INFO 16948 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-09-04 23:25:40.253  INFO 16948 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-09-04 23:25:40.257  INFO 16948 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms

postman访问:http://localhost:8080/hello/test1?name=Tony

后端结果:

MyFilter.doFilter
  URL:http://localhost:8080/hello/test1
HelloController.test1

postman结果

{
    "id": null,
    "name": "Tony",
    "age": null
}

 关闭SpringBoot

Disconnected from the target VM, address: '127.0.0.1:57939', transport: 'socket'
MyFilter.destroy
2020-09-04 23:26:00.810  INFO 16948 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

实例2:多过滤器

代码

过滤器1

package com.example.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class MyFilter1 implements Filter {
    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter1.init");
        System.out.println("  过滤器名:" + filterConfig.getFilterName());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
            FilterChain filterChain) throws IOException, ServletException {
        // do something 处理request 或response
        System.out.println("MyFilter1.doFilter");

        if (servletRequest instanceof HttpServletRequest) {
            System.out.println("  URL:" + ((HttpServletRequest)servletRequest).getRequestURL());
        }

        // 调用filter链中的下一个filter
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter1.destroy");
    }
}

过滤器2

package com.example.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class MyFilter2 implements Filter {

    @Override
    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter2.init");
        System.out.println("  过滤器名:" + filterConfig.getFilterName());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
                         FilterChain filterChain) throws IOException, ServletException {
        // do something 处理request 或response
        System.out.println("MyFilter2.doFilter");

        if (servletRequest instanceof HttpServletRequest) {
            System.out.println("  URL:" + ((HttpServletRequest)servletRequest).getRequestURL());
        }

        // 调用filter链中的下一个filter
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter2.destroy");
    }
}

配置类

package com.example.filter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean registrationBean1() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter1());
        filterRegistrationBean.addUrlPatterns("/*");
        // filterRegistrationBean.setName("xxx");  //可设置过滤器名字

        //过滤器执行顺序。(决定doFilter顺序,不决定init和destroy顺序)
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean registrationBean2() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter2());
        filterRegistrationBean.addUrlPatterns("/*");
        // filterRegistrationBean.setName("xxx");  //可设置过滤器名字

        //过滤器执行顺序(决定doFilter顺序,不决定init和destroy顺序)
        filterRegistrationBean.setOrder(2);
        return filterRegistrationBean;
    }
}

Controller

package com.example.controller;

import com.example.entity.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping("/test1")
    public User test1(User user) {
        System.out.println("HelloController.test1");
        return user;
    }
}

实体类 

package com.example.entity;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

测试

测试1:启动、访问接口、关闭

启动SpringBoot

MyFilter2.init
  过滤器名:myFilter2
MyFilter1.init
  过滤器名:myFilter1

postman访问:http://localhost:8080/hello/test1?name=Tony

后端结果

MyFilter1.doFilter
  URL:http://localhost:8080/hello/test1
MyFilter2.doFilter
  URL:http://localhost:8080/hello/test1
HelloController.test1

postman结果

{
    "id": null,
    "name": "Tony",
    "age": null
}

关闭SpringBoot 

Disconnected from the target VM, address: '127.0.0.1:57939', transport: 'socket'
MyFilter2.destroy
MyFilter1.destroy
2020-09-04 23:26:00.810  INFO 16948 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

测试2:配置类setOrder的值调换顺序

配置类:

package com.example.filter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean registrationBean1() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter1());
        filterRegistrationBean.addUrlPatterns("/*");
        // filterRegistrationBean.setName("xxx");  //可设置过滤器名字

        //过滤器执行顺序。(决定doFilter顺序,不决定init和destroy顺序)
        filterRegistrationBean.setOrder(2);
        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean registrationBean2() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter2());
        filterRegistrationBean.addUrlPatterns("/*");
        // filterRegistrationBean.setName("xxx");  //可设置过滤器名字

        //过滤器执行顺序(决定doFilter顺序,不决定init和destroy顺序)
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }
}

启动SpringBoot

MyFilter2.init
  过滤器名:myFilter2
MyFilter1.init
  过滤器名:myFilter1

postman访问:http://localhost:8080/hello/test1?name=Tony

后端结果

MyFilter2.doFilter
  URL:http://localhost:8080/hello/test1
MyFilter1.doFilter
  URL:http://localhost:8080/hello/test1
HelloController.test1

postman结果

{
    "id": null,
    "name": "Tony",
    "age": null
}

关闭SpringBoot

Disconnected from the target VM, address: '127.0.0.1:57939', transport: 'socket'
MyFilter2.destroy
MyFilter1.destroy
2020-09-04 23:26:00.810  INFO 16948 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录