系列十一、拦截器(二)#案例演示
一、案例演示
说明:如下案例通过springboot的方式演示拦截器是如何使用的,以获取Controller中的请求参数为切入点进行演示
1.1、前置准备工作
1.1.1、pom
<dependencies><!-- spring-boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 工具 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.3</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.6</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.4</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.3</version></dependency><!-- servlet --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency></dependencies>
1.1.2、WebRequestConstant
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/5 11:39* @Description:*/
public class WebRequestConstant {/*** 请求方法:POST*/public static final String METHOD_TYPE_POST = "POST";/*** 数据类型:application/json*/public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json";/*** 字符解码*/public static final String CHARACTER_U = "%u";}
1.1.3、EncodeUtil
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/5 11:12* @Description:*/
public class EncodeUtil {private static final String DEFAULT_URL_ENCODING = "UTF-8";private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();/*** Hex编码.*/public static String encodeHex(byte[] input) {return Hex.encodeHexString(input);}/*** Hex解码.*/public static byte[] decodeHex(String input) {try {return Hex.decodeHex(input.toCharArray());} catch (DecoderException e) {return null;}}/*** Base64编码.*/public static String encodeBase64(byte[] input) {return Base64.encodeBase64String(input);}/*** Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).*/public static String encodeUrlSafeBase64(byte[] input) {return Base64.encodeBase64URLSafeString(input);}/*** Base64解码.*/public static byte[] decodeBase64(String input) {return Base64.decodeBase64(input);}/*** Base62编码。*/public static String encodeBase62(byte[] input) {char[] chars = new char[input.length];for (int i = 0; i < input.length; i++) {chars[i] = BASE62[(input[i] & 0xFF) % BASE62.length];}return new String(chars);}/*** Html 转码.*/public static String escapeHtml(String html) {return StringEscapeUtils.escapeHtml4(html);}/*** Html 解码.*/public static String unescapeHtml(String htmlEscaped) {return StringEscapeUtils.unescapeHtml4(htmlEscaped);}/*** Xml 转码.*/public static String escapeXml(String xml) {return StringEscapeUtils.escapeXml(xml);}/*** Xml 解码.*/public static String unescapeXml(String xmlEscaped) {return StringEscapeUtils.unescapeXml(xmlEscaped);}/*** URL 编码, Encode默认为UTF-8.*/public static String urlEncode(String part) {try {return URLEncoder.encode(part, DEFAULT_URL_ENCODING);} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}}/*** URL 解码, Encode默认为UTF-8.*/public static String urlDecode(String part) {try {return URLDecoder.decode(part, DEFAULT_URL_ENCODING);} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}}
}
1.1.4、StreamUtil
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/5 1:15* @Description:*/
public class StreamUtil {public static String getRequestBody(InputStream inputStream) {String line = "";StringBuilder body = new StringBuilder();int counter = 0;// 读取POST提交的数据内容BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));try {while ((line = reader.readLine()) != null) {if (counter > 0) {body.append("rn");}body.append(line);counter++;}} catch (IOException e) {e.printStackTrace();}return body.toString();}public static HashMap<String, String[]> parseQueryString(String source) {String[] valueArray = null;if (source == null) {throw new IllegalArgumentException();}HashMap<String, String[]> hashMap = new HashMap<String, String[]>(16);StringTokenizer st = new StringTokenizer(source, "&");while (st.hasMoreTokens()) {String pair = (String) st.nextToken();int pos = pair.indexOf('=');if (pos == -1) {continue;}String key = pair.substring(0, pos);String val = pair.substring(pos + 1, pair.length());if (hashMap.containsKey(key)) {String[] oldValues = (String[]) hashMap.get(key);valueArray = new String[oldValues.length + 1];for (int i = 0; i < oldValues.length; i++) {valueArray[i] = oldValues[i];}valueArray[oldValues.length] = decodeValue(val);} else {valueArray = new String[1];valueArray[0] = decodeValue(val);}hashMap.put(key, valueArray);}return hashMap;}/*** 自定义解码函数** @param value* @return*/private static String decodeValue(String value) {if (value.contains(WebRequestConstant.CHARACTER_U)) {return EncodeUtil.urlDecode(value);} else {try {return URLDecoder.decode(value, "UTF-8");} catch (UnsupportedEncodingException e) {// 非UTF-8编码return "";}}}public static ServletInputStream getServletInputStream(ByteArrayInputStream bais) {return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener arg0) {}};}public static byte[] readBytes(InputStream in) throws IOException {BufferedInputStream bufin = new BufferedInputStream(in);int buffSize = 1024;ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);byte[] temp = new byte[buffSize];int size = 0;while ((size = bufin.read(temp)) != -1) {out.write(temp, 0, size);}bufin.close();byte[] content = out.toByteArray();return content;}}
1.1.5、MyHttpServletRequestWrapper
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/4 20:50* @Description:*/
@Getter
@Setter
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {/*** 用于保存读取到的body中的数据*/private byte[] body;private Map<String, String[]> paramsMap;@Overridepublic Map getParameterMap() {return paramsMap;}@Overridepublic String getParameter(String name) {String[] values = paramsMap.get(name);if (values == null || values.length == 0) {return null;}return values[0];}@Overridepublic String[] getParameterValues(String name) {return paramsMap.get(name);}@Overridepublic Enumeration getParameterNames() {return Collections.enumeration(paramsMap.keySet());}private HashMap<String, String[]> getParamMapFromPost(HttpServletRequest request) {String body = "";try {body = StreamUtil.getRequestBody(request.getInputStream());} catch (IOException e) {e.printStackTrace();}HashMap<String, String[]> result = new HashMap<String, String[]>(16);if (null == body || 0 == body.length()) {return result;}return StreamUtil.parseQueryString(body);}private Map<String, String[]> getParamMapFromGet(HttpServletRequest request) {return StreamUtil.parseQueryString(request.getQueryString());}public String getBody(){return new String(body);}public MyHttpServletRequestWrapper(HttpServletRequest request) throws Exception {super(request);body = StreamUtil.readBytes(request.getInputStream());}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return StreamUtil.getServletInputStream(bais);}}
1.1.6、UserDTO
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class UserDTO implements Serializable {/*** 用户名*/private String username;/*** 密码*/private String password;}
二、创建过滤器
2.1、MyFilter
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/4 20:37* @Description:*/
@Slf4j
@Component
@WebFilter(urlPatterns = "/*", filterName = "channelFilter")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("============= MyFilter init =============");}/*** 普通的参数可以通过request.getParameterMap中获取,而Controller层被@RequestBody修饰的参数需要从request的InputStream中获取,* 但是由于InputStream只能读取一次,如果过滤器读取了参数,那么后面的拦截器和Controller层就读取不到参数了,所以这类参数需要单独获取,可以把* request封装一下,copy一份request,一个用于在拦截器(过滤器)中读取参数,一个放行给Controller使用* * @param request* @param response* @param chain* @throws ServletException* @throws IOException*/@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {ServletRequest requestWrapper = null;String param = "";if (request instanceof HttpServletRequest) {HttpServletRequest httpServletRequest = (HttpServletRequest) request;String method = httpServletRequest.getMethod().toUpperCase();String type = httpServletRequest.getContentType();if (WebRequestConstant.METHOD_TYPE_POST.equals(method) && WebRequestConstant.CONTENT_TYPE_APPLICATION_JSON.equalsIgnoreCase(type)) {try {requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);} catch (Exception e) {throw new RuntimeException(e);}}}if (requestWrapper == null) {Map<String, String[]> originRequestMap = request.getParameterMap();Map<String, String> requestMap = new HashMap<String, String>(16);for (String key : originRequestMap.keySet()) {String[] values = originRequestMap.get(key);requestMap.put(key, values[0]);}param = JSON.toJSONString(requestMap);} else {param = ((MyHttpServletRequestWrapper) requestWrapper).getBody();}log.info("过滤器param:{}", param);//放行if (requestWrapper == null) {chain.doFilter(request, response);} else {chain.doFilter(requestWrapper, response);}}@Overridepublic void destroy() {log.info("============= MyFilter destroy =============");}}
三、拦截器
3.1、创建拦截器
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/4 18:29* @Description: 自定义的登录拦截器*/
@Slf4j
@Component
public class MyLoginHandlerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse response, Object handler) throws Exception {log.info("============= MyLoginHandlerInterceptor preHandle =============");try {String requestUrl = httpServletRequest.getRequestURI();ServletRequest requestWrapper = null;String param = "";String method = httpServletRequest.getMethod().toUpperCase();String type = httpServletRequest.getContentType();if (WebRequestConstant.METHOD_TYPE_POST.equals(method) && WebRequestConstant.CONTENT_TYPE_APPLICATION_JSON.equalsIgnoreCase(type)) {requestWrapper = new MyHttpServletRequestWrapper(httpServletRequest);}if (requestWrapper == null) {Map<String, String[]> originRequestMap = httpServletRequest.getParameterMap();Map<String, String> requestMap = new HashMap<String, String>(16);for (String key : originRequestMap.keySet()) {String[] values = originRequestMap.get(key);requestMap.put(key, values[0]);}param = JSON.toJSONString(requestMap);} else {param = ((MyHttpServletRequestWrapper) requestWrapper).getBody();}log.info("拦截器param:{}", param);} catch (Exception e) {e.printStackTrace();}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("============= MyLoginHandlerInterceptor postHandle =============");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("============= MyLoginHandlerInterceptor afterCompletion =============");}
}
3.2、注册拦截器
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/4 18:37* @Description:*/
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {/*** 引入自定义的拦截器对象*/@Resourceprivate MyLoginHandlerInterceptor loginHandlerInterceptor;/*** 注册拦截器* @param registry* addPathPatterns("/**"):拦截所有* excludePathPatterns("/business/*"):放行以/business打头的请求*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginHandlerInterceptor).addPathPatterns("/**").excludePathPatterns("/business/*").order(1);// registry.addInterceptor(loginHandlerInterceptor).addPathPatterns("/**");}
}
四、使用拦截器(案例)
4.1、获取Controller层@RequestBody中的对象参数
4.1.1、LoginController#login()
@PostMapping("/login")
public String login(@RequestBody UserDTO param) {log.info("LoginController login param:{}", param);return "OK";
}
4.1.2、测试
4.2、获取Controller层普通的对象参数
4.2.1、LoginController#login2()
@PostMapping("/login2")
public String login2(UserDTO param) {log.info("LoginController login2 param:{}", param);return "OK";
}
4.2.2、测试#form-data
4.2.3、测试#x-www-form-urlencoded
4.3、获取Controller层字符串参数
4.3.1、LoginController#login3()
@GetMapping("/login3")
public String login3(String username,String password) {log.info("LoginController login3 param username:{},password:{}", username,password);return "OK";
}
4.3.2、测试
五、参考
https://blog.csdn.net/w_t_y_y/article/details/103407841https://blog.csdn.net/weixin_45100881/article/details/128660421
相关文章:

系列十一、拦截器(二)#案例演示
一、案例演示 说明:如下案例通过springboot的方式演示拦截器是如何使用的,以获取Controller中的请求参数为切入点进行演示 1.1、前置准备工作 1.1.1、pom <dependencies><!-- spring-boot --><dependency><groupId>org.spring…...

数据分析实战 | 关联规则分析——购物车分析
目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据预处理 七、生成频繁项集 八、计算关联度 九、可视化 一、数据及分析对象 数据集链接:Online Retail.xlsx 该数据集记录了2010年12月01日至2011年12月09日…...
maven 添加 checkstyle 插件约束代码规范
本例示例,是引用 http 链接这种在线 checkstyle.xml 文件的配置方式,如下示例: <properties><maven.checkstyle.plugin.version>3.3.0</maven.checkstyle.plugin.version><!--支持本地绝对路径、本地相对路径、HTTP远程…...

什么是MySQL的执行计划(Explain关键字)?
什么是Explain Explain被称为执行计划,在语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,模拟MySQL优化器来执行SQL语句,执行查询时,会返回执行计划的信息,并不执行这条SQL。(注意&…...
编码格式科普ASCII unicode utf-8 usc-2 GB2312
1.ASCII(标准版) 可以表示所有英文字符(包括大写和小写)和数字,长度为7bit,最多可以表示0-127 个值,2的7次方个数字。比如比如“a” 对照ASCII码的值为97(十进制)或11000…...
Pycharm中新建一个文件夹下__init__.py文件有什么用
在PyCharm中新建一个文件夹下的__init__.py文件有以下几个作用: 声明文件夹为一个Python包:__init__.py文件的存在告诉Python解释器该文件夹是一个Python包。当你导入该文件夹下的模块时,Python会将其视为一个包而不是普通的文件夹。这允许你…...
OracleBulkCopy c#批量插入oracle数据库的方法
datatable中的数据 存入oracle表中,要求 二者字段名一致,如果不一致,通过这个实现对应: bulkCopy.ColumnMappings.Add("SERVNUMBER", "SN"); 首先要引入Oracle.DataAccess.dll文件(在oracle客户端…...

046_第三代软件开发-虚拟屏幕键盘
第三代软件开发-虚拟屏幕键盘 文章目录 第三代软件开发-虚拟屏幕键盘项目介绍虚拟屏幕键盘 关键字: Qt、 Qml、 虚拟键盘、 qtvirtualkeyboard、 自定义 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QML(Qt Meta-Object L…...

MySQL主从搭建,实现读写分离(基于docker)
一 主从配置原理 mysql主从配置的流程大体如图: 1)master会将变动记录到二进制日志里面; 2)master有一个I/O线程将二进制日志发送到slave; 3) slave有一个I/O线程把master发送的二进制写入到relay日志里面; 4…...
uni-app android picker选择默认月份
微信小程序选中月份后下次再点开是上次的选中的月份,而编译的android应用只默认当前月份 <picker mode"date" ref"picker" :disabled"disabled" :value"date" fields"month" change"bindDateChange&quo…...

Go 接口-契约介绍
Go 接口-契约介绍 文章目录 Go 接口-契约介绍一、接口基本介绍1.1 接口类型介绍1.2 为什么要使用接口1.3 面向接口编程1.4 接口的定义 二、空接口2.1 空接口的定义2.2 空接口的应用2.2.1 空接口作为函数的参数2.2.2 空接口作为map的值 2.3 接口类型变量2.4 类型断言 三、尽量定…...

变压器试验VR虚拟仿真操作培训提升受训者技能水平
VR电气设备安装模拟仿真实训系统是一种利用虚拟现实技术来模拟电气设备安装过程的培训系统。它能够为学员提供一个真实、安全、高效的学习环境,帮助他们更好地掌握电气设备的安装技能。 华锐视点采用VR虚拟现实技术、MR混合现实技术、虚拟仿真技术、三维建模技术、人…...
Mastering Makefile:模块化编程技巧与经验分享
在Linux项目管理中,Makefile是一个强大的工具,它可以帮助我们自动化编译和测试过程。然而,随着项目的增长,Makefile可能会变得越来越复杂,难以管理。在这篇文章中,我将分享一些模块化编程的技巧和经验&…...

el-input输入校验插件(正则表达式)
使用方法:在main.js文件中注册插件然后直接在<el-input>加入‘v-插件名’ (1)在main.js文件: // 只能输入数字指令 import onlyNumber from /directive/only-number; Vue.use(onlyNumber); (2)在src/directive文件夹中 &a…...

【Matplotlib】plt.plot() X轴横坐标展示完整整数坐标
比如说,我的数据应该是 x轴从2到21的20个整数 y轴对应值 但是直接plot的话x轴显示居然有小数点什么鬼 可以这样改...

左手 Jira,右手 Polarion,驶入互联网和制造业十字路口的新能源汽车
笔者之前一直在互联网公司从事软件研发,创立 Bytebase 之后,才开始接触到各行各业的用户。最近来自汽车行业的客户不少,所以就翻翻相关资料。周末微信收到了一条推送,提到汽车行业的软件研发管理,也由此了解到了 Polar…...

网络安全(黑客)-0基础小白自学
1.网络安全是什么 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高; 二、则是发展相对成熟…...

ActiveMQ、RabbitMQ、RocketMQ、Kafka介绍
一、消息中间件的使用场景 消息中间件的使用场景总结就是六个字:解耦、异步、削峰 1.解耦 如果我方系统A要与三方B系统进行数据对接,推送系统人员信息,通常我们会使用接口开发来进行。但是如果运维期间B系统进行了调整,或者推送过…...

unity打AB包,AssetBundle预制体与图集(二)
第二步:加载AB包的资源,用于显示 using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Networking; using UnityEngine.U2D; using UnityEngine.UI;public class GameLaunch : MonoBe…...

【网络安全 --- web服务器解析漏洞】IIS,Apache,Nginx中间件常见解析漏洞
一,工具及环境准备 以下都是超详细保姆级安装教程,缺什么安装什么即可(提供镜像工具资源) 1-1 VMware 16.0 安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程(提供资源)-CSDN博客文章浏览阅读20…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...