前言

在springboot配置过滤实现方案有两种, 一种是基于serlvet 的注解 @WebFilter 进行配置,一种是使用Springboot提供的 FilterRegistrationBean注册自定义过滤器。

该篇使用的方案是后者,因为按照我以前使用的记忆里,这种方式可以避免一些偶然出现的小问题,如:过滤器没生效;生效后url匹配不生效等。

正文

在开始敲代码前,先从上帝视角看看我们这次实践案例,做了些什么:

BodyReaderHttpServletRequestWrapper  

名字显然是随便取的, 但是从字面意义来看,就是关于body内容的读取。

为什么要写一个这样的东西?

简单讲讲:

@RequestBody 这个注解大家并不陌生,post请求里,规定参数传递使用application/json 流数据传递(序列化后的json字符串)。

正因为这个请求体重的流数据,流数据只能读取一次。 
而我们这次实践案例中,过滤器读取一次,接口还需要读取一次, 如果不整点手法,那么这个流数据明显不够用。

因此, 我们采取了 继承HttpServletRequestWrapper ,创建 BodyReaderHttpServletRequestWrapper 

将流数据进行复制存储起来。当无论第一次第二次需要使用到流数据时 ,都去当前存储起来的body数据里去读取。

上代码,新建 BodyReaderHttpServletRequestWrapper.java  :

import org.apache.commons.lang3.StringUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;/*** @Author : JCccc* @CreateTime : 2020/3/27* @Description :**/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;/*** 所有参数的集合*/private Map<String, String[]> parameterMap;public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);BufferedReader reader = request.getReader();body = readBytes(reader);parameterMap = request.getParameterMap();}@Overridepublic BufferedReader getReader() throws IOException {ServletInputStream inputStream = getInputStream();if (null == inputStream) {return null;}return new BufferedReader(new InputStreamReader(inputStream));}@Overridepublic Enumeration<String> getParameterNames() {Vector<String> vector = new Vector<>(parameterMap.keySet());return vector.elements();}@Overridepublic ServletInputStream getInputStream() throws IOException {if (body == null) {return null;}final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener listener) {}@Overridepublic int read() throws IOException {return bais.read();}};}/*** 通过BufferedReader和字符编码集转换成byte数组** @param br* @return* @throws IOException*/private byte[] readBytes(BufferedReader br) throws IOException {String str;StringBuilder retStr = new StringBuilder();while ((str = br.readLine()) != null) {retStr.append(str);}if (StringUtils.isNotBlank(retStr.toString())) {return retStr.toString().getBytes(StandardCharsets.UTF_8);}return null;}
}

