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:8888
	
dotnet 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 — 配置系统之自定义配置提供程序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索与创作:2024年CSDN平台上的成长与突破

文章目录 我与CSDN的初次邂逅初学阶段的阅读CSDN&#xff1a;编程新手的避风港初学者的福音&#xff1a;细致入微的知识讲解考试复习神器&#xff1a;技术总结的“救命指南”曾经的自己&#xff1a;为何迟迟不迈出写博客的第一步兴趣萌芽&#xff1a;从“读”到“想写”的初体验…

CSS中样式继承+优先级

继承属性和非继承属性 一、定义及分类 1、继承属性是指在父元素上设置了这些属性后&#xff0c;子元素会自动继承这些属性的值&#xff0c;除非子元素显式地设置了不同的值。 常见的继承属性: 字体 font 系列文本text-align text-ident line-height letter-spacing颜色 col…

macOS 安装JDK17

文章目录 前言介绍新特性下载安装1.下载完成后打开downloads 双击进行安装2.配置环境变量3.测试快速切换JDK 小结 前言 近期找开源软件&#xff0c;发现很多都已经使用JDK17springboot3 了&#xff0c;之前的JDK8已经被替换下场&#xff0c;所以今天就在本机安装了JDK17&#…

ChatGPT大模型极简应用开发-CH1-初识 GPT-4 和 ChatGPT

文章目录 1.1 LLM 概述1.1.1 语言模型和NLP基础1.1.2 Transformer及在LLM中的作用1.1.3 解密 GPT 模型的标记化和预测步骤 1.2 GPT 模型简史&#xff1a;从 GPT-1 到 GPT-41.2.1 GPT11.2.2 GPT21.2.3 GPT-31.2.4 从 GPT-3 到 InstructGPT1.2.5 GPT-3.5、Codex 和 ChatGPT1.2.6 …

vector迭代器的使用以及迭代器失效

一、iterator的使用注意 begin与end 遵循左闭右开的原则&#xff0c;begin 指向vector的第一个元素&#xff0c;end 指向vector的最后一个元素的往下一个位置。 rbegin 与 rend rbegin指向最后一个元素的位置&#xff0c;rend指向第一个元素的往前一个位置。 二、vector的常…

【Linux】15.Linux进程概念(4)

文章目录 程序地址空间前景回顾C语言空间布局图&#xff1a;代码1代码2代码3代码4代码5代码6代码7 程序地址空间前景回顾 历史核心问题&#xff1a; pid_t id fork(); if(id 0) else if(id>0) 为什么一个id可以放两个值呢&#xff1f;之前没有仔细讲。 C语言空间布局图&am…

【无法下载github文件】虚拟机下ubuntu无法拉取github文件

修改hosts来进行解决。 步骤一&#xff1a;打开hosts文件 sudo vim /etc/hosts步骤二&#xff1a;查询 github.com的ip地址 https://sites.ipaddress.com/github.com/#ipinfo将github.com的ip地址添加到hosts文件末尾&#xff0c;如下所示。 140.82.114.3 github.com步骤三…

Android BitmapShader实现狙击瞄具十字交叉线准星,Kotlin

Android BitmapShader实现狙击瞄具十字交叉线准星&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.…

Android系统开发(十):标准协议和通讯的桥梁:探索蓝牙、NFC、WLAN 的工作原理

引言&#xff1a; 现代社会已经是信息互联的世界&#xff0c;各种设备之间的互联互通已经成为了生活的一部分。而在这个过程中&#xff0c;Android 设备与其他硬件之间的通信扮演着至关重要的角色。从蓝牙耳机到 WiFi 路由器&#xff0c;甚至与电话功能的互动&#xff0c;所有…

node中文名的js文件有问题

新版Node无法运行含有中文名的JS文件&#xff0c;具体表现在无报错无反应。如下图&#xff1a; 源码如下&#xff1a; 改成英文的JS文件&#xff0c;则正常&#xff0c;如下图&#xff1a;

BERT与CNN结合实现糖尿病相关医学问题多分类模型

