【拦截器、过滤器、springAop】那些不为人知的隐秘
首先说到这几个词的时候,大家肯定都很熟悉了,甚至觉得这几个的区别刚刚毕业都能回答了,但是我想大家在实际应用过程中是真得会真正的使用吗?换言之,什么时候用过滤器什么时候使用拦截器,什么时候使用springAop呢?很多时候不觉得这些都可以实现吗?比如日志的打印,我觉得都可以实现,那在设计架构的时候应该如何去考量呢?废话不多说,接下来我会用实际的案例来展示,大家看看是否真的如你们心里所想的呢?或者有么有更好的方案欢迎评论区留言!!!
首先说一些基础的它们之间的执行顺序
作用域大小不一样。
过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。
拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller
中渲染了对应的视图之后请求结束。过滤器/拦截器与aop获取的信息不一样。过滤器/拦截器获取的是请求级别的信息,如url、传参、header、返回值等信息。
aop不能获取请求的参数等信息,和返回结果。aop能获取到调用的类,方法及方法参数。以及方法的返回值。
如果想通过方法进行拦截/过滤等处理,需要使用aop。如果想通过请求判断,需要使用过滤器。但是aop获取的是方法级别的信息,类、方法、方法的传参等等。
背景
现在有个业务场景就是通过前后端密文加解密实现参数传递,前端都是通过密文传递的并且是通过post请求方式的,后端之间使用对象来映射的,我们想通过上面的方式实现和业务解耦
方案讨论
过滤器可以获取到所有的request和response,是根据url匹配的
拦截器获取不到request和response参数,但是可以获取到所有的方法、类、参数等信息,也是根据url匹配的
springAop拦截器获取不到request和response参数,但是可以获取到所有的方法、类、参数等信息,是根据切点的也就是方法来匹配的
还有一点区别那就是如果是get请求可以很轻松获取但是如果是post那就要注意了,因为body的数据读取是通过流形式读取的,如果你在过滤器中读取到了,那么在controller中mvc参数映射的时候就会报错,因为拿不到body的值,因为流读取只会读取到一次,你在过滤器中读取到了,那么mvc参数映射的时候就无法读取不到,还有就是springAop或者是拦截器最早发生的时机也需要发生在mvc参数映射之后的,否则怎么能拿到参数信息呢,这点就是提下
那么既然这么说了,肯定有办法解决嘛,那就是你获取到了body的数据,就需要重新包装下然后set回去
springAop
import lombok.Data;/*** 责任链接口** @author fangh* @date 2023-02-09 11:22*/
@Data
public abstract class ProcessingObject<T> {private ProcessingObject<T> successor;public T handle(T input, String apiName) {T t = handleWork(input, apiName);if (successor != null) {return successor.handle(t, apiName);}return t;}/*** 子类的具体处理方法** @param input 待处理的参数* @param apiName 接口名* @return 处理后的参数*/abstract protected T handleWork(T input, String apiName);
}
import com.fh.inter.mgmt.service.GetVehicleInfoService;
import com.fh.inter.mgmt.service.impl.GenerateReturnSign;
import com.fh.standard.config.SystemCommonConfig;
import com.fh.standard.constant.MdcConstant;
import com.fh.standard.dto.BaseDTO;
import com.fh.standard.enums.ApiEnum;
import com.fh.standard.enums.ApiResultEnum;
import com.fh.standard.exception.BusinessException;
import com.fh.standard.vo.BaseVO;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Map;/*** <p>AOP 类,包含请求/响应日志打印、签名验证、车辆信息校验等</p>* <p>需要留意下 AOP 的执行顺序:</p>** @author fangh* @date 2023-02-09 11:22*/
@Aspect
@Component
@Order(0)
@Slf4j
@RequiredArgsConstructor
public class RequestAop {/*** 请求参数日志打印*/private final RequestLogPrint p1;/*** 签名处理*/private final ValidateSign p2;/*** 校验请求参数*/private final CheckRequestParam p3;private final ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal<>();/*** 返回报文签名生成*/private final GenerateReturnSign generateReturnSign;private final GetVehicleInfoService getVehicleInfoService;private final SystemCommonConfig config;/*** Key:apiName 接口方法名 Value:apiDesc 接口方法名中文描述*/private final static Map<String, String> METHOD_MAP = Maps.newHashMapWithExpectedSize(ApiEnum.values().length);static {METHOD_MAP.put(ApiEnum.RDS_REGISTER.getMethodName(), ApiEnum.RDS_REGISTER.getApiName());METHOD_MAP.put(ApiEnum.RDS_CHECK.getMethodName(), ApiEnum.RDS_CHECK.getApiName());METHOD_MAP.put(ApiEnum.RDS_TASK_INFO.getMethodName(), ApiEnum.RDS_TASK_INFO.getApiName());METHOD_MAP.put(ApiEnum.RDS_DOWNlOAD_STATE_REPORT.getMethodName(), ApiEnum.RDS_DOWNlOAD_STATE_REPORT.getApiName());METHOD_MAP.put(ApiEnum.RDS_REPORT_LOG.getMethodName(), ApiEnum.RDS_REPORT_LOG.getApiName());}/*** 对 Controller 做切点*/@Pointcut("execution(* com.adups.inter.mgmt.controller..*.*(..))")public void pointcut() {}@Before("pointcut()")public void doBefore(JoinPoint joinPoint) {// 接口形参列表Object[] args = joinPoint.getArgs();for (Object arg : args) {if (arg instanceof BaseDTO) {BaseDTO baseDTO = (BaseDTO) arg;String methodName = currentMethod(joinPoint);// 请求接口名称String apiName = METHOD_MAP.get(methodName);// 请求参数日志打印 -> 非注册接口的车辆信息获取 -> 验签 -> ecuDids 解析 -> ecuPartNum 解析 -> exts 解析// 设置调用顺序p1.setSuccessor(p2);p2.setSuccessor(p3);// 开始按顺序链式处理p1.handle(baseDTO, apiName);break;}}}@AfterReturning(pointcut = "pointcut()", returning = "returnValue")public void doAfterReturn(JoinPoint joinPoint, Object returnValue) {Map<String, String> signMap = threadLocal.get();String methodName = currentMethod(joinPoint);String apiName = METHOD_MAP.get(methodName);if (apiName == null) {log.error("请求 Url 不存在");throw new BusinessException(ApiResultEnum.PARAM_VERIFICATION_FAIL, "请求 Url 不存在");}if (returnValue == null) {log.error("{} 接口返回值为 null,请检查代码", apiName);throw new BusinessException(ApiResultEnum.UNKNOWN_ERROR);}BaseVO baseVO = (BaseVO) returnValue;String sign = generateReturnSign.initReturnSign(baseVO, signMap.get(MdcConstant.SIGN_KEY), null);baseVO.setSign(sign);// 正常响应参数日志打印log.info(apiName + "响应:" + JSON.toJSONString(baseVO));}private String currentMethod(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();Method[] methods = joinPoint.getTarget().getClass().getMethods();Method resultMethod = null;for (Method method : methods) {if (method.getName().equals(methodName)) {resultMethod = method;break;}}return resultMethod == null ? "" : resultMethod.getName();}}
/*** 请求参数打印** @author Xinling Jing* @date 2021-05-17 11:02*/
@Component
@Slf4j
@Setter
public class RequestLogPrint extends ProcessingObject<BaseDTO> {@Overrideprotected BaseDTO handleWork(BaseDTO input, String apiName) {log(JSON.toJSONString(input), apiName);return input;}private void log(String json, String apiName) {log.info(apiName + "请求:" + json);}
}
过滤器
package com.adups.inter.mgmt.filter;import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fh.inter.mgmt.dto.RegisterDTO;
import com.fh.inter.mgmt.service.GetVehicleInfoService;
import com.fh.standard.config.SystemCommonConfig;
import com.fh.standard.constant.MdcConstant;
import com.fh.standard.entity.VehicleInfoDO;
import com.fh.standard.enums.ApiEnum;
import com.fh.standard.util.AesUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 报文解密过滤器** @author fangh* @date 2023-02-15 18:27*/
@Order(0)
@WebFilter(urlPatterns = "/idiagnosis/*")
@RequiredArgsConstructor
public class DecreptFilter implements Filter {private final SystemCommonConfig config;private final GetVehicleInfoService getVehicleInfoService;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain) throws IOException, ServletException {if (!config.isEncrypt()) {chain.doFilter(servletRequest, response);return;}// 获取请求uriString uri = ((HttpServletRequest) servletRequest).getRequestURI();// 截取注册映射值String apiName = StrUtil.subAfter(uri, StrUtil.SLASH, true);RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);//获取post的值String bodyMessage = IOUtils.toString(requestWrapper.getBody(), "UTF-8");String decodeBodyMessage;if (ApiEnum.RDS_REGISTER.getMethodName().equals(apiName)) {// 解密后的报文decodeBodyMessage = config.isEncrypt() ? AesUtils.aesDecodeStr(bodyMessage, config.getKey()) : bodyMessage;// 解析jsonRegisterDTO registerDTO = JSONUtil.toBean(decodeBodyMessage, RegisterDTO.class);// 获取车辆信息VehicleInfoDO vehicleInfoDO = getVehicleInfoService.getVehicleInfoByVin(registerDTO.getVin());registerDTO.setVehicle(vehicleInfoDO);// 覆写request数据requestWrapper.setBody(JSONUtil.toJsonStr(registerDTO).getBytes(StandardCharsets.UTF_8));MDC.put(MdcConstant.REGISTER_BODY_MESSAGE, decodeBodyMessage);} else {// 截取到deviceId值String deviceId = StrUtil.subAfter(uri, StrUtil.SLASH, true);// 根据deviceId获取车辆信息VehicleInfoDO vehicleInfoDO = getVehicleInfoService.getVehicleInfoByDeviceId(deviceId);// 报文解密decodeBodyMessage = config.isEncrypt() ? AesUtils.aesDecodeStr(bodyMessage, vehicleInfoDO.getSecret()) : bodyMessage;// 车辆的secretMDC.put(MdcConstant.ENCRYPT_KEY, vehicleInfoDO.getSecret());// 解密后的报文MDC.put(MdcConstant.BODY_MESSAGE, decodeBodyMessage);// 车辆信息MDC.put(MdcConstant.VEHICLE_INFO, JSONUtil.toJsonStr(vehicleInfoDO));}chain.doFilter(requestWrapper, responseWrapper);// 获取原响应报文byte[] content = responseWrapper.getContent();// 解析responseString responseData = IOUtils.toString(content, "UTF-8");// 加密响应报文String result;if (ApiEnum.RDS_REGISTER.getMethodName().equals(apiName)) {result = AesUtils.aesEncryptStr(responseData, config.getKey());} else {// 非注册请求 加密key为车的密钥result = AesUtils.aesEncryptStr(responseData, MDC.get(MdcConstant.ENCRYPT_KEY));}// 覆写responsecontent = result.getBytes();// 注意 此处是servletResponse 不是responseWrapper,写responseWrapper的话 依旧响应不了ServletOutputStream outputStream = response.getOutputStream();outputStream.write(content);outputStream.flush();outputStream.close();MDC.clear();log.debug("当前线程局部变量已全部清除");}@Overridepublic void destroy() {Filter.super.destroy();}
}
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;/*** RequestWrapper** @author fangh* @date 2023-02-16 17:46*/
public class RequestWrapper extends HttpServletRequestWrapper {private byte[] body;public RequestWrapper(HttpServletRequest request) throws IOException {super(request);body = this.toByteArray(request.getInputStream());}private byte[] toByteArray(ServletInputStream inputStream) throws IOException {ByteArrayOutputStream out = new ByteArrayOutputStream();byte[] buffer = new byte[1024 * 4];int n;while ((n = inputStream.read(buffer)) != -1) {out.write(buffer, 0, n);}return out.toByteArray();}@Overridepublic BufferedReader getReader() {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() {return bais.read();}};}public byte[] getBody() {return body;}public void setBody(byte[] data) {body = data;}
}
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;/*** ResponseWrapper** @authorfangh* @date 2023-02-16 17:46*/
public class ResponseWrapper extends HttpServletResponseWrapper {private final ByteArrayOutputStream byteArrayOutputStream;private final ServletOutputStream servletOutputStream;private final PrintWriter writer;public ResponseWrapper(HttpServletResponse response) {super(response);byteArrayOutputStream = new ByteArrayOutputStream();servletOutputStream = new WapperedOutputStream(byteArrayOutputStream);writer = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8));}@Overridepublic ServletOutputStream getOutputStream() {return servletOutputStream;}@Overridepublic PrintWriter getWriter() {return writer;}@Overridepublic void flushBuffer() {if (servletOutputStream != null) {try {servletOutputStream.flush();} catch (IOException e) {e.printStackTrace();}}if (writer != null) {writer.flush();}}@Overridepublic void reset() {byteArrayOutputStream.reset();}public String getResponseData(String charset) throws IOException {flushBuffer();return byteArrayOutputStream.toString(charset);}private static class WapperedOutputStream extends ServletOutputStream {private final ByteArrayOutputStream bos;public WapperedOutputStream(ByteArrayOutputStream stream) {bos = stream;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setWriteListener(WriteListener writeListener) {}@Overridepublic void write(int b) {bos.write(b);}}public byte[] getContent() {flushBuffer();return byteArrayOutputStream.toByteArray();}
}
相关文章:

【拦截器、过滤器、springAop】那些不为人知的隐秘
首先说到这几个词的时候,大家肯定都很熟悉了,甚至觉得这几个的区别刚刚毕业都能回答了,但是我想大家在实际应用过程中是真得会真正的使用吗?换言之,什么时候用过滤器什么时候使用拦截器,什么时候使用spring…...

记录charles手机端配置https的成功过程
1.百度 https://www.likecs.com/show-204025787.html https://blog.csdn.net/enthan809882/article/details/117572094?spm1001.2101.3001.6650.6&utm_mediumdistribute.pc_relevant.none-task-blog-2defaultBlogCommendFromBaiduRate-6-117572094-blog-122959902.pc_rele…...

你知道这几种常见的JVM调优场景吗?
看此文前需已了解了运行时的数据区域和常用的垃圾回收算法,也了解了Hotspot支持的垃圾回收器。 一、cpu占用过高 cpu占用过高要分情况讨论,是不是业务上在搞活动,突然有大批的流量进来,而且活动结束后cpu占用率就下降了…...
华为OD机试真题Python实现【最长连续子串】真题+解题思路+代码(20222023)
最长连续子串 题目 给定一个字符串 只包含字母和数字 按要求找出字符串中的最长连续子串的长度 字符串本身是其最长的子串 子串要求 只包含一个字母(a~z A~Z)其余必须是数字字母可以在子串中的任意位置 如果找不到满足要求的子串 比如说,全是字母或数字则返回-1 🔥🔥🔥…...

