Springboot Filter 多过滤器的使用
前言
在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 多过滤器的使用相关推荐
- Springboot应用中过滤器chain.doFilter后设置header无效
Springboot应用中过滤器chain.doFilter后设置header无效 本文是在使用过滤器添加动态header过程中遇到设置header无效,经过研究源码而产生. 因为特殊需求,自定义的h ...
- springboot二:过滤器、拦截器、静态资源访问
一:springboot中的过滤器 过滤器是什么? 它是基于Servlet 技术实现的, 简单的来说,过滤器就是起到过滤的作用,在web项目开发中帮我们过滤一些指定的 url做一些特殊的 处理. 过滤 ...
- springBoot 2.x过滤器--监听器--拦截器
springboot 2.x过滤器 1.什么是 springboot 2.x过滤器 类似于检票员,检验游客的门票 2.springboot里的过滤器 ApplicationContextHeaderF ...
- 11、Filter(过滤器 重点)
文章目录 11.==Filter==(过滤器 重点) Filter开发步骤: 1.导包 2.编写过滤器 1.导包不要错 2.实现Filter接口 3.在web.xml中配置 servlet 和 fil ...
- Filter:过滤器
Filter:过滤器 1. 概念: * 生活中的过滤器:净水器,空气净化器,土匪. * web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能. ...
- Filter(过滤器) 和 interceptor(拦截器)的区别
Filter(过滤器) 和 interceptor(拦截器)的区别 1.拦截器是基于java反射机制的,而过滤器是基于函数回调的. 2.过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容 ...
- springboot编写自定义过滤器
springboot编写自定义过滤器 首先引入依赖,其次编写过滤器 @Configuration public class FilterRegisterConfig {@Beanpublic Filt ...
- 布隆过滤器速度_高并发系统一定要考虑的 Bloom Filter 布隆过滤器
开篇思考 你能想到哪些方式判断一个元素是否存在集合中? 布隆过滤器并不存储数据本身,那么是怎么做到过滤的? 布隆过滤器实现?参数配置? 一般我们用来判断一个元素是否存在,会想到用 List,Map,S ...
- java day43【Filter:过滤器 、Listener:监听器】
第一章 Filter:过滤器 1. 概念: * 生活中的过滤器:净水器,空气净化器,土匪. * web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能. * 过滤器的作 ...
最新文章
- founder of girton college
- java类的修改三个方面_Java 编程的动态性,第 6 部分: 利用 Javassist 进行面向方面的更改--转载...
- 【PIFO】以线速编程数据包调度
- 算法导论 第十三章 红黑树(python)-1插入
- oracle中LAG()和LEAD()等分析统计函数的使用方法(统计月增长率)
- Java 和 Python 并列第二、Julia 下滑,揭晓 RedMonk 最新编程语言榜单!
- 【算法与数据结构】二叉堆和优先队列 Priority Queue
- day25 在继承的背景下属性查找的顺序、组合、多态与接口、鸭子类型
- intel网卡驱动下载linux,intel网卡驱动下载
- 实现一个简单的类似spring的pointcut正则表达式
- Multisim的学习记录(一)
- 微信小程序开发中医药配方小程序药方后台管理系统|前后分离VUE.js
- 结合P2P软件使用Ansible分发大文件
- 计算机视觉经典书籍推荐
- 单元测试系列一-为什么要写单元测试,何时写,写多细
- 第五课:BCD计数器设计与验证
- throw er; // Unhandled ‘error’ event
- 2020到2021计算机试题,2020广东计算机一级考试试题和答案【2021年整理】-20210715002405.docx-原创力文档...
- 无代码开发的未来是什么样的?
- 金庸小说人物知识图谱构建——以《雪山飞狐》为例
热门文章
- 简单工厂 工厂方法 抽象工厂 如何理解
- mysql replicate函数_使用mysqlreplicate命令快速搭建 Mysql 主从复制
- IC先生网:磁性开关的工作原理及其应用详解
- 拉卡拉智能POS一站式服务实现商户精准营销
- android java 经纬度(国标WGS84/gps84/硬件/谷歌地球卫星,Gcj02/腾讯地图/高德地图,Bd09/百度地图)之间互换
- 细胞膜修饰多肽/多糖/红细胞膜/仿生细胞膜载蛋白/聚乙二醇修饰细胞膜的制备
- 四足机器人A1目标跟踪
- 压力容器用安全阀的问题
- 高通MSM8255串口驱动移植
- 服务器被攻击统计及被暴力破解过程(二)