从零手写实现 nginx-20-placeholder 占位符 $
前言
大家好,我是老马。很高兴遇到你。
我们为 java 开发者实现了 java 版本的 nginx
https://github.com/houbb/nginx4j
如果你想知道 servlet 如何处理的,可以参考我的另一个项目:
手写从零实现简易版 tomcat minicat
手写 nginx 系列
如果你对 nginx 原理感兴趣,可以阅读:
从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?
从零手写实现 nginx-02-nginx 的核心能力
从零手写实现 nginx-03-nginx 基于 Netty 实现
从零手写实现 nginx-04-基于 netty http 出入参优化处理
从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)
从零手写实现 nginx-06-文件夹自动索引
从零手写实现 nginx-07-大文件下载
从零手写实现 nginx-08-范围查询
从零手写实现 nginx-09-文件压缩
从零手写实现 nginx-10-sendfile 零拷贝
从零手写实现 nginx-11-file+range 合并
从零手写实现 nginx-12-keep-alive 连接复用
从零手写实现 nginx-13-nginx.conf 配置文件介绍
从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?
从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?
从零手写实现 nginx-16-nginx 支持配置多个 server
从零手写实现 nginx-17-nginx 默认配置优化
从零手写实现 nginx-18-nginx 请求头+响应头操作
从零手写实现 nginx-19-nginx cors
从零手写实现 nginx-20-nginx 占位符 placeholder
从零手写实现 nginx-21-nginx modules 模块信息概览
从零手写实现 nginx-22-nginx modules 分模块加载优化
从零手写实现 nginx-23-nginx cookie 的操作处理
从零手写实现 nginx-24-nginx IF 指令
nginx 的占位符
Nginx 是一个高性能的 HTTP 和反向代理服务器。它使用占位符(变量)来动态地生成配置和响应。
这些占位符可以在 Nginx 配置文件中使用,并在运行时被特定的值替换。
以下是对 Nginx 占位符的详细介绍,包括一些常见的变量及其用法。
1. 基本语法
Nginx 变量的语法格式是 $variable_name
。例如:
server {listen 80;server_name example.com;location / {return 200 "The request URI is $uri\n";}
}
在这个例子中,$uri
是一个占位符,表示请求的 URI。
2. 内置变量
Nginx 提供了许多内置变量,以下是一些常见的内置变量:
$args
:请求中的参数。$content_length
:请求的 Content-Length 头字段。$content_type
:请求的 Content-Type 头字段。$document_root
:当前请求的根目录或 alias 指定的路径。$host
:请求的主机头字段,如果主机头字段不可用,则等于服务器名称。$http_user_agent
:客户端的 User-Agent 头字段。$http_cookie
:客户端的 Cookie 头字段。$limit_rate
:用于限制连接速率。$request_method
:请求方法(GET、POST 等)。$remote_addr
:客户端 IP 地址。$remote_port
:客户端端口。$request_uri
:完整的原始请求 URI,包括参数。$scheme
:请求使用的协议(http 或 https)。$server_protocol
:请求使用的协议版本。$server_addr
:服务器的地址。$server_name
:服务器名称。$server_port
:服务器端口。$uri
:不包含请求参数的请求 URI。
3. 自定义变量
除了内置变量,Nginx 还允许用户自定义变量。自定义变量可以在 set
指令中定义。以下是一个示例:
server {listen 80;server_name example.com;set $my_variable "Hello, Nginx!";location / {return 200 "$my_variable\n";}
}
在这个例子中,定义了一个自定义变量 $my_variable
,其值为 "Hello, Nginx!"
,并在响应中返回这个值。
4. 使用变量进行条件控制
Nginx 的 if
指令可以根据变量的值进行条件控制。例如:
server {listen 80;server_name example.com;location / {if ($request_method = POST) {return 405 "Method Not Allowed\n";}return 200 "Hello, Nginx!\n";}
}
在这个例子中,如果请求方法是 POST,服务器会返回 405 状态码和 "Method Not Allowed" 信息,否则返回 200 状态码和 "Hello, Nginx!" 信息。
5. 变量的应用场景
变量在 Nginx 中有许多实际应用场景:
- 日志记录:可以在日志格式中使用变量记录详细的请求信息。
- URL 重写:使用变量来实现复杂的 URL 重写规则。
- 负载均衡:在负载均衡配置中使用变量进行复杂的请求路由。
- 限速限流:使用变量动态控制请求的限速限流策略。
示例:动态生成响应
下面是一个结合多个变量的示例,用于动态生成响应内容:
server {listen 80;server_name example.com;location / {set $custom_message "Your IP is $remote_addr and you are using $http_user_agent";return 200 "$custom_message\n";}
}
在这个示例中,服务器会返回一个包含客户端 IP 地址和 User-Agent 的消息。
Nginx 的占位符功能强大且灵活,通过合理地使用这些变量,可以实现许多复杂的功能和动态配置。
为什么 nginx 要支持占位符呢?
Nginx 支持占位符(变量)的主要原因是为了提供灵活性和动态性,使其配置能够适应各种复杂的应用场景。以下是 Nginx 支持占位符的一些关键原因和优势:
1. 动态配置
占位符使得 Nginx 配置文件能够根据实际请求动态生成响应或调整行为。例如,可以根据请求的 URI、方法或头信息来动态地路由请求、返回不同的内容或者做其他处理。
示例:动态内容返回
server {listen 80;server_name example.com;location / {return 200 "Requested URI: $uri\n";}
}
这个示例会根据请求的 URI 返回相应的消息,使得响应内容是动态生成的。
2. 细粒度控制
通过占位符,Nginx 可以对请求和响应进行细粒度控制。例如,基于客户端 IP 地址、User-Agent 或请求参数进行不同的处理。这种细粒度控制有助于实现精细的访问控制、安全检查、个性化服务等。
示例:基于 IP 地址的访问控制
server {listen 80;server_name example.com;location / {if ($remote_addr = "192.168.1.1") {return 403 "Access denied\n";}return 200 "Welcome\n";}
}
这个示例会根据客户端的 IP 地址进行访问控制。
3. 简化配置管理
占位符可以减少重复配置,提高配置文件的可读性和可维护性。通过定义变量和复用这些变量,可以使得配置文件更简洁、直观。
示例:复用变量简化配置
server {listen 80;server_name example.com;set $root_path /var/www/html;location / {root $root_path;}location /images {root $root_path;}
}
在这个示例中,通过定义变量 $root_path
,避免了重复配置根目录路径。
4. 支持复杂应用场景
Nginx 的占位符使其能够支持复杂的应用场景,例如负载均衡、日志记录、限速限流等。通过使用变量,可以实现更灵活的负载均衡策略、详细的日志记录格式、动态的限速策略等。
示例:自定义日志格式
log_format custom '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log custom;
这个示例通过占位符定义了自定义的日志格式,以记录详细的请求信息。
5. 安全与优化
通过使用占位符,可以实现动态的安全检查和优化策略。例如,根据请求头信息或者参数来启用或禁用某些功能,从而增强安全性和性能。
示例:根据 User-Agent 进行优化
server {listen 80;server_name example.com;location / {if ($http_user_agent ~* "Mobile") {set $mobile 1;}if ($mobile) {return 200 "Mobile optimization enabled\n";}return 200 "Standard optimization\n";}
}
这个示例展示了如何根据 User-Agent 实现移动设备优化。
总结
Nginx 支持占位符的主要目的是提供更高的灵活性和动态性,使其能够适应各种复杂的应用场景和需求。
通过占位符,Nginx 的配置能够变得更加简洁、可读、可维护,并且能够实现复杂的控制逻辑,从而提供更强大的功能和更高的性能。
java 如何设计实现?
系统内置的 placeholder 变量
我们首先实现内置的 placeholder 占位符操作。
定义抽象的接口
/*** 占位符处理类* @since 0.17.0** @author 老马啸西风*/
public abstract class AbstractNginxPlaceholder implements INginxPlaceholder {private static final Log logger = LogFactory.getLog(AbstractNginxPlaceholder.class);@Overridepublic void placeholder(NginxRequestDispatchContext context) {// 上下文存储的内容Map<String, Object> placeholderMap = context.getPlaceholderMap();// 请求头FullHttpRequest request = context.getRequest();String key = getKey(request, context);Object value = extract(request, context);placeholderMap.put(key, value);logger.info("placeholder put key={},value={}", key, value);}/*** 提取值* @param request 请求头* @param context 上下文* @return 结果*/protected abstract Object extract(FullHttpRequest request, NginxRequestDispatchContext context);/*** 唯一标识* @param request 请求头* @param context 上下文* @return 结果*/protected abstract String getKey(FullHttpRequest request, NginxRequestDispatchContext context);}
常见内置的实现
$args
:请求中的参数。$content_length
:请求的 Content-Length 头字段。$content_type
:请求的 Content-Type 头字段。$document_root
:当前请求的根目录或 alias 指定的路径。$host
:请求的主机头字段,如果主机头字段不可用,则等于服务器名称。$http_user_agent
:客户端的 User-Agent 头字段。$http_cookie
:客户端的 Cookie 头字段。$limit_rate
:用于限制连接速率。$request_method
:请求方法(GET、POST 等)。$remote_addr
:客户端 IP 地址。$remote_port
:客户端端口。$request_uri
:完整的原始请求 URI,包括参数。$scheme
:请求使用的协议(http 或 https)。$server_protocol
:请求使用的协议版本。$server_addr
:服务器的地址。$server_name
:服务器名称。$server_port
:服务器端口。$uri
:不包含请求参数的请求 URI。
以 args 为例,其他的实现类似:
/*** 占位符处理类* @since 0.17.0** @author 老马啸西风*/
public class NginxPlaceholderArgs extends AbstractNginxPlaceholder {private static final Log logger = LogFactory.getLog(NginxPlaceholderArgs.class);@Overrideprotected Object extract(FullHttpRequest request, NginxRequestDispatchContext context) {QueryStringDecoder decoder = new QueryStringDecoder(request.uri());StringBuilder args = new StringBuilder();for (Map.Entry<String, List<String>> entry : decoder.parameters().entrySet()) {for (String value : entry.getValue()) {if (args.length() > 0) {args.append("&");}args.append(entry.getKey()).append("=").append(value);}}return args.toString();}@Overrideprotected String getKey(FullHttpRequest request, NginxRequestDispatchContext context) {return "$args";}}
set 的支持
可以看到 nginx 默认支持了 set 操作符,可以设置一个变量。
这个属于操作指令,我们在上一期的指令中进行拓展:
/*** SET 符号,设置一个 $ 变量** @since 0.17.0* @author 老马啸西风*/
public class NginxParamHandleSet extends AbstractNginxParamHandle {private static final Log logger = LogFactory.getLog(NginxParamHandleSet.class);/*** # 设置一个占位符的值** set $mobile 1;** @param configParam 参数* @param context 上下文*/@Overridepublic void doBeforeDispatch(NginxUserConfigParam configParam, NginxRequestDispatchContext context) {Map<String, Object> placeholderMap = context.getPlaceholderMap();// 处理List<String> values = configParam.getValues();String headerName = values.get(0);String headerValue = values.get(1);// 变量名必须以 $ 开始if(!headerName.startsWith(NginxConst.PLACEHOLDER_PREFIX)) {throw new Nginx4jException("SET 指令对应的变量名必须以 $ 开始");}placeholderMap.put(headerName, headerValue);}//...@Overridepublic boolean doMatch(NginxUserConfigParam configParam, NginxRequestDispatchContext context) {return "set".equalsIgnoreCase(configParam.getName());}}
我们把 set 对应的指令值,放入到 placeholderMap 占位符中。
set指令 + 占位符的处理的时机
我们放在 request 分发处理前,统一处理:
/*** 请求头的统一处理* @param context 上下文* @author 老马啸西风*/protected void beforeDispatch(final NginxRequestDispatchContext context) {// 参数管理类final INginxParamManager paramManager = context.getNginxConfig().getNginxParamManager();// v0.17.0 占位符管理类final INginxPlaceholderManager placeholderManager = context.getNginxConfig().getNginxPlaceholderManager();// 提前处理内置的各种参数placeholderManager.init(context);//1. 当前的配置NginxUserServerLocationConfig locationConfig = context.getCurrentUserServerLocationConfig();if(locationConfig == null) {return;}List<NginxUserConfigParam> directives = locationConfig.getDirectives();if(CollectionUtil.isEmpty(directives)) {return;}// 处理for(NginxUserConfigParam configParam : directives) {// 占位符处理placeholderHandle(configParam, placeholderManager, context);List<INginxParamHandle> handleList = paramManager.paramHandleList(configParam, context);if(CollectionUtil.isNotEmpty(handleList)) {for(INginxParamHandle paramHandle : handleList) {paramHandle.beforeDispatch(configParam, context);}}}}/*** 占位符处理** SET 问题,这个是按顺序处理的,所以暂时不用特别考虑** @param configParam 配置指令* @param placeholderManager 占位符管理类* @param context 上下文* @since 0.17.0*/protected void placeholderHandle(NginxUserConfigParam configParam,final INginxPlaceholderManager placeholderManager,final NginxRequestDispatchContext context) {String name = configParam.getName();if(name.equals("set")) {logger.warn("暂时不处理 set 指令对应的操作符替换,后续可考虑改进。");return;}// name 暂时不添加 $ 处理// valueString value = configParam.getValue();String actualValue = getPlaceholderStr(value, placeholderManager, context);configParam.setValue(actualValue);// listList<String> valueList = configParam.getValues();List<String> newValueList = new ArrayList<>();if(CollectionUtil.isNotEmpty(valueList)) {for(String valueItem : valueList) {String actualValueItem = getPlaceholderStr(valueItem, placeholderManager, context);newValueList.add(actualValueItem);}configParam.setValues(newValueList);}// 结束}/*** 获取占位符对应的值* @param value 原始值* @param placeholderManager 管理类* @param context 上下文* @return 结果*/protected String getPlaceholderStr(String value,final INginxPlaceholderManager placeholderManager,final NginxRequestDispatchContext context) {// valueif(value.startsWith(NginxConst.PLACEHOLDER_PREFIX)) {Object actualValue = placeholderManager.getValue(context, value);if(actualValue == null) {logger.error("占位符未初始化 value={}", value);throw new Nginx4jException("占位符未初始化" + value);}// 设置值String actualValueStr = actualValue.toString();logger.info("占位符替换 value={}, actualValueStr={}", value, actualValueStr);return actualValueStr;}// 原始值return value;}
首先初始化所有的占位符策略;
然后依次执行以前的 param 用户指令,这里 set 会按照顺序执行。
我们在占位符策略处理时特意跳过了 set,其实可以细化一点,比如支持 value 值使用 $
占位符。
测试
完成了上面的实现,本地启动验证一下:
基本访问:http://192.168.1.12:8080/
信息: [Nginx] channelRead writeAndFlush start request=HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 0, cap: 0, components=0))
GET /favicon.ico HTTP/1.1
Host: 192.168.1.12:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://192.168.1.12:8080/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
content-length: 0, id=40a5effffe257be0-00002a80-00000004-f834a6fd4eed4fe9-527bc66f
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: 命中普通前缀配置 requestUri=/favicon.ico, value=/
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$args,value=
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$content_length,value=0
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$content_type,value=null
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$document_root,value=/D:/github/nginx4j/target/classes/
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$host,value=192.168.1.12:8080
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$http_cookie,value=
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$remote_addr,value=192.168.1.12
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$remote_port,value=54511
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$request_method,value=GET
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$request_uri,value=/favicon.ico
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$schema,value=http
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$server_addr,value=192.168.1.12
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$server_name,value=192.168.1.12:8080
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$server_port,value=192.168.1.12:8080
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$server_protocol,value=HTTP/1.1
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$uri,value=/favicon.ico
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl info
信息: placeholder put key=$user_agent,value=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
六月 09, 2024 8:51:12 下午 com.github.houbb.log.integration.adaptors.commons.JakartaCommonsLoggingImpl warn
警告: 暂时不处理 set 指令对应的操作符替换,后续可考虑改进。
...
这里的日志量还是比较多的,我们把级别还是从 INFO 调整为 debug 比较合理。
小结
占位符为 nginx 的配置提供了非常强大灵活的能力。
我们目前实现的指令比较少,后续考虑花一段时间,将 nginx 的常见指令都支持一下。
这样的 nginx 才是强大易用的。
我是老马,期待与你的下次重逢。
开源地址
为了便于大家学习,已经将 nginx 开源
https://github.com/houbb/nginx4j
相关文章:
从零手写实现 nginx-20-placeholder 占位符 $
前言 大家好,我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的,可以参考我的另一个项目: 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …...
leetcode290:单词规律
题目链接:290. 单词规律 - 力扣(LeetCode) class Solution { public:bool wordPattern(string pattern, string s) {unordered_map<char, string> s2t;unordered_map<string, char> t2s;int len pattern.size();int CountSpace…...
IDEA 2022
介绍 【尚硅谷IDEA安装idea实战教程(百万播放,新版来袭)】 jetbrains 中文官网 IDEA 官网 IDEA 从 IDEA 2022.1 版本开始支持 JDK 17,也就是说如果想要使用 JDK 17,那么就要下载 IDEA 2022.1 或之后的版本。 公司…...
Vue TypeScript 实战:掌握静态类型编程
title: Vue TypeScript 实战:掌握静态类型编程 date: 2024/6/10 updated: 2024/6/10 excerpt: 这篇文章介绍了如何在TypeScript环境下为Vue.js应用搭建项目结构,包括初始化配置、创建Vue组件、实现状态管理利用Vuex、配置路由以及性能优化的方法&#x…...
Hudi extraMetadata 研究总结
前言 研究总结 Hudi extraMetadata ,记录研究过程。主要目的是通过 extraMetadata 保存 source 表的 commitTime (checkpoint), 来实现增量读Hudi表写Hudi表时,保存增量读状态的事务性,实现类似于流任务中的 exactly-once 背景需求 有个需求:增量读Hudi表关联其他Hudi…...
Vue31-自定义指令:总结
一、自定义函数的陷阱 1-1、自定义函数名 自定义函数名,不能用驼峰式!!! 示例1: 示例2: 1-2、指令回调函数的this 【回顾】: 所有由vue管理的函数,里面的this直接就是vm实例对象。…...
Windows环境如何使用Flutter Version Manager (fvm)
Windows环境如何使用Flutter Version Manager (fvm) Flutter Version Manager (fvm) 是一个用于管理多个 Flutter SDK 版本的命令行工具,它允许开发者在不同项目之间轻松切换 Flutter 版本。这对于需要维护多个使用不同 Flutter 版本的项目的开发人员来说非常有用。…...
优化Elasticsearch搜索性能:查询调优与索引设计
在构建基于 Elasticsearch 的搜索解决方案时,性能优化是关键。本文将深入探讨如何通过查询调优和索引设计来优化 Elasticsearch 的搜索性能,从而提高用户体验和系统效率。 查询调优 优化查询是提高 Elasticsearch 性能的重要方法。以下是一些有效的查询…...
STM32-17-DAC
STM32-01-认识单片机 STM32-02-基础知识 STM32-03-HAL库 STM32-04-时钟树 STM32-05-SYSTEM文件夹 STM32-06-GPIO STM32-07-外部中断 STM32-08-串口 STM32-09-IWDG和WWDG STM32-10-定时器 STM32-11-电容触摸按键 STM32-12-OLED模块 STM32-13-MPU STM32-14-FSMC_LCD STM32-15-DMA…...
一杯咖啡的艺术 | 如何利用数字孪生技术做出完美的意式浓缩咖啡?
若您对数据分析以及人工智能感兴趣,欢迎与我们一起站在全球视野关注人工智能的发展,与Forrester 、德勤、麦肯锡等全球知名企业共探AI如何加速制造进程, 共同参与6月20日由Altair主办的面向工程师的全球线上人工智能会议“AI for Engineers”…...
使用QT制作QQ登录界面
mywidget.cpp #include "mywidget.h"Mywidget::Mywidget(QWidget *parent): QWidget(parent) {/********制作一个QQ登录界面*********************/this->resize(535,415);//设置登录窗口大小this->setFixedSize(535,415);//固定窗口大小this->setWindowTi…...
代码随想录训练营第七天 344反转字符串 541反转字符串II 替换数字
第一题: 原题链接:344. 反转字符串 - 力扣(LeetCode) 思路: 双指针,一根指向字符串的头部,一根指向字符串的尾部。两个指针向中间移动,交换两根指针指向的值。 代码如下…...
【Python】数据处理:SQLite操作
使用 Python 与 SQLite 进行交互非常方便。SQLite 是一个轻量级的关系数据库,Python 标准库中包含一个名为 sqlite3 的模块,可以直接使用。 import sqlite3数据库连接和管理 连接到 SQLite 数据库。如果数据库文件不存在,则创建一个新数据库…...
NXP RT1060学习总结 - fsl_flexcan 基础CAN函数说明 -3
概要 CAN测试源码: https://download.csdn.net/download/qq_35671135/89425377 根据fsl_flexcan.h文件从文件末尾往前面梳理,总共30个基础CAN函数; 该文章只梳理常规CAN,增强型CAN后面再单独梳理。 使用的是RT1064开发板进行测试…...
2024年第三届数据统计与分析竞赛(B题)数学建模完整思路+完整代码全解全析
你是否在寻找数学建模比赛的突破点?数学建模进阶思路! 详细请查 作为经验丰富的数学建模团队,我们将为你带来2024年第三届数据统计与分析竞赛(B题)的全面解析。这个解决方案包不仅包括完整的代码实现,还有…...
高通Android 12 右边导航栏改成底部显示
最近同事说需要修改右边导航栏到底部,问怎么搞?然后看下源码尝试下。 1、Android 12修改代码路径 frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java a/frameworks/base/services/core/java/com/android/server/wm/Display…...
2.6数据报与虚电路
数据报 当作为通信子网用户的端系统要发送一个报文时,在端系统中实现的高层协议先把报文拆成若干个带有序号的数据单元,并在网络层加上地址等控制信息后形成数据报分组(即网络层PDU)中间结点存储分组一段很短的时间,找到最佳的路由后&#x…...
小主机折腾记26
双独立显卡调用问题 前两天将tesla p4从x99大板上拆了下来,将880G5twr上的rx480 4g安装到了x99大板上,预计是dg1输出,rx480做3d运算。安装完驱动后,还想着按照之前tesla p4的设置方法去设置rx480,结果果然,…...
ArrayList浅析
目录 一、ArrayList源码1.1 迭代器1.1.1 Itr源码浅析1.1.2 ListItr源码浅析 1.2 常用方法1.3 System.arraycopy1.4 ArrayList 的创建方式 二、引申问题2.1 ArrayList的大小是如何增加的?2.2 什么情况下你会使用ArrayList2.3 在索引中ArrayList的增加或者删除某个对象…...
Spring Boot整合hibernate-validator实现数据校验
文章目录 概念基本概念常用校验注解 前置内容整合Hibernate Validator快速入门优雅处理参数校验异常其余注解校验自定义校验注解 参考来源 概念 基本概念 Hibernate Validator 是一个参数校验框架,可以非常方便地帮助我们校验应用程序的入参,实现了参数…...
Ubuntu系统中网易云音乐编译安装
项目地址: netease-cloud-music-gtk: Linux 平台下基于 Rust GTK 开发的网易云音乐播放器 目录 1.README.md中按照步骤来 2.安装git 3.报错 sudo apt install cmake sudo apt-get install libdbus-1-dev sudo apt install dnf sudo dnf install gettext 继…...
MPLS标签号
标签被压入在2层与3层之间 称为 2.5层 标签的格式----32 位4 个字节 前 20 位为标签号,2~20 个标签号;其中1-15号保留,作为特殊编号; 第 21-23位 exp,3位8个数,为优先级,用于Q0S 策略使用&a…...
OpenHarmony napi 编译 .so 并打包成 .har
一、前言 最近在搞公司标准产品适配OpenHarmony 平台, 按照行业上的常用方法,在Android 是将底层代码用c 封装成 xxx.so ,然后将其他一部分打包成 xxx.jar。 因此,在OpenHarmony 平台也是打算按照这个模式。正所谓,好…...
python 循环导入(circular imports)解决方法
在 Python 中,大部分人都应该都遇到过循环导入的问题。 循环导入是指两个文件各自尝试导入另一个文件(模块),当一个模块没有完全初始化时会导致失败。解决这种情况的最好方法是将代码分层组织,这样导入的关系就会自然…...
01、Linux网络设置
目录 1.1 查看及测试网络 1.1.1 查看网络配置 1、查看网络接口地址 2、查看主机状态 3、查看路由表条目 4、查看网络连接qing 1.1.2 测试网络连接 1.测试网络连接 2.跟踪数据包的路由路径 3.测试DNS域名解析 1.2 设置网络地址参数 1.2.1 使用网络配置命令 1.修改网卡…...
ssm160基于Java技术的会员制度管理的商品营销系统的设计与实现+vue
商品营销系统计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本商品营销系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理…...
边缘计算网关在智慧厕所远程监测与管理的应用
随着智慧城市建设的不断深入,城市公共设施的智慧化管理成为了提升城市品质和居民生活质量的关键建设。公厕作为城市基础设施的重要组成部分,其管理效率和卫生状况直接影响着市民的日常生活体验。在公厕设施建设背景下,边缘计算网关技术的应用…...
嵌入式linux中设备树使用of函数操作基本方法
各位开发者大家好,今天主要给大家分享一下,如何使用of操作函数,获取对应设备树节点先关的属性信息。 第一:of_find_property函数 of_find_property 函数用于在设备树中查找节点下具有指定名称的属性。如果找到了该属性,可以通过返回的属性结构体指针进行进一步的操作,比…...
10.GLM
智谱AI GLM 大模型家族 最强基座模型 GLM-130B GLM (General Language Model Pretraining with Autoregressive Blank Infilling) 基于自回归空白填充的通用语言模型(GLM)。GLM通过增加二维位置编码并允许以任意顺序预测跨度来改进空白填充预训练&…...
【深度学习】Transformer分类器,CICIDS2017,入侵检测,随机森林、RFE、全连接神经网络
文章目录 1 前言2 随机森林训练3 递归特征消除 RFE Recursive feature elimination4 DNN5 Transformer5.1. 输入嵌入层(Input Embedding Layer)5.2. 位置编码层(Positional Encoding Layer)5.3. Transformer编码器层(T…...
怎么做网站投放adsense/关键词查网站
代码的github地址:https://github.com/philipperemy/yolo-9000 我是Ubuntu 16.04系统 1、拉取项目 git clone --recursive https://github.com/philipperemy/yolo-9000.git 因为我只能用http的地址,当然你可以跟github里面一样用git地址,…...
建标网/线上seo关键词优化软件工具
在现实问题中我们对于一个实验往往会重复成千上万次,那么我们就需要关注在实验次数趋于无穷之后,整个实验的期望会趋于怎样一个结果。其实这一章“极限定理”都是在处理这个问题。 强大数定理: 这里的证明过程给出了一些前提条件,…...
郑州做网站推广价格/自助建站系统个人网站
在知乎看到一篇文章,https://zhuanlan.zhihu.com/p/357075502,里边提到model.eval模式不会影响各层的gradient计算行为,即gradient计算和存储与training模式一样,只是不进行反向传播(back probagation)。 这个地方的不…...
如何打击网站/宁波seo外包公司
毕业工作一年之后,有了转行的想法,偶然接触到程序员这方面,产生了浓厚且强烈的兴趣,开始学习前端,成功收割了大厂offer,开始了我的程序员生涯。 在自学过程中有过一些小厂的面试经历,也在一些小…...
网站设计培训成都/seo关键词外包
由于网络原因,访问国外的pip源超级慢,因此可将源改为国内源(都是pipy官网的镜像),就能体验到流的飞起的速度了 可临时修改,也可永久修改 临时修改:在后边加个-i参数指定pip源,如下…...
长春 网络设计/做seo必须有网站吗
我无法使用pyodbc连接到mySQl数据库。以下是我的脚本片段:import pyodbcimport csvcnxn pyodbc.connect("DRIVER{MySQL ODBC 3.51 Driver}; SERVERlocalhost;DATABASEmydb; UIDroot; PASSWORDthatwouldbetelling;")crsr cnxn.cursor()with open(C:\\sku…...