接着,自定义 第一个过滤器 , CheckUserFilter.java:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;/*** @Author : JCccc* @CreateTime : 2020/3/27* @Description :**/public class CheckUserFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("过滤器一初始化");}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {System.out.println("进入到第一个过滤器,执行相关逻辑处理");HttpServletRequest request = (HttpServletRequest) req;String path = request.getRequestURI();String method = request.getMethod();System.out.println(method);//排除一些url的拦截if (path.equals("/test/testContext")) {filterChain.doFilter(request, res);}if ("POST".equals(method)) {BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(request);// 从Request的包装类中读取数据BufferedReader reader = requestWrapper.getReader();StringBuilder sb = new StringBuilder();String line;while ((line = reader.readLine()) != null) {sb.append(line);}reader.close();System.out.println(sb.toString());filterChain.doFilter(requestWrapper, res);}}@Overridepublic void destroy() {System.out.println("过滤器一销毁了");}}

然后再自定义一个过滤器,CheckUserFilterNext.java :

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;/*** @Author : JCccc* @CreateTime : 2020/3/27* @Description :**/public class CheckUserFilterNext implements Filter {@Overridepublic void init(FilterConfig filterConfig) {System.out.println("过滤器二初始化");}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {System.out.println("进入到第二个过滤器,执行相关逻辑处理");HttpServletRequest request = (HttpServletRequest) req;String path = request.getRequestURI();String method = request.getMethod();System.out.println(method);//排除一些url的拦截if (path.equals("/test/testContext")) {filterChain.doFilter(request, res);}if ("POST".equals(method)) {BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(request);// 从Request的包装类中读取数据BufferedReader reader = requestWrapper.getReader();StringBuilder sb = new StringBuilder();String line;while ((line = reader.readLine()) != null) {sb.append(line);}reader.close();System.out.println(sb.toString());filterChain.doFilter(requestWrapper, res);}}@Overridepublic void destroy() {System.out.println("过滤器二销毁了");}}

然后是将这两个过滤器都丢进spring容器里面去,顺便配置一些 拦截的url和执行顺序(毕竟是两个过滤器,肯定有执行顺序):

那么我们来到 application加上相关代码:

  /*** 第一个过滤器配置**/@BeanCheckUserFilter getCheckUserFilter(){return new CheckUserFilter();}@Bean("checkUserFilter")public FilterRegistrationBean<CheckUserFilter> checkUserFilter(CheckUserFilter checkUserFilter) {FilterRegistrationBean<CheckUserFilter> registrationBean = new FilterRegistrationBean();registrationBean.setFilter(checkUserFilter);registrationBean.addUrlPatterns("/test/*"); //url拦截registrationBean.setOrder(1);registrationBean.setAsyncSupported(true);return registrationBean;}/*** 第二个过滤器配置**/@BeanCheckUserFilterNext getCheckUserFilterNext(){return new CheckUserFilterNext();}@Bean("checkUserFilterNext")public FilterRegistrationBean<CheckUserFilterNext> checkUserFilterNext(CheckUserFilterNext checkUserFilterNext) {FilterRegistrationBean<CheckUserFilterNext> registrationBean = new FilterRegistrationBean();registrationBean.setFilter(checkUserFilterNext);registrationBean.addUrlPatterns("/test/*"); //url拦截registrationBean.setOrder(2);registrationBean.setAsyncSupported(true);return registrationBean;}

若想要配置第三个过滤器,那么也是一样,自定义一个过滤器继承Filter,然后再一样注册到application里面去。

接下来我们开始写点接口去测试一下,

新建一个 MyTestController.java :

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;/*** @Author : JCccc* @CreateTime : 2020/3/27* @Description :**/@Controller
@RequestMapping("/test")
public class MyTestController {@ResponseBody@RequestMapping(value="testFilter",method={RequestMethod.POST})public void testFilter(@RequestBody  String jsonStr) {System.out.println("aaaaa");System.out.println(jsonStr);}}

项目跑起来,可以看到:

咱们刚刚配置的过滤器都已经初始化准备好了,

接下来我们调用一下测试接口:

直接看结果:

ok,过滤器的使用就暂且到这吧。

Springboot Filter 多过滤器的使用相关推荐

  1. Springboot应用中过滤器chain.doFilter后设置header无效

    Springboot应用中过滤器chain.doFilter后设置header无效 本文是在使用过滤器添加动态header过程中遇到设置header无效,经过研究源码而产生. 因为特殊需求,自定义的h ...

  2. springboot二:过滤器、拦截器、静态资源访问

    一:springboot中的过滤器 过滤器是什么? 它是基于Servlet 技术实现的, 简单的来说,过滤器就是起到过滤的作用,在web项目开发中帮我们过滤一些指定的 url做一些特殊的 处理. 过滤 ...

  3. springBoot 2.x过滤器--监听器--拦截器

    springboot 2.x过滤器 1.什么是 springboot 2.x过滤器 类似于检票员,检验游客的门票 2.springboot里的过滤器 ApplicationContextHeaderF ...

  4. 11、Filter(过滤器 重点)

    文章目录 11.==Filter==(过滤器 重点) Filter开发步骤: 1.导包 2.编写过滤器 1.导包不要错 2.实现Filter接口 3.在web.xml中配置 servlet 和 fil ...

  5. Filter:过滤器

    Filter:过滤器 1. 概念:     * 生活中的过滤器:净水器,空气净化器,土匪.     * web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能.      ...

  6. Filter(过滤器) 和 interceptor(拦截器)的区别

    Filter(过滤器) 和 interceptor(拦截器)的区别 1.拦截器是基于java反射机制的,而过滤器是基于函数回调的. 2.过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容 ...

  7. springboot编写自定义过滤器

    springboot编写自定义过滤器 首先引入依赖,其次编写过滤器 @Configuration public class FilterRegisterConfig {@Beanpublic Filt ...

  8. 布隆过滤器速度_高并发系统一定要考虑的 Bloom Filter 布隆过滤器

    开篇思考 你能想到哪些方式判断一个元素是否存在集合中? 布隆过滤器并不存储数据本身,那么是怎么做到过滤的? 布隆过滤器实现?参数配置? 一般我们用来判断一个元素是否存在,会想到用 List,Map,S ...

  9. java day43【Filter:过滤器 、Listener:监听器】

    第一章  Filter:过滤器 1. 概念: * 生活中的过滤器:净水器,空气净化器,土匪. * web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能. * 过滤器的作 ...

最新文章

  1. founder of girton college
  2. java类的修改三个方面_Java 编程的动态性,第 6 部分: 利用 Javassist 进行面向方面的更改--转载...
  3. 【PIFO】以线速编程数据包调度
  4. 算法导论 第十三章 红黑树(python)-1插入
  5. oracle中LAG()和LEAD()等分析统计函数的使用方法(统计月增长率)
  6. Java 和 Python 并列第二、Julia 下滑,揭晓 RedMonk 最新编程语言榜单!
  7. 【算法与数据结构】二叉堆和优先队列 Priority Queue
  8. day25 在继承的背景下属性查找的顺序、组合、多态与接口、鸭子类型
  9. intel网卡驱动下载linux,intel网卡驱动下载
  10. 实现一个简单的类似spring的pointcut正则表达式
  11. Multisim的学习记录(一)
  12. 微信小程序开发中医药配方小程序药方后台管理系统|前后分离VUE.js
  13. 结合P2P软件使用Ansible分发大文件
  14. 计算机视觉经典书籍推荐
  15. 单元测试系列一-为什么要写单元测试,何时写,写多细
  16. 第五课:BCD计数器设计与验证
  17. throw er; // Unhandled ‘error’ event
  18. 2020到2021计算机试题,2020广东计算机一级考试试题和答案【2021年整理】-20210715002405.docx-原创力文档...
  19. 无代码开发的未来是什么样的?
  20. 金庸小说人物知识图谱构建——以《雪山飞狐》为例

热门文章

  1. 简单工厂 工厂方法 抽象工厂 如何理解
  2. mysql replicate函数_使用mysqlreplicate命令快速搭建 Mysql 主从复制
  3. IC先生网:磁性开关的工作原理及其应用详解
  4. 拉卡拉智能POS一站式服务实现商户精准营销
  5. android java 经纬度(国标WGS84/gps84/硬件/谷歌地球卫星,Gcj02/腾讯地图/高德地图,Bd09/百度地图)之间互换
  6. 细胞膜修饰多肽/多糖/红细胞膜/仿生细胞膜载蛋白/聚乙二醇修饰细胞膜的制备
  7. 四足机器人A1目标跟踪
  8. 压力容器用安全阀的问题
  9. 高通MSM8255串口驱动移植
  10. 服务器被攻击统计及被暴力破解过程(二)