sql >> Databasteknik >  >> RDS >> Mysql

Hur man dynamiskt laddar in värden i Tomcat's Context XML-fil

Säg att du har en tomcat/conf/context.xml-fil som ser ut ungefär så här:

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

Vad vi vill ersätta i det här fallet är allt i ${.*}-grejen i den här resursdefinitionen. Med en liten modifiering av koden nedan kan du dock utföra dessa ersättningar på i stort sett vilka kriterier du vill.

Lägg märke till raden factory="com.mycompany.util.configuration.CustomDataSourceFactory"

Vad detta betyder är att Tomcat kommer att försöka använda den här fabriken för att bearbeta den här resursen. Det bör nämnas att detta betyder att den här fabriken måste vara på Tomcats klassväg vid uppstart (Personligen lägger jag min i en JAR i Tomcat lib katalog).

Så här ser min fabrik ut:

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

Sedan, när den här koden är på klassvägen, starta om Tomcat och titta på catalina.out för loggmeddelanden. OBS:System.out.println uttalanden kommer sannolikt att skriva ut känslig information till dina loggar, så du kanske vill ta bort dem när du är klar med felsökningen.

På en anteckning skrev jag ut detta eftersom jag fann att många exempel var för specifika för ett specifikt ämne (som att använda kryptografi), och jag ville visa hur detta kan göras generellt. Dessutom förklarar några av de andra svaren på den här frågan sig inte så bra, och jag var tvungen att gräva lite för att ta reda på vad som behövde göras för att få det här att fungera. Jag ville dela mina fynd med er. Kommentera gärna detta, ställ några frågor eller gör korrigeringar om du hittar problem, så kommer jag att se till att korrigera dem i mitt svar.



  1. Fel vid försök att installera Django CMS i virtualenv w/ MySQL på Mac OSX

  2. MySQL - Ange standardvärde för fält som en strängsammansättningsfunktion

  3. Spelar ordningen på kolumner i en WHERE-sats någon roll?

  4. Hämta TOP 10 rader utan att använda TOP eller LIMIT? – Veckans intervjufråga #247