系列十一、拦截器(二)#案例演示
一、案例演示
说明:如下案例通过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…...

Python基础——注释、缩进、语法、标识符、关键字
注释 Python中单行注释用#表示,多行注释由3对双引号或单引号包裹:可以使用快捷键CTRLR进行注释 # 我是单行注释"""我是多行注释 """缩进 python使用“缩进”即一行代码前的空白区域确定代码之间的逻辑关系和层次关系。…...

排序算法的分析及实现
目录 1. 排序 1.1. 排序的概念 1.2. 排序的稳定性 1.3. 内部排序和外部排序 2. 直接插入排序 2.1. 直接插入排序 2.2. 直接插入排序的两种情况 1. 情况一 2. 情况二 2.3. 直接插入排序的单趟排序 2.4. 直接插入排序的完整实现 2.5. 直接插入排序的时…...

rancher或者其他容器平台使用非root用户启动jar
场景: java程序打成镜像,在rancher上运行,默认是root账户,发现hdfs或者hive不允许root账户操作;所以打算用费root账户启动jar,使其具有hive和hdfs的操作权限。 Dockerfile entrypoint.sh 思路就是上面这样…...

Scrapy使用和学习笔记
前言 Scrapy是非常优秀的一个爬虫框架,基于twisted异步编程框架。yield的使用如此美妙。基于调度器,下载器可以对scrapy扩展编程。插件也是非常丰富,和Selenium,PlayWright集成也比较轻松。 当然,对网页中的ajax请求…...

<sa8650> sa8650介绍
一、sa8650 描述 设备说明 QAM8650P/QAMSRV1H是高通公司的下一代Snapdragon高级驾驶员辅助系统(ADAS)模块,旨在实现卓越的性能和电源效率。 它已被开发为SEooC(上下文之外的安全元素),针对假定的ASIL B用例*。QAM8650P/QAMSRV1H模块的关键组件包括SA8650P/SRV1H SoC、PM…...

[架构之路-244]:目标系统 - 设计方法 - 软件工程 - 软件开发方法:结构化、面向对象、面向服务、面向组件的开发方法
目录 前言: 一、概述: 软件聚合的程度由简单到复杂 二、主要开发方法详见 2.1 结构化的开发方法 2.2 面对对象的开发方法 2.3 面向服务的开发方法 2.4 面向组件的开发方法 三、不同开发方法比较 3.1 结构化开发方法 3.2 面向对象(OOP)开发方法 3.3 面向服…...

Qt窗体自动销毁
Qt中通过对象树的方式,实现了窗体自动析构,只要我们使用得当,就能免去自己去释放窗体对象的内存,但是我们得清楚Qt窗体自动析构的机制,什么情况下能够自动析构,什么情况不能。操作不当的情况可能造成内存泄…...

制造业企业设备管理常见的三个问题及对应的解决方案
当今的市场如同茫茫大海,既充满机遇,也伴随着波动的风险。在现代制造业中,企业常常面临着各种挑战,这些挑战可能妨碍其发展和竞争力。但制造企业往往具备能够解决挑战的能力,借助软件工具的力量,可以更好地…...

linux文件目录
/bin 二进制可执行命令。该目录下存放着普通用户的命令 /boot 启动Linux的核心文件 /data 用户用于存放日志等数据的目录 /dev 系统的设备文件,即设备的驱动程序 /etc 系统所有的配置文件都在这个目录中 /home 用户主目录的基点 /lib 存放着和…...

流量卡是什么?流量卡为什么有虚量,51物联卡带你全面了解一下。
上个月在网上买了一张流量卡,用了之后才发现剩余流量和套餐不符,这种流量是虚的吗?还有必要接着使用吗?这是一个网友跟小编私信咨询的一个问题。 其实流量卡流量和套餐不符,这个问题是比较常见的一个问题ÿ…...