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

【Linux网络】Http服务优化 - 增加请求后缀、状态码描述、重定向、自动跳转及注册多功能服务

📢博客主页:https://blog.csdn.net/2301_779549673
📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 CSDN🙉
📢未来很长,值得我们全力奔赴更美好的生活✨

在这里插入图片描述

在这里插入图片描述

文章目录

  • 🏳️‍🌈一、增加请求后缀
    • 1.1 HttpRequest 类
    • 1.2 HttpHandler 类
  • 🏳️‍🌈二、状态码描述 及 自动跳转404
    • 2.1 状态码描述
    • 2.2 自动跳转404
  • 🏳️‍🌈三、重定向状态码
  • 🏳️‍🌈四、注册等多功能服务
    • 4.1 HttpRequest 类
    • 4.2 HttpHandler 类
    • 4.3 TcpServer.cpp
    • 4.4 测试
  • 👥总结


🏳️‍🌈一、增加请求后缀

我们在浏览器上访问我们自己的服务端时,会遇到客户端发送来的请求,想要访问 1.jpg 或者 default.html 因此我们可以将这个后缀给整理一下,通过日志打印告诉我们自己目标想要访问的资源在当前的哪里。

1.1 HttpRequest 类

我们在这个类里进行如下操作

  1. 添加成员变量 _suffix
  2. 在请求行解析方法中,增添一段,通过后缀分隔符 "." ,来找到我们的后缀,没有找到就返回默认后缀
  3. 添加函数方法,获取当前请求的后缀名
const static std::string _suffixsep = ".";                      // 后缀分隔符    class HttpRequest {
private:// 解析请求行void PraseReqLine() {// 以空格为分隔符,不断读取std::stringstream ss(_req_line);ss >> _method >> _url >> _version;_path += _url;// 处理url,如果是根目录,则返回默认路径if (_url == "/")_path += _default_path;// 获取后缀auto pos = _path.rfind(_suffixsep);if (pos == std::string::npos)_suffix = ".default";else_suffix = _path.substr(pos);}public:std::string Suffix() {LOG(LogLevel::INFO) << "client want suffix : " << _suffix;return _suffix;}
}

1.2 HttpHandler 类

这里我们需要先知道一个概念 - MIMIE

MIME 是一种 ​互联网标准,最初设计用于扩展电子邮件协议(如 SMTP),使其能传输非文本数据(如图片、音频)。后被 HTTP 协议广泛采用,用于标识网络资源的 ​数据类型。

  • .html → text/html(HTML 文档)
  • .jpg → image/jpeg(JPEG 图片)
  • .json → application/json(JSON 数据)

这个类中我们需要增加一个后缀映射,并将其添加在返回报文的报头列表中