Vue使用distpicker插件实现省市级下拉框三级联动
前言 这几天做项目,想着用一个全国省市区插件,之前就知道有几种,比如通过JSON文件生成对应的区域下拉框,element-china-are插件,包括distpicker插件 今天主要介绍的是如何使用distpicker插件实现省市级三联跳动 官网…...

Unity Avatar Foot IK - Avatar Foot Placement Resolution
文章目录简介实现Avatar FBX Import SettingsAnimator SettingsOn Animator IKCalculate IK Position & RotationBody PositionApply IK Position & Rotation简介 通过Unity内部的Mecanim动画系统实现的FootIK功能,效果如图所示,左右分别为开启…...
是时候告别这些 Python 库了
随着每个 Python 版本的发布,都会添加新模块,并引入新的更好的做事方式,虽然我们都习惯了使用好的旧 Python 库和某些做事方式,但现在也时候升级并利用新的和改进的模块及其特性了。 文章目录技术提升PathlibSecretsZoneinfoDatac…...

nodejs基于vue论坛交流管理系统
可定制框架:ssm/Springboot/vue/python/PHP/小程序/安卓均可开发目录 目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 2 系统开发环境 4 3 系统分析 6 3.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行性 6 3.1.3运行可行…...

企业电子招投标采购系统源码之系统的首页设计
功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为…...
华为OD机试真题Python实现【竖直四子棋】真题+解题思路+代码(20222023)
竖直四子棋 题目 竖直四子棋的棋盘是竖立起来的,双方轮流选择棋盘的一列下子, 棋子因重力落到棋盘底部或者其他棋子之上,当一列的棋子放满时,无法再在这列上下子。 一方的4个棋子横、竖或者斜方向连成一线时获胜。 现给定一个棋盘和红蓝对弈双方的下子步骤,判断红方或蓝…...

