Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment charger dynamiquement des valeurs dans le fichier XML de contexte de Tomcat

Supposons que vous ayez un fichier tomcat/conf/context.xml qui ressemble à ceci :

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

Ce que nous voulons remplacer dans ce cas, c'est tout ce qui se trouve dans les éléments ${.*} de cette définition de ressource. Cependant, avec une légère modification du code ci-dessous, vous pouvez effectuer ces substitutions sur à peu près tous les critères que vous souhaitez.

Remarquez la ligne factory="com.mycompany.util.configuration.CustomDataSourceFactory"

Cela signifie que Tomcat tentera d'utiliser cette usine pour traiter cette ressource. Il faut préciser que cela signifie que cette fabrique devra être sur le classpath de Tomcat au démarrage (Personnellement, j'ai mis le mien dans un JAR dans la lib de Tomcat annuaire).

Voici à quoi ressemble mon usine :

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

Ensuite, une fois que ce code est sur le classpath, redémarrez Tomcat et regardez catalina.out pour les messages de journal. REMARQUE :Le System.out.println finiront probablement par imprimer des informations sensibles dans vos journaux, vous pouvez donc les supprimer une fois le débogage terminé.

En passant, j'ai écrit ceci parce que j'ai trouvé que de nombreux exemples étaient trop spécifiques à un sujet spécifique (comme l'utilisation de la cryptographie), et je voulais montrer comment cela peut être fait de manière générique. De plus, certaines des autres réponses à cette question ne s'expliquent pas très bien, et j'ai dû creuser pour comprendre ce qu'il fallait faire pour que cela fonctionne. Je voulais partager mes découvertes avec vous les gars. N'hésitez pas à commenter cela, à poser des questions ou à apporter des corrections si vous rencontrez des problèmes, et je m'assurerai d'intégrer les correctifs dans ma réponse.