Katakanlah Anda memiliki file Tomcat/conf/context.xml yang terlihat seperti ini:
<?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>
Apa yang ingin kami ganti dalam kasus ini adalah apa pun yang ada di ${.*} dalam definisi sumber daya ini. Namun, dengan sedikit modifikasi pada kode di bawah ini, Anda dapat melakukan penggantian ini pada hampir semua kriteria yang Anda inginkan.
Perhatikan baris factory="com.mycompany.util.configuration.CustomDataSourceFactory"
Artinya, Tomcat akan mencoba menggunakan pabrik ini untuk memproses sumber daya ini. Harus disebutkan bahwa ini berarti bahwa pabrik ini harus berada di classpath Tomcat saat startup (Secara pribadi, saya meletakkan milik saya di JAR di lib
Tomcat direktori).
Inilah tampilan pabrik saya:
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.
}
}
Kemudian, setelah kode ini berada di classpath, mulai ulang Tomcat dan perhatikan catalina.out untuk pesan log. CATATAN:System.out.println
pernyataan kemungkinan akan mencetak informasi sensitif ke log Anda, jadi Anda mungkin ingin menghapusnya setelah Anda selesai men-debug.
Sebagai tambahan, saya menulis ini karena saya menemukan bahwa banyak contoh terlalu spesifik untuk satu topik tertentu (seperti menggunakan kriptografi), dan saya ingin menunjukkan bagaimana hal ini dapat dilakukan secara umum. Selain itu, beberapa jawaban lain untuk pertanyaan ini tidak menjelaskan dengan baik, dan saya harus melakukan penggalian untuk mencari tahu apa yang perlu dilakukan untuk membuat ini berhasil. Saya ingin berbagi temuan saya dengan kalian. Silakan mengomentari ini, mengajukan pertanyaan, atau membuat koreksi jika Anda menemukan masalah, dan saya pasti akan memasukkan perbaikan ke dalam jawaban saya.