StandardContext
Context代表一個web應用,每個Context包含多個代表servlet的Wrapper,同時Context還需要加載器和管理器。
StandardContext配置
當StandardContext被構造以後,必須調用它的start方法,確保StandardContext爲HTTP請求提供服務。如果start失敗StandardContext的available屬性將會被設置爲false。
爲了確保啓動方法運行成功,需要做適當的配置。在Tomcat部署過程中,配置StandardContext過程中需要做很多事情,首先,必須確保StandardContext能讀取%CATALINA_HOME%/conf目錄下所有應用部署都要使用的默認web.xml文件;其次,也必須確保StandardContext實例能夠處理應用級的web.xml,通常在其中有一些有效參數。
構造函數
public StandardContext() {
super();
pipeline.setBasic(new StandardContextValve());
namingResources.setContainer(this);
}
這裏最重要的步驟是爲管道pipeline添加StandardContextValue作爲基礎value,用來處理來自客戶端的HTTP請求。
啓動StandardContext
start方法初始化StandardContext,並告知監聽則配置StandardContext實例,需要做如下事情:
1、 觸發BEFORE_START事件;
2、 設置available屬性值爲false;
3、 設置configured屬性值爲false;
4、 設置resources;
5、 設置加載器;
6、 設置管理器;
7、 初始化字符集匹配器;
8、 啓動其他分配給該Context的組件;
9、 啓動子容器Wrapper;
10、 啓動管道(pipeline);
11、 啓動管理器;
12、 觸發START事件,這裏監聽器(ContextConfig)會執行配置操作,配置成功以後會把configred爲true;
13、 檢測configred值,如果爲true,則做後面操作:調用postWelcomePages方法,加載需要在啓動時候加載的wrapper,設置available爲true;如果configred爲false,則調用stop方法;
14、 觸發AFTER_START事件。
start方法實現如下:
public synchronized void start() throws LifecycleException {
if (started)
throw new LifecycleException
(sm.getString("containerBase.alreadyStarted", logName()));
if (debug >= 1)
log("Starting");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
if (debug >= 1)
log("Processing start(), current available=" + getAvailable());
setAvailable(false);
setConfigured(false);
boolean ok = true;
// Add missing components as necessary
if (getResources() == null) { // (1) Required by Loader
if (debug >= 1)
log("Configuring default Resources");
try {
if ((docBase != null) && (docBase.endsWith(".war")))
setResources(new WARDirContext());
else
setResources(new FileDirContext());
} catch (IllegalArgumentException e) {
log("Error initializing resources: " + e.getMessage());
ok = false;
}
}
if (ok && (resources instanceof ProxyDirContext)) {
DirContext dirContext =
((ProxyDirContext) resources).getDirContext();
if ((dirContext != null)
&& (dirContext instanceof BaseDirContext)) {
((BaseDirContext) dirContext).setDocBase(getBasePath());
((BaseDirContext) dirContext).allocate();
}
}
if (getLoader() == null) { // (2) Required by Manager
if (getPrivileged()) {
if (debug >= 1)
log("Configuring privileged default Loader");
setLoader(new WebappLoader(this.getClass().getClassLoader()));
} else {
if (debug >= 1)
log("Configuring non-privileged default Loader");
setLoader(new WebappLoader(getParentClassLoader()));
}
}
if (getManager() == null) { // (3) After prerequisites
if (debug >= 1)
log("Configuring default Manager");
setManager(new StandardManager());
}
// Initialize character set mapper
getCharsetMapper();
// Post work directory
postWorkDirectory();
// Reading the "catalina.useNaming" environment variable
String useNamingProperty = System.getProperty("catalina.useNaming");
if ((useNamingProperty != null)
&& (useNamingProperty.equals("false"))) {
useNaming = false;
}
if (ok && isUseNaming()) {
if (namingContextListener == null) {
namingContextListener = new NamingContextListener();
namingContextListener.setDebug(getDebug());
namingContextListener.setName(getNamingContextName());
addLifecycleListener(namingContextListener);
}
}
// Binding thread
ClassLoader oldCCL = bindThread();
// Standard container startup
if (debug >= 1)
log("Processing standard container startup");
if (ok) {
try {
addDefaultMapper(this.mapperClass);
started = true;
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
if ((logger != null) && (logger instanceof Lifecycle))
((Lifecycle) logger).start();
// Unbinding thread
unbindThread(oldCCL);
// Binding thread
oldCCL = bindThread();
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
// Start our Mappers, if any
Mapper mappers[] = findMappers();
for (int i = 0; i < mappers.length; i++) {
if (mappers[i] instanceof Lifecycle)
((Lifecycle) mappers[i]).start();
}
// Start our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}
// Start the Valves in our pipeline (including the basic),
// if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start();
} finally {
// Unbinding thread
unbindThread(oldCCL);
}
}
if (!getConfigured())
ok = false;
// We put the resources into the servlet context
if (ok)
getServletContext().setAttribute
(Globals.RESOURCES_ATTR, getResources());
// Binding thread
oldCCL = bindThread();
// Create context attributes that will be required
if (ok) {
if (debug >= 1)
log("Posting standard context attributes");
postWelcomeFiles();
}
// Configure and call application event listeners and filters
if (ok) {
if (!listenerStart())
ok = false;
}
if (ok) {
if (!filterStart())
ok = false;
}
// Load and initialize all "load on startup" servlets
if (ok)
loadOnStartup(findChildren());
// Unbinding thread
unbindThread(oldCCL);
// Set available status depending upon startup success
if (ok) {
if (debug >= 1)
log("Starting completed");
setAvailable(true);
} else {
log(sm.getString("standardContext.startFailed"));
try {
stop();
} catch (Throwable t) {
log(sm.getString("standardContext.startCleanup"), t);
}
setAvailable(false);
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
invoke方法
在Tomcat4中invoke方法被連接器調用,如果StandardContext是Host的子容器則被Host的invoke方法調用,在invoke方法中會檢測是否重載應用,會等待應用重載完成,方法實現如下:
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Wait if we are reloading
while (getPaused()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
;
}
}
// Normal request processing
if (swallowOutput) {
try {
SystemLogHandler.startCapture();
super.invoke(request, response);
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
log(log);
}
}
} else {
super.invoke(request, response);
}
}