Mysql
 sql >> Database >  >> RDS >> Mysql

Come caricare dinamicamente i valori nel file XML del contesto di Tomcat

Supponiamo che tu abbia un file tomcat/conf/context.xml che assomiglia a questo:

<?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>

Quello che vogliamo sostituire in questo caso è qualcosa nella roba ${.*} in questa definizione di risorsa. Con una leggera modifica al codice seguente, tuttavia, puoi eseguire queste sostituzioni praticamente con qualsiasi criterio desideri.

Notare la riga factory="com.mycompany.util.configuration.CustomDataSourceFactory"

Ciò significa che Tomcat tenterà di utilizzare questa fabbrica per elaborare questa risorsa. Va detto che questo significa che questa factory dovrà essere sul percorso di classe di Tomcat all'avvio (Personalmente, ho messo il mio in un JAR nel Tomcat lib directory).

Ecco come appare la mia fabbrica:

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.
    }
}

Quindi, una volta che questo codice è nel percorso di classe, riavvia Tomcat e guarda catalina.out per i messaggi di registro. NOTA:System.out.println È probabile che le istruzioni finiranno per stampare informazioni riservate sui tuoi log, quindi potresti voler rimuoverle una volta terminato il debug.

In una nota a margine, l'ho scritto perché ho scoperto che molti esempi erano troppo specifici per un argomento specifico (come l'utilizzo della crittografia) e volevo mostrare come questo può essere fatto in modo generico. Inoltre, alcune delle altre risposte a questa domanda non si spiegano molto bene e ho dovuto scavare un po' per capire cosa era necessario fare per farlo funzionare. Volevo condividere le mie scoperte con voi ragazzi. Sentiti libero di commentare questo, porre domande o apportare correzioni se trovi problemi e sarò sicuro di inserire le correzioni nella mia risposta.