DirContext 對象,文件根路徑指向上下文的文件根路徑Loader 接口),內部包含一個類載入器(默認 WebappClassLoader)WEB-INF/classes 和 WEB-INF/lib)public interface Loader {
ClassLoader getClassLoader(); // 獲取內部類載入器
Container getContainer(); // 關聯的容器
void setContainer(Container container);
boolean getDelegate(); // 是否委派給父類載入器
void setDelegate(boolean delegate);
boolean getReloadable(); // 是否支持自動重載
void setReloadable(boolean reloadable);
void addRepository(String repository); // 添加倉庫路徑
String[] findRepositories();
boolean modified(); // 類文件是否被修改
// ... PropertyChangeListener 相關方法
}
在 server.xml 中配置 Context 元素:
<Context debug="0" docBase="myApp" path="/myApp" reloadable="true" />
WebappLoader.start() 執行以下關鍵步驟:
WebappClassLoader,可通過 setLoaderClass 自定義(需繼承 WebappClassLoader)setRepositories 添加 WEB-INF/classes 和 WEB-INF/librun() 方法,定期檢查類文件修改(間隔 checkInterval 秒),檢測到變更調用 container.reload()public void run() {
while (!threadDone) {
threadSleep(); // 休眠 checkInterval 秒
if (!started) break;
try {
if (!classLoader.modified()) continue; // 無變更繼續
} catch (Exception e) { log(...); continue; }
notifyContext(); // 觸發重載
break;
}
}
private void notifyContext() {
new Thread(new WebappContextNotifier()).start(); // 新線程避免阻塞
}
class WebappContextNotifier implements Runnable {
public void run() { ((Context) container).reload(); }
}
// 禁止加載的類
private static final String[] triggers = {
"javax.servlet.Servlet"
};
// 禁止委派給系統載入器的包
private static final String[] packageTriggers = {
"javax", "org.xml.sax", "org.w3c.dom",
"org.apache.xerces", "org.apache.xalan"
};
WebappClassLoader 實例管理的 HashMap resourceEntries java.lang.ClassLoader 維護的 Vector 緩存public class ResourceEntry {
public long lastModified = -1; // 最後修改時間
public byte[] binaryContent = null; // 類文件字節碼
public Class loadedClass = null; // 已加載的 Class 對象
public URL source = null; // 來源 URL
public URL codeBase = null; // 代碼庫 URL
public Manifest manifest = null; // 清單信息
public Certificate[] certificates = null; // 證書
}
未找到的資源存放在 notFoundResources 中,避免重複查找。
