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

ASP.NET Core - 配置系统之配置提供程序

ASP.NET Core - 配置系统之配置提供程序

  • 3. 配置提供程序
    • 3.1 文件配置提供程序
      • 3.1.1 JSON配置提供程序
      • 3.1.2 XML配置提供程序
      • 3.1.3 INI配置提供程序
    • 3.2 环境变量配置提供程序
    • 3.3 命令行配置提供程序
    • 3.4 内存配置提供程序
    • 3.5 配置加载顺序
  • 3.6 默认配置来源

3. 配置提供程序

前面的章节提到,通过 IConfigurationBuilder 的实现类对象,我们可以自由地往配置系统中添加不同的配置提供程序,从而获取不同来源的配置信息。.NET Core 中,微软提供了以下这些内置的配置提供程序:

  • 文件配置提供程序
  • 环境变量配置提供程序
  • 命令行配置提供程序
  • Azure应用配置提供程序
  • Azure Key Vault 配置提供程序
  • Key-per-file配置提供程序
  • 内存配置提供程序
  • 应用机密(机密管理器)
  • 自定义配置提供程序

这里稍微介绍一下常用的几个。

3.1 文件配置提供程序

顾名思义,这个就是我们熟悉的配置加载方式,从配置文件中加载配置信息。配置文件多种多样,.NET Core 框架内置支持 Json、xml、ini 三种格式的文件提供程序:

  • JSON配置提供程序(JsonConfigurationProvider)
  • XML配置提供程序(XmlConfigurationProvider)
  • INI配置提供程序(IniConfigurationProvider)

以上这些配置提供程序,均继承于抽象基类 FileConfigurationProvider,当一个提供程序中发现重复的键时,提供程序会引发 FormatException,所有类型的文件提供程序都是这样的机制。

另外,所有文件配置提供程序都支持提供两个配置参数:

  • optional:bool 类型,指示该文件是否是可选的。如果该参数为false,但是指定的文件又不存在,则会报错。
  • reloadOnChange:bool 类型,指示该文件发生更改时,是否要重新加载配置。

3.1.1 JSON配置提供程序

JSON 配置提供程序被封装在 Microsoft.Extensions.Configuration.Json Nuget包中,若通过 ConfigurationBuilder 自行构建配置系统需要先安装该依赖包。它通过 JsonConfigurationProvider 在运行时从 Json 文件中加载配置。

