Intro
我把配置放在了数据库或者是 Redis 里, 配置需要修改的时候我要直接修改数据库, 然后调用一个接口去重新加载应用配置, 于是就尝试写一个运行时重新加载配置的接口.
Configuration 重新加载实现
重新加载配置的接口其实很简单, 经过看 Configuration 的源码可以知道, 如果想要重新加载应用配置, 需要一个 IConfigurationRoot 对象, 而 IConfigurationRoot 其实可以直接拿注入服务中的 IConfiguration 对象, 服务中的 IConfiguration 对象也是实现了 IConfigurationRoot 接口的实例. 后面我们一起看源码就更清晰了.
来看实现重新加载配置的代码
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- namespace TestwebApplication.Controllers
- {
- [Route("api/[controller]")]
- public class ConfigurationsController : Controller
- {
- private readonly IConfigurationRoot _configuration;
- public ConfigurationsController(IConfiguration configuration)
- {
- _configuration = configuration as IConfigurationRoot;
- }
- [HttpGet]
- public IActionResult Get()
- {
- return Ok(new
- {
- RootUser = _configuration.GetAppSetting("RootUser") // 这里 GetAppSetting 是一个自定义扩展方法, 获取 AppSettings 节点下的配置信息
- });
- }
- [HttpPut]
- public IActionResult Put()
- {
- _configuration.Reload();
- return Ok();
- }
- }
- }
是不是很简单, 下面我们来尝试一下, 你可以参考这个示例项目
因为默认的项目配置会监听 appsettings.JSON 文件是否修改, 如果已修改就会重新 reload, 这里我新加一个文件, 这里设置 reloadOnChange 为 false, 示例代码如下:
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .ConfigureAppConfiguration(configBuilder =>
- {
- configBuilder.AddJsonFile("abc.json", optional: true, reloadOnChange: false);
- })
- .UseStartup<Startup>();
abc.JSON 的文件内容如下:
- {
- "AppSettings": {
- "TestNumber": 12,
- "RootUser": "WeihanLi"
- }
- }
dotnet run 启动网站, 然后在浏览器中访问 http://localhost:5000/API/configurations
然后我们修改 abc.JSON 文件
- {
- "AppSettings": {
- "TestNumber": 12,
- "RootUser": "WeihanLi 123"
- }
- }
修改保存之后刷新刚才的页面, 可以看到还是刚才的内容, 证明并没有重新加载配置, 接下来尝试我们的重新加载配置方法
使用 postman 或 fiddler 或其他你喜欢的工具发一个 PUT 请求到 http://localhost:5000/API/configurations, 这里我使用 postman 调用 PUT 接口重新加载配置
返回 200 即接口调用成功, 重新刷新刚才的页面就可以看到页面上的数据已经发生变化, 这也就证明了我们重新加载配置的接口生效了.
源码解析
来看 ConfigurationBuilder 在 Build 的时候做了什么, ConfigurationBuilder 源码
可以看到这里最后返回的是一个 IConfigurationRoot 对象, 再来看 IConfigurationRoot 源码
可以看到 IConfigurationRoot 定义了一个 Reload 的方法, 这个方法会从下面的 Providers 中重新加载配置, 看到这里我们就知道可以通过 IConfiguration 的 Reload 方法来重新加载应用程序的配置了, 然后我们来看 WebHost.CreateDefaultBuilder(args).Build() 做了什么
这里我们可以看到为什么 appsettings.JSON 文件会自动 reload 配置, 可以看到最后返回了一个 WebHostBuilder 对象
看 ASP.NET core WebHostBuilder 对象的 Build 方法
在 BuildCommonServices 可以看到这样一段代码
上面我们已经知道 ConfigurationBuilder Build 之后返回的是一个 IConfigurationRoot 对象, 而这里注入是一个 IConfiguration 对象 (IConfigurationRoot 实现 IConfiguration 接口), 所以我们就可以从依赖注入中获取 IConfiguration 对象直接当作 IConfigurationRoot 来使用, 这也就是为什么我们会直接获取一个 IConfiguration 对象直接 as IConfigurationRoot
Memo
到此就暂时结束了, 希望你能有所收获~
来源: https://www.cnblogs.com/weihanli/p/reload-app-configuration-in-aspnetcore.html