Giả sử bạn có tệp tomcat / conf / context.xml trông giống như sau:
<?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>
Những gì chúng tôi muốn thay thế trong trường hợp này là bất kỳ thứ gì trong $ {. *} Trong định nghĩa tài nguyên này. Tuy nhiên, với sửa đổi nhỏ đối với mã bên dưới, bạn có thể thực hiện các thay thế này dựa trên bất kỳ tiêu chí nào bạn muốn.
Lưu ý dòng factory="com.mycompany.util.configuration.CustomDataSourceFactory"
Điều này có nghĩa là Tomcat sẽ cố gắng sử dụng nhà máy này để xử lý tài nguyên này. Cần lưu ý rằng điều này có nghĩa là nhà máy này sẽ phải nằm trên classpath của Tomcat khi khởi động (Cá nhân tôi đặt của tôi vào một JAR trong Tomcat lib
danh mục).
Đây là nhà máy của tôi trông như thế nào:
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.
}
}
Sau đó, khi mã này nằm trên classpath, hãy khởi động lại Tomcat và xem catalina.out để biết thông báo nhật ký. LƯU Ý:System.out.println
các câu lệnh có thể sẽ kết thúc việc in thông tin nhạy cảm vào nhật ký của bạn, vì vậy bạn có thể muốn xóa chúng sau khi gỡ lỗi xong.
Trên một ghi chú bên lề, tôi viết điều này ra vì tôi thấy rằng nhiều ví dụ quá cụ thể cho một chủ đề cụ thể (chẳng hạn như sử dụng mật mã) và tôi muốn chỉ ra cách thức chung chung có thể thực hiện điều này. Hơn nữa, một số câu trả lời khác cho câu hỏi này không tự giải thích rõ lắm, và tôi đã phải thực hiện một số nghiên cứu để tìm ra những gì cần phải làm để làm cho câu hỏi này thành công. Tôi muốn chia sẻ những phát hiện của tôi với các bạn. Vui lòng bình luận về vấn đề này, đặt bất kỳ câu hỏi nào hoặc sửa chữa nếu bạn thấy vấn đề và tôi chắc chắn sẽ đưa các bản sửa lỗi vào câu trả lời của mình.