使用方式非常简单,通过 IConfigurationBuilder 的实现类对象调用 AddJsonFile 扩展方法指定Json配置文件的路径即可。以下代码可用于控制台程序中创建主机并设置配置系统:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;using var host = Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((context, config) =>{// 清除原有的配置提供程序config.Sources.Clear();var env = context.HostingEnvironment;// 添加 json 配置文件config.AddJsonFile("appsettings.json",true, true).AddJsonFile($"appsetting.{env.EnvironmentName}.json", true, true);}).Build();var configuration = host.Services.GetService<IConfiguration>();Console.WriteLine($"Settings:Provider: {configuration.GetValue<string>("Settings:Provider")}");host.Run();

appsetting.json 配置文件中的内容如下:

{"Settings": {"Provider": "JsonProvider","version": {"subKey1": "value","subKey2": 1},"items": [ "item1", "item2", "item3" ]}
}

控制台程序运行之后输出如下:

在这里插入图片描述
这样有一点要注意的是,对于我们手动添加的配置文件需要设置一下文件属性,让其在项目生成的时候能够正常生成到运行目录,确保应用可以正常获取到该文件:

在这里插入图片描述

3.1.2 XML配置提供程序

XML 配置提供程序被封装在 Microsoft.Extensions.Configuration.Xml Nuget包中,通过 XmlConfigurationProvider 类在运行时从 XML 文件加载配置。

使用方式也很简单,与 JSON 配置提供程序类似,通过 AddXmlFile 扩展方法指定配置文件路径。

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;using var host = Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((context, config) =>{// 清除原有的配置提供程序config.Sources.Clear();var env = context.HostingEnvironment; 添加 json 配置文件//config.AddJsonFile("appsettings.json",true, true)//    .AddJsonFile($"appsetting.{env.EnvironmentName}.json", true, true);config.AddXmlFile("appsettings.xml", true, true);}).Build();var configuration = host.Services.GetService<IConfiguration>();Console.WriteLine($"Settings:Provider: {configuration.GetValue<string>("Settings:Provider")}");
Console.WriteLine($"Settings:items[1]: {configuration.GetValue<string>("Settings:items:1")}");host.Run();

xml 配置文件内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><Settings><Provider>XmlProvider</Provider><version><subKey1>value</subKey1><subKey2>1</subKey2></version><items>item1</items><items>item2</items><items>item3</items></Settings>
</configuration>

运行程序控制台输出如下:
在这里插入图片描述
这里有一个和版本有关的点,对Xml文件中使用同一元素名称的重复元素,一般也就是数组,.NET 6及之后的xml配置提供程序会自动为其编制索引,不再需要显式指定name属性。如果是 .NET 6 以下的版本则需要这样了:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><Settings><Provider>XmlProvider</Provider><version><subKey1>value</subKey1><subKey2>1</subKey2></version><items name="itemkey1">item1</items><items name="itemkey2">item2</items><items name="itemkey3">item3</items></Settings>
</configuration>
Console.WriteLine($"Settings:items[1]: {configuration.GetValue<string>("Settings:items:itemkey2")}");

另外xml文件中的属性也可用于提供值:

<?xml version="1.0" encoding="UTF-8"?>
<configuration><key attribute="value" /><section><key attribute="value" /></section>
</configuration>

获取属性的值可用以下配置键:

key:attribute
section:key:attribute

3.1.3 INI配置提供程序

INI 配置提供程序被封装在 Microsoft.Extensions.Configuration.Ini Nuget包,通过 IniConfigurationProvider 类在运行时从 INI 文件加载配置。使用方式如下:

ini 配置文件内容如下:

[Settings]
Provider="IniProvider"
version:subKey1="value"
version:subKey2=1
items:0="item1"
items:1="item2"
items:3="item3"

运行应用,控制台输出如下:

在这里插入图片描述

3.2 环境变量配置提供程序

环境变量配置提供程序被封装在 Microsoft.Extensions.Configuration.EnvironmentVariables, 通过 EnvironmentVariablesConfigurationProvider 在运行时从环境变量中以键值对的方式加载配置。

环境变量一般情况下是配置在机器上的,而不同的操作系统对环境变量的设置要求有所不同,当环境变量存在多层的时候,层级之间的分隔有些支持通过 : 号进行分隔,有些不支持,双下划线 __ 是全平台支持的,所以设置环境变量的时候要使用双下划线 __ 来代替冒号 :

各种不同的平台下怎么去添加环境变量这里就不细说了,Windows 下大家最起码都应该知道可以通过 我的电脑 -> 属性 -> 高级系统设置 去可视化的添加,命令行的方式可阅读下官方文章: ASP.NET Core 中的配置 | Microsoft Learn,Linux 平台下可以通过 export 命令临时添加,或者修改相应的配置文件 ~/.bashrc/etc/profile,大家仔细查一下资料就行了。

除了在机器上直接设置环境变量外,我们开发测试的过程中也可以通过 ASP.NET Core 框架下的 launchSettings.json 配置文件设置用于调试的临时环境变量。在应用启动调试时,该文件中的环境变量会替代系统的中的环境变量。

{"$schema": "https://json.schemastore.org/launchsettings.json","profiles": {"ConfigurationSample": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"launchUrl": "swagger","applicationUrl": "http://localhost:5004","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development","Custom_settings__Provider": "EnvironmentVariablesProvider","Custom_settings__version__subKey1": "value","Custom_settings__items__0": "item1","Custom_settings__items__1": "item2","Custom_settings__items__2": "item3"}}}
}

环境变量配置提供程序使用也很简单,注意以下示例为了使用 launchSettings.json 中的环境变量是在 ASP.NET Core 项目中测试的。

var builder = WebApplication.CreateBuilder(args);builder.Host.ConfigureAppConfiguration(builder =>
{builder.Sources.Clear();// 筛选前置为 Custom_ 的环境变量,将其加载为应用配置,其他的不加载builder.AddEnvironmentVariables("Custom_");
});var app = builder.Build();Console.WriteLine($"Settings:Provider: {app.Configuration.GetValue<string>("Settings:Provider")}");
Console.WriteLine($"Settings:items[1]: {app.Configuration.GetValue<string>("Settings:items:1")}");app.Run();

在添加环境变量时,通过指定参数 prefix,只读取限定前缀的环境变量。不过在读取环境变量时,会将前缀删除。如果不指定参数 prefix,那么会读取所有环境变量。

当创建默认通用主机(Host)时,默认就已经添加了前缀为DOTNET_的环境变量,如果是在 ASP.NET Core 中,配置了 Web 主机时,默认添加了前缀为 ASPNETCORE_ 的环境变量,而后主机加载应用配置时,再根据策略添加了其他的环境变量,如果没有传递 prefix 参数则是所有环境变量。这一块的加载机制,下面再细讲。

运行应用,控制台输出如下:

在这里插入图片描述
除此之外,环境变量提供程序还有一些隐藏的功能点,当没有向 AddEnvironmentVariables 传入前缀时,默认也会针对含有以下前缀的环境变量进行特殊处理:

在这里插入图片描述
这个功能点比较少用到,但是大家看到这个大概都会有点疑惑,具体的形式是怎么样的,下面稍微测试一下

首先在 launchSettings.json 文件中添加多一个环境变量:

"MYSQLCONNSTR_Default": "Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd=myPassword;"

之后在应用中打印如下两个配置:

Console.WriteLine($"ConnectionStrings:Default: { app.Configuration.GetValue<string>("ConnectionStrings:Default") }");
Console.WriteLine($"ConnectionStrings:Default_Provider: { app.Configuration.GetValue<string>("ConnectionStrings:Default_ProviderName") }");

输出结果如下:
在这里插入图片描述
也就是说,这种形式的环境变量会被自动转换为两个。

3.3 命令行配置提供程序

命令行配置提供程序被封装在 Microsoft.Extensions.Configuration.CommandLine 包中,通过 CommandLineConfigurationProvider 在运行时从命令行参数键值对中加载配置。

当我们通过 dotnet 命令启动一个 .NET Core 应用时,我们可以在命令后面追加一些参数,这些参数将在入口文件中被 args 变量接收到。命令行配置提供程序使用如下:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;using var host = Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((context, config) =>{// 清除原有的配置提供程序config.Sources.Clear();config.AddCommandLine(args);}).Build();var configuration = host.Services.GetService<IConfiguration>();Console.WriteLine($"Settings:Provider: {configuration.GetValue<string>("Settings:Provider")}");
Console.WriteLine($"Settings:items[1]: {configuration.GetValue<string>("Settings:items:1")}");host.Run();

之后通过命令行程序启动应用,并传入相应的参数:

dotnet ConfigurationSampleConsole.dll Settings:Provider=CommandLineProvider Settings:items:1=item1

在这里插入图片描述
命令行参数的设置有三种方式:

(1) 使用 = 号连接键值:

dotnet ConfigurationSampleConsole.dll Settings:Provider=CommandLineProvider Settings:items:0=item1 Settings:items:1=item2

(2) 使用 / 号表示键,值跟在键后面,键值以空格分隔

dotnet ConfigurationSampleConsole.dll /Settings:Provider CommandLineProvider /Settings:items:0 item1 /Settings:items:1 item2

(3) 使用 – 符号表示键,值跟在键后面,键值以空格分隔

dotnet ConfigurationSampleConsole.dll --Settings:Provider CommandLineProvider --Settings:items:0 item1 --Settings:items:1 item2

如果值之中本来就有空格的,可以使用 “” 号包括。

dotnet ConfigurationSampleConsole.dll --Settings:Provider CommandLineProvider --Settings:items:0 item1 --Settings:items:1 "test item2"

AddCommandLine 扩展方法提供了重载,允许额外传入一个参数,该参数提供一个交换映射字典,针对命令行配置参数进行key映射。例如命令行传入键是 name01 ,映射后的的键为 project:name。这里有一些要注意的点:

  • 交换映射key必须以---开头。当使用-开头时,命令行参数书写时也要以-开头,当使用--开头时,命令行参数书写时可以以--/开头。
  • 交换映射字典中的 key 不区分大小写,不能包含重复 key。如不能同时出现-n-N,但可以同时出现-n--n
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;using var host = Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((context, config) =>{// 清除原有的配置提供程序config.Sources.Clear();var switchMappings = new Dictionary<string, string>{["--b1"] = "Settings:Provider",["-b2"] = "Settings:items"};config.AddCommandLine(args, switchMappings);}).Build();var configuration = host.Services.GetService<IConfiguration>();Console.WriteLine($"Settings:Provider: {configuration.GetValue<string>("Settings:Provider")}");
Console.WriteLine($"Settings:items[1]: {configuration.GetValue<string>("Settings:items:1")}");host.Run();

在这里插入图片描述

3.4 内存配置提供程序

内存配置提供程序就比较简单了,它直接被包含在 Microsoft.Extensions.Configuration,通过 MemoryConfigurationProvider 在运行时从内存中的集合中加载配置。使用方式如下:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;using var host = Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((context, config) =>{// 清除原有的配置提供程序config.Sources.Clear();config.AddInMemoryCollection(new Dictionary<string, string> {{ "Settings:Provider", "InMemoryProvider" },{ "Settings:items:1", "MemoryItem" }});}).Build();var configuration = host.Services.GetService<IConfiguration>();Console.WriteLine($"Settings:Provider: {configuration.GetValue<string>("Settings:Provider")}");
Console.WriteLine($"Settings:items[1]: {configuration.GetValue<string>("Settings:items:1")}");host.Run();

在这里插入图片描述

3.5 配置加载顺序

上面介绍了一些常用的配置提供程序,这些配置提供程序都是通过扩展方法添加到 ConfigurationBuilder 对象中的,而从上面 ConfigurationBuilder 的源码可以看出,添加一个配置提供程序的时候其实应该是添加了一个对应的 IConfigurationSource 对象,而后在 ConfigurationBuilder 中被保存到集合中。

这就可以看出,配置系统是允许同时添加多种配置提供程序,支持多来源的配置信息同时存在的。那么当多个配置处理程序都被添加到配置系统之中,那我们从配置系统中通过配置键获取配置值的时候是怎么进行的呢,当多个配置提供程序存在相同的配置键时,我们获取到的配置值是哪个呢?

从 ConfigurationRoot 的源码中可以可以看到,当我们用索引器API读取配置值时,是调用了 GetConfiguration 方法

在这里插入图片描述

而GetConfiguration方法中的逻辑也很简单,只是遍历提供程序集合尝试从提供程序去获取值,需要关注的是遍历的顺序。

在这里插入图片描述
这里的逻辑是这样子的,倒序进行遍历,后添加的配置处理程序先被遍历,一旦通过key从提供程序中获取到值就返回结果,不再继续遍历。所以添加配置提供程序的顺序决定相同配置键最终的值, 当多个配置处理程序存在相同键时,越后添加的配置提供程序优先级越高,从最后的一个提供程序获取到值之后就不再从其他处理程序获取。

3.6 默认配置来源

上面也有提到通过主机运行和管理应用,在通过主机运行的项目中,主机在启动的时候就已经默认添加了一些配置提供程序,所以我们创建了一个 ASP.NET Core 模板项目之后就可以获取到 appsettings.json 等配置文件中的配置信息。下面介绍一下默认添加的配置提供程序。

在 Host.CreateDefaultBuilder(String[]) 方法或者 WebApplication.CreateBuilder(args) 方法执行的时候,会按照以下顺序添加应用的配置提供程序:

(1) 内存配置提供程序
(2) Chained 配置提供程序(添加现有的主机配置)
(3) JSON 配置提供程序 (添加 appsettings.json 配置文件)
(4) JSON 配置提供程序 (添加 appsettings.{Environment}.json 配置文件)
(5) 机密管理器(仅Windows)
(6) 环境变量配置提供程序 (未限定前缀)
(7) 命令行配置提供程序

配置分主机配置和应用配置,主机启动时应用仍未启动,主机启动过程中的配置就是主机配置。上面第一个Chained 配置提供程序就是承接过来的主机配置。而主机配置是按照以下顺序加载的:

(1) 环境变量配置提供程序(以 DOTNET_ 为前缀的环境变量)
(2) 命令行配置提供程序 (命令行参数)
(3) 环境变量配置提供程序(以 ASPNETCORE_ 为前缀的环境变量,如果是Web主机的话)

所以最终的应用配置加载顺序应该是下面这样:

(1) 内存配置提供程序
(2) 环境变量配置提供程序(以 DOTNET_ 为前缀的环境变量)
(3) 命令行配置提供程序 (命令行参数)
(4) 环境变量配置提供程序(以 ASPNETCORE_ 为前缀的环境变量,如果是Web主机的话)
(5) JSON 配置提供程序 (添加 appsettings.json 配置文件)
(6) JSON 配置提供程序 (添加 appsettings.{Environment}.json 配置文件)
(7) 机密管理器(仅Windows)
(8) 环境变量配置提供程序 (未限定前缀)
(9) 命令行配置提供程序 (命令行参数)

按照越后面添加的提供程序优先的方式,最终应用配置会覆盖主机配置,并且最优先是最后添加的命令行配置提供程序,我们可以通过以下方式打印配置系统中所有的配置提供程序,进行验证:

var builder = WebApplication.CreateBuilder(args);var app = builder.Build();var configurationRoot = (IConfigurationRoot)app.Configuration;
foreach (var provider in configurationRoot.Providers.AsEnumerable())
{Console.WriteLine(provider.ToString());
}app.Run();

最终控制台打印出来的结果如下:
在这里插入图片描述
虽然应用配置优先,会覆盖前面的主机配置,但是有一些变量会在初始化主机生成器的时候就提前进行锁定,并且之后不会受应用配置的影响:

  • 应用程序名称
  • 环境名称,例如 Development、Production 和 Staging
  • 内容根目录
  • Web 根目录
  • 是否要扫描托管启动程序集以及要扫描哪些程序集(IHostringStartup)。
  • 应用和库代码从 IHostBuilder.ConfigureAppConfiguration 回调中的 HostBuilderContext.Configuration 读取的变量。

这里提到环境名称,其实也就是软件运行的环境,最最基本的也会分为开发环境、生产环境两种。软件运行环境通过环境变量来设置,普通的.NET Core 应用环境变量key为NETCORE_ENVIRONMENT,Web应用环境变量key为ASPNETCORE_ENVIRONMENT,Web应用下如果两者同时存在,后者会覆盖前者。软件应用根据不同的环境会有不同的行为逻辑,例如上面讲到的 appsettings.{environment}.json 根据环境而不同的配置文件,例如之前的 入口文件 文章中讲到的 Startup 文件根据不同环境的分离配置方式,而我们在代码中有时也会根据环境处理不同的逻辑,这时候我们可以注入 IHostEnvironment 服务,通过它获取当前应用的运行环境,入口文件中无论是 WebApplicationBuilder 对象还是 WebApplication 对象都包含该类型的属性。

通过环境变量设置当前运行环境,其实环境变量的值只是一个字符串,我们可以设置成任意值,.NET Core 框架下 IHostEnvironment 也能够正常加载到相应的环境名称,但是.NET Core 默认只提供了对 Development、Production 和 Staging 三种环境的判别,以及相应的处理逻辑和扩展方法,如果是其他的自定义环境则需要开发人员自行进行相应的处理了。和 .NET Core 应用环境相关的知识点大家可以看一下官方文档: 在 ASP.NET Core 中使用多个环境 | Microsoft Learn

除了上面讲到的主机配置,其他还有一些主机配置,例如URLS,但这个是可以通过应用配置设置的,读取相应的配置值时也应从应用配置读取。

URLS 配置Web应用启动后的访问地址,这个配置可以多个地方设置,其中命令行参数最优先,其他地方设置的应该被命令行参数覆盖。但是如果通过Kestrel 终结点方式设置了Web应用的访问地址,那Kestrel 终结点的配置将覆盖其他所有的访问地址的配置。

如在 appsettings.json 中添加以下配置:

"Kestrel": {"Endpoints": {"Https": {"Url": "https://localhost:9999"}}
}

那么以下几种方式设置的 URLS 都会失效:

  • UseUrls
  • 命令行上的 --urls
  • 环境变量 ASPNETCORE__URLS

也就是说,就算我们用以下命令启动应用,应用最终的访问地址还是以 Kestrel 终结点配置的为准:

dotnet run --urls="https://localhost:7777"

Kestrel 配置与 URLS 配置不是一个参数,我们可以通过在命令行或者环境变量中设置 kestrel 中间点配置来覆盖 appsettings.json 中的,这又回到配置提供程序的优先级问题了。

set Kestrel__Endpoints__Https__Url=https://localhost:8888dotnet run Kestrel__Endpoints__Https__Url=https://localhost:8888

在主机启动的逻辑中Kestrel具备更高的最终优先级,但是其实主机内部是先根据URLS创建了一个终结点,之后又替换为 Kestrel 配置的终结点的。通过应用启动时的控制台输出可以看出。

在这里插入图片描述
这种情况对于单机应用没有什么影响,但是对于使用自动服务发现的微服务架构而言就可能有问题了,可能导致注册到服务注册中心的终结点是第一个,而后应用终结点又被改变,导致注册中心记录的服务终结点和实际的不一致。



参考文章:

ASP.NET Core 中的配置 | Microsoft Learn
配置 - .NET | Microsoft Learn
理解ASP.NET Core - 配置(Configuration)



ASP.NET Core 系列总结:
目录:ASP.NET Core 系列总结
上一篇:ASP.NET Core — 配置系统之配置添加
下一篇:ASP.NET Core — 配置系统之自定义配置提供程序

相关文章:

ASP.NET Core - 配置系统之配置提供程序

ASP.NET Core - 配置系统之配置提供程序 3. 配置提供程序3.1 文件配置提供程序3.1.1 JSON配置提供程序3.1.2 XML配置提供程序3.1.3 INI配置提供程序 3.2 环境变量配置提供程序3.3 命令行配置提供程序3.4 内存配置提供程序3.5 配置加载顺序 3.6 默认配置来源 3. 配置提供程序 前…...

【LeetCode: 215. 数组中的第K个最大元素 + 快速选择排序】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…...

【Flink系列】10. Flink SQL

10. Flink SQL Table API和SQL是最上层的API&#xff0c;在Flink中这两种API被集成在一起&#xff0c;SQL执行的对象也是Flink中的表&#xff08;Table&#xff09;&#xff0c;所以我们一般会认为它们是一体的。Flink是批流统一的处理框架&#xff0c;无论是批处理&#xff08…...

JavaScript网页设计案例-JavaScript实现数据脱敏的几种解决方式

数据脱敏是指对数据进行处理&#xff0c;使其在不改变原始数据含义的前提下&#xff0c;降低数据泄露的风险&#xff0c;保护用户隐私。 案例&#xff1a;JavaScript实现数据脱敏 1. 掩码脱敏 掩码脱敏是通过替换或隐藏数据中的部分字符来达到脱敏的效果。常见的掩码方式包括…...

第12篇:从入门到精通:掌握python高级函数与装饰器

第12篇&#xff1a;高级函数与装饰器 内容简介 本篇文章将深入探讨Python中的高级函数与装饰器。您将学习什么是高阶函数&#xff0c;掌握常用的高阶函数如map、filter、reduce的使用方法&#xff1b;理解闭包的概念及其应用&#xff1b;深入了解装饰器的定义与使用&#xff…...

审计文件标识作为水印打印在pdf页面边角

目录 说明 说明 将审计文件的所需要贴的编码直接作为水印贴在页面四个角落&#xff0c;节省辨别时间 我曾经写过一个给pdf页面四个角落加上文件名水印的python脚本&#xff0c;现在需要加一个图形界面进一步加强其实用性。首先通过路径浏览指定文件路径&#xff0c;先检测该路…...

leetcode416.分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#xff1a;数组可以分割成 [1, 5, 5] 和 [11] 。 示例 2&…...

使用docker-compose安装ELK(elasticsearch,logstash,kibana)并简单使用

首先服务器上需要安装docker已经docker-compose&#xff0c;如果没有&#xff0c;可以参考我之前写的文章进行安装。 https://blog.csdn.net/a_lllk/article/details/143382884?spm1001.2014.3001.5502 1.下载并启动elk容器 先创建一个网关&#xff0c;让所有的容器共用此网…...

深度学习中超参数

深度学习中的超参数(hyperparameters)是决定网络结构的变量(例如隐藏层数量)和决定网络训练方式的变量(例如学习率)。超参数的选择会显著影响训练模型所需的时间&#xff0c;也会影响模型的性能。超参数是在训练开始之前设置的&#xff0c;而不是从数据中学习的参数。超参数是模…...

[JavaScript] 运算符详解

文章目录 算术运算符&#xff08;Arithmetic Operators&#xff09;注意事项&#xff1a; 比较运算符&#xff08;Comparison Operators&#xff09;注意事项&#xff1a; 逻辑运算符&#xff08;Logical Operators&#xff09;短路运算&#xff1a;逻辑运算符的返回值&#xf…...

Hooks 使用规则

Hooks 使用规则 命名规则 Hook 必须 useXxx 格式来命名。 PS&#xff1a;这种命名规则也很易读&#xff0c;简单粗暴 调用位置 Hook 或自定义 Hook &#xff0c;只能在两个地方被调用 组件内部其他 Hook 内部 组件外部&#xff0c;或一个普通函数中&#xff0c;不能调用…...

Ubuntu 24.04 LTS 安装 Docker Desktop

Docker 简介 Docker 简介和安装Ubuntu上学习使用Docker的详细入门教程Docker 快速入门Ubuntu版&#xff08;1h速通&#xff09; Docker 安装 参考 How to Install Docker on Ubuntu 24.04: Step-by-Step Guide。 更新系统和安装依赖 在终端中运行以下命令以确保系统更新并…...

智能创造的幕后推手:AIGC浪潮下看AI训练师如何塑造智能未来

文章目录 一、AIGC时代的算法与模型训练概览二、算法与模型训练的关键环节三、AI训练师的角色与职责四、AI训练师的专业技能与素养五、AIGC算法与模型训练的未来展望《AI训练师手册&#xff1a;算法与模型训练从入门到精通》亮点内容简介作者简介谷建阳 目录 《AI智能化办公&am…...

从 JIRA 数据到可视化洞察:使用 Python 创建自定义图表

引言 在项目管理和软件开发中&#xff0c;JIRA 是最广泛使用的工具之一&#xff0c;尤其是在追踪问题、任务和团队进度方面。对于开发者和团队来说&#xff0c;能够从 JIRA 中提取并分析数据&#xff0c;以便更好地理解项目状态和趋势&#xff0c;至关重要。虽然 JIRA 本身提供…...

【网络原理】万字详解 HTTP 协议

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. HTTP 前置知识1.1 HTTP 是什么1.2 HTPP 协议应用场景1.3 HTTP 协议工作过程 2. HTTP 协议格式2.1 fiddler…...

PHP企业IM客服系统

&#x1f4ac; 企业IM客服系统——高效沟通&#xff0c;无缝连接的智慧桥梁 &#x1f680; 卓越性能&#xff0c;释放无限可能 在瞬息万变的商业环境中&#xff0c;我们深知沟通的力量。因此&#xff0c;基于先进的ThinkPHP5框架与高性能的Swoole扩展&#xff0c;我们匠心独运…...

Linux操作系统的灵魂,深度解析MMU内存管理

在计算机的奇妙世界里&#xff0c;我们每天使用的操作系统看似流畅自如地运行着各类程序&#xff0c;背后实则有着一位默默耕耘的 “幕后英雄”—— 内存管理单元&#xff08;MMU&#xff09;。它虽不常被大众所熟知&#xff0c;却掌控着计算机内存的关键命脉&#xff0c;是保障…...

PHP代码审计学习01

目录 两种思路 addslashes函数和magic_quotes_gpc配置&#xff1a; 今天来开php代码审计。 PHP无框架项目SQL注入挖掘技巧。 可以看看小迪老师的学习流程或者说是路线吧。 其中&#xff0c;最下面的代码审计工具推荐用下面两款&#xff0c;fortify&#xff0c;seay。 &…...

《数据思维》之数据可视化_读书笔记

文章目录 系列文章目录前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 数据之道&#xff0c;路漫漫其修远兮&#xff0c;吾将上下而求索。 一、数据可视化 最基础的数据可视化方法就是统计图。一个好的统计图应该满足四个标准&#xff1a;准确、有…...

深度学习常见术语解释

正例与负例&#xff1a; 在分类任务中&#xff0c;通常将目标类别称为正例&#xff08;positive&#xff09;&#xff0c;非目标类别称为负例&#xff08;negative&#xff09;。 True Positives&#xff08;TP&#xff09;&#xff1a; 被正确地划分为正例的个数&#xff0c;…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...