LeetCode 73. 矩阵置零
LeetCode 73. 矩阵置零 难度:middle\color{orange}{middle}middle 题目描述 给定一个 KaTeX parse error: Double subscript at position 3: _m_̲ x _n_ 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法…...

「TCG 规范解读」第10章 TPM工作组 保护你的数字环境
可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…...
华为OD机试真题Python实现【 找字符】真题+解题思路+代码(20222023)
找字符 题目 给定两个字符串, 从字符串2中找出字符串1中的所有字符, 去重并按照 ASCII 码值从小到大排列。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 字符范围满足 ASCII 编码要求, 输入字符串1长度不超过1024, 字符串…...

如何解决多继承下的 菱形继承 问题
目录 概念: 菱形虚拟继承: 概念: 此时D类属于多继承,可以看到D类里面会有两份A类的数据,菱形继承也并不一定就一定就是上图的菱形,假如B类下面还有一个类,D类继承它,同样也是菱形继承问题 cla…...

rk3288-android8.1-以太网ethernet和蓝牙Bluetooth
遇到一个现象,以太网和蓝牙打不开 经过不断分析和查找发现问题在.config中 CONFIG_MOTORCOMM_PHYy 会导致以太网的eth0注册不成功(现在是双网口,还有个USB网卡) 改成# CONFIG_MOTORCOMM_PHY is not set 后以太网可以正常 # CONFIG_RTC_DRV_RK808 is not set 会导致蓝牙打不…...

