Prefacio
Hoy en día, casi la mayoría de las aplicaciones de Java, como Tomcat, Struts2, Netty, etc., con las que estamos familiarizados, no podemos contarlas,
Para cumplir con la universalidad, se proporcionan archivos de configuración para que los usuarios personalicen las funciones.
Incluso hay algunos marcos de red, como Netty, que están casi completamente configurados, y generalmente llamamos a dicho software "arquitectura de microker".
Lo que sea que lo configues, es lo que es.
Es lo que configura que sea.
Los formatos de archivo de configuración más comunes son XML, propiedades y otros archivos.
Este artículo analiza el escenario más común y común en la carga de configuraciones, que es asignar un archivo de configuración en un objeto POJO en Java.
Y discutir cómo implementar diferentes formas de carga. Por ejemplo, algunas configuraciones se cargan desde archivos XML locales, mientras que algunas configuraciones deben cargarse a partir de archivos de propiedades locales, y más aún, algunas configuraciones deben cargarse a través de la red.
Cómo implementar dicho mecanismo de carga de configuración para que después de tener este mecanismo, la configuración de carga de código no se extenderá en todas partes, y es escalable y manejable.
Configurar el cargador
Primero, necesitamos un cargador de configuración, y este cargador de configuración puede tener muchos métodos de carga diferentes. Por lo tanto, usamos una interfaz para describirla de la siguiente manera:
/** * * * * @author bean * @Date 21 de enero de 2016 a las 11:47:12 am * @version 1.0 * */public interface iconfigloader <t> {/** * Cargue la configuración tipificada por t * * @return * @throws configException */public toad () lanza ConfigException;} Pero, ¿por qué necesitamos declarar genéricos <t> en esta interfaz?
Obviamente, cuando queremos usar un cargador de configuración, debe decirle a este cargador de configuración qué resultados necesita obtener después de la carga.
Por ejemplo, si desea cargar la configuración y obtener un objeto AppleconFig, puede usar la interfaz definida anteriormente:
Iconfigloader <AppleConFig> Loader = new AppleconFigLoader <PricConFig> (); Appleconfig config = loader.load ();
Entonces, convierte la información en el archivo de configuración en un objeto Appleconfig, y puede obtener esta instancia de objeto Appleconfig.
Hasta ahora, parece que mientras nuestro AppleconFigLoader implementa la mano de obra específica de cómo cargar archivos de configuración, podemos cargar fácilmente configuraciones.
Se puede decir que, pero no es que la configuración se pueda cargar de diferentes maneras, como la carga a través de propiedades, DOM, SAX o cargar a través de algunas bibliotecas de código abierto de terceros.
Por lo tanto, además de configurar el cargador, también necesitamos otro rol, el proveedor de configurar el método de carga. Llamémoslo IconFigProvider.
Configurar el proveedor de métodos de carga
El proveedor de métodos de carga de configuración puede proporcionar un método de carga al cargador de configuración, en otras palabras, proporcionar un objeto al cargador de configuración.
Si se carga a través de DOM, el proveedor proporciona un objeto de documento al cargador.
Si se carga a través de propiedades, el proveedor proporciona un objeto Propiedades al cargador. Si se carga a través del método proporcionado por una biblioteca de clase de terceros, como Apache-Commons-Digester3 (carga de configuración de TomCat), el proveedor proporciona un objeto de digestor al proveedor del cargador es proporcionarlo. Eso es todo, solo proporciona los objetos necesarios para configurar el cargador, pero no participa en la mano de obra de configurar la carga.
Utilizamos una interfaz iconfigProvider para definir este proveedor
/** * * * * @author bean * @Date 21 de enero de 2016 a las 11:54:28 am * @version 1.0 * */public interface iconfigProvider <t> {/** * proporciona una fuente de configuración utilizada para cargar config * * @return * @throws configException */public t proviene () lanza configException;} ¿Por qué hay <t> aquí para declarar genéricos?
Si necesita un proveedor, al menos debe decirle al proveedor qué debe proporcionar.
Por lo tanto, lo que proporcionará un proveedor está determinado por esto.
Al mismo tiempo, primero podemos construir una fábrica y dejar que produzca proveedores específicos:
/** * * * * @author bean * @Date 21 de enero de 2016 a las 11:56:28 am * @version 1.0 * */public class ConfigProviderFactory {private configProviderFactory () {throw new UnpportedOperationException ("No se pueda inicializar una clase de fábrica:" + getClass (). } public static iconfigProvider <ocument> CreatOcumentProvider (String FilePath) {return New DocumentProvider (FilePath); } public static iconfigProvider <Properties> CreatePropertiesProvider (String FilePath) {return New PropertiesProvider (FilePath); } public static iconfigProvider <igester> creatiGesterProvider (string filepath) {return new DigesterProvider (FilePath); }}¿Puede comenzar a implementar el cargador de configuración específico?
¡No está bien todavía!
En este punto, supongamos que tenemos un archivo de configuración llamado Apple.xml. Y necesitamos cargar este Apple.xml en un objeto Appleconfig a través de DOM.
Entonces, en primer lugar, quiero crear un proveedor que pueda proporcionar documento a través de la fábrica de proveedores. Luego obtengo este proveedor y puedo llamar a su método Proporcionar para obtener el objeto de documento.
Con el objeto de documento, puedo comenzar a cargar la configuración.
Sin embargo, si desea cargar Bananaconfig, PearConfig ......, los pasos son los mismos. Por lo tanto, también necesitamos una clase abstracta para implementar algunos comportamientos comunes predeterminados.
/** * * * * @author bean * @Date 21 de enero de 2016 a las 11:59:19 am * @version 1.0 * */public abstract Class AbstractConfigLoader <t, u> implementa iconfigloader <t> {protegido IconFigProvider <u> Provider; ProstractConfigLoader protegido (IconFigProvider <u> Provider) {this.Provider = Provider; } / * * @see iconfigloader#load () * / @Override public t load () lanza configException {return load (getProvider (). proporcionar ()); } public abstract t load (U loaderSource) lanza configException; iconfigProvider protegido <u> getProvider () {return this.provider; }}Cada cargador de configuración tiene un constructor de parámetros que recibe un proveedor.
El genérico indica si quiero cargar Appleconfig o Bananconfig. El genérico <u> indica qué método de carga cargar, ¿es un documento, propiedades o algo más?
Ejemplos de aplicaciones prácticas
Hay un archivo de configuración de mercado de vegetales Market.xml, que configura los productos del mercado de vegetales, incluidos dos productos, a saber, manzanas y huevos.
<set Market> <Apple> <Color> Red </ Color> <Price> 100 </price> </saple> <ging> <weight> 200 </weight> </gg> </set>
También hay un archivo de configuración para los nombres de los jefes en cada puesto, propietario.
Port1 = Steve JobsPort2 = Bill Gatesport3 = Kobe Bryant
Definamos primero las siguientes clases:
MarketConfig.java
/** * * * @author bean * @Date 21 de enero de 2016 a las 11:03:37 pm * @Version 1.0 * */public class MarketCig {private Appleconfig Appleconfig; EggConfig privado EggConfig; OwnerConfig privado OwnerConfig; public Appleconfig getAppleconfig () {return Appleconfig; } public void setAppleconfig (AppleconFig Appleconfig) {this.appLeconfig = Appleconfig; } public EggConfig geteggConfig () {return EggConfig; } public void seteggConfig (EggConfig EggConfig) {this.eggConfig = EggConfig; } public OwnerConfig getownerConfig () {return othereConfig; } public void setOWNERCOnfig (OwnerConfig OwnerConfig) {this.OWNERCONFIG = OwnerConfig; }}Appleconfig.java
/** * * * @author bean * @Date 21 de enero de 2016 a las 11:03:45 pm * @version 1.0 * */public class Appleconfig {private int Price; color de cuerda privada; public void setPrice (int precio) {this.price = precio; } public int getPrice () {return this.price; } public void setColor (Color de cadena) {this.color = color; } public String getColor () {return this.color; }}EggConfig.java
/** * * * @author bean * @Date 21 de enero de 2016 a las 11:03:58 pm * @version 1.0 * */public class EggConfig {private int Weight; public void setweight (int weight) {this.weight = weight; } public int getPeight () {return this.weight; }} OwnerConfig.java
/** * * * * @author bean * @Date 21 de enero de 2016 a las 11:04:06 pm * @version 1.0 * */public class OwnerConfig {private map <string, string> propietario = nuevo hashmap <string, string> (); public void addowner (String PortName, String propietario) {this.owner.put (portname, propietario); } public String getOwnerByPortName (String PortName) {return this.owner.get (portname); } mapa público <string, string> getowners () {return Collections.unmodifiablemapp (this.owner); }} Hay dos métodos de carga de configuración para este ejemplo, a saber, DOM y métodos de carga de propiedades.
Por lo tanto, nuestros proveedores necesitan construir fábricas con dos proveedores.
Y dos cargadores de configuración deben definirse, a saber:
OwnerConfigloader
/** * * * * @Author Bean * @Date el 21 de enero de 2016 a las 11:24:50 pm * @Version 1.0 * */public class OwnerConfigLoader extiende AbstractConfigLoader <OwnerConfig, Properties> {/** * @param Provider */ProtectedERConfigLoader (IconfigProvidere> Provider) {Super (Provider); } / * * @see AbstractConfigLoader#Load (java.lang.object) * / @Override public OwnerConfig Load (Propiedades de propiedades) arroja configException {OwnerConfig OwnerConfig = new OwnerConFig (); / ** * Use accesorios para establecer el valor de la propiedad de OwnerConfig * * El código aquí se omite */ return OwnerConfig; }}Luego está MarketConfigLoader
import org.w3c.dom.Document;/** * * @author Bean * @date January 21, 2016 at 11:18:56 pm * @version 1.0 * */public class MarketConfigLoader extends AbstractConfigLoader<MarketConfig, Document> { /** * @param provider */ protected MarketConfigLoader(IConfigProvider<Document> provider) { super(provider); } / * * AbstractConfigLoader#load (java.lang.object) * / @Override public MarketCig Load (documento documento) arroja configException {MarketCig MarketConfig = new MarketCig (); Appleconfig Appleconfig = new AppleconFig (); EggConfig EggConfig = new EggConfig (); / ** * Procese el documento aquí, y luego puede obtener * Appleconfig y EggConfg * * El código aquí se omite */ MarketCig.SetApplecOnfig (AppleConFig); MarketConfig.SeteGGConfig (EggConfig); / ** * Dado que OwnerConfig requiere que las propiedades se carguen, no es XML *, por lo que aquí necesitamos crear un nuevo OwnerConfigLoader y delegarlo para cargar OwnerConfig */ OwnerConfigLoader OwnerConfigLoader = nuevo OwnerConfigLoader (configProviderFactory.createPreperTiesProvider (su_file_path)); OwnerConfig OwnerConfig = OwnerConfigLoader.load (); MarketConfig.SetOwnerConfig (OwnerConfig); devolver MarketConfig; }}Entonces, ¿cómo obtenemos MarketConfig a nivel de aplicación?
MarketCigLoader MarketCigLoader = new MarketCigLoader (configProviderFactory.CreateDocumentProvider (your_file_path));
Marketconfig MarketConfig = MarketCigLoader.Load ();
Tal vez hay un lugar donde la gente puede sorprenderse. Obviamente, hay cuatro clases de configuración, entonces, ¿por qué hay solo dos cargadores de configuración?
Debido a que MarketConfig, EggConfig y Appleconfig se cargan desde el mismo archivo de configuración XML, siempre que se use un objeto de documento, se puede cargar a través del MarketCigLoader.
OwnerConfig es un método de carga diferente, por lo que se necesita otro cargador.
fin
El mecanismo de carga de configuración propuesto en este artículo no puede ayudar a cargar la configuración. Esto debe dejarse a Dom, Sax y algunas otras bibliotecas de código abierto como DOM4J y Digester.
Sin embargo, el mecanismo de carga de configuración propuesto en este artículo puede hacer que el mecanismo de carga de configuración sea más flexible y fácil de expandir, y puede integrar múltiples métodos de carga de configuración, integrarlos en un mecanismo y jugar sus propios puntos.
De hecho, algún software a menudo necesita cargar configuraciones de archivos de configuración en múltiples formatos diferentes al mismo tiempo, como Struts2 y un software de middleware de base de datos de código abierto interno que he estado investigando y vomitando sangre recientemente.
Si no hay un mecanismo de carga de configuración completo, el código estará más disperso y menos mantenible. Puede hacer que las personas vomiten sangre.