sql >> Base de Datos >  >> RDS >> Mysql

Cómo cargar valores dinámicamente en el archivo XML de contexto de Tomcat

Digamos que tiene un archivo tomcat/conf/context.xml que se parece a esto:

<?xml version="1.0" encoding="utf-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Resource 
            name="jdbc/MyDB" 
            auth="Container" 
            type="javax.sql.DataSource" 
            removeAbandoned="true" 
            removeAbandonedTimeout="15" 
            maxActive="5" 
            maxIdle="5" 
            maxWait="7000" 
            username="${db.mydb.uid}"
            password="${db.mydb.pwd}"
            driverClassName="${db.mydb.driver}"
            url="${db.mydb.url}${db.mydb.dbName}?autoReconnectForPools=true&amp;characterEncoding=UTF-8"
            factory="com.mycompany.util.configuration.CustomDataSourceFactory"
            validationQuery="SELECT '1';"
            testOnBorrow="true"/>
</Context>

Lo que queremos reemplazar en este caso es algo en el material ${.*} en esta definición de recurso. Sin embargo, con una ligera modificación en el código a continuación, puede realizar estas sustituciones en prácticamente cualquier criterio que desee.

Observe la línea factory="com.mycompany.util.configuration.CustomDataSourceFactory"

Lo que esto significa es que Tomcat intentará usar esta fábrica para procesar este recurso. Cabe mencionar que esto significa que esta fábrica tendrá que estar en el classpath de Tomcat al inicio (personalmente, puse el mío en un JAR en Tomcat lib directorio).

Así es como se ve mi fábrica:

package com.mycompany.util.configuration;

import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import org.apache.commons.dbcp.BasicDataSourceFactory;

public class CustomDataSourceFactory extends BasicDataSourceFactory implements ObjectFactory {

    private static final Pattern _propRefPattern = Pattern.compile("\\$\\{.*?\\}");

    //http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html#Adding_Custom_Resource_Factories
    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
        if (obj instanceof Reference) {
            Reference ref = (Reference) obj;
            System.out.println("Resolving context reference values dynamically");

            for(int i = 0; i < ref.size(); i++) {
                RefAddr addr = ref.get(i);
                String tag = addr.getType();
                String value = (String) addr.getContent();

                Matcher matcher = _propRefPattern.matcher(value);
                if (matcher.find()) {
                    String resolvedValue = resolve(value);
                    System.out.println("Resolved " + value + " to " + resolvedValue);
                    ref.remove(i);
                    ref.add(i, new StringRefAddr(tag, resolvedValue));
                }
            }
        }
        // Return the customized instance
        return super.getObjectInstance(obj, name, nameCtx, environment);
    }

    private String resolve(String value) {
        //Given the placeholder, do stuff to figure out what it's true value should be, and return that String.
        //This could be decryption, or maybe using a properties file.
    }
}

Luego, una vez que este código esté en el classpath, reinicie Tomcat y observe catalina.out para ver los mensajes de registro. NOTA:El System.out.println Es probable que las declaraciones terminen imprimiendo información confidencial en sus registros, por lo que es posible que desee eliminarlas una vez que haya terminado con la depuración.

En una nota al margen, escribí esto porque descubrí que muchos ejemplos eran demasiado específicos para un tema específico (como el uso de criptografía), y quería mostrar cómo se puede hacer esto de manera genérica. Además, algunas de las otras respuestas a esta pregunta no se explican muy bien, y tuve que investigar un poco para averiguar qué se necesitaba hacer para que esto funcionara. Quería compartir mis hallazgos con ustedes. Siéntase libre de comentar sobre esto, hacer cualquier pregunta o hacer correcciones si encuentra problemas, y me aseguraré de incluir las correcciones en mi respuesta.