1, 增加成员变量 后缀后缀存储 的映射
2.`构造函数 时,初始化映射
3. 处理请求时,将映射结果添加到响应报头中

class HttpHandler {
public:HttpHandler() {_mime_type.insert(std::make_pair(".html", "text/html"));_mime_type.insert(std::make_pair(".jpg", "image/jpg"));_mime_type.insert(std::make_pair(".png", "image/png"));_mime_type.insert(std::make_pair(".default", "text/html"));}std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);std::string content = GetFileContent(req_obj.Path());if (content.empty())return std::string();HttpResponse rsp;rsp.AddCode(200);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);return rsp.Serialize();}
private:std::unordered_map<std::string, std::string> _mime_type;
};

🏳️‍🌈二、状态码描述 及 自动跳转404

前面的文章中我们已经知道了状态码描述的存在,但是没有可利用过,这里再介绍一下这个状态码,添加一个状态码的映射并且根据访问内容,去判断要不要显示404界面

2.1 状态码描述

这里需要进行两方面的更改,一个是 HttpResponse一个是 HttpHandler 的构造和成员变量

HttpHandler 中我们添加 状态码状态码描述映射,然后在构造中表示出来

class HttpHandler {
public:HttpHandler() {_mime_type.insert(std::make_pair(".html", "text/html")); // HTML 类型_mime_type.insert(std::make_pair(".jpg", "image/jpeg")); // JPEG 图片_mime_type.insert(std::make_pair(".png", "image/png"));  // PNG 图片_mime_type.insert(std::make_pair(".default", "text/html")); // 默认文本类型_status_code_desc.insert(std::make_pair(100, "Continue"));_status_code_desc.insert(std::make_pair(200, "OK"));_status_code_desc.insert(std::make_pair(201, "Created"));_status_code_desc.insert(std::make_pair(404, "Not Found"));}
private:std::unordered_map<int, std::string> _status_code_desc;
};

HttpResponse 中的 AddCode 方法,我们之前默认是不论什么都是 OK,现在我们对其进行专属化处理

// 添加 状态码 和 状态码描述
void AddCode(int code, std::string desc) {_status_code = code;_desc = desc;
}

2.2 自动跳转404

我们在 HttpHandlerHandleRequest 方法中,当判定访问的路径内容为空时,就将这个路径改成 404.html

std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);std::string content = GetFileContent(req_obj.Path());HttpResponse rsp;if (content.empty()) {content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);} else {rsp.AddCode(200, _status_code_desc[200]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);}return rsp.Serialize();
}

🏳️‍🌈三、重定向状态码

在这里插入图片描述

HTTP 状态码 301(永久重定向)和 302(临时重定向)都依赖 Location 选项。

无论是 HTTP 301 还是 HTTP 302 重定向,都需要依赖 Location 选项来指定资源的新位置。这个 Location 选项是一个标准的 HTTP 响应头部,用于告诉浏览器应该将请求重定向到哪个新的 URL 地址。

我们现在 default.html 中添加 测试重定向 的选项

在这里插入图片描述

我们测试永久重定向,将当前的网址重定向到 qq.com

std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);HttpResponse rsp;if (req_obj.Url() == "/redirect") {// 重定向处理std::string redirect_path = "https://www.qq.com";rsp.AddCode(302, _status_code_desc[302]);rsp.AddHeader("Location", redirect_path);rsp.AddHeader("Content-Type", "text/plain"); // 添加 Content-Typersp.AddHeader("Content-Length", "0");        // 显式设置内容长度为 0rsp.AddBodyText("");                         // 确保响应体为空} else {std::string content = GetFileContent(req_obj.Path());if (content.empty()) {content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);} else {rsp.AddCode(200, _status_code_desc[200]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);}}return rsp.Serialize();
}

在这里插入图片描述

🏳️‍🌈四、注册等多功能服务

因为存在两种主要的提交方式,分别是 POSTGET,因此参数的位置会不一样,

GET 下,位于 网址 的 后面

在这里插入图片描述

POST 下,位于请求正文中

所以我们要根据不同的情况,分出响应的 参数,以及路径

4.1 HttpRequest 类

需要改的主要有三部分

  1. 增加新的成员变量_args 用来记录参数,_isexcute 用来记录是否有参数
  2. 构造函数中给 _isexcute 默认为false
  3. 更改 Descrialize 细节,使其区分 GETPOST,并且能够准确提取出 _args_path
class HttpRequest{private:public:HttpRequest() : _blank_line(_base_sep), _path(_prefix_path), _isexcute(false) {}void Descrialize(std::string& reqstr){// 基本的反序列化_req_line = GetLine(reqstr);    // 读取第一行请求行// 请求报头std::string header;do{header = GetLine(reqstr);// 如果既不是空,也不是空行,就是请求报头,加入到请求报头列表中if(header.empty()) break;else if(header == _base_sep) break;_req_headers.push_back(header);}while(true);// 正文if(!reqstr.empty())_req_body = reqstr;// 进一步反序列化请求行PraseReqLine();// 分割请求报头,获取键值对PraseHeader(); // 判断是否需要动态执行if(_method == "POST"){_isexcute = true;_args = _req_body;LOG(LogLevel::INFO) << "POST _path : " << _path;LOG(LogLevel::INFO) << "POST _args : " << _args;} else if(_method == "GET"){auto pos = _path.find("?");if(pos != std::string::npos){_isexcute = true;_args = _path.substr(pos + 1);_path = _path.substr(0, pos);LOG(LogLevel::INFO) << "GET _path : " << _path;LOG(LogLevel::INFO) << "GET _args : " << _args;}}}std::string Args(){LOG(LogLevel::INFO) << "client want _args : " << _args;  return _args;}bool Isexecute(){LOG(LogLevel::INFO) << "client want _isexcute : " << _isexcute;  return _isexcute;}private:bool _isexcute;                              // 是否需要动态执行std::string _args;                           // 动态执行的参数};

4.2 HttpHandler 类

增加功能路由表也就是映射目标路径和方法unoredered_map。同时也要构建能够处理相应操作的回调函数类型

using http_handler_t = std::function<HttpResponse(HttpRequest&)>;
std::unordered_map<std::string, http_handler_t> _route; // 功能路由表

增加注册服务的相关功能

	// 注册服务功能void RegisterHandler(std::string funcname, http_handler_t service) {std::string name = _prefix_path + funcname;_route.insert(std::make_pair(name, service));}// 判断是否存在该功能bool HasHandler(std::string funcname) {auto iter = _route.find(funcname);if (iter == _route.end())return false;elsereturn true;}

将http请求处理主要分为三块

  1. 重定向处理
  2. 动态操作处理
  3. 静态页面变化处理
std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);HttpResponse rsp;if (req_obj.Url() == "/redirect") {LOG(LogLevel::DEBUG) << "重定向服务";// 重定向处理std::string redirect_path = "https://www.qq.com";rsp.AddCode(302, _status_code_desc[302]);rsp.AddHeader("Location", redirect_path);rsp.AddHeader("Content-Type", "text/plain"); // 添加 Content-Typersp.AddHeader("Content-Length", "0");        // 显式设置内容长度为 0rsp.AddBodyText("");                         // 确保响应体为空} else if (req_obj.Isexecute()) {LOG(LogLevel::DEBUG) << "注册服务";if (HasHandler(req_obj.Path())) {LOG(LogLevel::DEBUG) << "找到注册服务";rsp = _route[req_obj.Path()](req_obj);} else {LOG(LogLevel::DEBUG) << "没有找到注册服务";std::string content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);}} else {LOG(LogLevel::DEBUG) << "静态页面服务";std::string content = GetFileContent(req_obj.Path());if (content.empty()) {content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);} else {rsp.AddCode(200, _status_code_desc[200]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);}}return rsp.Serialize();
}

4.3 TcpServer.cpp

这里我们需要将注册服务具体化,并添加到 功能路由表

现实生活中,我们还需要对这个传进来的参数(用户名、密码等)进行序列化,到数据库中查找等操作,这里就不拓展了,简简单单地使用 success.html 界面表示我们登录成功就行了

HttpResponse Login(HttpRequest& req){HttpResponse rsp;LOG(LogLevel::INFO) << "进入登录模块" << req.Path() << ", " << req.Args();std::string req_args = req.Args();// 1. 解析参数格式,得到要的参数// 2. 访问数据库,验证对应的用户是否是合法用户,以及...// 3. 登录成功HttpHandler httphandler;std::string content = httphandler.GetFileContent("wwwroot/success.html");rsp.AddCode(200, "OK");rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-Type", "text/html");rsp.AddHeader("Set-Cokkie", "req_args");rsp.AddBodyText(content);return rsp;
}

4.4 测试

当 ·login 方法是 GET
在这里插入图片描述

在这里插入图片描述

当是 POST
在这里插入图片描述

在这里插入图片描述


👥总结

本篇博文对 【Linux网络】Http服务优化 - 增加请求后缀、状态码描述、重定向、自动跳转及注册多功能服务 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

相关文章:

【Linux网络】Http服务优化 - 增加请求后缀、状态码描述、重定向、自动跳转及注册多功能服务

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

Docker compose 部署微服务项目(从0-1出发纯享版无废话)

目录 一.Docker安装 &#xff08;1&#xff09;安装依赖 &#xff08;2&#xff09;安装Docker &#xff08;3&#xff09;启动Docker服务 &#xff08;4&#xff09;系统配置 &#xff08;5&#xff09;镜像加速配置 &#xff08;6&#xff09;验证安装 二.编写Docke…...

C#学习第19天:多线程

什么是多线程&#xff1f; 定义&#xff1a;多线程允许一个程序分成多个独立的执行路径来进行并发操作。用途&#xff1a;提高程序的执行效率&#xff0c;特别是在I/O操作、计算密集型任务和用户交互中。 多线程核心概念 1. 创建和管理线程 使用 Thread 类 using System; u…...

day7 python针对心脏病数据集预处理

在数据科学与机器学习领域&#xff0c;数据预处理与可视化是挖掘数据价值的关键前置步骤。本文以 heart1.csv 心脑血管疾病数据集为例&#xff0c;借助 Python 中的 pandas、matplotlib、seaborn 以及 scikit-learn 库&#xff0c;详细演示数据加载、缺失值处理、特征相关性分析…...

树莓派学习专题<9>:使用V4L2驱动获取摄像头数据--设定分辨率和帧率

树莓派学习专题&#xff1c;9&#xff1e;&#xff1a;使用V4L2驱动获取摄像头数据--设定分辨率和帧率 1. 设定分辨率2. 设定帧率3. 设定分辨率代码解析4. 获取与设定帧率代码解析5. 实测 1. 设定分辨率 使用如下代码设定摄像头的分辨率&#xff1a; #define CAMERA_RESOLUTI…...

模态链:利用视觉-语言模型从多模态人类视频中学习操作程序

25年4月来自谷歌 DeepMind 和斯坦福大学的论文“Chain-of-Modality: Learning Manipulation Programs from Multimodal Human Videos with Vision-Language-Models”。 从人类视频中学习执行操作任务&#xff0c;是一种很有前景的机器人教学方法。然而&#xff0c;许多操作任务…...

JAVAEE初阶01

个人主页 JavaSE专栏 JAVAEE初阶01 操作系统 1.对下&#xff08;硬件&#xff09;管理各种计算机设备 2.对上&#xff08;软件&#xff09;为各种软件提供一个稳定的运行环境 线程 运行的程序在操作系统中以进程的形式存在 进程是系统分配资源的最小单位 进程与线程的关…...

【网络安全】用 Linux 命令行 CLI 日志文件处理指南

Linux 命令行 CLI 神技回忆录&#xff1a;日志文件处理指南&#xff08;以 Zeek Logs 为例&#xff09; 1. CLI简介2. 基础操作3. 文件读取4. 查找与筛选5. 进阶操作6. Zeek 日志骚操作7. 结语 1. CLI简介 在数据分析的世界里&#xff0c;图形界面&#xff08;GUI&#xff09;…...

[C++] 高精度乘法

目录 引入: 大整数比较比较方法例题1-青蛙计数题目描述 输入描述输出描述输入输出样例AC代码 高精度乘法模版高精度运算小合集(这集乘法上集加法) 注意: 若还没有学过高精度运算的话先去看高精度加法 引入: 大整数比较 比较方法 大整数比较可以使用此方法比较(注释有讲解): …...

反事实——AI与思维模型【82】

一、定义 反事实思维模型是一种心理认知模型,它指的是人们在头脑中对已经发生的事件进行否定,然后构建出一种可能性假设的思维活动。简单来说,就是思考“如果当时……,那么就会……”的情景。这种思维方式让我们能够超越现实的限制,设想不同的可能性和结果,从而对过去的…...

Java学习手册:Java开发常用的内置工具类包

以下是常用 Java 内置工具包。 • 日期时间处理工具包 • java.time包&#xff08;JSR 310&#xff09;&#xff1a;这是 Java 8 引入的一套全新的日期时间 API&#xff0c;旨在替代陈旧的java.util.Date和java.util.Calendar类。其中的LocalDate用于表示不带时区的日期&…...

JAVA多线程(8.0)

目录 线程池 为什么使用线程池 线程池的使用 工厂类Executors&#xff08;工厂模式&#xff09; submit 实现一个线程池 线程池 为什么使用线程池 在前面我们都是通过new Thread() 来创建线程的&#xff0c;虽然在java中对线程的创建、中断、销毁、等值等功能提供了支持…...

通过门店销售明细表用Python Pandas得到每月每个门店的销冠和按月的同比环比数据

假设我在本地有Excel销售表&#xff0c;包含ID主键、门店ID、日期、销售员姓名和销售额&#xff0c;需要用Pandas统计出每个月所有门店和各门店销售额最高的人&#xff0c;不一定是一个人&#xff0c;以及他所在的门店ID和月总销售额。 步骤1&#xff1a;导入数据并处理日期 …...

详解最新链路追踪skywalking框架介绍、架构、环境本地部署配置、整合微服务springcloudalibaba 、日志收集、自定义链路追踪、告警等

1.skywalking介绍 多种监控手段&#xff0c;可以通过语言探针和service mesh 获得监控数据支持多种语言自动探针&#xff0c;包含java/net/nodejs轻量高效&#xff0c;无需大数据平台和大量的服务器资源模块化&#xff0c;UI、存储、集群管理都有多种机制可选支持告警优秀的可…...

【OSG学习笔记】Day 11: 文件格式与数据交换

OSG 常用文件格式简介 在开始转换前,先了解 OSG 生态中常见的文件格式: .osg:OSG 标准二进制格式,存储场景图数据,体积小、加载快,适合实时渲染。 .ive:OSG 标准文本格式,可读性强,便于手动编辑或调试场景图结构(本质是 XML 格式的文本描述)。 .osgb:OSG 二进制格…...

2025.04.26-美团春招笔试题-第二题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 02. 曼哈顿距离探测器 问题描述 K小姐正在研发一种城市交通探测器,该探测器能够检测城市中任意两个位置之间的曼哈顿距离是否恰好为特定值。曼哈顿距离是在直角坐标系中,两点之间…...

搭建基于火灾风险预测与防范的消防安全科普小程序

基于微信小程序的消防安全科普互动平台的设计与实现&#xff0c;是关于微信小程序的&#xff0c;知识课程学习&#xff0c;包括学习后答题。 技术栈主要采用微信小程序云开发&#xff0c;有下面的模块&#xff1a; 1.课程学习模块 2.资讯模块 3.答题模块 4.我的模块 还需…...

05--Altium Designer(AD)的详细安装

一、软件的下载 Altium Designer官网下载 1、临近五一的假期&#xff0c;想着搞个项目&#xff0c;且这个项目与PCB有关系&#xff0c;所以就下这个软件来玩玩。下面保姆级教大家安装。 2、选择适合自己的版本下载&#xff08;我安装的是24的&#xff09; 3、软件安装 1.下…...

药监平台上传数据报资源码不存在

问题&#xff1a;电子监管码上传药监平台提示“导入的资源码不存在” 现象&#xff1a;从生产系统导出的关联关系数据包上传到药监平台时显示&#xff1a; 原因&#xff1a;上传数据包的通道的资源码与数据包的资源码不匹配。 解决方法&#xff1a;检查药监平台和生产系统的药…...

DeepSeek预训练追求极致的训练效率的做法

DeepSeek在预训练阶段通过多种技术手段实现了极致的训练效率,其中包括采用FP8混合精度训练框架以降低计算和内存需求 ,创新性地引入Multi-head Latent Attention(MLA)压缩KV缓存以提升推理效率,以及基于Mixture-of-Experts(MoE)的稀疏计算架构以在保证性能的同时显著降低…...

Windows11系统中GIT下载

Windows11系统中GIT下载 0、GIT背景介绍0.0 GIT概述0.1 GIT诞生背景0.2 Linus Torvalds 的设计目标0.3 Git 的诞生&#xff08;2005 年&#xff09;0.4 Git 的后续发展0.5 为什么 Git 能成功&#xff1f; 1、资源下载地址1.1 官网资源1.2 站内资源 2、安装指导3、验证是否下载完…...

Maven的概念与初识Maven

目录 一、Maven的概念 1. 什么是Maven 2. 项目构建&#xff1a;从代码到部署的标准化流程 2.1 Maven构建生命周期 2.2 传统构建 vs Maven构建 3. 依赖管理&#xff1a;解决“JAR地狱”的利器 3.1 依赖声明 3.2 依赖传递与冲突解决 4. Maven仓库&#xff1a;依赖的存储…...

【Android】app调用wallpaperManager.setBitmap的隐藏权限

这是一个杞人忧天的问题&#xff0c;app中&#xff0c;可以通过wallpaperManager.setBitmap来设置壁纸&#xff0c; private void setWallpaper() {// 获取 WallpaperManager 实例WallpaperManager wallpaperManager WallpaperManager.getInstance(getApplicationContext());t…...

ORACLE数据库备份入门:第四部分:2-备份场景举例

下面以4个常见的场景为例&#xff0c;介绍如何规划备份方案。备份方案没有标准答案&#xff0c;需要根据实现情况来制定&#xff0c;也和管理员的个人使用习惯有很大相关性。 1 交易型数据库备份 以银行的交易系统为例&#xff0c;除了前一章节提到的关于RPO和RTO的指标外&am…...

STL中emplace实现原理是什么?

template <class... Args>void emplace_back (Args&&... args);这个是vector的emplace_back方法&#xff0c;用到的c11的语法有三个&#xff0c;分别是万能引用、完美转发、参数包。 参数包中的参数是用来构造vector<T>中的T对象。 假如我直接传的就是一个…...

血泪之arduino库文件找不到ArduinoJSON.h: No such file or directory错误原因

#include <ArduinoJson.h> 始终报这个错误&#xff0c; C:\techxixi_project\Arduino\test\camer\camertoserver\camertoserver.ino:6:10: fatal error: ArduinoJSON.h: No such file or directory 6 | #include <ArduinoJSON.h> | ^~~~~~~~~…...

通过门店销售明细表用PySpark得到每月每个门店的销冠和按月的同比环比数据

假设我在Amazon S3上有销售表的Parquet数据文件的路径&#xff0c;包含ID主键、门店ID、日期、销售员姓名和销售额&#xff0c;需要分别用PySpark的SparkSQL和Dataframe API统计出每个月所有门店和各门店销售额最高的人&#xff0c;不一定是一个人&#xff0c;以及他所在的门店…...

【前后端分离项目】Vue+Springboot+MySQL

文章目录 1.安装 Node.js2.配置 Node.js 环境3.安装 Node.js 国内镜像4.创建 Vue 项目5.运行 Vue 项目6.访问 Vue 项目7.创建 Spring Boot 项目8.运行 Spring Boot 项目9.访问 Spring Boot 项目10.实现 Vue 与 Spring Boot 联动11.安装 axios12.编写请求13.调用函数请求接口14.…...

图解 Redis 事务 ACID特性 |源码解析|EXEC、WATCH、QUEUE

写在前面 Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务功能。Redis的事务是将多个命令请求打包&#xff0c;然后一次性、按照顺序的执行多个命令的机制&#xff0c;并且在事务执行期间&#xff0c;服务器不会中断事务而该去执行其他客户端的命令请求。 就像下面这样&#…...

w~嵌入式C语言~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/13870307 一、单片机多任务事件驱动 单片机的ROM与RAM存贮空间有限&#xff0c;一般没有多线程可用&#xff0c;给复杂的单片机项目带来困扰。 经过多年的单片机项目实践&#xff0c;借鉴windows消息机制的思想&#xff…...

CMCC RAX3000M CH EC 算力版刷机(中国移动 RAX3000M 算力版)刷机

刷机前面的工作参考&#xff1a; https://blog.csdn.net/asdcls/article/details/147434218 刷机 eMMC Flash instructions: 1. SSH to RAX3000M, and backup everything, especially factory part. (data partition can be ignored, its useless.) 2. Write new GPT tabl…...

cron定时任务

cron定时任务 一、Cron表达式的定义 基础结构 Cron表达式是由空格分隔的6或7个字段组成的字符串&#xff0c;格式为&#xff1a; 秒 分 时 日 月 星期 [年]其中&#xff0c;年通常可以被省略 字段说明&#xff1a; 秒&#xff08;0-59&#xff09; 秒字段表示每分钟的哪一…...

1.4 大模型应用产品与技术架构

目录 一&#xff0c;产品架构 1.1 AI Embedded产品架构 1.2 AI Copilot产品架构 1.3 AI Agent产品架构 二&#xff0c;技术架构 2.1 纯Prompt 2.2 Agent Function Calling 2.3 RAG &#xff08;Retrieval-Augmented Generation 检索增强生成&#xff09; 2.4 Fine-tu…...

Android HAL HIDL

1 Android HAL HIDL 1.1 Android中查看有哪些HIDL HAL HIDL是Treble Interface的一部分。 adb root adb shell # lshal 1.2 Android打印C调用栈 #include <utils/CallStack.h> 在需要打印的地方加如下的定义。 android::CallStack stack("oem"); logcat | g…...

std::mutex底层实现原理

std::mutex是一个用于实现互斥访问的类&#xff0c;其具备两个成员函数——lock和unlock 锁的底层实现原理 锁的底层实现是基于原子操作的&#xff0c;这些原子操作是由指令支持的&#xff0c;因为单个指令是不能被中断的 一些与锁的实现有关的原子指令为&#xff1a; 待补充…...

性能提升手段--池化技术

看到hadoop代码里有ByteBufferPool,使用池子来避免频繁创建、销毁ByteBuffer,减轻GC压力,提高性能。 顺便总结一下池化技术 一、什么是池化技术?​​ ​​池化(Pooling)​​ 是一种资源管理策略,通过​​预先创建并复用资源​​(如数据库连接、线程、内存对象等)来提…...

精益数据分析(28/126):解读商业模式拼图与关键指标

精益数据分析&#xff08;28/126&#xff09;&#xff1a;解读商业模式拼图与关键指标 在创业和数据分析的探索旅程中&#xff0c;每一次深入研究都可能带来新的启发和突破。今天&#xff0c;我们依旧带着共同进步的初心&#xff0c;深入解读《精益数据分析》中关于商业模式的…...

QT6 源(52)篇二:存储 c 语言字符串的类 QByteArray 的使用举例,

&#xff08;3&#xff09; &#xff08;4&#xff09; 谢谢...

工业摄像头通过USB接口实现图像

工业摄像头系列概览&#xff1a;类型与应用 工业摄像头系列涵盖了多种类型&#xff0c;以满足不同行业和应用的需求。以下是对工业摄像头系列的一些介绍&#xff1a; 一、主要类型与特点 USB工业摄像头 &#xff1a;这类摄像头通常通过USB接口与计算机连接&#xff0c;适用于…...

【BBDM】main.py -- notes

命令行接口 python main.py [OPTIONS]参数 参数类型默认值说明-c, --configstr"BBDM_base.yml"配置文件路径-s, --seedint1234随机种子&#xff0c;用于结果复现-r, --result_pathstr"results"结果保存目录-t, --trainflagFalse训练模式开关&#xff1a;…...

X86物理机安装iStoreOS软路由

目录 安装前准备 制作启动盘 安装系统到硬盘 启动与初始配置 常见问题与注意事项 参考资料 安装前准备 硬件设备 X86物理机&#xff08;如普通电脑、J4125/N5105等小主机&#xff09; U盘&#xff08;建议容量≥2GB&#xff09; 显示器、键盘&#xff08;用于初始配置…...

QML Date:日期处理示例

目录 引言相关阅读QML Date对象知识概要格式化选项 DateExamples示例解析代码解析示例1&#xff1a;日期格式化示例2&#xff1a;不同地区的日期显示示例3&#xff1a;日期解析示例4&#xff1a;自定义格式示例5&#xff1a;日期与时间戳转换 运行效果总结下载链接 引言 在Qt …...

python 与Redis操作整理

以下是使用 Python 操作 Redis 的完整整理&#xff0c;涵盖基础操作、高级功能及最佳实践&#xff1a; 1. 安装与连接 (1) 安装库 pip install redis(2) 基础连接 import redis# 创建连接池&#xff08;推荐复用连接&#xff09; pool redis.ConnectionPool(hostlocalhost, …...

【Linux】环境监控系统软件框架

目录 tasks.h type.h main.c tasks.c makefile 运行结果 调用多线程框架&#xff0c;在主函数写好环境监控文件的函数&#xff0c;使用结构体封装环境指标的参数 最后使用makefile管理工程文件 tasks.h #include<pthread.h>#ifndef __TASK_H__ #define __TASK_H_…...

WPF实现数字孪生示例

WPF 数字孪生系统实现示例 数字孪生(Digital Twin)是通过数字化手段在虚拟空间中构建物理实体的精确数字模型,并实现虚实映射、实时交互和智能决策的技术。本文将展示如何使用WPF实现一个基础的数字孪生系统示例。 一、系统架构设计 1. 整体架构 +-------------------+ | …...

对卡尔曼滤波的理解和简单示例实现

目录 一、概述 二、基本公式解释 1&#xff09;状态转移方程 2&#xff09;状态更新方程 3&#xff09;卡尔曼系数更新方程 4&#xff09;误差协方差估计方程 三、一个简单示例 一、概述 经典卡尔曼滤波算法在线性系统中运用非常广泛&#xff0c;可以对数据实现很好的平…...

Linux基础命令总结

Linux系统命令 1. systemctl 1. 基本语法 systemctl start | stop | restart | status 服务名 2. 经验技巧查看服务的方法:/usr/lib/systemd/system 3. 案例实操 (1)查看防火墙服务的状态 systemctl status firewalld (2)停止防火墙服务 systemctl stop firewalld (…...

视觉大模型专栏导航

关于视觉大模型专栏&#xff0c;暂时还没有比较明确的更新计划&#xff0c;最近会在本专栏上更新关于Sam模型的基本原理&#xff0c;包括Image Encoder、Prompt Encoder及Mask Decoder等模块的实现&#xff1b;还有记录下如何利用Sam代码跑通一个demo。 后期接触了其他视觉大模…...

Eigen的主要类及其功能

Eigen 是一个高性能的 C 模板库&#xff0c;主要用于线性代数、矩阵和向量运算。它提供了许多类来支持各种数学运算&#xff0c;以下是 Eigen 的主要类及其功能分类。 1. 核心矩阵和向量类 这些是 Eigen 中最常用的类&#xff0c;用于表示矩阵和向量&#xff1a; Matrix - 通用…...

深入理解TransmittableThreadLocal:原理、使用与避坑指南

一、ThreadLocal与InheritableThreadLocal回顾 在介绍TransmittableThreadLocal之前&#xff0c;我们先回顾一下Java中的ThreadLocal和InheritableThreadLocal。 1. ThreadLocal ThreadLocal提供了线程局部变量&#xff0c;每个线程都可以通过get/set访问自己独立的变量副本…...