Prefácio
Atualmente, quase a maioria dos aplicativos Java, como Tomcat, Struts2, Netty, etc., com os quais estamos familiarizados, não podem contá -los,
Para atender à universalidade, são fornecidos arquivos de configuração para os usuários personalizarem funções.
Existem até algumas estruturas de rede, como a Netty, que são quase completamente configuradas, e geralmente chamamos esse software de "arquitetura de microoker".
Tudo o que você configura, é o que é.
É o que você configura para ser.
Os formatos de arquivo de configuração mais comuns são XML, propriedades e outros arquivos.
Este artigo discute o cenário mais comum e comum em carregar configurações, que é mapear um arquivo de configuração em um objeto Pojo em Java.
E discuta como implementar diferentes maneiras de carregar. Por exemplo, algumas configurações são carregadas a partir de arquivos XML locais, enquanto algumas configurações precisam ser carregadas a partir de arquivos de propriedades locais e, mais ainda, algumas configurações precisam ser carregadas através da rede.
Como implementar esse mecanismo de carregamento de configuração para que, depois de termos esse mecanismo, a configuração de carregamento de código não seja espalhada por toda parte e é escalável e gerenciável.
Configure o carregador
Primeiro, precisamos de um carregador de configuração e esse carregador de configuração pode ter muitos métodos de carregamento diferentes. Portanto, usamos uma interface para descrevê -lo da seguinte maneira:
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 11:47:12 * @Version 1.0 * */interface pública ICONFIGLOADER <T> {/** * Carregue a configuração digitada por t * * @return * @THOWS ConfigException */public t load () Throws confeception;} Mas por que precisamos declarar genéricos <T> nessa interface?
Obviamente, quando queremos usar um carregador de configuração, você deve dizer a este carregador de configuração quais resultados você precisa obter após o carregamento.
Por exemplo, se você deseja carregar a configuração e obter um objeto AppleConfig, poderá usar a interface definida acima:
IconfigLoader <PpleConfig> carregador = new AppConfigLoader <Pelpeconfig> (); AppConfig config = carregador.load ();
Assim, você converte as informações no arquivo de configuração em um objeto AppleConfig e pode obter essa instância do objeto AppleConfig.
Até agora, parece que, desde que nosso AppleConFigLoader implemente o trabalho específico de como carregar arquivos de configuração, podemos carregar facilmente configurações.
Pode-se dizer que, mas não é que a configuração possa ser carregada de maneiras diferentes, como o carregamento através de propriedades, DOM, Sax ou carregando algumas bibliotecas de código aberto de terceiros.
Portanto, além de configurar o carregador, também precisamos de outra função, o fornecedor de configurar o método de carregamento. Vamos chamá -lo de iconfigProvider.
Configure o fornecedor de métodos de carregamento
O provedor de métodos de carregamento de configuração pode fornecer um método de carregamento para o carregador de configuração, ou seja, fornecer um objeto para o carregador de configuração.
Se carregado através do DOM, o provedor fornece um objeto de documento para o carregador.
Se carregado por meio de propriedades, o provedor fornece um objeto de propriedades para o carregador. Se carregado através do método fornecido por uma biblioteca de classes de terceiros, como o Apache-Commons-Digester3 (carregamento de configuração do Tomcat), o provedor fornece um objeto de digestor para o provedor de carregador deve fornecer, tudo isso é tudo, fornecendo apenas os objetos necessários para configurar o carregador, mas ele próprio não participa do trabalho de configuração de configuração.
Usamos um IconfigProvider de interface para definir este provedor
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 11:54:28 * @version 1.0 * */interface pública ICONFIGPROVER <T> {/** * fornece uma fonte de configuração usada para carregar configxception; Por que há <T> aqui para declarar genéricos?
Se você precisar de um provedor, deve pelo menos informar ao provedor o que ele deve fornecer.
Portanto, o que um provedor fornecerá é determinado por isso.
Ao mesmo tempo, podemos primeiro construir uma fábrica e deixá -la produzir fornecedores específicos:
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 11:56:28 * @Version 1.0 * */public class ConfigProviderFactory {private configProviderFactory () {throw New UnsupportEdOperException ("Inclua de inicializar) uma classe fábrica:" + getclass (). } public static iconfigProvider <documber> CreateDocumentProvider (String filepath) {return new DocumentProvider (FilePath); } public static iconfigProvider <Properts> CreatePropertiesProvider (String filepath) {return New PropertiesProvider (FilePath); } public static iconfigProvider <Digester> criougesterProvider (string filepath) {return new DigesterProvider (filepath); }}Você pode começar a implementar o carregador de configuração específico?
Ainda não está bem!
Neste ponto, suponha que tenhamos um arquivo de configuração chamado Apple.xml. E precisamos carregar este Apple.xml em um objeto AppConfig através do DOM.
Então, antes de tudo, quero criar um provedor que possa fornecer documentos através da fábrica do provedor. Então eu recebo esse provedor e posso chamar seu método de fornecimento para obter o objeto Document.
Com o objeto do documento, posso começar a carregar a configuração.
No entanto, se você deseja carregar Bananaconfig, PearConfig ......, as etapas são as mesmas. Portanto, também precisamos de uma classe abstrata para implementar alguns comportamentos comuns padrão.
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 11:59:19 * @Version 1.0 * */public class Class AbstractConfigLoader <t, u> implementa o iconfigLoader <T> {Protect IConfigProvider <U> Provedor; AbstractConfigLoader protegido (provedor iconfigProvider <u> provedor) {this.provider = provider; } / * * @see iconfigLoader#load () * / @Override public t load () lança ConfigException {return load (getProvider (). fornece ()); } Public abstract load t (u loaderSource) lança ConfigException; iconfigProvider protegido <u> getProvider () {return this.provider; }}Cada carregador de configuração possui um construtor de parâmetro que recebe um provedor.
O genérico indica se eu quero carregar o AppConfig ou Bananconfig. O <u> genérico indica qual método de carga carregar, é um documento, propriedades ou outra coisa.
Exemplos de aplicação práticos
Existe um arquivo de arquivo de configuração do mercado de vegetais Market.xml, que configura os produtos do mercado de vegetais, incluindo dois produtos, a saber, maçãs e ovos.
<Market> <pple> <bor> Red </ro Color> <Price> 100 </sice> </pple> <gug> <us Weight> 200 </ight> </ovo> </monkery>
Há também um arquivo de configuração para os nomes dos chefes em cada barraca, proprietário.properties
PORT1 = Steve Jobsport2 = Bill Gatesport3 = Kobe Bryant
Vamos definir as seguintes aulas primeiro:
MarketConfig.java
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 23:03:37 * @version 1.0 * */public class MarketConfig {private appleConfig appleConfig; Private EggConfig EggConfig; Private OwnerConfig OwnConfig; public AppleConfig getAppleConfig () {return appleConfig; } public void setAppleConfig (AppConfig AppleConfig) {this.apppleConfig = appleConfig; } public EggConfig getEggConfig () {return EggConfig; } public void setEggConfig (EggConfig EggConfig) {this.EggConfig = EggConfig; } public OwnerConfig getOwRerConfig () {return ownerConfig; } public void setOwnserConfig (OwnerConfig OwnConfig) {this.ownserConfig = OwnerConfig; }}AppleConfig.java
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 23:03:45 * @Version 1.0 * */public classe AppleConfig {private int price; cor de corda privada; public void setPrice (int price) {this.price = price; } public int getPrice () {return this.price; } public void setColor (cor da string) {this.color = color; } public string getColor () {return this.color; }}EggConfig.java
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 23:03:58 * @version 1.0 * */public class EggConfig {private int Weight; Public void Setweight (int peso) {this.weight = peso; } public int getWeight () {return this.weight; }} OwnConfig.java
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 23:04:06 * @version 1.0 * */public classe OUNCONFIG {private map <string, string> proprietário = new hashmap <string, string> (); public void AddOwner (String PortName, String proprietário) {this.owner.put (PortName, proprietário); } public string getwnerByportName (string portName) {return this.owner.get (portName); } mapa public <string, string> viTowners () {return collections.unmodifiablemap (this.owner); }} Existem dois métodos de carregamento de configuração para este exemplo, a saber, métodos de carregamento de DOM e propriedades.
Portanto, nossos provedores precisam construir fábricas com dois provedores.
E dois carregadores de configuração precisam ser definidos, a saber:
OwnConfigLoader
/** * * * @Author Bean * @Date 21 de janeiro de 2016 às 23:24:50 * @Version 1.0 * */public class OwnConfigLoader estende abstrateConfigLoader <OwnConfig, Properties> {/** * @param provender */proteged ProtecterCoLer (ICONFIGROVER <PERSOURMOMPRERSO) } / * * @see abstractConfigLoader#load (java.lang.object) * / @Override public OwnConfig Load (Properties Props) lança ConfigException {OwnerConfig OwnConfig = new OwnerConfig (); / ** * Use adereços para definir o valor da propriedade de OwnConfig * * O código aqui é omitido */ retornar o próprioConfig; }}Depois, há MarketConfigLoader
importar org.w3c.dom.document;/** * * @Author Bean * @Date 21 de janeiro de 2016 às 23:18:56 * @Version 1.0 * */public class MarketConfigLoader estende o abstrateConfigLoader <MarketConfig, Document> {** ** ** @paramider Provender */ProtectedFfffffffffg (DocumentConfig, # (** * * } / * * AbstractConfigLoader#load (java.lang.object) * / @Override public MarketConfig LOAD (documento documento) lança ConfigException {MarketConfig MarketConfig = new MarketConfig (); AppConfig AppleConfig = new AppConfig (); EggConfig EggConfig = new EggConfig (); / ** * Processe o documento aqui e, em seguida, você pode obter * AppleConfig e EggConfg * * O código aqui é omitido */ marketconfig.setAppleConfig (AppleConfig); MarketConfig.seteggConfig (EggConfig); / ** * Como o OUNCONFIG requer propriedades para carregar, não é XML * Então, aqui precisamos criar um novo OwnConfigLoader e delegar para carregar OwnerConfig */ OwnConfigLoader OwnConfigLoader = NewerConfigLoader (configProviderFiplorPory.cretePropertiesProvider = NewerConfigLoader (configProViderFactory.cretePropertiesProvider = OwnConfig OwnConfig = OwnConfigLoader.Load (); MarketConfig.SetOwRerConfig (OwnConfig); Return MarketConfig; }}Então, como obtemos o MarketConfig no nível do aplicativo?
MarketConfigLoader marketConfigLoader = new MarketConfigLoader (configProviderFactory.createCumentProvider (your_file_path));
MarketConfig MarketConfig = MarketConfigLoader.Load ();
Talvez haja um lugar onde as pessoas possam se surpreender. Obviamente, existem quatro classes de configuração, então por que existem apenas dois carregadores de configuração?
Como o MarketConfig, o EggConfig e o AppConfig são todos carregados do mesmo arquivo de configuração XML, desde que um objeto de documento seja usado, ele pode ser carregado através do MarketConfigLoader.
O OwnConfig é um método de carregamento diferente, para que outro carregador seja necessário.
fim
O mecanismo de carregamento de configuração proposto neste artigo não pode realmente ajudar a carregar a configuração. Isso deve ser deixado para DOM, Sax e algumas outras bibliotecas de código aberto, como DOM4J e Digester.
No entanto, o mecanismo de carregamento de configuração proposto neste artigo pode tornar o mecanismo de carregamento de configuração mais flexível e fácil de expandir e pode integrar vários métodos de carregamento de configuração, integrá -los a um mecanismo e reproduzir seus próprios pontos.
De fato, alguns softwares geralmente precisam carregar configurações de arquivos de configuração em vários formatos diferentes ao mesmo tempo, como o STRUTS2, e um software de middleware de banco de dados de código aberto doméstico que eu tenho pesquisado e vomitando sangue recentemente.
Se não houver um mecanismo completo de carregamento de configuração, o código será mais disperso e menos sustentável. Pode facilmente fazer com que as pessoas vomitem o sangue.