Lad os sige, at du har en tomcat/conf/context.xml-fil, der ser sådan ud:
<?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&characterEncoding=UTF-8"
factory="com.mycompany.util.configuration.CustomDataSourceFactory"
validationQuery="SELECT '1';"
testOnBorrow="true"/>
</Context>
Det, vi ønsker at erstatte i dette tilfælde, er alt i ${.*}-tingene i denne ressourcedefinition. Med en lille ændring af koden nedenfor kan du dog udføre disse erstatninger på stort set hvilke kriterier du ønsker.
Bemærk linjen factory="com.mycompany.util.configuration.CustomDataSourceFactory"
Det betyder, at Tomcat vil forsøge at bruge denne fabrik til at behandle denne ressource. Det skal nævnes, at dette betyder, at denne fabrik skal være på Tomcats klassesti ved opstart (Personligt satte jeg min i en JAR i Tomcat lib
vejviser).
Sådan ser min fabrik ud:
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.
}
}
Så, når denne kode er på klassestien, genstart Tomcat og hold øje med catalina.out for logmeddelelserne. BEMÆRK:System.out.println
Udsagn vil sandsynligvis ende med at udskrive følsomme oplysninger til dine logfiler, så du vil måske fjerne dem, når du er færdig med at fejlfinde.
På en sidenote skrev jeg dette ud, fordi jeg fandt ud af, at mange eksempler var for specifikke for et specifikt emne (såsom brug af kryptografi), og jeg ville vise, hvordan dette kan gøres generisk. Desuden forklarer nogle af de andre svar på dette spørgsmål sig ikke særlig godt, og jeg var nødt til at grave lidt for at finde ud af, hvad der skulle gøres for at få dette til at fungere. Jeg ville dele mine resultater med jer. Du er velkommen til at kommentere dette, stille spørgsmål eller lave rettelser, hvis du finder problemer, så vil jeg sørge for at rulle rettelserne ind i mit svar.