springboot系列--拦截器执行原理
一、拦截器核心概念
一、定义
拦截器(Interceptor)是框架级别的组件,用于在请求的不同阶段(如到达控制器之前(也就是接口)、处理完成之后)动态地拦截和处理 HTTP 请求。
二、使用场景
一、用户认证和授权
if (!isValidToken(request.getHeader("Authorization"))) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write("Unauthorized");return false;
}
二、请求日志记录
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {long endTime = System.currentTimeMillis();long executionTime = endTime - (long) request.getAttribute("startTime");System.out.println("URI: " + request.getRequestURI() + " | 耗时: " + executionTime + " ms");
}
三、性能监控
统计每个请求的执行时间并记录慢请求日志。
四、跨域处理
设置跨域响应头(更推荐用
CorsRegistry
实现)。
三、执行流程
preHandle
:请求到达控制器之前执行。- 控制器逻辑(也就是接口):拦截器放行后,执行目标控制器的方法。
postHandle
:控制器逻辑处理完成后(视图渲染前)执行。afterCompletion
:视图渲染完成后执行(或者每个拦截器执行出现异常后执行),用于资源清理或日志输出。
二、拦截器的实现与配置
一、创建拦截器
拦截器通过实现 HandlerInterceptor
接口来定义。该接口包含以下三个核心方法:
preHandle
在目标方法调用之前执行,用于权限验证或日志记录。
返回true
表示继续处理,返回false
表示中断请求。
postHandle
在目标方法执行之后,视图渲染之前执行。
适合处理返回数据或修改模型数据。
afterCompletion
在视图渲染完成后执行,用于资源清理或捕获异常。
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class LoggingInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle: 开始拦截请求");// 检查用户是否登录String token = request.getHeader("Authorization");if (token == null || !token.startsWith("Bearer ")) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);return false; // 拦截请求}return true; // 放行}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle: 请求处理完成");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion: 视图渲染完成或拦截器出现异常");}
}
二、注册拦截器
拦截器需要在配置类中注册,并指定拦截路径和排除路径。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggingInterceptor()).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/login", "/error", "/static/**"); // 排除的路径}
}
三、拦截器与过滤器的区别
四 、拦截器的高级用法
一、链式拦截器
可以注册多个拦截器,Spring 会按注册顺序依次执行。
在 preHandle
方法中,任一拦截器返回 false
都会中断后续处理。
registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new LoggingInterceptor()).addPathPatterns("/**");
执行顺序:
preHandle
:AuthInterceptor
->LoggingInterceptor
postHandle
:LoggingInterceptor
->AuthInterceptor
afterCompletion
:LoggingInterceptor
->AuthInterceptor
二、拦截器与异步请求
对于异步请求(如使用
@Async
),postHandle
可能不会被触发。如果需要确保拦截器对异步请求生效,可以使用AsyncHandlerInterceptor
接口。
import org.springframework.web.servlet.AsyncHandlerInterceptor;public class AsyncLoggingInterceptor implements AsyncHandlerInterceptor {// 同步和异步请求都可拦截
}
三、动态拦截路径
拦截器的路径规则可以通过配置文件或数据库动态加载。
@Value("${interceptor.paths}")
private List<String> paths;@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new DynamicPathInterceptor()).addPathPatterns(paths.toArray(new String[0]));
}
interceptor:paths:- /api/**- /admin/**
五、常见问题
一、preHandle
拦截中断后,如何返回自定义响应?
可以直接通过 HttpServletResponse
写入 JSON 或其他格式的响应:
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"error\":\"Unauthorized\"}");
return false;
二、拦截器的执行顺序与性能优化
- 尽量减少复杂计算或阻塞操作。
- 使用
excludePathPatterns
排除无需拦截的静态资源或公共接口。- 结合 AOP 实现增强功能
六、拦截器底层原
请求一进来都是通过前端控制器DispatcherServlet进行处理,然后处理器映射器找到具体的handler,在通过处理器适配器,适配到具体的handler中进行处理。
// 直接进入到DispatcherServlet这个类里面的这个方法protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// Determine handler for the current request. 这里就是获取具体的handler,也就是知道了具体的controller中的那个方法可以处理mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request. 这里就是获取处理器适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}// 这里就是处理拦截器的preHandle方法。如果返回为false,这里取反,就进入,然后直接退出。if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler. 这里就是之前研究过的去执行具体的handler,也就是具体的接口,nv就是执行完接口后的返回数据封装的ModelAndView对象mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);// 这里就是开始执行拦截器的postHandle方法mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and other scenarios.dispatchException = new NestedServletException("Handler dispatch failed", err);}// 这里就开始进行视图解析等各种操作processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {// 以上操作如果出现异常,都会执行拦截器的afterCompletion发明合法triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {// 以上操作如果出现异常,都会执行拦截器的afterCompletion发明合法triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}// HandlerExecutionChain类下的方法,这里会循环执行拦截器链中的preHandle方法,注意,这里是顺序执行,也就是从第一个开始执行boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {// 如果拦截器链中的方法preHandle,返回为false,进入这里执行拦截器中给的异常方法afterCompletion,然后返回false,中断循环,之后的拦截器都不执行了,如果为true,则执行下一个拦截器triggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;}// HandlerExecutionChain类下的方法,注意这里就是拦截器出现异常开始执行的方法,这里是倒序执行,也就是开始是先执行preHandle方法的拦截器,如果出现异常就会倒序执行// afterCompletion方法,也就是之前限制性preHandle方法的拦截器,变成了后执行afterCompletion方法。void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);try {interceptor.afterCompletion(request, response, this.handler, ex);}catch (Throwable ex2) {logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);}}}// HandlerExecutionChain类下的方法,这里执行完目标方法,也就是接口中的方法后,执行拦截器中的PostHandle方法,这个也是倒序执行void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)throws Exception {for (int i = this.interceptorList.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler, mv);}}// HandlerExecutionChain类下的方法,无论哪里处理出了异常,都会执行拦截器的AfterCompletion方法void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);try {interceptor.afterCompletion(request, response, this.handler, ex);}catch (Throwable ex2) {logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);}}}// DispatcherServlet类里面的方法,这里就开始进行视图解析等各种操作
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {boolean errorView = false;if (exception != null) {if (exception instanceof ModelAndViewDefiningException) {logger.debug("ModelAndViewDefiningException encountered", exception);mv = ((ModelAndViewDefiningException) exception).getModelAndView();}else {Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);mv = processHandlerException(request, response, handler, exception);errorView = (mv != null);}}// Did the handler return a view to render?if (mv != null && !mv.wasCleared()) {render(mv, request, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isTraceEnabled()) {logger.trace("No view rendering, null ModelAndView returned.");}}if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Concurrent handling started during a forwardreturn;}// 页面渲染完也会执行拦截器的AfterCompletion方法if (mappedHandler != null) {// Exception (if any) is already handled..mappedHandler.triggerAfterCompletion(request, response, null);}}
总结:
1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】
2、先来顺序执行 所有拦截器的 preHandle方法
- 1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
- 2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;
3、如果任何一个拦截器返回false。直接跳出不执行目标方法
4、所有拦截器都返回True。执行目标方法
5、倒序执行所有拦截器的postHandle方法。
6、前面的步骤有任何异常都会直接倒序触发 afterCompletion
7、页面成功渲染完成以后,也会倒序触发 afterCompletion
相关文章:
springboot系列--拦截器执行原理
一、拦截器核心概念 一、定义 拦截器(Interceptor)是框架级别的组件,用于在请求的不同阶段(如到达控制器之前(也就是接口)、处理完成之后)动态地拦截和处理 HTTP 请求。 二、使用场景 一、用户…...
数据可视化复习2-绘制折线图+条形图(叠加条形图,并列条形图,水平条形图)+ 饼状图 + 直方图
目录 目录 一、绘制折线图 1.使用pyplot 2.使用numpy 编辑 3.使用DataFrame 编辑 二、绘制条形图(柱状图) 1.简单条形图 2.绘制叠加条形图 3.绘制并列条形图 4.水平条形图 编辑 三、绘制饼状图 四、绘制散点图和直方图 1.散点图 2…...
STM32F10x 定时器
使用定时器实现:B5 E5的开关 添加相关的.h路径文件 添加相关的.c配置文件 led.h文件 用于声明LED函数 #ifndef __LED_H //没有定义__LED_H #define __LED_H //就定义__LED_H #define LED1_ON GPIO_ResetBits(GPIOB,GPIO_Pin_5) #defi…...
VBA技术资料MF230:展开所有折叠视图并恢复
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…...
【数据结构OJ】【图论】图综合练习--拓扑排序
题目描述 已知有向图,顶点从0开始编号,求它的求拓扑有序序列。 拓扑排序算法:给出有向图邻接矩阵 1.逐列扫描矩阵,找出入度为0且编号最小的顶点v 2.输出v,并标识v已访问 3.把矩阵第v行全清0 重复上述步骤࿰…...
网络安全防范
网络安全防范技术 所属课程网络攻防实践作业要求第六次作业 实践内容 学习总结 PDR,$$P^2$$DR安全模型。 防火墙(Firewall): 网络访问控制机制,布置在网际间通信的唯一通道上。 不足:无法防护内部威胁&…...
Linux nc 命令详解
简介 nc 全称 netcat,是一个在 Linux 中多功能的网络工具,通常用于通过 TCP 或 UDP 读取和写入网络连接,也能作为客户端或服务端用来 debug,测试,网络问题分析。 常用示例 检查端口是否是打开的 nc -zv <hostna…...
解决 Gradle 报错:`Plugin with id ‘maven‘ not found` 在 SDK 开发中的问题
在 SDK 开发过程中,使用 Gradle 构建和发布 SDK 是常见的任务。在将 SDK 发布为 AAR 或 JAR 包时,你可能会使用 apply plugin: maven 来发布到本地或远程的 Maven 仓库。但是,随着 Gradle 版本的更新,特别是从 Gradle 7 版本开始&…...
stm32cubemx+VSCODE+GCC+makefile 开发环境搭建
title: stm32cubemxVSCODEGCCmakefile 开发环境搭建 tags: FreertosHalstm32cubeMx 文章目录 内容往期内容导航第一步准备环境vscode 插件插件配置点灯 内容 往期内容导航 第一步准备环境 STM32CubeMXVSCODEMinGWOpenOcdarm-none-eabi-gcc 然后把上面下载的软件 3 4 5 bin 文…...
postgresql|数据库开发|python的psycopg2库按指定顺序批量执行SQL文件(可离线化部署)
一、 psycopg2简介 psycopg2库是python的一个可直接操作postgresql数据库的类库,是一个用于Python编程语言的PostgreSQL数据库适配器。它允许开发人员使用Python语言与PostgreSQL数据库进行交互和操作,不同于java,需要专用的一个驱动&#…...
学习ASP.NET Core的身份认证(基于Cookie的身份认证3)
用户通过验证后调用HttpContext.SignInAsync函数将用户的身份信息保存在认证Cookie中,以便后续的请求可以验证用户的身份,该函数原型如下所示,其中properties参数的主要属性已在前篇文章中学习,本文学习scheme和principal的意义及用法。 public static …...
Java 中的 HashMap 原理详解:底层结构与实现机制
HashMap 是 Java 中最常用的数据结构之一,它以其高效的存取速度在众多应用场景中被广泛使用。理解 HashMap 的底层实现原理,对提升开发效率、优化性能以及编写高效的代码都至关重要。本文将深入探讨 HashMap 的数据结构、存储机制、解决冲突的策略、扩容…...
数据库MYSQL——表的设计
文章目录 前言三大范式:几种实体间的关系:一对一关系:一对多关系:多对多关系: 前言 之前的博客中我们讲解的是关于数据库的增删改查与约束的基本操作, 是在已经创建数据库,表之上的操作。 在实…...
CUDA补充笔记
文章目录 一、不同核函数前缀二、指定kernel要执行的线程数量三、线程需要两个内置坐标变量来唯一标识线程四、不是blocksize越大越好,上限一般是1024个blocksize 一、不同核函数前缀 二、指定kernel要执行的线程数量 总共需要线程数是: 1 * N N个线程…...
OSI七层模型和TCP/IP五层模型详细介绍
这里写目录标题 一.OSI含义二.OSI七层模型1.应用层2.表示层3.会话层4.传输层5.网络层6.数据链路层7.物理层 TCP/IP五层协议1.应用层2.运输层运行在TCP上的协议运行在UDP上的协议 3.网络层IP协议配套使用的协议 4.数据链路层 四.网络协议分层的好处 一.OSI含义 OSI即是开放式通…...
mac安装Pytest、Allure、brew
安装环境 安装pytest 命令 pip3 install pytest 安装allure 命令:brew install allure 好吧 那我们在安装allure之前 我们先安装brew 安装brew 去了官网复制了命令 还是无法下载 如果你们也和我一样可以用这个方法哦 使用国内的代码仓库来执行brew的安装脚本…...
Linux/Windows/OSX 上面应用程序重新启动运行。
1、Linux/OSX 上面重新运行程序,直接使用 execvp 函数就可以了,把main 函数传递来的 argv 二维数组(命令行参数)传进去就可以,注意不要在 fork 出来的子进程搞。 2、Windows 平台可以通过 CreateProcess 函数来创建新的…...
自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例
Kafka:分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析:从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析:…...
Odoo :免费且开源的农牧行业ERP管理系统
文 / 开源智造Odoo亚太金牌服务 引言 提供农牧企业数字化、智能化、无人化产品服务及全产业链高度协同的一体化解决方案,提升企业智慧种养、成本领先、产业互联的核心竞争力。 行业典型痛点 一、成本管理粗放,效率低、管控弱 产品研发过程缺少体系化…...
AI的自我陷阱:大型神经网络训练中的模型崩溃现象
10月7日,发布在arxiv上的一篇名为Strong Model Collapse的论文,由Meta 、纽约大学和加州大学洛杉矶分校的研究人员共同发表的研究表明在训练大型神经网络(如 ChatGPT 和 Llama)时,由于训练语料库中包含合成数据而导致的…...
Python(下载安装)
简介 开发工具:pycharm, VS Code 1. 下载(解释器程序) Download Python | Python.org 2. 安装(解释器程序) 双击下载后的exe文件 查看版本:python(并可以执行python代码) 3. 下载…...
记录一种在内核空间向用户空间通知中断的方法
记录一种在内核空间向用户空间通知中断的方法 0.前言1.代码实现1)内核设备驱动实现2)消息通知实现3)测试程序 2.解析 参考文章:Linux驱动实践:中断处理函数如何【发送信号】给应用层? 0.前言 最近在项目中遇到一个需求,需要将一个…...
Apache Maven 标准文件目录布局
Apache Maven 采用了一套标准的目录布局来组织项目文件。这种布局提供了一种结构化和一致的方式来管理项目资源,使得开发者更容易导航和维护项目。理解和使用标准目录布局对于有效的Maven项目管理至关重要。本文将探讨Maven标准目录布局的关键组成部分,并…...
【vim】使用 gn 组合命令实现搜索选中功能
gn是Vim 7.4新增的一个操作(motion),作用是跳到并选中下一个搜索匹配项。 具体说,Vim里执行搜索后,执行n操作只会跳转到下一个匹配项,而不选中它。但是我们往往需要对匹配项执行一些修改操作,例…...
解决登录Google账号遇到手机上Google账号无法验证的问题
文章目录 场景小插曲解决方案总结 场景 Google账号在新的设备上登录的时候,会要求在手机的Google上进行确认验证,而如果没有安装Google play就可能出现像我一样没有任何弹框,无法实现验证 小插曲 去年,我在笔记本上登录了Googl…...
基于YOLOv10深度学习的公共安全持刀行为检测系统研究与实现(PyQt5界面+数据集+训练代码)
随着社会的不断进步和城市化进程的加快,人口密度的增加和社会结构的复杂化使得公共安全问题日益凸显。近年来,各类公共安全事件频发,其中持刀行为作为一种典型的暴力行为,已成为威胁公共安全的严重因素之一。这种行为在公共场所发…...
HP6心率血压传感器
目录 一、介绍 1、工作原理概述 2、具体实现步骤 二、HP6的通信及配置 1、通信接口 2、器件地址/命令 3、校验 三、程序设计 ①IIC通信相关基础函数 ②HP6相关基础函数 一、介绍 HP6心率血压传感器的原理主要基于光电容积脉搏波描记法(PPG)&…...
深入理解 JVM 中的 G1 垃圾收集器原理、算法、过程和参数配置
引言 Java 虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称 GC)是自动内存管理的核心部分。G1(Garbage-First)垃圾收集器是 Oracle 在 JDK 7u4 版本中引入的一种新型垃圾收集器,…...
细说敏捷:敏捷四会之standup meeting
上一篇文章中,我们讨论了 敏捷四会 中 冲刺计划会 的实施要点,本篇我们继续分享敏捷四会中实施最频繁,团队最容易实施但往往也最容易走形的第二个会议:每日站会 关于每日站会的误区 站会是一个比较有标志性的仪式活动࿰…...
MySQL系列之身份鉴别(安全)
导览 前言Q:如何保障MySQL数据库身份鉴别的有效性一、有效性检查1. 用户唯一2. 启用密码验证3. 是否存在空口令用户4. 是否启用口令复杂度校验5. 是否设置口令的有效期6. 是否限制登录失败尝试次数7. 是否设置(超过尝试次数)锁定的最小时长8.…...
vue3封装Element Plus table表格组件
支持绝大部分Element Plus原有设置属性,支持分页,支持动态适配高度 效果展示 组件代码: <template><div class"table-wrap" ref"tableWrap"><el-tableclass"w100 h100":data"tableInfo.…...
SFP+光模块介绍
SFP光模块介绍 1 SFP光模块简介(Small Form -Factor Pluggable)2 光模块管脚定义 1 SFP光模块简介(Small Form -Factor Pluggable) 光模块(Optical Module)由光电子器件、功能电路和光接口等组成,光电子器件包括激光发射器(Laser Transmitte…...
神经网络的初始化
目录 为什么需要初始化? 初始化的常用方法: 是否必须初始化? 初始化神经网络中的权重和偏置是深度学习模型训练中非常重要的一步,虽然在某些情况下不进行初始化也能训练出模型,但正确的初始化方法能够显著提高训练效…...
数据集搜集器0.01
我们使用Python的Tkinter库来创建GUI界面,并使用requests库来从360百科获取数据。下面是一个完整的示例代码,它包括了一个简单的GUI界面,用户可以输入问题,点击按钮后会从360百科获取相关信息,并显示在同一个Text组件中…...
【Lucene】搜索引擎和文档相关性评分 BM25 算法的工作原理
BM25 算法的工作原理: 什么是 BM25 算法? BM25 是一种流行的文本检索算法,广泛用于搜索引擎和文档相关性评分。它基于概率检索模型,旨在评估查询和文档之间的相关性。 核心公式 BM25 的公式如下: score ( D , Q ) …...
嵌入式Linux——文件类型
目录 普通文件 目录文件 目录文件的权限与管理 字符设备文件和块设备文件 符号链接文件 查看符号链接 删除符号链接 修改符号链接 管道文件 匿名管道(Anonymous Pipe) 匿名管道的特点: 使用示例: 命名管道(…...
ES6 模块化语法
目录 ES6 模块化语法 分别暴露 统一暴露 编辑 默认暴露 ES6 模块化引入方式 ES6 模块化语法 模块功能主要由两个命令构成:export 和 import。 ⚫ export 命令用于规定模块的对外接口(哪些数据需要暴露,就在数据前面加上关键字即可…...
Gradio学习笔记记录
安装指令:pip install gradio方法介绍 Interface》用于构建一些简单的页面,可以直接用这个指令搞定 形式》接收三个参数分别为处理函数、输入、输出三部分,呈现一般左/上为输入,右或下为输出 fn:将用户界面 ࿰…...
Node.js的下载与安装(支持各种新旧版本)
目录 1、node官网 2、node软件下载 3、软件安装(完整版) 1、node官网 Node.js — Download Node.jshttps://nodejs.org/en/download/package-manager 2、node软件下载 按照下图进行选择node版本(真心推荐16/18,而是尽量是LTS…...
数据库和缓存的数据一致性 -20241124
问题描述 一致性 缓存中有数据,缓存的数据值数据库中的值缓存中本没有数据,数据库中的值最新值(有请求查询数据库时,会将数据写入缓存,则变为上面的“一致”状态) “数据不一致”: 缓存的数据值…...
【计算机网络】多路转接之select
系统提供select()来实现多路转接 IO 等 拷贝 -> select()只负责等待,可以一次等待多个fd select()本身没有数据拷贝的能力,拷贝要read()/write()来完成 一、select的使用 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exc…...
Linux命令思维导图
看到一个很不错的Linux命令思维导图,用机器翻译了一下,建议收藏备用。 附上英文版:...
自然语言处理(词嵌入和词向量的使用)
一、实验目的 1.了解词嵌入和词向量的基本概念及其在自然语言处理中的应用。 2.掌握使用One-Hot编码和Word2Vec模型构建词向量的方法。 3.掌握Doc2Vec模型构建文档向量的方法以及如何计算文档向量之间的相似度。 二、实验内容 (1)使用One-Hot编码构…...
量子感知机
神经网络类似于人类大脑,是模拟生物神经网络进行信息处理的一种数学模型。它能解决分类、回归等问题,是机器学习的重要组成部分。量子神经网络是将量子理论与神经网络相结合而产生的一种新型计算模式。1995年美国路易斯安那州立大学KAK教授首次提出了量子…...
[HarmonyOS] 解决HMRouter路由地址无法抽取的问题
解决HMRouter路由地址无法抽取的问题 背景 最近开始学习HarmonyOS开发,搭建项目的时候采用了 HMRouter 路由框架,在项目里使用到路由跳转,官方链接在这: https://gitee.com/hadss/hmrouter/blob/master/HMRouterLibrary/README…...
七天掌握SQL--->第四天:事务处理与并发控制
# 7天掌握SQL - 第四天:事务处理与并发控制 ## 目标 - 学习事务处理的基本概念,如ACID特性。 - 掌握并发控制的方法,如锁机制、事务隔离级别等。 - 通过实际案例练习事务处理和并发控制。 ## 1. 事务处理的基本概念 事务处理是数据库管理系…...
Docker学习笔记整理
这周不知道写点啥内容做个分享,但还是秉持学会分享的精神,粗略放一些Docker相关的问题和解答吧,后面有机会再补补再深挖深挖o(>﹏<)o 1. 容器VS虚拟机 虚拟机是一种带环境安装的解决方案(资源完全隔离),有以下缺…...
PIMPL模式和D指针
一、PIMPL模式概念: Pimpl(pointer to implementation, 指向实现的指针)是一种用来对“类的接口与实现”进行解耦合的方法。就是将真正的实现细节的Implementor从类定义的头文件中分离出去,公有类通过一个私有指针指向隐藏的实现类…...
Linux入门系列--文件与目录
一、介绍 在Linux中,有着一句话,叫做:一切皆文件。也就是任何东西都是以文件的形式存储的。 目录结构 bin:全程binary,含义是二进制。该目录中存储的都是一些二进制文件。我们学过C/C,其实也都知道机器能…...
论文阅读——Intrusion detection systems using longshort‑term memory (LSTM)
一.基本信息 论文名称:Intrusion detection systems using longshort‑term memory (LSTM) 中文翻译:基于长短期记忆(LSTM)的入侵检测系统 DOI:10.1186/s40537-021-00448-4 作者:FatimaEzzahra Laghrissi1* , Samira Douzi2*, Kha…...