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

springboot系列--拦截器加载原理

一、拦截器加载原理

        拦截器是在容器启动时,就创建并加载好,此时并未放入拦截器链中,只是放在一个拦截器集合当中,当一个请求进来之后,会通过匹配路径,查看是否有命中集合中的拦截器的拦截路径,如果命中,则放入拦截器链中,如果没有命中则不会放入。之后在执行请求之前,会循环遍历执行命中的拦截器中的逻辑,如果都通过,则执行请求,反之则不执行。

一、拦截器加载进拦截器集合

        默认情况下DispatcherServlet会注册3个HandlerMapping,分别是BeanNameUrlHandlerMapping、RequestMappingHandlerMapping以及RouterFunctionMapping。

        其中HandlerMapping的作用是存储请求路径与处理方法的映射,收到请求后就能通过HandlerMapping找到对应的处理方法RequestMappingHandlerMapping对象处理通过Controller注解的类中RequestMapping注解标注的方法。

        这个对象主要是在WebMvcConfigurationSupport这个配置类里面做了Bean的创建,这个配置类,主要是对springMVC所有配置做初始化。会在项目启动时自动纳入容器管理,并初始化。

@Bean@SuppressWarnings("deprecation")public RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,@Qualifier("mvcConversionService") FormattingConversionService conversionService,@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {// 创建一个RequestMappingHandlerMapping对象,由于这个对象继承了AbstractHandlerMapping这个对象,会先去创建AbstractHandlerMapping这个对象,再创建创建一个RequestMappingHandlerMapping对象RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();mapping.setOrder(0);
// 添加拦截器		mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));mapping.setContentNegotiationManager(contentNegotiationManager);mapping.setCorsConfigurations(getCorsConfigurations());PathMatchConfigurer configurer = getPathMatchConfigurer();Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();if (useSuffixPatternMatch != null) {mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);}Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();if (useRegisteredSuffixPatternMatch != null) {mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);}Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();if (useTrailingSlashMatch != null) {mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);}UrlPathHelper pathHelper = configurer.getUrlPathHelper();if (pathHelper != null) {mapping.setUrlPathHelper(pathHelper);}PathMatcher pathMatcher = configurer.getPathMatcher();if (pathMatcher != null) {mapping.setPathMatcher(pathMatcher);}Map<String, Predicate<Class<?>>> pathPrefixes = configurer.getPathPrefixes();if (pathPrefixes != null) {mapping.setPathPrefixes(pathPrefixes);}return mapping;}


// WebMvcConfigurationSupport类里面的方法
protected final Object[] getInterceptors(FormattingConversionService mvcConversionService,ResourceUrlProvider mvcResourceUrlProvider) {// 加载开始时是为空的if (this.interceptors == null) {InterceptorRegistry registry = new InterceptorRegistry();// 添加拦截器,这个方法是一个空方法,有 WebMvcConfigurationSupport的子类实现,这里会进入DelegatingWebMvcConfiguration这个类addInterceptors(registry);registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));this.interceptors = registry.getInterceptors();}return this.interceptors.toArray();}

 

// DelegatingWebMvcConfiguration这个类的添加拦截器方法protected void addInterceptors(InterceptorRegistry registry) {// 从这进入会到WebMvcConfigurerComposite类的方法this.configurers.addInterceptors(registry);}

	
// WebMvcConfigurerComposite的addInterceptors方法public void addInterceptors(InterceptorRegistry registry) {// 这里循环遍历的delegates是当前类创建的一个private final List<WebMvcConfigurer> delegates = new ArrayList<>();集合,for (WebMvcConfigurer delegate : this.delegates) {delegate.addInterceptors(registry);}}//  WebMvcConfigurerComposite这个类里面有一个方法对这个集合进行设置值public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {if (!CollectionUtils.isEmpty(configurers)) {this.delegates.addAll(configurers);}}// 这个设置值的方法又是被DelegatingWebMvcConfiguration这个类调用了,这个类里面有这个方法,再去点击会发现没有地方调用了,@Autowired(required = false)public void setConfigurers(List<WebMvcConfigurer> configurers) {if (!CollectionUtils.isEmpty(configurers)) {this.configurers.addWebMvcConfigurers(configurers);}}
	// 点击DelegatingWebMvcConfiguration这个类会发现是由EnableWebMvc这个注解将这个类导入进容器中,除此之外,springboot中的WebMvcAutoConfiguration类中// EnableWebMvcConfiguration这个内部类继承了DelegatingWebMvcConfiguration这个类,然后注入了容器中/**那也就是说当创建EnableWebMvcConfiguration这个类对象时,容器会先创建DelegatingWebMvcConfiguration对象,然后扫描实现了这个接口的WebMvcConfigurer类,然后设置进**private final List<WebMvcConfigurer> delegates = new ArrayList<>();集合中***/// 注解EnableWebMvc
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}// EnableWebMvcConfiguration这个内部类
@Configuration(proxyBeanMethods = false)public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {}

添加完拦截器后还是会回到WebMvcConfigurationSupport这个类中的getInterceptors

这个方法里继续执行 剩余逻辑。

下面代码就是InterceptorRegistry类对外提供获取拦截器集合里所有拦截器的方法

	protected List<Object> getInterceptors() {return this.registrations.stream().sorted(INTERCEPTOR_ORDER_COMPARATOR).map(InterceptorRegistration::getInterceptor).collect(Collectors.toList());}

然后将获取到的所有拦截器放到AbstractHandlerMapping这个抽象类中的

private final List<Object> interceptors = new ArrayList<>();

这个集合当中。

之后将继续执行剩下的逻辑

之后会执行RequestMappingHandlerMapping的拦截器初始化方法initInterceptors,这个方法是在他的父类AbstractHandlerMapping这个类中。

	@Overrideprotected void initApplicationContext() throws BeansException {extendInterceptors(this.interceptors);detectMappedInterceptors(this.adaptedInterceptors);
// 这里就是初始化拦截器initInterceptors();}
// 还是在当前类下protected void initInterceptors() {if (!this.interceptors.isEmpty()) {for (int i = 0; i < this.interceptors.size(); i++) {Object interceptor = this.interceptors.get(i);if (interceptor == null) {throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");}this.adaptedInterceptors.add(adaptInterceptor(interceptor));}}}

这样做的目的是为了之后请求进来了,将拦截器添加到拦截器链中 

 

 二、拦截器加载进拦截器链

 

 

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
// 如果handler不是handler执行链对象,就创建一个HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));// 获取请求进来的路径,这里一定要注意server:servlet:context-path: /work  这个在yaml配置的路径,不会被截取到。    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);// 循环遍历这个就是之前挡在AbstractHandlerMapping这个类里面的adaptedInterceptors集合中的拦截器for (HandlerInterceptor interceptor : this.adaptedInterceptors) {if (interceptor instanceof MappedInterceptor) {MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;// 关键在这里,如果匹配上了,才会添加进拦截器链中等待执行if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {chain.addInterceptor(mappedInterceptor.getInterceptor());}}else {chain.addInterceptor(interceptor);}}return chain;}

 

 原始请求:/work/work/test/export,才能命中拦截器路径,这是由于系统配置多加了一个/work

server:servlet:context-path: /work

二、实现多拦截器链式执行,确保每个拦截器按顺序执行且支持动态添加或移除拦截器

想要动态添加和移除拦截器可以借用nacos来进行控制。由于spring并未提供直接从拦截器链中或者拦截器集合中移除的方法,所以可以使用控制拦截器是否执行拦截器逻辑的方式,变相达到动态移除和添加拦截器的效果

一、nacos配置

test:dynamic-interceptors: [{"name": "FirstInterceptor","enabled": true, // 控制是否添加进容器"valid": false, // 控制是否开启拦截器"order": 2,  // 控制排序"includePatterns": ["/work/test/**"],"excludePatterns": ["/work/demo/**"] // 白名单},{"name": "SecondInterceptor","enabled": true,"valid": false,"order": 1,"includePatterns": ["/work/**"],"excludePatterns": []}]

二、获取nacos配置

// 可动态获取最新的nacos配置
@Data
@Configuration
@ConfigurationProperties("test")
public class InterceptorPro {// 拦截器信息private List<DynamicInterceptors> dynamicInterceptors;@Datapublic static class DynamicInterceptors {private String name;private boolean enabled;private boolean valid;private Integer order;private List<String> includePatterns;private List<String> excludePatterns;
}}

 

三、提前创建好的拦截器,需要实现自己的拦截逻辑

@Slf4j
@Component("FirstInterceptor")
public class FirstInterceptor implements HandlerInterceptor {@Resourceprivate InterceptorPro interceptorPro;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {log.info("开始进入拦截器:{}","FirstInterceptor");for (InterceptorPro.DynamicInterceptors dynamicInterceptors : interceptorPro.getDynamicInterceptors()) {if(this.getClass().getSimpleName().equals(dynamicInterceptors.getName()) && Boolean.FALSE == dynamicInterceptors.isValid()){log.info("当前拦截器未开启|拦截器名:{}",dynamicInterceptors.getName());return Boolean.TRUE;}}String channel = request.getHeader("channel");if (!"test".equalsIgnoreCase(channel)) {log.info("channel不等于test,禁止通过:{}","FirstInterceptor");return Boolean.FALSE;}return Boolean.TRUE;}
}
@Slf4j
@Component("SecondInterceptor")
public class SecondInterceptor implements HandlerInterceptor {@Resourceprivate InterceptorPro interceptorPro;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("开始进入拦截器:{}","SecondInterceptor");for (InterceptorPro.DynamicInterceptors dynamicInterceptors : interceptorPro.getDynamicInterceptors()) {if(this.getClass().getSimpleName().equals(dynamicInterceptors.getName()) && Boolean.FALSE == dynamicInterceptors.isValid()){log.info("当前拦截器未开启|拦截器名:{}",dynamicInterceptors.getName());return Boolean.TRUE;}}String channel = request.getHeader("channel");if (!"test".equalsIgnoreCase(channel)){log.info("channel不等于test,禁止通过:{}","SecondInterceptor");return Boolean.FALSE;}return Boolean.TRUE;}
}

 四、添加添加器到拦截器集合当中

@Component
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {@Resourceprivate ApplicationContext applicationContext;@Resourceprivate InterceptorPro interceptorPro;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 这里按照nacos配置好的顺序由低到高进行排序,拦截器的顺序是按照添加拦截器的先后,由高到低进行排序的,越先添加的拦截器优先级越高List<InterceptorPro.DynamicInterceptors> interceptors = interceptorPro.getDynamicInterceptors().stream().filter(Objects::nonNull).sorted(Comparator.comparing(InterceptorPro.DynamicInterceptors::getOrder)).collect(Collectors.toList());// 遍历nacos配置for (InterceptorPro.DynamicInterceptors config : interceptors) {// 通过nacos配置好的拦截器名字,从容器中获取拦截器对象HandlerInterceptor interceptor = (HandlerInterceptor) applicationContext.getBean(config.getName());// 如果enabled配置开启,则添加进拦截器集合当中,注意这里并没有添加到拦截器链中if (config.isEnabled()) {registry.addInterceptor(interceptor).addPathPatterns(config.getIncludePatterns().toArray(new String[0])).excludePathPatterns(config.getExcludePatterns().toArray(new String[0]));}}}

 

 

第二种排序方式:

 

 

 

相关文章:

springboot系列--拦截器加载原理

一、拦截器加载原理 拦截器是在容器启动时&#xff0c;就创建并加载好&#xff0c;此时并未放入拦截器链中&#xff0c;只是放在一个拦截器集合当中&#xff0c;当一个请求进来之后&#xff0c;会通过匹配路径&#xff0c;查看是否有命中集合中的拦截器的拦截路径&#xff0c;如…...

当Nginx所在服务器的磁盘空间满了,会有什么影响及如何避免这种问题

大家好&#xff0c;我是G探险者&#xff01; 最近遇到一个问题是&#xff0c;nginx所在服务器磁盘满了&#xff0c;导致前端页面上的一个文件上传功能不好使了&#xff0c;搞得我排查半天&#xff0c;找不见原因&#xff0c;最后发现是nginx的磁盘满了导致&#xff0c;清理了里…...

光猫开DMZ教程

本教程以移动光猫未例&#xff0c;具体操作以实际光猫为准 1、登录移动光猫管理后台 打开浏览器&#xff0c;在浏览器地址栏输入移动光猫登录管理地址192.168.1.1或者tplogin.cn 按“回车键”打开登录页面&#xff0c;然后输入路由器管理密码登录。 移动光猫登录页面 超级密…...

WireShark速成

1.WireShark安装 官网&#xff1a; Wireshark Go Deep Kali Linux系统自带WireShark工具。 2.WireShark介绍 WireShark是一个网络包分析工具&#xff0c;该工具主要用于捕获网络数据包&#xff0c;并自动解析数据包&#xff0c;为用户显示数据包的详情信息&#xff0c;供…...

BFS入门

目录 定义二叉树层次遍历电梯问题倒可乐BFS基本思想算法 四方访问 定义 BFS 通常是指广度优先搜索&#xff08;Breadth - First Search&#xff09;&#xff0c;它是一种图形数据结构的遍历算法。从给定的起始顶点开始&#xff0c;首先访问起始顶点的所有邻接顶点&#xff0c;然…...

ElementUI:el-tabs 切换之前判断是否满足条件

<div class"table-card"><div class"card-steps-class"><el-tabsv-model"activeTabsIndex":before-leave"beforeHandleTabsClick"><el-tab-pane name"1" label"基础设置"><span slot&…...

mid360使用cartorapher进行3d建图导航

1. 添加urdf配置文件&#xff1a; 添加IMU配置关节点和laser关节点 <!-- imu livox --> <joint name"livox_frame_joint" type"fixed"> <parent link"base_link" /> <child link"livox_frame" /> <o…...

【CSS in Depth 2 精译_073】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(中):对 CSS 行高的深入思考

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 12.1.1 使用 em 还是 px12.1.2 对行高的深入思考 ✔️12.1.3 行内元素的间距设置 文章目录 12.1.2 对行高的深入思考…...

JAVA设计模式-观察者模式

概述&#xff1a; 观察者模式通常由两个对象组成&#xff1a;观察者和被观察者。当被观察者状态发生改变时&#xff0c;它会通知所有的观察者对象&#xff0c;使他们能够及时做出响应&#xff0c;所以也被称作“发布-订阅模式”。 特点&#xff1a; 优点&#xff1a; 解耦且可…...

Java调用SSE流式接口,并流式返回给前端实现打字输出效果

目录 1.SSE概述 1.1 什么是是SSE2.2 与长链接(Long Polling)的区别 长链接(Long Polling)Server-Sent Events (SSE) 比较总结 2.通过okhttp调用SSE流式接口并流式返回给前端 环境要求使用okhttp相关依赖示例 3. 如果Spring Framework 低于5.0&#xff0c;可使用Servlet 3.0进行…...

倚光科技助力自由曲面设计与加工

近年来&#xff0c;自由曲面因其在光学、汽车、航空航天等领域的广泛应用&#xff0c;受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜&#xff0c;能够在光学系统中实现更加精确的光线控制&#xff0c;优化像差校正&#xff0c;并且在满足功能需求…...

【推荐算法】推荐系统中的单目标精排模型

前言&#xff1a;推荐系统中模型发展较快&#xff0c;初学者【也就是笔者】很难对模型进行一个系统的学习。因此&#xff0c;这篇文章总结了王树森中的视频以及《深度学习推荐系统》中的单目标精排模型&#xff0c;绘制了一个单目标精排模型的思维导图来帮助初学者【笔者】更好…...

Android UI:ViewTree:源码分析:事件处理:显示事件

文章目录 概述测量:measure和onMeasure​​​​​​​ View.MeasureSpecViewViewGroupLinearLayoutRelativeLayout布局:layout和onLayout ViewViewGroupLinearLayoutRelativeLayout绘制:dispatchDraw、draw和onDraw ViewViewGroupLinearLayoutRelativeLayout总结概述 显示事…...

esp32 OTA学习笔记

csv分区表中ota-0和ota-1存放程序 不超过1600kb的程序可以ota&#xff08;可手动划分&#xff09; 分区表中有 ota0和ota1两个数据分区。 ota是指先下载固件到ota1然后下次从ota1启动&#xff0c;回滚就是回到ota0 启动。 关于固件&#xff1a; bin文件可以用arduino生成也可以…...

口语笔记——祈使句用法

省略主语 (You give me) a cup of tea, please. 一杯茶(You wait for) another minute. 两等一分钟(You) keep quiet. 保持安静give me a break. 饶了我吧take your hand off. 把你的手拿开take this thing away 把这东西拿开never talk to strangers. 永远不要跟陌生人说话Do…...

【微软azure】【devtunnel隧道】工具的使用及介绍

简介&#xff1a;这是一个微软自带的能进行内网穿透的工具&#xff0c;最长30天有效期&#xff0c;可以定时更新&#xff0c;保证端口永久可用----可以理解为永久的nginx 前提&#xff1a;有azure账号&#xff0c;且要有相关权限&#xff0c;试用账号是不行滴 使用说明 1.环…...

重生之我在异世界学智力题(1)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言智力题题目&#xff1a;《奇怪的时钟…...

九、页面级变量的状态管理

状态管理概述 在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。 自定义组件拥有变量,变…...

#Vue3篇:defineOptionsvueUse

定义组件name 从 3.3 开始你可以直接通过 defineOptions 来设置组件名或 inheritAttrs 属性。 defineProps() 和 defineEmits() const props defineProps<{foo: stringbar?: number }>()const emit defineEmits<{(e: change, id: number): void(e: update, val…...

李飞飞的生成式3D场景,对数字孪生的未来影响几何?

大家好&#xff0c;我是日拱一卒的攻城师不浪&#xff0c;致力于技术与艺术的融合。这是2024年输出的第47/100篇文章。 前言 这两天&#xff0c;AI界的教母李飞飞团队重磅发布了空间智能生成式AI大模型。 仅通过一张图片就能够生成一个可操作和交互的3D空间场景。 空间智能的…...

《操作系统 - 清华大学》6 -7:局部页面置换算法:Belady现象

文章目录 1. 定义2. LRU、FIFO和Clock的比较 1. 定义 局部页面置换算法的特点是针对一个正在运行的程序&#xff0c;它访问内存的情况&#xff0c;访问页的情况&#xff0c;来决定应该采取什么样策略&#xff0c;把相应的页替换出去&#xff0c;站在算法本身角度来考虑置换哪个…...

网络原理之 TCP 协议

目录 1. TCP 协议格式 2. TCP 原理 (1) 确认应答 (2) 超时重传 (3) 连接管理 a) 三次握手 b) 四次挥手 (4) 滑动窗口 (5) 流量控制 (6) 拥塞控制 (7) 延时应答 (8) 捎带应答 3. TCP 特性 4. 异常情况的处理 1) 进程崩溃 2) 主机关机 (正常流程) 3) 主机掉电 (…...

pinn爱看论文展

1.zhiwang 基于物理信息神经网络的波动方程优化求解方法 吴丹澜1梁展弘2余懿3蔡博3郑邦宏4王梓超4张紫玲4 1.肇庆学院计算机科学与软件学院,大数据学院2.香港城市大学电气工程系3.云浮市新兴县公安局4.肇庆学院计算机科学与软件学院、大数据学院 2&#xff0c;zhiwang 就爱…...

Burp(5)web网页端抓包与app渗透测试

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&…...

Spring 基础

什么是 Spring 框架? Spring 是一款开源的轻量级 Java 开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 我们一般说 Spring 框架指的都是 Spring Framework&#xff0c;它是很多模块的集合&#xff0c;使用这些模块可以很方便地协助我们进行开发&#…...

go 集成nacos注册中心、配置中心

使用限制 Go>v1.15 Nacos>2.x 安装 使用go get安装SDK&#xff1a; go get -u github.com/nacos-group/nacos-sdk-go/v2 快速使用 初始化客户端配置ClientConfig constant.ClientConfig{TimeoutMs uint64 // 请求Nacos服务端的超时时间&#xff0c;默…...

一文掌握 OpenGL 几何着色器的使用

学习本文需要具备 OpenGL ES 编程基础,如果看起来比较费劲,可以先看入门文章 OpenGL ES 3.0 从入门到精通系统性学习教程 。 什么是几何着色器 几何着色器(Geometry Shader) OpenGL 管线中的可选着色器阶段,位于顶点着色器(Vertex Shader) 和光栅化阶段 之间。 其核心…...

《数据资产入表:企业资产评估的新契机》

《数据资产入表&#xff1a;企业资产评估的新契机》 在当今数字经济时代&#xff0c;数据作为关键生产要素&#xff0c;其重要性日益凸显。国家高度重视数据资产&#xff0c;陆续出台了一系列重磅政策。其中&#xff0c;“数据二十条” 即《中共中央 国务院关于构建数据基础制度…...

架构14-资源与调度

零、文章目录 架构14-资源与调度 1、资源模型 &#xff08;1&#xff09;概述 在 Kubernetes 中&#xff0c;资源模型是一个非常重要的概念&#xff0c;它涉及如何管理和分配集群中的资源&#xff0c;以确保 Pod 能够在最合适的节点上运行。资源模型不仅包括物理资源&#…...

uni-app H5端使用注意事项 【跨端开发系列】

&#x1f517; uniapp 跨端开发系列文章&#xff1a;&#x1f380;&#x1f380;&#x1f380; uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…...

springboot407美发管理系统(论文+源码)_kaic

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装美发管理系统软件来发挥其高效地信息处理的作用&#xff0…...

Apache-HertzBeat 开源监控默认口令登录

0x01 产品描述: HertzBeat(赫兹跳动) 是一个开源实时监控系统,无需Agent,性能集群,兼容Prometheus,自定义监控和状态页构建能力。HertzBeat 的强大自定义,多类型支持,高性能,易扩展,希望能帮助用户快速构建自有监控系统。0x02 漏洞描述: HertzBeat(赫兹跳动) 开源实时…...

发送请求时遇到了数据库完整性约束错误 1048 Column ‘platform‘ cannot be null

可以这样解决 在 Vue 2 中封装接口请求时&#xff0c;确保每次请求都包含 platform Header 参数的最佳实践是通过创建一个全局的 Axios 实例&#xff0c;并为这个实例设置默认的 Header。这样可以确保所有通过该实例发送的请求都会自动包含 platform 参数。此外&#xff0c;你…...

Go快速开发框架集成Vue3漂亮的动态流程图编辑和动态流程展示插件

温馨提示&#xff1a;我们分享的文章是给需要的人&#xff0c;不需要的人请绕过&#xff0c;文明浏览&#xff0c;误恶语伤人&#xff01; 前言 为大家在开发流程相关业务时有个漂亮流程图展示&#xff0c;我们集成一个实用的流程图编辑器&#xff0c;让流程开发变得简单&…...

【SH】微信小程序调用EasyDL零门槛AI开发平台的图像分类研发笔记

文章目录 微信小程序字符串字符串模板字符串拼接 上传图片GET请求测试编写测试代码域名不合法问题 GET和POST请求测试 微信小程序字符串 字符串模板 这是ES6引入的特性&#xff0c;允许你通过反引号&#xff08;&#xff09;创建模板字符串&#xff0c;并在其中嵌入变量或表达…...

NanoLog起步笔记-6-StaticLogInfo

nonolog起步笔记-6-StaticLogInfo StaticLogInfo文件名和行号文件名和行号的传入log参数 RuntimeLogger::registerInvocationSitelogid为什么只能被赋一次值 reserveAlloc加入消息头finishAlloc返回 StaticLogInfo 写C语言编译前端时&#xff0c;给我印象深刻的一部分是&#…...

【OpenCV】视频录制

初始化一个视频写入对象&#xff0c;目的是将图像帧序列保存为视频文件。使用了OpenCV库中的cv2.VideoWriter类来创建这个对象&#xff0c;并且设置了视频的编码格式、帧率以及分辨率。 导入库 import cv2 import datetime cv2 是 OpenCV 库的 Python 接口&#xff0c;提供了…...

同城到家预约上门服务解决方案:家政预约同城服务小程序

### 系统架构"同城到家预约上门服务解决方案&#xff1a;PHP家政预约同城服务小程序"采用B/S架构&#xff0c;后端使用PHP语言开发&#xff0c;前端则基于微信小程序平台。系统分为用户端、服务端和后台管理端&#xff0c;各端相互依赖又相互独立&#xff0c;支持多种…...

linux-14 关于shell(十三)type,内置命令和外部命令

我们说一个命令&#xff0c;叫做type&#xff0c;先来看看type的效果&#xff0c;比如说我指定type后面这个命令叫cd&#xff0c;如下图&#xff0c; 你看它说什么&#xff1f;cd is a shell builtin&#xff0c;我再 type ls&#xff0c;看它会说什么&#xff1f;如下图&#…...

使用php生成、识别二维码

1、生成二维码 要求&#xff1a; # 详见&#xff1a;https://packagist.org/packages/bacon/bacon-qr-code php: ^8.1iconv Library imagick Library # 或者&#xff1a;GD library 下载&#xff1a; # 详见&#xff1a;https://packagist.org/packages/bacon/bacon-qr-cod…...

pytorch多GPU训练教程

pytorch多GPU训练教程 文章目录 pytorch多GPU训练教程1. Torch 的两种并行化模型封装1.1 DataParallel1.2 DistributedDataParallel 2. 多GPU训练的三种架构组织方式2.2 数据不拆分&#xff0c;模型拆分&#xff08;Model Parallelism&#xff09;2.3 数据拆分&#xff0c;模型…...

日拱一卒(12)——leetcode学习记录:2的幂

一、题目 判断一个整数n是否是2的幂次&#xff0c;是返回True&#xff0c;否返回False 二、分析 1. 递归法&#xff1a;如果n是0&#xff0c;返回False&#xff0c;如果n是1&#xff0c;返回True&#xff0c;其他情况&#xff0c;将n//2递归 2. 数学法&#xff1a;还是从数…...

非文件形式的内存动态函数库调用接口

使用memfd的系统调用接口将动态库加载到proc虚拟文件系统&#xff0c;提供的fd为进程持有的句柄&#xff0c;通过dlopen的path指向此句柄&#xff0c;即可实现非文件系统加载动态链接库。 文章目录 一、memfd_create二、dl_open三、示例参考 一、memfd_create 接口名称int mem…...

TimeXplusplus——提高时间序列数据的可解释性,避免琐解和分布偏移问题的深度学习可解释性的框架

摘要 论文地址&#xff1a;https://arxiv.org/abs/2405.09308 源码地址&#xff1a;https://github.com/zichuan-liu/timexplusplus 信号传输技术的优化对于推动光通信的发展至关重要。本文将详细探讨线路编码技术的目标及其实现方式。线路编码旨在提高带宽和功率效率&#xf…...

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项资源任务书样题②

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项资源任务书样题② 模块A 基础设施设置与安全加固(200分)A-1 登录安全加固&#xff08;Windows, Linux&#xff09;A-2 Nginx安全策略&#xff08;Linux&#xff09;A-3日志监控&#xff08;Windows&#xff09;A-4中间件…...

嵌入式蓝桥杯学习9 usart串口

复制一下之前ADC的工程&#xff0c;打开cubemx cubemx配置 1.在Connectivity中点击USART1 Mode&#xff08;模式&#xff09;:Asynchronous&#xff08;异步模式&#xff09; 2.将PA9设置为USART1_TX&#xff0c;PA10设置为USART1_RX。 3.配置Parameter Settings. Baud R…...

golang实现简单的redis服务4.0(持久化)

redis的持久化机制与实现原理RDB工作原理问题1:如果数量很大怎么办?问题2:子线程在持久化期间有新的数据写入会发生什么?如何保证数据一致性? AOF的原理如何解决aof文件越来越大的问题aof文件如何重写?aof如何恢复数据aof文件有问题(损坏了)恢复会发生什么?怎么办?aof有哪…...

安卓底层相机流的传输方式

这是安卓 相机流的定义 typedef enum {CAM_STREAMING_MODE_CONTINUOUS, /* continous streaming */CAM_STREAMING_MODE_BURST, /* burst streaming */CAM_STREAMING_MODE_BATCH, /* stream frames in batches */CAM_STREAMING_MODE_MAX} cam_streaming_mode_t; 在ca…...

【YashanDB知识库】使用c-调用yashandb odbc驱动执行SQL时报YAS-08008 not all variables bounded

本文内容来自YashanDB官网&#xff0c;原文内容请见 https://www.yashandb.com/newsinfo/7508307.html?templateId1718516 问题现象 某客户的应用(c# asp.net)在运行时报如下异常&#xff1a; 问题的风险及影响 客户的应用无法正常运行 问题影响的版本 所有的yashandb版本…...

SQL项目实战与综合应用——项目设计与需求分析

项目设计与需求分析是软件开发过程中的核心环节&#xff0c;尤其在涉及数据库的应用时&#xff0c;良好的设计将直接影响到项目的可扩展性、性能和维护性。本文将深入探讨数据库设计的最佳实践&#xff0c;结合 C 与 SQL 的实际应用场景&#xff0c;涵盖项目需求收集、数据库设…...