算法比赛——必备的数论知识
秋名山码民的主页 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 🙏作者水平有限,如发现错误,还请私信或者评论区留言! 目录一、欧几里得二、扩展欧几里得三、算术基本定理四、线性筛选求质数五…...

Docker概述
什么是Docker我们要学习在Linux(RockyLinux)中安装使用Docker来配置软件的功能Docker是一个用来开发、运输和运行应用程序的开放平台。使用Docker可以将应用程序与基础结构分离,以便快速交付软件。使用Docker,您可以以管理应用程序的方式管理基础架构。通…...

实验室设计建设方案主要内容
实验室设计建设整体解决方案SICOLAB需要综合考虑实验室的功能需求、空间布局、设备选型、安全防护、节能环保等多方面因素。以下是一个基本的实验室设计建设方案的流程:一、需求分析:了解实验室的使用目的、实验内容、使用人数、设备种类、实验标准等&am…...
华为OD机试真题Python实现【日志采集系统】真题+解题思路+代码(20222023)
日志采集系统 题目 日志采集是运维系统的的核心组件。日志是按行生成,每行记做一条,由采集系统分批上报。 如果上报太频繁,会对服务端造成压力; 如果上报太晚,会降低用户的体验; 如果一次上报的条数太多,会导致超时失败。 为此,项目组设计了如下的上报策略: 每成功上…...
Python的模块与工具包
模块 模块是一个Python文件,以 .py结尾。模块能定义函数,类和变量,模块里也能包含可执行的代码。 作用 python 中有很多各种不同的模块,每一个模块都可以帮助我们快速的实现一些功能,比如实现和时间相关的功能就可以…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...

快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...

uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
js 设置3秒后执行
如何在JavaScript中延迟3秒执行操作 在JavaScript中,要设置一个操作在指定延迟后(例如3秒)执行,可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法,它接受两个参数: 要执行的函数&…...
统计学(第8版)——统计抽样学习笔记(考试用)
一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征(均值、比率、总量)控制抽样误差与非抽样误差 解决的核心问题 在成本约束下,用少量样本准确推断总体特征量化估计结果的可靠性(置…...
【Pandas】pandas DataFrame dropna
Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值(NaN)DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充(即“下一个有效观测值”)…...

(12)-Fiddler抓包-Fiddler设置IOS手机抓包
1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求,也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求,比如 iPhone、iPad 和 MacBook 等苹…...