当前位置: 首页 > news >正文

系列十一、拦截器(二)#案例演示

一、案例演示

说明:如下案例通过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

相关文章:

系列十一、拦截器(二)#案例演示

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

数据分析实战 | 关联规则分析——购物车分析

目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据预处理 七、生成频繁项集 八、计算关联度 九、可视化 一、数据及分析对象 数据集链接&#xff1a;Online Retail.xlsx 该数据集记录了2010年12月01日至2011年12月09日…...

maven 添加 checkstyle 插件约束代码规范

本例示例&#xff0c;是引用 http 链接这种在线 checkstyle.xml 文件的配置方式&#xff0c;如下示例&#xff1a; <properties><maven.checkstyle.plugin.version>3.3.0</maven.checkstyle.plugin.version><!--支持本地绝对路径、本地相对路径、HTTP远程…...

什么是MySQL的执行计划(Explain关键字)?

什么是Explain Explain被称为执行计划&#xff0c;在语句之前增加 explain 关键字&#xff0c;MySQL 会在查询上设置一个标记&#xff0c;模拟MySQL优化器来执行SQL语句&#xff0c;执行查询时&#xff0c;会返回执行计划的信息&#xff0c;并不执行这条SQL。&#xff08;注意&…...

编码格式科普ASCII unicode utf-8 usc-2 GB2312

1.ASCII&#xff08;标准版&#xff09; 可以表示所有英文字符&#xff08;包括大写和小写&#xff09;和数字&#xff0c;长度为7bit&#xff0c;最多可以表示0-127 个值&#xff0c;2的7次方个数字。比如比如“a” 对照ASCII码的值为97&#xff08;十进制&#xff09;或11000…...

Pycharm中新建一个文件夹下__init__.py文件有什么用

在PyCharm中新建一个文件夹下的__init__.py文件有以下几个作用&#xff1a; 声明文件夹为一个Python包&#xff1a;__init__.py文件的存在告诉Python解释器该文件夹是一个Python包。当你导入该文件夹下的模块时&#xff0c;Python会将其视为一个包而不是普通的文件夹。这允许你…...

OracleBulkCopy c#批量插入oracle数据库的方法

datatable中的数据 存入oracle表中&#xff0c;要求 二者字段名一致&#xff0c;如果不一致&#xff0c;通过这个实现对应&#xff1a; bulkCopy.ColumnMappings.Add("SERVNUMBER", "SN"); 首先要引入Oracle.DataAccess.dll文件&#xff08;在oracle客户端…...

046_第三代软件开发-虚拟屏幕键盘

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

MySQL主从搭建,实现读写分离(基于docker)

一 主从配置原理 mysql主从配置的流程大体如图&#xff1a; 1&#xff09;master会将变动记录到二进制日志里面&#xff1b; 2&#xff09;master有一个I/O线程将二进制日志发送到slave; 3) slave有一个I/O线程把master发送的二进制写入到relay日志里面&#xff1b; 4&#xf…...

uni-app android picker选择默认月份

微信小程序选中月份后下次再点开是上次的选中的月份&#xff0c;而编译的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电气设备安装模拟仿真实训系统是一种利用虚拟现实技术来模拟电气设备安装过程的培训系统。它能够为学员提供一个真实、安全、高效的学习环境&#xff0c;帮助他们更好地掌握电气设备的安装技能。 华锐视点采用VR虚拟现实技术、MR混合现实技术、虚拟仿真技术、三维建模技术、人…...

Mastering Makefile:模块化编程技巧与经验分享

在Linux项目管理中&#xff0c;Makefile是一个强大的工具&#xff0c;它可以帮助我们自动化编译和测试过程。然而&#xff0c;随着项目的增长&#xff0c;Makefile可能会变得越来越复杂&#xff0c;难以管理。在这篇文章中&#xff0c;我将分享一些模块化编程的技巧和经验&…...

el-input输入校验插件(正则表达式)

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

【Matplotlib】plt.plot() X轴横坐标展示完整整数坐标

比如说&#xff0c;我的数据应该是 x轴从2到21的20个整数 y轴对应值 但是直接plot的话x轴显示居然有小数点什么鬼 可以这样改...

左手 Jira,右手 Polarion,驶入互联网和制造业十字路口的新能源汽车

笔者之前一直在互联网公司从事软件研发&#xff0c;创立 Bytebase 之后&#xff0c;才开始接触到各行各业的用户。最近来自汽车行业的客户不少&#xff0c;所以就翻翻相关资料。周末微信收到了一条推送&#xff0c;提到汽车行业的软件研发管理&#xff0c;也由此了解到了 Polar…...

网络安全(黑客)-0基础小白自学

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

ActiveMQ、RabbitMQ、RocketMQ、Kafka介绍

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

unity打AB包,AssetBundle预制体与图集(二)

第二步&#xff1a;加载AB包的资源&#xff0c;用于显示 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中间件常见解析漏洞

一&#xff0c;工具及环境准备 以下都是超详细保姆级安装教程&#xff0c;缺什么安装什么即可&#xff08;提供镜像工具资源&#xff09; 1-1 VMware 16.0 安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客文章浏览阅读20…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...