完整源码项目包获取→点击文章末尾名片&#xff01; 使用HuggingFace开发的Transformers库&#xff0c;使用BERT模型实现中文文本分类&#xff08;二分类或多分类&#xff09; 首先直接利用transformer.models.bert.BertForSequenceClassification()实现文本分类 然后手动实现B…

openharmony应用开发快速入门

开发准备 本文档适用于OpenHarmony应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用&#xff08;如下图所示&#xff09;&#xff0c;快速了解工程目录的主要文件&#xff0c;熟悉OpenHarmony应用开发流程。 在开始之前&#xff0c;您需要了解有关OpenHarmon…

RabbitMQ---TTL与死信

&#xff08;一&#xff09;TTL 1.TTL概念 TTL又叫过期时间 RabbitMQ可以对队列和消息设置TTL&#xff0c;当消息到达过期时间还没有被消费时就会自动删除 注&#xff1a;这里我们说的对队列设置TTL,是对队列上的消息设置TTL并不是对队列本身&#xff0c;不是说队列过期时间…

51.WPF应用加图标指南 C#例子 WPF例子

完整步骤&#xff1a; 先使用文心一言生成一个图标如左边使用Windows图片编辑器编辑&#xff0c;去除背景使用正方形&#xff0c;放大图片使图标铺满图片使用格式工程转换为ico格式&#xff0c;分辨率为最大 在资源管理器中右键项目添加ico类型图片到项目里图片属性设置为始终…

多语言插件i18n Ally的使用

先展示一下效果 1.第一步首先在vscode下载插件 2.第二步在 setting.json 里面配置 要区分文件是js&#xff0c;ts或json结尾 以zh.ts和en.ts结尾的用这个 { "i18n-ally.localesPaths": ["src/locales"],"i18n-ally.keystyle": "nested"…

蓝桥杯备考:堆和priority queue(优先级队列)

堆的定义 heap堆是一种特殊的完全二叉树&#xff0c;对于树中的每个结点&#xff0c;如果该结点的权值大于等于孩子结点的权值&#xff0c;就称它为大根堆&#xff0c;小于等于就叫小根堆&#xff0c;如果是大根堆&#xff0c;每个子树也是符合大根堆的特征的&#xff0c;如果是…

【人工智能】:搭建本地AI服务——Ollama、LobeChat和Go语言的全方位实践指南

前言 随着自然语言处理&#xff08;NLP&#xff09;技术的快速发展&#xff0c;越来越多的企业和个人开发者寻求在本地环境中运行大型语言模型&#xff08;LLM&#xff09;&#xff0c;以确保数据隐私和提高响应速度。Ollama 作为一个强大的本地运行框架&#xff0c;支持多种先…

Java锁 从乐观锁和悲观锁开始讲 面试复盘

目录 面试复盘 Java 中的锁 大全 悲观锁 专业解释 自我理解 乐观锁 专业解释 自我理解 悲观锁的调用 乐观锁的调用 synchronized和 ReentrantLock的区别 相同点 区别 详细对比 总结 面试复盘 Java 中的锁 大全 悲观锁 专业解释 适合写操作多的场景 先加锁可以…

OpenVela——专为AIoT领域打造的开源操作系统

目录 一、系统背景与开源 1.1. 起源 1.2. 开源 二、系统特点 2.1. 轻量化 2.2. 标准兼容性 2.3. 安全性 2.4. 高度可扩展性 三、技术支持与功能 3.1. 架构支持 3.2. 异构计算支持 3.3. 全面的连接套件 3.4. 开发者工具 四、应用场景与优势 4.1. 应用场景 4.2. …

使用 Java 实现基于 DFA 算法的敏感词检测

使用 Java 实现基于 DFA 算法的敏感词检测 1. 引言 敏感词检测在内容审核、信息过滤等领域有着广泛的应用。本文将介绍如何使用 DFA&#xff08;Deterministic Finite Automaton&#xff0c;确定有限状态自动机&#xff09; 算法&#xff0c;在 Java 中实现高效的敏感词检测。…