次のようなtomcat/conf/context.xmlファイルがあるとします。
<?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>
この場合に置き換えたいのは、このリソース定義の${。*}のものです。ただし、以下のコードを少し変更するだけで、ほとんどすべての基準でこれらの置換を実行できます。
factory="com.mycompany.util.configuration.CustomDataSourceFactory"
という行に注意してください。
これが意味するのは、Tomcatがこのファクトリを使用してこのリソースを処理しようとするということです。これは、このファクトリが起動時にTomcatのクラスパス上にある必要があることを意味することに注意してください(個人的には、Tomcat lib
のJARに私のものを入れました ディレクトリ)。
私の工場は次のようになります:
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.
}
}
次に、このコードがクラスパスに追加されたら、Tomcatを再起動し、catalina.outでログメッセージを確認します。注:System.out.println
ステートメントは機密情報をログに出力する可能性が高いため、デバッグが完了したら、ステートメントを削除することをお勧めします。
補足として、多くの例が1つの特定のトピック(暗号化の利用など)に固有であることがわかったため、これを書き留めました。これを一般的に行う方法を示したいと思いました。さらに、この質問に対する他の回答のいくつかは、それ自体を十分に説明しておらず、この作業を行うために何をする必要があるかを理解するために、いくつかの掘り下げを行う必要がありました。私の発見を皆さんと共有したいと思いました。これについてコメントしたり、質問したり、問題が見つかった場合は修正したりしてください。修正を私の答えに反映させます。