第一個
有一個養雞場幾千只雞分別排列的被關在狹小的雞籠裡雞籠的前面有傳送帶為小雞送來食物後面有傳送帶送走產下的雞蛋可是卻注意到有幾十只小雞在外面逍遙還有飼養員在給他們喂食
於是就問是否需要幫忙吧這些雞趕到籠子裡去呢?
飼養員回答說哦這些雞是在外面養著的要是籠子裡的那些雞看不到有的雞自由自在的生活它們就會失去信心不下蛋沒有這些放養的雞其它的就會放棄一切然後死去
突然驚異的發現我們的生活方式和這些雞是何等的相似有多少人生活在籠子裡看著外面的世界裡別人在探險在實現自己的夢想自由自在的生活然後繼續省會在自己的籠子裡
作者描述自己起先放棄一年的時間去到外面的世界看看最後放棄了自己的職業成為了逍遙自在的那一個
第二個故事我放到本文的最後告訴各位哦哈哈
主題
在前面的主題中我們已經了解過servlet的工作流程Servlet我們到底能走多遠系列()
問題:tomcat什麼時候加載servlet?
有兩種情況
一種是啟動時加載
一種是請求時加載
第一種是在webxml中的<servlet>節點下增加類似<loadonstartup></loadonstartup>的節點
例子如下
<servlet>
<servletname>DicDataIniter</servletname>
<servletclass>cominitDicDataIniter</servletclass>
<loadonstartup></loadonstartup> </servlet> <servletmapping>
<servletname>DicDataIniter</servletname>
<urlpattern>/DicDataIniter</urlpattern> </servletmapping>
關於loadonstartup需要了解的是
)loadonstartup元素標記容器是否在啟動的時候就加載這個servlet(實例化並調用其init()方法))它的值必須是一個整數表示servlet應該被載入的順序)當值為或者大於時表示容器在應用啟動時就加載並初始化這個servlet;)當值小於或者沒有指定時則表示容器在該servlet被選擇時才會去加載)正數的值越小該servlet的優先級越高應用啟動時就越先加載)當值相同時容器就會自己選擇順序來加載所以<loadonstartup>x</loadonstartup>中x的取值代表的是優先級
第二種的流程類似如下圖
問題:tomcat是怎麼加載一個servlet類的呢?
根據上篇對一個簡單的webServer模擬(How Tomcat Works 學習我們到底能走多遠系列())在到達加載servlet類實例化一個servlet實例這一步之前的工作我們已經完成了我們已經取得了來自http消息中的uri也就已經取得了需要調用的servlet的名字
根據《How tomcat works》先搞一個自己的servlet:沒什麼邏輯只是生成class文件放到指定的文件夾下等待加載
package codetomcatservletContainer;import javaioIOException;import javaioPrintWriter;import javaxservlet*;public class PrimitiveServlet implements Servlet{
public void init(ServletConfig config) throws ServletException {
Systemoutprint(init)
}
public ServletConfig getServletConfig() {
return null;
}
// 一旦實現了service方法那麼就不會就不會調用父類的service方法從而調用doGet或doPost
public void service(ServletRequest req ServletResponse res)
throws ServletException IOException {
Systemoutprint(service)
PrintWriter writer = resgetWriter()
writerprintln(Hello Roses are red)
}
public String getServletInfo() {
return null;
}
public void destroy() {
Systemoutprint(destroy)
}}
加載方法如下
package codetomcatservletContainer;import javaioFile;import javaioIOException;import MalformedURLException;import URL;import URLClassLoader;import URLStreamHandler;import javaxservletServlet;import javaxservletServletRequest;import javaxservletServletResponse;public class ServletProcessor {
public void process(Request request Response response){
// 取得request處理好的uri
String uri = requestgetUri()
// servlet 類名
String servletName = urisubstring(uriindexOf(/) + )
// 類加載器利用提供的url目錄來加載class文件大多數情況下我們的程序在jvm啟動的已經有類加載器加載我們需要的類文件
// 但是最為需要及時部署的服務器servlet容器需要自己去加載放到服務器的工程
URLClassLoader loader = null;
// URLClassLoader構造函數需要URL數組這裡是需要加載一個類
URL[] urls = new URL[];
// 構造URL用雖然是null但如果直接在URL中直接用null來代替編譯器不答應啊
URLStreamHandler streamHandler = null;
File classPath = new File(/webroot)
try {
// servlet文件夾位置
String repository = (new URL(file null classPathgetCanonicalPath() + Fileseparator))toString()
urls[] = new URL(null repository streamHandler)
// 得到傳說中的類加載器
loader = new URLClassLoader(urls)
} catch (MalformedURLException e) {
eprintStackTrace()
} catch (IOException e) {
eprintStackTrace()
}
// class文件加載後就是java中的Class類實例啦
Class myClass = null;
try {
// servlet Class類實例
myClass = loaderloadClass(servletName)
} catch (ClassNotFoundException e) {
eprintStackTrace()
}
Servlet servlet = null;
try {
// 用newInstance方法得到一個servlet實例
servlet = (Servlet)myClassnewInstance()
// 調用PrimitiveServlet的service方法
servletservice((ServletRequest)request (ServletResponse)response)
} catch (Exception e) {
Systemoutprintln(etoString())
}
}}
如此servlet流程中的初始加載這一步就可以勉強完成了tomcat中的實現要復雜很多吧原理基本是差不多了先打下基礎
關於類加載
其實tomcat啟動的時候就有大量的類加載工作需要做應為tomcat本身就是個java工程嘛
SystemgetProperty:
有個類似寫日志的方法
/**
* 寫日志
* @param logString
* @throws IOException
*/
public void writeLog(String logString) throws IOException {
File logFile = new File(d:\\我的文檔\\testlog)
// 寫
FileWriter writer = new FileWriter(logFiletrue)
// 取得回車符號
String nextLine = SystemgetProperty(lineseparator)
writerwrite(logString + nextLine)
writerflush()
writerclose()
}
其中SystemgetProperty(lineseparator)方法值得熟悉
我們可以通過這樣的方式取得一些System級別的常量
javaversion Java 運行時環境版本javavendor Java 運行時環境供應商javavendorurl Java 供應商的 URLjavahome Java 安裝目錄javavmspecificationversion Java 虛擬機規范版本javavmspecificationvendor Java 虛擬機規范供應商javavmspecificationname Java 虛擬機規范名稱javavmversion Java 虛擬機實現版本javavmvendor Java 虛擬機實現供應商javavmname Java 虛擬機實現名稱javaspecificationversion Java 運行時環境規范版本javaspecificationvendor Java 運行時環境規范供應商javaspecificationname Java 運行時環境規范名稱javaclassversion Java 類格式版本號javaclasspath Java 類路徑javalibrarypath 加載庫時搜索的路徑列表javaiotmpdir 默認的臨時文件路徑piler 要使用的 JIT 編譯器的名稱javaextdirs 一個或多個擴展目錄的路徑osname 操作系統的名稱osarch 操作系統的架構osversion 操作系統的版本fileseparator 文件分隔符(在 UNIX 系統中是/)pathseparator 路徑分隔符(在 UNIX 系統中是:)lineseparator 行分隔符(在 UNIX 系統中是/n)username 用戶的賬戶名稱userhome 用戶的主目錄userdir 用戶的當前工作目錄
好吧來講一下第二個故事吧
一個印第安人和他的朋友走到美國繁華的街道上汽車的鳴笛聲警笛聲人們的喊聲整個街道噪聲簡直震耳欲聾
突然一個印第安人說我聽到有個蟋蟀在叫
他的朋友說什麼?你瘋了嗎?在這麼吵的地方你怎麼可能聽到蟋蟀的叫聲呢?
可是那個印第安人卻非常肯定他走到街對面的一塊水泥石板前上面長滿了灌木他在灌木堆裡找就在那裡找到了一只蟋蟀
他的朋友問太不可思議了你是怎麼做到的?
印第安人說沒有什麼不可思議的著取決於什麼對你是真正重要的來我來告訴你怎麼回事
他拿出一塊硬幣扔到人行道上他們發現幾乎所有在人行道上的人都低頭去查看地上的硬幣是不是他們遺落的
你明白了嗎?這一切取決於什麼對你來說是最重要的
讓我們繼續前行
努力不一定成功但不努力肯定不會成功
共勉
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25895.html