springmvc从请求到响应的流程分析
一、创建springmvc项目
通过网盘分享的文件:hello-springmvc.zip
链接: https://pan.baidu.com/s/1VmUHurgph661ND9LWqKhaw 提取码: b36a
二、从请求到响应流程
我们先画一下流程图,如下图所示。
三、源码解析
3.1 HttpServlet接收请求
用户发送http请求后,首先进入到的是HttpServlet当中,执行的是service方法,如下所示,这个方法中首先获取到method,然后根据具体是get或者post或者其他类型请求来进行不同的处理。我们的代码中用的是get类型的请求。因此调doGet(req, resp);
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{String method = req.getMethod();if (method.equals(METHOD_GET)) {long lastModified = getLastModified(req);if (lastModified == -1) {// servlet doesn't support if-modified-since, no reason// to go through further expensive logicdoGet(req, resp);} else {long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);if (ifModifiedSince < lastModified) {// If the servlet mod time is later, call doGet()// Round down to the nearest second for a proper compare// A ifModifiedSince of -1 will always be lessmaybeSetLastModified(resp, lastModified);doGet(req, resp);} else {resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}} else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} else if (method.equals(METHOD_POST)) {doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req,resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req,resp);} else {//// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.//String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);}}
3.2 FrameworkServlet处理get方法
FrameworkServlet类继承了HttpServletBean类,而HttpServletBean又继承了HttpServlet,因此它是HttpServlet的子类,它重写了doGet方法,具体实现doGet方法如下,内部调用了processRequest(request, response);
/*** Delegate GET requests to processRequest/doService.* <p>Will also be invoked by HttpServlet's default implementation of {@code doHead},* with a {@code NoBodyResponse} that just captures the content length.* @see #doService* @see #doHead*/
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {processRequest(request, response);
}
processRequest方法源码如下,我们跳过非主要代码,直接看try方法中doService(request, response);
/*** Process this request, publishing an event regardless of the outcome.* <p>The actual event handling is performed by the abstract* {@link #doService} template method.*/
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {doService(request, response);} catch (ServletException | IOException ex) {failureCause = ex;throw ex;} catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);} finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}
}
3.3 DispatcherServlet处理doService方法
DispatcherServlet继承了FrameworkServlet类,它实现了doService方法,如下所示,刨除掉不重要的代码,直接看doDispatch(request, response);
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {logRequest(request);// Keep a snapshot of the request attributes in case of an include,// to be able to restore the original attributes after the 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();if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects.request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}try {doDispatch(request, response);} finally {if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}}
}
3.4 DispatcherServlet处理doDispatch方法
DispatcherServlet中doDispatch方法如下图所示
我们进入getHandler方法内部,可以看到HandlerExecutionChain的获取是从handlerMapping中获取的。
/*** Return the HandlerExecutionChain for this request.* <p>Tries all handler mappings in order.* @param request current HTTP request* @return the HandlerExecutionChain, or {@code null} if no handler could be found*/
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping: this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;
}
我们再回顾一下我们开头所画的那张图,如下所示,可以看到第2步是从HandlerMapping(处理器映射器)中获取处理器执行链(HanlderExcutionChain)。
什么是HandlerMapping?HandlerMapping在SpringMVC中扮演着请求路由的核心角色,其作用是将客户端请求(如HTTP请求)映射到对应的处理器(如Controller方法)。HandlerMapping是我们添加在controller接口上的注解,如下图所示,@RequestMapping注解的方法由RequestMappingHandlerMapping实现映射。从HandlerMapping中可以获取到HandlerExecutionChain,这个处理器执行器链中包含目标处理器及相关的拦截器(HandlerInterceptor),实现权限检查、日志等统一逻辑。
映射过程:当请求http://localhost:8080/firstController时,RequestMappingHandlerMapping根据URL和HTTP方法匹配到sayHello方法。
接着看doDispatch方法,如下图,在获取到HandlerExecutionChain之后,紧接着就该获取HandlerAdapter了,如下图所示,HandlerAdapter(处理器适配器)的核心作用是统一调用不同类型的处理器(Handler),解决不同处理器接口的兼容性问题。它充当了请求处理逻辑与具体处理器实现之间的适配层,使DispatcherServlet能够以统一的方式调用各种处理器(如@Controller、Servlet、HttpRequestHandler等)。
接着我们代码来到执行前置拦截器,如下图所示,那么我们有必要说下拦截器的例子,这样更好理解。
我们假如自定义了一个拦截器,如下所示代码,里面重点重写了preHandle和postHandle方法,顾名思义,preHandler是要在调用controller方法前先调用,比如做一些权限校验啊之类的。postHandle方法则是在执行完controller接口后,视图渲染前做一些特殊处理。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;public class CustomInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 在 Controller 方法执行前调用// 返回 true 继续执行,false 中断请求return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {// 在 Controller 方法执行后、视图渲染前调用}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 在视图渲染完成后调用(整个请求处理完毕)}
}
有了自定义拦截器类,那么怎么让自定义拦截器被springmvc管理,我们通过下面的方式来处理,如下所示,将自定义拦截器添加到springmvc的拦截器链中。配置的拦截所有请求路径(排除登录地址)
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 CustomInterceptor()).addPathPatterns("/**") // 拦截所有路径.excludePathPatterns("/login"); // 排除特定路径}
}
看完拦截器的例子,我们再回到下图的位置,执行前置拦截器就可以执行到我们刚才自定义拦截器的preHandle方法。执行完前置拦截器后,就到了ha.handle这行代码(这个对应我们流程图中的第5步),它是执行controller方法的意思,比如我们例子中的sayHello方法,执行sayHello方法后,返回的是ModelAndView(mv变量就是ModelAndView,这一步对应的是流程图中的第7步),返回ModelAndView对应我们流程中的第6步。ModelAndView是一个核心对象,用于封装控制器(Controller)处理请求后的返回结果,包含一下两部分信息:1)模型数据(Model):传递给视图(View)的动态数据(如查询结果、表单提交内容)。2)视图信息(View):决定客户端最终看到哪个页面(视图名称或视图对象)。它是连接控制器与视图层的桥梁。
在生成ModelAndView后,就开始执行拦截器的后置处理(如上图中的applyPostHandle方法),这个会执行到我们自定义拦截器的postHandle方法。
接着我们分析下面的流程,我们再次回顾一下我们的流程图,如下,我们该分析第8步了。
我们再回到刚才分析到的执行后置拦截器方法那里,代码再往下执行就到processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);这行了,我们需要进入到内部查看源码。
processDispatchResult方法内部源码如下,跳过不重要的代码,直接看标出来的render方法,如下图所示。
接着我们进入到render方法内部,源码如下,可以看到第8步视图解析就是将从ModelAndView中获取到的viewName和model等参数交给ViewResolver(视图解析器)来处理。处理完之后,就生成View对象并返回,这个对应流程图中的第9步。
protected View resolveViewName(String viewName, @Nullable Map < String, Object > model,Locale locale, HttpServletRequest request) throws Exception {if (this.viewResolvers != null) {for (ViewResolver viewResolver: this.viewResolvers) {View view = viewResolver.resolveViewName(viewName, locale);if (view != null) {return view;}}}return null;
}
接着回到如下图所示代码位置,在生成View对象后,接下来就到了view.render方法那一行代码。
上图中view.render方法实际执行的是AbstractView中的render方法,如下图所示,我们直接看最后一行代码renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
然后看renderMergedOutputModel方法内部的源码,这个方法有很多实现类,我们应该看哪个呢?这个我们在spring-mvc.xml文件中已经配置了,如下图所示。
从上图我们知道应该去InternalResourceViewResolver这个实现类中去看源码,如下图所示,这个方法处理的内容就对应了我们流程图中的第10步,这一步会将Model中的数据填充到View中并且根据用户使用的展示组件如HTML、jsp、freemarker,生成对应的组件,最后进行转发。
最后就是第11步,rd.forward方法将将处理好的HTML或者jsp等返给浏览器进行渲染展示。从而我们完成了整个处理流程的分析。
相关文章:
springmvc从请求到响应的流程分析
一、创建springmvc项目 通过网盘分享的文件:hello-springmvc.zip 链接: https://pan.baidu.com/s/1VmUHurgph661ND9LWqKhaw 提取码: b36a 二、从请求到响应流程 我们先画一下流程图,如下图所示。 三、源码解析 3.1 HttpServlet接收请求 用户发送htt…...
RabbitMQ 启动报错 “crypto.app“ 的解决方法
RabbitMQ 启动报错 “crypto.app” 的解决方法 在使用 RabbitMQ 时,有时会遇到启动报错的问题,其中一种常见的报错是: {"init terminating in do_boot",{error,{crypto,{"no such file or directory","crypto.app…...
idm 禁止自动更新提示(修改注册表)
目前版本:v 6.42 Bulid 35 运行-regedit- 计算机\HKEY_CURRENT_USER\SOFTWARE\DownloadManager 计算机\HKEY_CURRENT_USER\SOFTWARE\DownloadManagerLstCheck -> 0 重启...
LeetCode - 02.02.返回倒数第 k 个节点
目录 题目 解法一 双指针算法 原理 详细过程 为什么它有效? 时间复杂度与空间复杂度 代码 解法二 递归算法 核心思想 执行流程详解 具体例子 代码 题目 面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode) 解法一 双指针算…...
<c++>使用detectMultiScale的时候出现opencv.dll冲突
最近在试着弄一下opencv,看网上很多人都是的用的python,但是python跑起来没有c快,生成的qt工程也大一些,想着试试c看能不能生成opencv。然后就用到这个函数,detectMultiScale。 出现一个问题,就是我的程序在…...
从实列中学习linux shell脚本2: shell 的变量 方法 命名和使用规则之类 比如拿:获取cpu 负载,以及负载超过2.0 以后就发生邮件为例子
以下是对 Linux Shell 中变量、方法(函数)、命名规则的详细说明,并结合 获取CPU负载并在负载超过2.0时发送邮件 的示例进行演示: 1. Shell 变量 命名规则 命名格式:变量名由字母、数字、下划线组成,不能以…...
Centos Ubuntu RedOS系统类型下查看系统信息
文章目录 一、项目背景二、页面三、说明四、代码1.SysInfo2.EmsSysConfig3.HostInformationController4.HostInfo 一、项目背景 公司项目想展示当前部署系统的:操作系统,软件版本、IP、主机名。 二、页面 三、说明 说明点1:查询系统类型及…...
【Hive入门】Hive高级特性:视图与物化视图
在大数据分析中,Hive作为Hadoop生态系统中的重要组件,提供了强大的数据查询和管理能力。除了基本表的操作,Hive还支持 视图和 物化视图,这两种特性在数据管理和查询优化中扮演着重要角色。本文将深入探讨视图的创建与性能影响&…...
特征工程四-2:使用GridSearchCV 进行超参数网格搜索(Hyperparameter Tuning)的用途
1. GridSearchCV 的作用 GridSearchCV(网格搜索交叉验证)用于: 自动搜索 给定参数范围内的最佳超参数组合。交叉验证评估 每个参数组合的性能,避免过拟合。返回最佳模型,可直接用于预测或分析。 2. 代码逐行解析 (1…...
【Hive入门】Hive函数:内置函数与UDF开发
Apache Hive作为Hadoop生态系统中的重要组件,为大数据分析提供了强大的SQL-like查询能力。Hive不仅支持丰富的内置函数,还允许用户开发自定义函数(UDF)以满足特定需求。本文将深入探讨Hive的内置函数(包括数学函数、字…...
HTML Picture标签详细教程
HTML Picture标签详细教程 简介 <picture>标签是HTML5中引入的一个强大元素,它为开发者提供了更灵活的图像资源管理方式。该标签主要用于让浏览器根据不同条件(如设备屏幕大小、分辨率或支持的图像格式)选择最适合当前显示环境的图像…...
Html1
一,HTML概述 网页开发需要学习的知识: html css javaScript 两个框架 VUE.js ElementUI UI user interface 用户界面 HTML xml 可扩展标记语言-->存储数据 Markup Language标签语言都会提供各种标…...
runpod team 怎么设置自己的ssh key呢?
生成 ed25519 公钥密钥 ssh-keygen -t ed25519 -C "yourqq.com"然后在pod容器配置key以及启动方式 选择edit pod 添加启动代码 启动代码可以参考官方给的内容: https://docs.runpod.io/pods/configuration/use-ssh bash -c apt update;DEBIAN_FRONT…...
Flutter:组件10、倒计时
import dart:async; import package:flutter/material.dart;class CountdownTimer extends StatefulWidget {final int seconds;final double? fontSize;final Color? textColor;final bool showDays;final bool showHours;final bool showMinutes;final bool showSeconds;fi…...
存储器分类
按宏观分类 内部存储:用于临时存储当前程序运行所需要的数据外部存储:指硬盘,用于存储需要保存下的数据 按存储功能分 磁盘存储器(Disk),如机械硬盘非易失性存储器(Flash memory),分为固态硬…...
案例解析:基于量子计算的分子对接-QDOCK(Quantum Docking)
分子对接(Moleculardocking)在药物发现中具有重要意义,但对接的计算速度和准确率始终难以平衡,其巨大解搜索空间对传统计算机来说异常艰巨。 本文通过引入网格点匹配(GPM, Grind point matching)和特征原子…...
人工智能和机器学习在包装仿真中的应用与价值
引言 随着包装成为消费品关键的差异化因素,对智能设计、可持续性和高性能的要求比以往任何时候都更高 。为了满足这些复杂的期望,公司越来越多地采用先进的仿真方法,而现在人工智能 (AI) 和机器学习 (ML) 又极大地增强了这些方法 。本文探讨…...
系统的环境变量
目录 基本概念 用途之一 环境变量表 命令行参数表 理解 更多的环境变量 基本概念 环境变量(environmentvariables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数。环境变量通常具有某些特殊⽤途,还有在系统当中通常具有全局特性 用途之一 我们看…...
css3伸缩盒模型第一章(主轴以及伸缩盒模型)
css3伸缩盒模型第一章(主轴) 一、伸缩盒模型简介 2009 年, W3C 提出了一种新的盒子模型 —— Flexible Box (伸缩盒模型,又称:弹性盒 子)。它可以轻松的控制:元素分布方式、元素对齐方式、元素视觉顺序 ……...
【MySQL】(9) 视图
一、什么是视图 视图是一张虚拟表,是表、其它视图的查询结果集。它本身不像基础表(物理表)一样存储数据,而是将 SQL 查询语句包装起来,通过执行查询语句动态生成数据。 二、视图的作用 当我们需要频繁使用一条查询语句…...
day10 python机器学习全流程实践
在机器学习的实践中,数据预处理与模型构建是极为关键的环节。本文将回顾数据预处理的全流程,并基于处理后的数据完成简单的机器学习建模与评估,暂不涉及复杂的调参过程。 一、预处理流程回顾 机器学习的成功,很大程度上依赖于高…...
Rust Ubuntu下编译生成环境win程序踩坑指南
前言: 1,公司要给一线搞一个升级程序,需要在win下跑。 之前都是找开发总监帮忙,但是他最近比较忙。就让我自己搞。有了下文.。说来惭愧,之前写过一篇ubuntu下编译windows的文章。里面的demo就一句话 fuck world。依赖…...
2025年- H12-Lc119-56.合并区间(普通数组)---java版
1.题目描述 2.思路 思路参考了代码随想录: 按照左边界从小到大排序之后,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]的左边界 < intervals[i - 1]的右边界,则一定有重叠。(本题相邻区间也算重贴ÿ…...
合并两个有序链表
题目:21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入&#x…...
rsync命令详解与实用案例
rsync命令详解与实用案例 rsync是一款功能强大的Linux文件同步工具,通过高效的增量传输算法,能够显著减少数据传输量和时间,是备份、镜像和跨平台文件同步的理想选择。其核心价值在于只传输文件的差异部分,而非全量复制ÿ…...
gitee 如何修改提交代码的邮箱
gitee 如何修改提交代码的邮箱 1. 修改全局提交邮箱2. 修改特定仓库的提交邮箱3. 修改已提交记录的邮箱 4. 可能遇到的问题git filter-repo 拒绝执行解决办法方法一:使用 --force 参数 (亲测有效)方法二:创建一个全新的克隆仓库 注…...
MATLAB画一把伞
% 伞的参数num_ribs 5; % 伞骨数量修改为5R 1; % 伞的半径height 0.5; % 伞的高度handle_length 2; % 伞柄长度semicircle_radius 0.26; % 伞柄末端半圆的半径% 生成伞叶网格theta linspace(0, 2*pi, 100);phi linspace(0, pi/2, 50);[Theta, Phi] meshgrid(theta, phi…...
vue 实现文件流下载功能 前端实现文件流下载
首先场景就是,一般的文件下载是通过后端返回的文件地址下载文件,但当后端返回的是文件流的时候,下载要做特殊处理 案例截图: 下载成功: 代码处理,首先就是要在接口封装的地方加上 在 Vue 前端开发中实现文件流下载与普通文件下载的核心区别在于 数据处理方式。文件流…...
[Android]导航栏中插入电源菜单
1. 新增 frameworks/base/packages/SystemUI/res/layout/power.xml <?xml version"1.0" encoding"utf-8"?> <com.android.systemui.navigationbar.buttons.KeyButtonView xmlns:android"http://schemas.android.com/apk/res/android"…...
VSCode Verilog环境搭建
VSCode Verilog环境搭建 下载Iverilog安装Iverilog验证安装VS Code安装插件 下载Iverilog 官网下载Iverilog 安装Iverilog 一定要勾选这两项 建议勾选这两项 验证安装 运行Windows PowerShell输入命令:iverilog输入命令:Get-Command gtkwave …...
Hadoop 和 Spark 生态系统中的核心组件
通过jps命令,可以看到如下进程名,请解释一下它们各自是哪个命令产生的,有什么作用?一、Worker 1.来源:Spark 集群的 工作节点(Worker Node),由 start-worker.sh 启动 2.作用&#…...
MySQL多表操作
熟能生巧,全部代码在最后!!! 一、多表关系 一对一关系、一对多关系、多对多关系 注意多对多关系必须有中间表进行关联 多对多的关系就相当于是两个一对多关系 二、创建外键约束 专门用于多表操作的一种约束方式 控制的那个表…...
WPF TextBlock控件性能优化指南
WPF TextBlock控件性能优化指南 1. 引言 TextBlock作为WPF中最基础且使用最广泛的文本显示控件,其性能优化对整个应用程序的响应速度和资源占用有着重要影响。尽管TextBlock是一个轻量级控件,但在大型应用或需要显示大量文本的场景中,不恰当…...
DotNet 入门:(一) 环境安装
一、前言 本想用 Go 语言实现一个通过小爱同学操作电脑的,比如我对着手机说打开音乐,或调小音乐,电脑能做相应的处理。奈何我一时间没看懂,就想着用.Net 来试一下,于是就有了下面这篇文章。 二、安装.Net 环境 1. 下…...
初识Redis · 分布式锁
目录 前言: 分布式锁 setnx lua脚本和看门狗 redlock算法 Redlock 的加锁流程(5 步) 前言: 到了分布式锁这一章之后,我们首先能联想到的问题就是线程安全的问题,线程安全指的是多个线程在并发执行的…...
使用 OpenCV 实现图像中心旋转
在图像处理中,围绕中心点旋转图像是一个常见的需求。无论是为了数据增强、视觉效果,还是图像对齐,旋转图像都是一项基础且重要的操作。本文将详细介绍如何使用 OpenCV 实现围绕图像中心旋转的功能,并深入探讨其背后的数学原理。 一…...
云钥科技红外短波工业相机
云钥科技的红外短波相机是一款基于短波红外(SWIR,波长范围约1-3微米)技术的成像设备,专为高精度检测、全天候成像及特殊场景应用设计。以下从核心技术、性能参数、应用场景及产品优势等方面进行详细介绍: 一、核心…...
npm如何安装pnpm
在 npm 中安装 pnpm 非常简单,你可以通过以下步骤完成: 1. 使用 npm 全局安装 pnpm 打开终端(命令行工具),运行以下命令: npm install -g pnpm2. 验证安装 安装完成后,可以检查 pnpm 的版本以确保安装成功: pnpm --version如果正确显示版本号(如 8.x.x),说明安…...
GTC Taipei 2025 医疗域前瞻:从AI代理到主权生态,解码医疗健康与生命科学的未来图景
引言 2025年,全球医疗健康领域正经历一场由人工智能、机器人技术与分布式计算驱动的范式转移。随着NVIDIA及其生态伙伴在GTC Taipei 2025大会上的深度布局,医疗行业的核心趋势愈发清晰:AI代理程序(Digital AI Agents)赋能临床协作、医疗大数据与精准医学加速落地、医学影…...
【AI学习】李宏毅新课《DeepSeek-R1 这类大语言模型是如何进行「深度思考」(Reasoning)的?》的部分纪要
针对推理模型,主要讲了四种方法,两种不需要训练模型,两种需要。 对于reason和inference,这两个词有不同的含义! 推理时计算不是新鲜事,AlphaGo就是如此。 这张图片说明了将训练和推理时计算综合考虑的关系&…...
npm打包内存不足- JavaScript heap out of memory
直接贴出报错信息 <--- Last few GCs --->[30904:0000010F60FE58E0] 22090 ms: Scavenge 2037.4 (2069.4) -> 2036.4 (2074.2) MB, 2.5 / 0.0 ms (average mu 0.228, current mu 0.216) allocation failure [30904:0000010F60FE58E0] 22101 ms: Scavenge 2…...
【最新 MCP 战神手册 08】工具使用详解:实现 AI 行动
文章目录 1. 开始啦!2. 第一部分:设计高效且安全的工具3. 第二部分:定义工具蓝图——参数、输出与约束条件4. 第三部分:弥合差距:LLM 兼容性(函数调用)5. 第四部分:实施与测试的最佳实践1. 开始啦! 在前几章中,我们将工具介绍为 AI 模型在 MCP 客户端引导下向 MCP 服…...
开发iOS App时,我常用的一款性能监控小工具分享
开发iOS App时,我常用的一款性能监控小工具分享 最近在做一个iOS应用的性能优化,频繁遇到内存泄露、界面卡顿和网络请求超时的问题。平时用Xcode Instruments虽然专业,但流程繁琐,临时排查问题不够灵活。 于是开始找有没有轻量一…...
如何防止 ES 被 Linux OOM Killer 杀掉
当 Linux 系统内存不足时,内核会找出一个进程 kill 掉它释放内存,旨在保障整个系统不至于崩溃。如果 ES 按照最佳实践去实施部署,会保留一半的内存,不至于发生此类事情。但事情总有例外,有的朋友可能 ES 和其他的程序部…...
Windows权限与icacls命令详解
在Windows操作系统中,权限管理是确保系统安全和资源访问控制的核心机制。特别是在使用NTFS(New Technology File System)文件系统的环境中,访问控制列表(ACL)用于定义哪些用户或组可以对文件、文件夹或其他…...
5.4.2 MVVM例2-用户控件的使用(水在水管中流动的实例)
本文以一个例子介绍用户控件的使用(UserControl),下图所示: 一、主要技术点 1.MainViewModel使用CommunityToolkit.Mvvm 这个Nuget包 2.LinearGradientBrush使用,下面代码可以产生如下的效果 <LinearGradientBrush x:Key="HorizontalBackground" …...
PHP代码-服务器下载文件页面编写
内部环境的服务资源下载页面有访问需求,给开发和产品人员编写一个简洁的下载页面提供资源下载。直接用nginxphp的形式去编写了,这里提供展示index.php文件代码如下: <?php // 配置常量 define(BASE_DIR, __DIR__); // 当前脚本所在目录作…...
51单片机快速入门之 SPI通信 2025年4月29日09:26:32
SPI通信 : SPI(Serial Peripheral Interface)通信是一种同步串行数据传输协议,主要用于嵌入式系统内部设备之间的通信。它由Motorola公司在2000年提出,广泛应用于微控制器、传感器、存储设备等之间的数据传输。 SPI通信的主要特点…...
SpringMVC再复习1
一、三层架构 表现层(WEB 层) 定义 :是应用程序与客户端进行交互的最外层,主要负责接收用户的请求,并将处理结果显示给用户。 作用 :在 Spring MVC 中,表现层通常采用 MVC 设计模式来构建。 技…...
音视频之H.265/HEVC网络适配层
H.265/HEVC系列文章: 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 4、音视频之H.265/HEVC变换编码 5、音视频之H.265/HEVC量化 6、音视频之H.265/HEVC环路后处理 7、音视频之H.265/HEVC熵编…...