Servlet
servlet沒有main方法,他受一個叫做容器的java應(yīng)用(比如Tomcat)控制。當(dāng)web server應(yīng)用(比如Apache)收到容器訪問servlet請求,server不是先把請求直接給servlet,而是先給部署這個servlet的容器,容器“看到”找的是servlet,創(chuàng)建兩個對象:HttpServletResponse和HttpServletRequest。容器根據(jù)URL找到servlet類,為這個請求創(chuàng)建或從池里分配線程,把request和response對象傳給該線程,servlet的生命周期就開始了。
容器啟動的時候這步就發(fā)生了,一啟動容器就開始找部署的web項目。第一尋找其servlet類,第二就開始加載這個類。A servlet moves from does not exist to initialized (which really means ready to service client requests), beginning with a constructor. But the constructor makes only an object, not a servlet. To be a servlet, the object needs to be granted servletness. 所以在構(gòu)造函數(shù)和init()之間的狀態(tài)是一種“半死半活狀態(tài)”,這時候不能接觸很多作為servlet能接觸的資源(like getting web app configuration info, or looking up a reference to another part of the application),所以init()之前都不要做什么操作,不要在構(gòu)造函數(shù)中放東西。在創(chuàng)建servlet實(shí)例之后在為任何客戶端請求服務(wù)之前,容器就調(diào)用init方法,你可以在處理請求之前在里面初始化你的servlet(重寫此方法可以建立數(shù)據(jù)庫連接,用其他對象注冊自己等)。接著調(diào)用service方法(重寫此方法的可能性不大),接著doGet/doPost(至少重寫其中一個方法)。service結(jié)束后,線程就消亡或者放回池里。但第二個請求來,容器再次創(chuàng)建或從池里分配線程,繼續(xù)service->doGet/doPost 序列。因此,在一個時間段內(nèi),有多少客戶請求就有多少運(yùn)行的線程,當(dāng)然也受容器的策略、配置或資源限制(比如指定容器的最大并發(fā)線程數(shù),當(dāng)請求的客戶數(shù)超過的時候,客戶就必須等待)。容器運(yùn)行多個線程來處理多個對一個servlet的請求(不管是不是同一個客戶發(fā)出請求,一個請求一個線程),對于分布式web應(yīng)用,一個JVM只對應(yīng)一個servlet實(shí)例
成為一個servlet可以給你什么:一個ServletConfig對象,一個ServletContext。
ServletConfig對象:每個servlet有一個;Use it to pass deploy-time information to the servlet (a database or enterprise bean lookup name, for example)that you don’t want to hard-code into the servlet (servlet init parameters);訪問ServletContext;Parameters are configured in the Deployment Descriptor(如<init-param>方式配置).我們可以通過servletconfig獲得初始化參數(shù)(getServletConfig().getInitParameter(“foo”);),然后通過setAttribute dispatch給某個jsp頁面,但是針對一個servlet的初始化參數(shù)很有局限性,所以引入針對應(yīng)用的<context-param>,這時候通過servletContext獲得初始化參數(shù)(getServletContext().getInitParameter(“foo”)),這個初始化參數(shù)可以被應(yīng)用的任意servlet,jsp訪問。注意初始化參數(shù)是一個deploy-time constants,不能在runtime改變他們,只能通過重新部署。
ServletContext :每個web app有一個(嚴(yán)格說來如果是分布式的話,應(yīng)該是每個JVM一個);Use it to access web app parameters (also confi gured in the Deployment Descriptor) ;類似application bulletin-board功能,讓其他應(yīng)用也能訪問;用來獲得服務(wù)器信息,比如容器名字和版本,以及支持的API版本。ServletContextListener 可以監(jiān)聽ServletContext 的初始化(從ServletContext中獲得初始化參數(shù),用參數(shù)連接數(shù)據(jù)庫,把連接作為attribute存起來以便所有應(yīng)用都可以訪問)和銷毀階段(關(guān)閉連接)。為了使context attributes 線程安全,可以對context進(jìn)行同步鎖的方式:
synchronized(getServletContext()) { getServletContext().setAttribute(“foo”, “22”); getServletContext().setAttribute(“bar”, “42”); out.println(getServletContext().getAttribute(“foo”)); out.println(getServletContext().getAttribute(“bar”)); }
ServletResponse接口有兩種流可供輸出:ServletOutputStream for bytes, or a PrintWriter for character data.
例:1 PrintWriter writer = response.getWriter();
writer.println(“some text and HTML”);
2 ServletOutputStream out = response.getOutputStream();
out.write(aByteArray);
如果不想自己處理,可通過redirect給一個全新的URL(注意如果response已提交后不能再redirect),或者dispatch the request 給你應(yīng)用中的某個組件(如jsp)。redirect會先返回給客戶,客戶再重新發(fā)請求,而dispatch 的話,服務(wù)器會直接轉(zhuǎn)給某個組件。這樣兩種方式的區(qū)別就很明顯了。 servlet->容器調(diào)用service()->doGet()/doPost() 產(chǎn)生動態(tài)頁面并把頁面放入response對象,記住此時容器仍然有引用指向該response對象!線程完成,容器把response對象轉(zhuǎn)換為HTTP對象,送回客戶端,然后刪除request和response對象。
posted on 2009-05-15 10:22 yuxh 閱讀(261) 評論(0) 編輯 收藏 所屬分類: j2ee