asp.net core重新加載應用配置


asp.net core重新加載應用配置

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();
        }
    }
}

精簡版

        /// <summary>
        /// 重新加載系統配置
        /// </summary>
        /// <returns></returns>
        public IActionResult ReloadConfiguration()
        {
            var configurationRoot = HttpContext.RequestServices.GetService<IConfiguration>() as IConfigurationRoot;
            if (null == configurationRoot)
            {
                return BadRequest();
            }
            configurationRoot.Reload();
            return Ok();
        }

是不是很簡單,下面我們來嘗試一下,你可以參考這個示例項目

因為默認的項目配置會監聽 appsettings.json 文件是否修改,如果已修改就會重新reload,這里我新加一個文件,這里設置 reloadOnChangefalse,示例代碼如下:

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 接口重新加載配置

reload configuration

返回 200 即接口調用成功,重新刷新剛才的頁面就可以看到頁面上的數據已經發生變化,這也就證明了我們重新加載配置的接口生效了。

源碼解析

來看 ConfigurationBuilder 在 Build 的時候做了什么,ConfigurationBuilder 源碼

ConfigurationBuilder.Build()

可以看到這里最后返回的是一個 IConfigurationRoot 對象,再來看 IConfigurationRoot 源碼

IConfigurationRoot

可以看到 IConfigurationRoot 定義了一個 Reload 的方法,這個方法會從下面的 Providers 中重新加載配置,看到這里我們就知道可以通過 IConfigurationReload 方法來重新加載應用程序的配置了,然后我們來看 WebHost.CreateDefaultBuilder(args).Build() 做了什么
https://github.com/aspnet/AspNetCore/blob/master/src/DefaultBuilder/src/WebHost.cs#L149

WebHost

這里我們可以看到為什么 appsettings.json 文件會自動 reload 配置,可以看到最后返回了一個 WebHostBuilder 對象

看 Asp.Net core WebHostBuilder 對象的 Build 方法 https://github.com/aspnet/AspNetCore/blob/master/src/Hosting/Hosting/src/WebHostBuilder.cs#L135

BuildCommonServices 可以看到這樣一段代碼 https://github.com/aspnet/AspNetCore/blob/master/src/Hosting/Hosting/src/WebHostBuilder.cs#L277

image.png

上面我們已經知道 ConfigurationBuilder Build 之后返回的是一個 IConfigurationRoot 對象,而這里注入是一個 IConfiguration 對象(IConfigurationRoot 實現 IConfiguration 接口),所以我們就可以從依賴注入中獲取 IConfiguration 對象直接當作 IConfigurationRoot 來使用,這也就是為什么我們會直接獲取一個 IConfiguration 對象直接 as IConfigurationRoot

Memo

到此就暫時結束了,希望你能有所收獲~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM