ABP開發框架先後端開發系列---(12)配置模塊的管理

通常來講,一個系統或多或少都會涉及到一些系統參數或者用戶信息的配置,而ABP框架也提供了一套配置信息的管理模塊,ABP框架的配置信息,必須提早定義好配置的各項內容,而後才能在系統中初始化或者經過接口查詢來使用,本篇隨筆引入了另一種配置信息的定義,實現更加簡化的處理,本篇隨筆着重介紹二者之間的差別和不一樣的地方。html

一、ABP框架的配置管理

以下面是郵件配置信息,配置信息通常先繼承自SettingProvider,初始化定義後,才能被系統所使用。數據庫

EmailSettingProvider:繼承自SettingProvider, 將SMTP的各項設置封裝成SettingDefinition,並以數組形式返回後端

配置的管理類,主要經過接口ISettingManager來進行統一管理的,底層協同了SettingStore配置存儲和SetttingDefinitionMananger的配置定義管理兩個部分。數組

這種方式的配置信息,糅合了配置項的定義(強制性),以及多語言特性的處理,根據不一樣的語言返回不一樣的配置名稱,同時也整合了緩存信息的處理,以減小系統的一些消耗。 緩存

不過從上面的圖示咱們也能夠看到,整個配置模塊因爲引入這些內容,致使處理起來必須循序漸進的建立配置管理類,定義配置信息,從新編譯系統後,而後才能進行信息的調用,所以這些配置信息必須預約義。並且管理起來協同這些類的處理,也略顯得有點複雜化。服務器

在ABP核心模塊的啓動過程當中,會預先初始化這些配置管理類,以下代碼所示框架

而後在AddSettingProviders中加入預先定義好的配置類。async

接着在完成初始化過程當中,有配置定義類統一根據這些配置對象,進行定義的初始化,這樣才能在系統中進行使用。ide

配置定義的管理類接口,能夠用下面這個圖示進行說明。函數

以上就是在ABP框架中,基於配置模塊的管理過程。

通常狀況下,若是咱們須要在Web API端中對這些接口進行調用管理,如對用戶或者系統Email配置信息的獲取和修改,那麼咱們須要定義一個配置接口服務(默認下載的ABP框架中沒有公佈這個接口定義和實現)。

以下咱們定義一個SettingsAppService和他的接口

而後咱們能夠實現它的獲取信息和修改信息的接口,以下所示是對系統級別的郵件參數進行配置管理。

        /// <summary>
        /// 獲取應用程序級別的郵件配置(系統郵件配置)
        /// </summary>
        /// <returns></returns>
        public async Task<EmailSettingsEditDto> GetEmailSettingsForApplication()
        {
            var smtpPassword = await SettingManager.GetSettingValueForApplicationAsync(EmailSettingNames.Smtp.Password);

            return new EmailSettingsEditDto
            {
                DefaultFromAddress = await SettingManager.GetSettingValueForApplicationAsync(EmailSettingNames.DefaultFromAddress),
                DefaultFromDisplayName = await SettingManager.GetSettingValueForApplicationAsync(EmailSettingNames.DefaultFromDisplayName),
                SmtpHost = await SettingManager.GetSettingValueForApplicationAsync(EmailSettingNames.Smtp.Host),
                SmtpPort = await SettingManager.GetSettingValueForApplicationAsync<int>(EmailSettingNames.Smtp.Port),
                SmtpUserName = await SettingManager.GetSettingValueForApplicationAsync(EmailSettingNames.Smtp.UserName),
                SmtpPassword = SimpleStringCipher.Instance.Decrypt(smtpPassword),
                SmtpDomain = await SettingManager.GetSettingValueForApplicationAsync(EmailSettingNames.Smtp.Domain),
                SmtpEnableSsl = await SettingManager.GetSettingValueForApplicationAsync<bool>(EmailSettingNames.Smtp.EnableSsl),
                SmtpUseDefaultCredentials = await SettingManager.GetSettingValueForApplicationAsync<bool>(EmailSettingNames.Smtp.UseDefaultCredentials)
            };
        }

        /// <summary>
        /// 更新應用程序級別的郵件配置(系統郵件配置)
        /// </summary>
        /// <returns></returns>
        public async Task UpdateEmailSettingsForApplication(EmailSettingsEditDto input)
        {
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.DefaultFromAddress, input.DefaultFromAddress);
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.DefaultFromDisplayName, input.DefaultFromDisplayName);
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Host, input.SmtpHost);
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Port, input.SmtpPort.ToString(CultureInfo.InvariantCulture));
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.UserName, input.SmtpUserName);
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Password, SimpleStringCipher.Instance.Encrypt(input.SmtpPassword));
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.Domain, input.SmtpDomain);
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.EnableSsl, input.SmtpEnableSsl.ToString().ToLowerInvariant());
            await SettingManager.ChangeSettingForApplicationAsync(EmailSettingNames.Smtp.UseDefaultCredentials, input.SmtpUseDefaultCredentials.ToString().ToLowerInvariant());
        }

 

二、使用自定義的參數配置管理

我在較早的隨筆《Winform開發框架之參數配置管理功能實現-基於SettingsProvider.net的構建》中介紹過對配置信息的管理實現,這種配置參數方式一直很好的應用在個人各個框架上,定義和使用都相對比較簡單,可以知足絕大多數的應用場景,相對ABP框架的配置模塊來講,簡單易用。

首先咱們定義一個用來存儲通用配置信息的表,以下所示。

這個配置表的主要特色也是以鍵爲操做對象,而後內容是JSON序列化後的內容,能夠存儲用戶自定義的類的序列號字符串,這個是它的靈魂所在。和ABP框架僅僅存儲簡單類型的值有所不一樣。

和其餘模塊的定義同樣,咱們能夠先根據常規表的方式,使用代碼快速生成類的結構,以下所示。

    /// <summary>
    /// 用戶參數配置,應用層服務接口實現
    /// </summary>
    [AbpAuthorize]
    public class UserParameterAppService : MyAsyncServiceBase<UserParameter, UserParameterDto, string, UserParameterPagedDto, CreateUserParameterDto, UserParameterDto>, IUserParameterAppService
    {
        private readonly IRepository<UserParameter, string> _repository;

        public UserParameterAppService(IRepository<UserParameter, string> repository) : base(repository)
        {
            _repository = repository;
        }

而後定義幾個用於用戶級別和系統程序級別的接口實現,如獲取信息,修改信息等。

而後,在生成的Caller層類裏面,增長以上的Web API接口調用的實現代碼,以下所示

 

    /// <summary>
    /// 用戶參數配置的Web API調用處理
    /// </summary>
    public class UserParameterApiCaller : AsyncCrudApiCaller<UserParameterDto, string, UserParameterPagedDto, CreateUserParameterDto, UserParameterDto>, IUserParameterAppService
    {
        /// <summary>
        /// 提供單件對象使用
        /// </summary>
        public static UserParameterApiCaller Instance
        {
            get
            {
                return Singleton<UserParameterApiCaller>.Instance;
            }
        }

        /// <summary>
        /// 默認構造函數
        /// </summary>
        public UserParameterApiCaller()
        {
            this.DomainName = "UserParameter";//指定域對象名稱,用於組裝接口地址
        }

        public async Task<UserParameterDto> GetSettingForUser(NameInputDto input)
        {
            return await DoActionAsync<UserParameterDto>(MethodBase.GetCurrentMethod(), input);
        }

        public async Task ChangeSettingForUser(NameValueDto input)
        {
            await DoActionAsync(MethodBase.GetCurrentMethod(), input);
        }

        public async Task<UserParameterDto> GetSettingForApplication(NameInputDto input)
        {
            return await DoActionAsync<UserParameterDto>(MethodBase.GetCurrentMethod(), input);
        }

        public async Task ChangeSettingForApplication(NameValueDto input)
        {
            await DoActionAsync(MethodBase.GetCurrentMethod(), input);
        }
    }

若是對於上面的DoActionAsyn的處理有疑問,能夠參考以前隨筆《ABP開發框架先後端開發系列---(10)Web API調用類的簡化處理》進行了解。

我在以前介紹過的配置模塊裏面,結合過FireFoxDialog界面效果,實現較好的參數配置管理功能,以下界面所示。

 咱們本次使用這兩個不一樣的配置模塊,也但願使用這個來展示一下,以便更好的理解。

因爲整合了SettingsProvider.net組件,咱們只須要封裝一下對數據庫的存儲獲取方式就能夠了。

    /// <summary>
    /// 數據庫參數存儲設置
    /// </summary>
    public class DatabaseStorage : JsonSettingsStoreBase
    {
        /// <summary>
        /// 配置級別
        /// </summary>
        public SettingScopes Scope { get; set; }

        /// <summary>
        /// 構造函數
        /// </summary>
        public DatabaseStorage()
        {
            this.Scope = SettingScopes.User;
        }

        /// <summary>
        /// 參數構造函數
        /// </summary>
        /// <param name="scope">配置級別</param>
        public DatabaseStorage(SettingScopes scope)
        {
            this.Scope = scope;
        }

        /// <summary>
        /// 保存到數據庫
        /// </summary>
        /// <param name="filename">文件名稱(類型名稱)</param>
        /// <param name="fileContents">參數內容</param>
        protected override void WriteTextFile(string filename, string fileContents)
        {
            var info = new NameValueDto(filename, fileContents);
            if (this.Scope == SettingScopes.Application)
            {
                AsyncContext.Run(()=> UserParameterApiCaller.Instance.ChangeSettingForApplication(info));
            }
            else
            {
                AsyncContext.Run(() => UserParameterApiCaller.Instance.ChangeSettingForUser(info));
            }
        }

        /// <summary>
        /// 從數據庫讀取
        /// </summary>
        /// <param name="filename">文件名稱(類型名稱)</param>
        /// <returns></returns>
        protected override string ReadTextFile(string filename)
        {
            var info = new NameInputDto(filename);

            UserParameterDto result = null;
            if (this.Scope == SettingScopes.Application)
            {
                result = AsyncContext.Run(() => UserParameterApiCaller.Instance.GetSettingForApplication(info));
            }
            else
            {
                result = AsyncContext.Run(() => UserParameterApiCaller.Instance.GetSettingForUser(info));
            }

            return result != null ? result.Content : null;
        }
    }

有了這個實現,這樣在操做上,就不用管理這些內容如何獲取和更新了,和以前的使用配置管理方式一致了。能夠處理各類不一樣的配置對象信息。

先來看看默認ABP的配置處理方式,管理界面以下所示。

這裏的配置存儲咋ABP的AbpSettings表裏面,以下所示,每項內容是以字符串方式獨立存儲的。

它的調用主要就是SettingsApiCaller的內容了,注意這個郵件配置,必須在EmailSettingProvider中提早定義好對象的信息。

        private EmailSettingsEditDto GetParameter()
        {
            EmailSettingsEditDto param =  AsyncContext.Run(() => SettingsApiCaller.Instance.GetEmailSettingsForApplication());
            if(param == null)
            {
                param = new EmailSettingsEditDto();
            }
            return param;
        }

        public override void OnInit()
        {
            var parameter = GetParameter();
            if (parameter != null)
            {
                this.txtEmail.Text = parameter.DefaultFromAddress;
                this.txtLoginId.Text = parameter.SmtpUserName;
                this.txtPassword.Text = parameter.SmtpPassword;
                this.txtPassword.Tag = parameter.SmtpPassword;
                this.txtSmtpPort.Value = parameter.SmtpPort;
                this.txtSmtpServer.Text = parameter.SmtpHost;
                this.txtUseSSL.Checked = parameter.SmtpEnableSsl;
            }
        }

下面咱們再來看看自定義的配置管理方式。以下是自定義配置模塊獲取顯示的內容。

這個配置是系統級別的,它的獲取方式以下所示。

    public partial class PageEmailApplication : PropertyPage
    {
        private SettingsProvider settings;
        private ISettingsStorage store;

        public PageEmailApplication()
        {
            InitializeComponent();

            if (!this.DesignMode)
            {
                store = new DatabaseStorage(SettingScopes.Application);
                settings = new SettingsProvider(store);
            }
        }

        public override void OnInit()
        {
            EmailParameter parameter = settings.GetSettings<EmailParameter>();
            if (parameter != null)
            {
                this.txtEmail.Text = parameter.Email;
                this.txtLoginId.Text = parameter.LoginId;
                this.txtPassword.Text = parameter.Password;
                this.txtPassword.Tag = parameter.Password;
                this.txtPop3Port.Value = parameter.Pop3Port;
                this.txtPop3Server.Text = parameter.Pop3Server;
                this.txtSmtpPort.Value = parameter.SmtpPort;
                this.txtSmtpServer.Text = parameter.SmtpServer;
                this.txtUseSSL.Checked = parameter.UseSSL;
            }
        }

以上是標準的SettingsProvider.net的組件調用方式,咱們不用知道具體的數據存儲,只須要把內容直接GetSetting方式獲取出來便可。

而保存內容,直接經過使用SaveSettings保存便可。

                EmailParameter parameter = settings.GetSettings<EmailParameter>();
                if (parameter != null)
                {                    
                    parameter.Email = this.txtEmail.Text;
                    parameter.LoginId = this.txtLoginId.Text;
                    parameter.Password = this.txtPassword.Text;
                    parameter.Pop3Port = Convert.ToInt32(this.txtPop3Port.Value);
                    parameter.Pop3Server = this.txtPop3Server.Text;
                    parameter.SmtpPort = Convert.ToInt32(this.txtSmtpPort.Value);
                    parameter.SmtpServer = this.txtSmtpServer.Text;
                    parameter.UseSSL = this.txtUseSSL.Checked;

                    settings.SaveSettings<EmailParameter>(parameter);
                }

其中 EmailParameter 類是咱們定義的一個類,用來承載相關的配置信息,以下所示。它支持默認值,加密處理等設置。

    /// <summary>
    /// 郵箱設置
    /// </summary>
    public class EmailParameter
    {
        /// <summary>
        /// 郵件帳號
        /// </summary>
        //[DefaultValue("wuhuacong@163.com")]
        public string Email { get; set; }

        /// <summary>
        /// POP3服務器
        /// </summary>
        [DefaultValue("pop.163.com")]
        public string Pop3Server { get; set; }

        /// <summary>
        /// POP3端口
        /// </summary>
        [DefaultValue(110)]
        public int Pop3Port { get; set; }

        /// <summary>
        /// SMTP服務器
        /// </summary>
        [DefaultValue("smtp.163.com")]
        public string SmtpServer { get; set; }

        /// <summary>
        /// SMTP端口
        /// </summary>
        [DefaultValue(25)]
        public int SmtpPort { get; set; }

        /// <summary>
        /// 登錄帳號
        /// </summary>
        public string LoginId { get; set; }

        /// <summary>
        /// 登錄密碼
        /// </summary>
        [ProtectedString]
        public string Password { get; set; }

        /// <summary>
        /// 使用SSL加密
        /// </summary>
        [DefaultValue(false)]
        public bool UseSSL { get; set; }
    }

 

因爲SettingsProvider.net組件的支持,咱們還能夠把配置信息當成本地文件存儲起來,對於一些須要存爲文件的方式的配置,很是不錯。

    public partial class PageReport : PropertyPage
    {
        private SettingsProvider settings;
        private ISettingsStorage store;

        public PageReport()
        {
            InitializeComponent();

            if (!this.DesignMode)
            {
                // PortableStorage: 在運行程序目錄建立一個setting的文件記錄參數數據
                store = new PortableStorage();
                settings = new SettingsProvider(store);
            }
        }

以上就是介紹了ABP配置管理模塊的實現原理和客戶端的調用,以及使用自定義配置管理模塊的方式進行處理更加動態化或者靈活一點的配置信息,使用自定義配置信息管理服務,整合了SettingProvider.net的支持,能夠實現更好的參數配置管理體驗。 

相關文章
相關標籤/搜索