系列十一、拦截器(二)#案例演示
一、案例演示
说明:如下案例通过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…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...

Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...