SpringMVC请求执行流程源码解析
文章目录
- 0.SpringMVC九大内置组件
- 1.processRequest方法
- 1.请求先到service方法
- 2.然后不管是get还是post都会跳转到processRequest方法统一处理
- 2.doService方法
- 3.doDispatch方法
- 1.代码
- 2.checkMultipart
- 4.核心流程
0.SpringMVC九大内置组件
1.processRequest方法
1.请求先到service方法
org.springframework.web.servlet.FrameworkServlet#service
2.然后不管是get还是post都会跳转到processRequest方法统一处理
org.springframework.web.servlet.FrameworkServlet#processRequest
/*** 处理 HTTP 请求的核心方法,负责执行 Spring MVC 的核心请求处理流程。* 该方法由 FrameworkServlet 调用,用于请求的前后处理、异常捕获、异步支持等。** @param request HttpServletRequest 对象,表示客户端的 HTTP 请求* @param response HttpServletResponse 对象,表示服务器返回的 HTTP 响应* @throws ServletException 处理 Servlet 相关异常* @throws IOException 处理 I/O 相关异常*/
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 记录请求处理的开始时间(用于统计请求耗时)long startTime = System.currentTimeMillis();Throwable failureCause = null; // 记录请求处理过程中发生的异常// 1. 获取当前线程的 LocaleContext(国际化上下文)LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);// 2. 获取当前线程的 RequestAttributes(SpringMVC 请求属性)RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);// 3. 获取 WebAsyncManager(用于处理异步请求)WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());// 4. 初始化线程变量(将请求作用域信息存入 ThreadLocal)initContextHolders(request, localeContext, requestAttributes);try {// 5. 调用 doService 进行实际的请求处理(由子类实现,比如 DispatcherServlet)doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex; // 记录异常throw ex; // 继续向上抛出异常}catch (Throwable ex) {failureCause = ex; // 记录异常throw new NestedServletException("Request processing failed", ex);}finally {// 6. 还原之前的 LocaleContext 和 RequestAttributes,防止线程污染resetContextHolders(request, previousLocaleContext, previousAttributes);// 7. 标记请求处理完成,通知所有监听器if (requestAttributes != null) {requestAttributes.requestCompleted();}// 8. 记录请求处理结果(用于日志记录)logResult(request, response, failureCause, asyncManager);// 9. 发布请求处理完成事件(Spring 事件机制)publishRequestHandledEvent(request, response, startTime, failureCause);}
}
2.doService方法
org.springframework.web.servlet.DispatcherServlet#doService
/*** 处理 HTTP 请求的核心方法,负责调度 SpringMVC 请求,并将请求转发给 `doDispatch()` 进行处理。* 该方法由 `FrameworkServlet` 调用,主要职责包括:* 1. 记录请求日志* 2. 处理包含(include)请求* 3. 将 SpringMVC 组件(如 `WebApplicationContext`、`LocaleResolver`)绑定到 `request`* 4. 处理 FlashMap(用于跨请求传递参数)* 5. 解析 `RequestPath`* 6. 调用 `doDispatch()` 进行请求分发** @param request HttpServletRequest 对象,表示客户端的 HTTP 请求* @param response HttpServletResponse 对象,表示服务器返回的 HTTP 响应* @throws Exception 可能抛出的异常*/
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {// 1. 记录请求日志(用于调试)logRequest(request);// 2. 处理包含(include)请求(一般不用)// 如果请求是 include(如 JSP 的 <jsp:include>),需要保存原始的请求属性Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap<>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();// 只有在 cleanupAfterInclude 为 true 或者 以 `org.springframework.` 开头的属性才会保存if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// 3. 将 SpringMVC 相关对象存入 `request`,供 Controller 和 View 使用request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); // 绑定 WebApplicationContextrequest.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); // 绑定 LocaleResolverrequest.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); // 绑定 ThemeResolverrequest.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); // 绑定 ThemeSource(主题源)// 4. 处理 FlashMap(用于跨请求数据传输,方便重定向时传递参数)if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {// 绑定输入 FlashMap,防止多次修改request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}// 绑定输出 FlashMap(用于存储新传递的数据)request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}// 5. 解析 `RequestPath`RequestPath previousRequestPath = null;if (this.parseRequestPath) {// 先保存原始的 RequestPath(如果有的话)previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);// 解析并缓存 RequestPathServletRequestPathUtils.parseAndCache(request);}try {// 6. 处理请求:调用 `doDispatch()` 进行请求分发doDispatch(request, response);}finally {// 7. 如果请求是 include,并且不是异步请求,则恢复原始请求属性if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}// 8. 如果解析了 `RequestPath`,则恢复之前的路径信息if (this.parseRequestPath) {ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);}}
}
3.doDispatch方法
1.代码
/*** 执行请求分发,调用对应的 `Handler` 处理 HTTP 请求。* <p>主要流程:* 1. 确定请求的处理器(Handler)和处理器适配器(HandlerAdapter)* 2. 处理 `Last-Modified` 头,提高 GET 请求的缓存命中率* 3. 执行拦截器 `preHandle()`* 4. 调用 `HandlerAdapter.handle()` 方法,执行控制器(Controller)* 5. 处理 `ModelAndView`,渲染视图* 6. 处理异常* 7. 执行拦截器 `postHandle()` 和 `afterCompletion()`* 8. 处理异步请求** @param request 当前 HTTP 请求* @param response 当前 HTTP 响应* @throws Exception 处理过程中可能抛出的异常*/
@SuppressWarnings("deprecation")
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request; // 处理后的请求对象HandlerExecutionChain mappedHandler = null; // 处理器链(包含处理器 + 拦截器)boolean multipartRequestParsed = false; // 是否解析了 multipart 请求(是否是上传请求)// 获取 WebAsyncManager(用于管理异步请求)WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null; // 视图模型Exception dispatchException = null; // 处理过程中可能抛出的异常try {// 1. 检查请求是否为 Multipart 类型(如文件上传),并进行解析processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// 2. 通过 `HandlerMapping` 获取当前请求对应的 `HandlerExecutionChain`mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response); // 404 处理return;}// 3. 通过 `HandlerAdapter` 获取支持该处理器的适配器(SpringMVC 允许不同的控制器风格)HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 4. 处理 HTTP `Last-Modified` 头,提高 GET 请求的缓存命中率String method = request.getMethod();boolean isGet = HttpMethod.GET.matches(method);if (isGet || HttpMethod.HEAD.matches(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return; // 直接返回 304 Not Modified}}// 5. 执行拦截器 `preHandle()`,如果返回 false,直接终止请求if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 6. 调用 `HandlerAdapter.handle()`,执行 Controller 方法mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 7. 检查是否为异步请求,如果是,则不继续执行后续流程if (asyncManager.isConcurrentHandlingStarted()) {return;}// 8. 处理默认视图名称applyDefaultViewName(processedRequest, mv);// 9. 执行拦截器 `postHandle()`,此时 `ModelAndView` 还未渲染mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// 处理 `Handler` 方法中抛出的 `Error`dispatchException = new NestedServletException("Handler dispatch failed", err);}// 10. 处理请求结果,包括渲染视图和异常处理processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {// 11. 触发 `afterCompletion()` 方法,保证拦截器总能执行triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// 12. 如果请求是异步的,则调用拦截器的 `applyAfterConcurrentHandlingStarted()`if (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// 13. 清理 multipart 请求的资源if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}
}
2.checkMultipart
/*** 检查当前请求是否是 multipart(多部分)请求,并进行解析。* <p>如果请求是 multipart 类型(如文件上传),则使用 `MultipartResolver` 进行解析,* 并将请求转换为 `MultipartHttpServletRequest`,否则返回原始请求。** <p>主要处理逻辑:* 1. **检查是否配置了 `MultipartResolver`*** 2. **检查请求是否是 multipart 类型*** 3. **如果请求已经被解析过,则直接返回*** 4. **如果解析失败过,则跳过重新解析*** 5. **尝试解析 multipart 请求*** 6. **异常处理**** @param request 当前 HTTP 请求* @return 处理后的请求(如果是 multipart,则返回 `MultipartHttpServletRequest`,否则返回原始请求)* @throws MultipartException 如果解析 multipart 失败,则抛出异常* @see MultipartResolver#resolveMultipart*/
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {// 1. 判断是否配置了 `MultipartResolver`,并且请求是否为 multipart 类型if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {// 2. 如果请求已经是 `MultipartHttpServletRequest`,说明已经解析过,直接返回if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {if (DispatcherType.REQUEST.equals(request.getDispatcherType())) {logger.trace("Request already resolved to MultipartHttpServletRequest, e.g. by MultipartFilter");}}// 3. 如果当前请求之前解析 multipart 失败,则跳过重新解析else if (hasMultipartException(request)) {logger.debug("Multipart resolution previously failed for current request - " +"skipping re-resolution for undisturbed error rendering");}// 4. 尝试解析 multipart 请求else {try {return this.multipartResolver.resolveMultipart(request);}catch (MultipartException ex) {// 5. 如果请求中已经存在 `ERROR_EXCEPTION_ATTRIBUTE`,说明是错误请求,记录日志后继续处理if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) {logger.debug("Multipart resolution failed for error dispatch", ex);// 继续使用原始 request 进行处理}else {// 6. 解析失败,抛出异常throw ex;}}}}// 7. 如果请求不是 multipart,或解析失败,则返回原始请求return request;
}
4.核心流程
相关文章:
SpringMVC请求执行流程源码解析
文章目录 0.SpringMVC九大内置组件1.processRequest方法1.请求先到service方法2.然后不管是get还是post都会跳转到processRequest方法统一处理 2.doService方法3.doDispatch方法1.代码2.checkMultipart 4.核心流程 0.SpringMVC九大内置组件 1.processRequest方法 1.请求先到se…...
LabVIEW与小众设备集成
在LabVIEW开发中,当面临控制如布鲁克OPUS红外光谱仪这类小众专业设备的需求,而厂家虽然提供了配套软件,但由于系统中还需要控制其他设备且不能使用厂商的软件时,必须依赖特定方法通过LabVIEW实现设备的控制。开发过程中࿰…...
docker-compose暴露端口,但其他主机无法访问问题。
问题描述:docker-compose暴露端口,但其他主机无法访问问题。 排障思路: 执行命令:ss -antlp | grep 80,发现端口正常监听0.0.0.0:80(ps:如果是127.0.0.1:80则只能本机访问同区域网段服务器执行…...
【MySQL】 基本查询(上)
欢迎拜访:雾里看山-CSDN博客 本篇主题:【MySQL】 基本查询(上) 发布时间:2025.2.14 隶属专栏:MySQL CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除) 目录 Create基…...
python 爬虫教程 0 基础入门 一份较为全面的爬虫python学习方向
文章目录 前言一、Python 爬虫简介二、环境搭建1. 下载 Python2. 安装 Python3. 安装必要的库 三、一个简单的爬虫示例四、应对网站反爬机制五、深入学习方向 前言 以下是一份较为全面的 Python 爬虫教程,涵盖基础知识、环境搭建、简单示例、反爬应对及深入学习方向…...
总结:使用JDK原生HttpsURLConnection,封装HttpsUtil工具类,加载自定义证书验证,忽略ssl证书验证
总结:使用JDK原生HttpsURLConnection,封装HttpsUtil工具类,加载自定义证书验证,忽略ssl证书验证 一HttpsUtil工具类二SSLUtil工具类 一HttpsUtil工具类 package com.example.util;import javax.net.ssl.HttpsURLConnection; impo…...
你认为如何理解“约定大于配置”?
SpringBoot的“约定大于配置”(Convention Over Configuration)是一种核心理念,旨在简化开发过程,减少开发人员在配置上的繁琐工作。以下是对其含义的详细介绍: 一、定义与目的 定义:约定优于配置&#x…...
Linux 基础IO——重定向和缓冲区
目录 一、重定向 1、重定向的本质 2、使用 dup2 系统调用 (1)输出重定向 (2)追加重定向 (3) 输入重定向 二、缓冲区 1.理解缓冲区 2.缓冲区刷新问题 3.为什么要有缓冲区? 4.这个缓冲区在哪里ÿ…...
基于若依开发的工程项目管系统开源免费,用于工程项目投标、进度及成本管理的OA 办公开源系统,非常出色!
一、简介 今天给大家推荐一个基于 RuoYi-Flowable-Plus 框架二次开发的开源工程项目管理系统,专为工程项目的投标管理、项目进度控制、成本管理以及 OA 办公需求设计。 该项目结合了 Spring Boot、Mybatis、Vue 和 ElementUI 等技术栈,提供了丰富的功能…...
华为云之CodeArts IDE的使用体验
一、CodeArts IDE介绍 1.1 CodeArts IDE简介 CodeArts IDE定位华为云开发者桌面,是利用华为自研IDE内核技术,面向华为云开发者提供的智能化可扩展桌面集成开发环境(IDE),结合华为云行业和产业开发套件,实现…...
DeepSeek-VL2 环境配置与使用指南
DeepSeek-VL2 环境配置与使用指南 DeepSeek-VL2 是由 DeepSeek 公司开发的一种高性能视觉-语言模型(VLM)。它是 DeepSeek 系列多模态模型中的一个版本,专注于提升图像和文本之间的交互能力。 本文将详细介绍如何配置 DeepSeek-VL2 的运行环…...
超纯水设备的智能化控制系统为用户带来安全简便的操作体验
随着信息技术的发展,智能化已经成为工业装备的重要发展方向之一。超纯水设备在这方面也走在了前列,配备了高性能的PLC控制系统及人机交互界面,实现了全方位的智能监控和自动化操作。本文将重点介绍该设备的智能化控制系统,探讨它如…...
若依系统环境搭建记录
开源若依系统网上资料也很全的,本篇博文记录下自己搭建环境过程中遇到的一些问题。 配置Maven和编辑器选择 我懒得配置Eclipse了,直接用vscode作为编辑器,后面构建运行都用命令行。 配置数据库连接 按照mysql5.7按网上教程即可࿱…...
基于Docker-compose的禅道部署实践:自建MySQL与Redis集成及故障排查指南
基于Docker-compose的禅道部署实践:自建MySQL与Redis集成及故障排查指南 禅道镜像版本:easysoft/zentao:21.4 Redis版本:redis:6.2.0 Mysql版本:mysql:8.0.35 文章目录 **基于Docker-compose的禅道部署实践:自建MySQL与…...
为AI聊天工具添加一个知识系统 之102 详细设计之43 自性三藏 之3 祖传代码
本文要点 法宝和三藏 总括如下: 三藏[经/律/论] 法宝:法阵/法轮/法力(三“件” 证件 / 表件 / 物件 ,分别对应三藏:论藏/律藏/经藏 --反序)。“法宝”演示了 发轮轮转的法阵中物件具有的法力。 这里的“…...
fork: retry: No child processes-linux18
根据错误信息 fork: retry: Resource temporarily unavailable 和 sh: fork: retry: No child processes,这通常是因为系统资源不足(例如可用的进程数、内存或 CPU 限制)导致的。为了解决这个问题,您可以尝试以下几种方法…...
渗透测试--文件包含漏洞
文件包含漏洞 前言 《Web安全实战》系列集合了WEB类常见的各种漏洞,笔者根据自己在Web安全领域中学习和工作的经验,对漏洞原理和漏洞利用面进行了总结分析,致力于漏洞准确性、丰富性,希望对WEB安全工作者、WEB安全学习者能有所帮助…...
【物联网】电子电路基础知识
文章目录 一、基本元器件1. 电阻2. 电容3. 电感4. 二极管(1)符号(2)特性(3)实例分析5. 三极管(1)符号(2)开关特性(3)实例6. MOS管(产效应管)(1)符号(2)MOS管极性判定(3)MOS管作为开关(4)MOS管vs三极管7. 门电路(1)与门(2)或门(3)非门二、常用元器件…...
vue学习10
1.GPT和Copilot Copilot Tab接受 删除键,不接受 ctrlenter更多方案 更适合的是修改方向 const submitForm async () > {//等待校验结果await formRef.value.validate()//提交修改await userUpdateInfoService(form.value)//通知user模块,进行数据更…...
【C语言】C语言 停车场管理系统的设计与实现(源码)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 系列文章目录 目录 系列文章目录一、设计要求二、设…...
LeetCodehot100 力扣热题100 二叉树展开为链表
代码思路 目标: 将二叉树展平(flatten)为一个单链表。展平后的链表应该按照前序遍历的顺序排列节点,即: • 节点的左子树指针设置为 nullptr。 • 节点的右子树指针指向下一个节点。 代码注释及思路 class Solution…...
备战蓝桥杯 Day1 回顾语言基础
开启蓝桥杯刷题之路 Day1 回顾语言基础 1.配置dev 工具->编译选项->勾选编译时加入以下命令->设定编译器配置(release和debug)都要-> -stdc11 ->代码生成/优化->代码生成/优化->语言标准(-std)->ISO C11 ->代码警告->显示最多警告信息(-Wall)…...
基于Ceedling的嵌入式软件单元测试
Ceedling 如果你使用 Ceedling(一个针对 C 代码单元测试的构建管理器),可以更方便地管理测试。Ceedling 会自动处理 Unity 和 CMock 的集成,无需手动编写 Makefile。 1.环境搭建 1.1 Ruby环境 sudo apt-get install ruby1.2 安…...
聊一聊FutureTask源码中体现的“自旋锁”思想
前言 这篇文章记录了笔者自己对FutureTask的部分源码设计的思考与心得,属于笔者自己的观点,若有哪位热爱源码研究的同仁觉得我说的不对,欢迎批评指正。 提示:在阅读之前必须对FutureTask的源码和实现原理有一定的了解。本文要聊…...
自有证书的rancher集群使用rke部署k8s集群异常
rancher使用自签域名,或者商业证书容易踩到的坑。 最开始的报错: docker logs kubelet‘s id E0214 13:04:14.590268 9614 pod_workers.go:1300] "Error syncing pod, skipping" err"failed to \"StartContainer\" for …...
LabVIEW外腔二极管激光器稳频实验
本项目利用LabVIEW软件开发了一个用于外腔二极管激光器稳频实验的系统。系统能够实现激光器频率的稳定控制和实时监测,为激光实验提供了重要支持。 项目背景: 系统解决了外腔二极管激光器频率不稳定的问题,以满足对激光器频率稳定性要求较高…...
使用docker compose启动postgres并设置时区
设置PostGres时区 方法 1: 使用 POSTGRES_INITDB_ARGS 设置时区方法 2: 使用初始化脚本设置时区创建 init-user-db.sql更新 docker-compose.yml 启动服务 要在启动 PostgreSQL 数据库时设置时区,可以通过在 docker-compose.yml 文件中添加环境变量或通过配置文件来实…...
杜绝遛狗不牵绳,AI技术助力智慧城市宠物管理
在我们的生活中,宠物扮演着越来越重要的角色。然而,随着养宠人数的增加,一系列问题也随之而来,如烈性犬伤人、遛狗不牵绳、流浪犬泛滥等。这些问题不仅影响了社会秩序,也给宠物本身带来了安全隐患。幸运的是࿰…...
【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第二十节】
ISO 14229-1:2023 UDS诊断服务测试用例全解析(WriteMemoryByAddress_0x3D服务) 作者:车端域控测试工程师 更新日期:2025年02月14日 关键词:UDS协议、0x3D服务、内存写入、ISO 14229-1:2023、ECU测试 一、服务功能概述…...
[npm install 报错] Verion 9 of Highlight.js has reached EOL
1、在项目中执行npm install 报错 Verion 9 of Highlight.js has reached EOL,如下图: 2、报错原因 Highlight.js 不再支持10以前的版本,需下载10及之后的版本 3、解决办法 打开项目中的package.json文件,将highlight.js的版本修改为:10.7.2,删除node…...
Flutter Gradle 命令式插件正式移除,你迁移旧版 Gradle 配置了吗?
在 Flutter 3.29 版本里官方正式移除了 Flutter Gradle Apply 插件,其实该插件自 3.19 起已被弃用,同时 Flutter 团队后续也打算把 Flutter Gradle 从 Groovy 转换为 Kotlin,并将其迁移到使用 AGP(Android Gradle Pluginÿ…...
CCF-GESP 等级考试 2024年9月认证C++二级真题解析
2024年9月真题 一、单选题(每题2分,共30分) 正确答案:A 考察知识点:计算机存储 解析:磁心存储元件是早期计算机中用于存储数据的部件,它和现代计算机中的内存功能类似,都是用于临时…...
CubeMX配置STM32L071KZT6
明确需要配置的项 下面是工作中遇到某个项目提炼出来的的功能需求。其中MCU选用STM32L071KZT6。 名称 标识 IO功能 对应引脚 备注 蜂鸣器 BUZZER 开关量输出 PA2 指示灯 LED-R PA15 LED-G PA12 LED-Y PA11 按键 KEY-1 开关量输入 PB5 外…...
RadASM环境,win32汇编入门教程之二
;win32汇编环境,RadAsm入门教程之二 ;前面我们已经学了教程一,生成了第一个软件。那么让我们继续我们的学习旅程。本教程讲解一下基本窗口模版的原理。让我们打开RadASM后,双击右侧的ABC.Asm文件,一点点研究。 ;首先,我…...
mysql开启gtid并配置主从
默认主从都开启了bin log. 1.主从都在/etc/my.cnf中加入并重启服务 gtid_mode ON enforce_gtid_consistency ON 2.在主库创建用户并授权 create user slave identified with mysql_native_password by 123456 mysql>GRANT REPLICATION SLAVE ON *.* to slave% identified…...
RAG科普文!检索增强生成的技术全景解析
RAG 相关技术的八个主题:https://pub.towardsai.net/a-taxonomy-of-retrieval-augmented-generation-a39eb2c4e2ab 增强生成 (RAG) 是塑造应用生成式 AI 格局的关键技术。Lewis 等人在其开创性论文中提出了一个新概念面向知识密集型 NLP 任务的检索增强生成之后&…...
【Sceneform-EQR】实现3D场景背景颜色的定制化(背景融合的方式、Filament材质定制)
写在前面的话 Sceneform-EQR是基于(filament)扩展的一个用于安卓端的渲染引擎。故本文内容对Sceneform-EQR与Filament都适用。 需求场景 在使用Filament加载三维场景的过程中,一个3D场景对应加载一个背景纹理。而这样的话,即便…...
python自动化测试之统一请求封装及通过文件实现接口关联
一、接口文档怎么看? http://www.aaa.com/api.php?sindex/index&applicationapp&application_client_typeweixi n&tokentokenvalue&ajaxajax 参数解释: http 协议 www.aaa.com IP和端口 api.php 接口的地址 sindex/index 接口名称以 …...
Redis笔记
文章目录 Redis笔记通用命令get和setkeysexistsdelexpirettlRedis的key过期策略定时器的实现原理type 持久化RDB(Redis DataBase)---定期备份bgsave AOF(Append Only File)---实时备份 Redis笔记 Redis是一个“客户端-服务器”结构的程序,客户端和服务器之间通过网…...
repo学习使用
Repo 是以 Git 为基础构建的代码库管理工具。Repo 可以在必要时整合多个 Git 代码库,将相关内容上传到版本控制系统。借助单个 Repo 命令,可以将文件从多个代码库下载到本地工作目录。 Repo 命令是一段可执行的 Python 脚本,你可以将其放在路…...
windows 通过docker 安装mysql
参考:Docker安装并使用Mysql(可用详细)_docker 安装mysql-CSDN博客 1. 拉取镜像:docker pull mysql:5.7 2. 查看镜像:docker image 3. 创建mysql 容器实例,并将data 目录挂载到本地d盘上 docker run --n…...
高效利用Python爬虫开发批量获取商品信息
在当今电商行业竞争激烈的环境下,精准且高效地获取商品信息对于商家和数据分析师来说至关重要。无论是进行市场调研、优化商品布局,还是制定竞争策略,商品信息的全面掌握都是关键。Python爬虫技术以其强大的功能和灵活性,成为批量…...
【C语言】左旋字符串(三种实现方式)
题目: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 方法一: 我们画个图分析一下: 基本逻辑: 就是我们每一次旋转之前,我们就取出…...
Spring Security,servlet filter,和白名单之间的关系
首先,Servlet Filter是Java Web应用中的基础组件,用于拦截请求和响应,进行预处理和后处理。它们在处理HTTP请求时处于最外层,可以执行日志记录、身份验证、授权等操作。白名单机制通常指允许特定IP、用户或请求通过的安全策略&…...
Python 调用 Azure OpenAI API
在人工智能和机器学习快速发展的今天,Azure OpenAI 服务为开发者提供了强大的工具来集成先进的 AI 能力到他们的应用中。本文将指导您如何使用 Python 调用 Azure OpenAI API,特别是使用 GPT-4 模型进行对话生成。 准备工作 在开始之前,请确保您已经: 拥有一个 Azure 账户…...
Git标签管理:从基础到高阶自动化实践
引言 在软件发布过程中,88%的生产事故与版本标记错误相关。Git标签(Tag)作为版本控制的关键锚点,不仅是发布流程的里程碑,更是代码审计和问题追溯的重要依据。本文将深入Git标签的底层机制,揭示企业级标签…...
运行Petalinux的准备
参考文档 建议使用Xilinx官方的文档中心DocNav,在Design Hub View选项卡中可以看到Xilinx官方组织的开发流程,非常详尽且总是最新的。 《UG1144-petalinux-tools-reference-guide》 安装linux系统 1.查看Petalinux版本支持的系统版本,对于官方未提及或…...
Jenkins 通过 Execute Shell 执行 shell 脚本 七
Jenkins 通过 Execute Shell 执行 shell 脚本 七 一、创建 .sh 文件 项目目录下新建 .sh 文件 jenkins-script\shell\ci_android_master.sh添加 Execute Shell 模块 在 Command 中添加 # 获取 .sh 路径 CI_ANDROID_MASTER_PATH"${WORKSPACE}/jenkins-script/shell/…...
AT32系列微控制器低压电机控制开发板
参考:《UM0014_AT32_LV_Motor_Control_EVB_V20_User_Manual_V1.0.1_ZH.pdf》 开发板介绍 此电机开发板是一个泛用型的低压三相电机驱动器,应用雅特力科技AT32系列微控制器搭配雅特力电机函数库,可驱动直流无刷电机、交流同步电机࿰…...
k8s部署redis集群
前置环境:已部署k8s集群,ip地址为 192.168.10.1~192.168.10.5,总共5台机器。 1. 创建provisioner制备器(如果已存在,则不需要) 需要部署方式,可以参考我之前的文章:k8s部署rabbitmq-CSDN博客 2. 新增redis配置文件 redis-6001.yaml --- apiVersion: v1 kind: Serv…...