Servlet專題

Servlet就是一段運(yùn)行在Web容器里的Java程序盼樟。(自己不能獨(dú)立運(yùn)行)?


Sun公司是如何實(shí)現(xiàn)這件事情的呢渤昌??

1) 首先Sun公司編寫了一系列Class愁铺,比如javax.servlet.http.HttpServlet余素,你編寫的Servlet需要利用或繼承它 們奔穿。這一系列Class都放在servlet-api.jar這個文件當(dāng)中镜沽。這樣底層和復(fù)雜機(jī)器環(huán)境比如網(wǎng)絡(luò)或Tomcat(Apache公司依據(jù)sun公司J2EE(Enterprise<企業(yè)> Edition)規(guī)范開發(fā))打交道的工作,Servlet 編寫者就不用考慮了贱田!servlet只需要考慮一段時(shí)期(Session)的相關(guān)的請求(Request)響應(yīng)(Response)系列就可以了缅茉。客戶端 把它想要發(fā)給服務(wù)器的數(shù)據(jù)男摧,存放在Request當(dāng)中蔬墩。而服務(wù)器把它想給客戶端的數(shù)據(jù),存在Response當(dāng)中耗拓。如果跨越幾個Request- Response的交互拇颅。數(shù)據(jù)就可以放在Session當(dāng)中。

Tomcat的部署war包里主要是class文件和Web.xml乔询,以及頁面樟插。

1.瀏覽器和Servlet的互傳參數(shù):

doGet(HttpServletRequest request, HttpServletResponse response)。

request當(dāng)中包含客戶端送到服務(wù)器的數(shù)據(jù)竿刁。response包含服務(wù)器送回給客戶端的數(shù)據(jù)黄锤。

當(dāng)用戶在瀏覽器輸入Servlet地址,按回車以后食拜,通過網(wǎng)絡(luò)鸵熟,Tomcat就 會運(yùn)行用戶這個Servlet的doGet方法,而且傳入兩個參數(shù)负甸。一個就是代表從客戶端來的request流强。另外一個就是代表從服務(wù)器去客戶端的 resonse痹届。

response有個buffer,flushBuffer()會強(qiáng)行把Buffer的 內(nèi)容寫到客戶端瀏覽器.

public class ServletHello1 extends HttpServlet {

??? protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

??????? response.setContentType("text/html; charset=GBK");

??????? PrintWriter out = response.getWriter();

??????? out.println("<html>");

??????? out.println("<head><title>Servlet1</title></head>");

??????? out.println("<body bgcolor=\"#ff0000\">");

??????? out.println("<p><H1>我們The servlet </H1></p>");

??????? out.println("</body></html>");??? }

}

2打月,HttpServlet的Service方法短纵。它的功能就是調(diào)用與HTTP請求的方法相對應(yīng)的do功能。例如僵控,如果HTTP請求方法為GET香到,則調(diào)用doGet() 。這樣作為Servlet編寫者的你报破,只需覆蓋doGet方法悠就。這也是我們迄今為止的做法。

3,Servlet的生命周期


servlet的生命周期有三個:

1)初始化時(shí)期

在啟動Tomcat后充易,客戶機(jī)首次訪問Servlet時(shí)梗脾,tomcat裝入和實(shí)例化Servlet,僅執(zhí)行一次init()方法盹靴。

無論有多少客戶機(jī)訪問 Servlet炸茧,都不會重復(fù)執(zhí)行init()。這里通常進(jìn)行一些初始化的操作稿静,如數(shù)據(jù)庫的連接梭冠。init()方法不能反復(fù)調(diào)用,一旦調(diào)用就是重裝載 servlet改备。直到服務(wù)器調(diào)用destroy方法卸載servlet后才能再調(diào)用控漠。

2)Servlet的執(zhí)行時(shí)期

在服務(wù)器裝載初始化servlet后,servlet就能夠無限循環(huán)往復(fù)的處理客戶端的請求悬钳。

在前面的例子中盐捷,我們用doXXX方法來處理每個客戶的請求,且發(fā)回相應(yīng)的響應(yīng)默勾。

3)Servlet結(jié)束時(shí)期

Servlets一直運(yùn)行到他們被服務(wù)器卸載碉渡。

比如,在eclipse的情況下母剥,當(dāng)我們點(diǎn)擊服務(wù)器窗口的紅色按鈕時(shí)滞诺,就關(guān)停Tomcat,這時(shí) Servlet的destroy方法就會被tomcat調(diào)用媳搪。通常铭段,大家在destroy方法里收回在init()方法中初始化的資源骤宣,如關(guān)閉數(shù)據(jù)庫的連 接等秦爆。

4,session的用法

如何跨越幾次請求響應(yīng)之間傳遞參數(shù)呢?

Sun公司為我 們提供了HttpSession這個接口憔披。

HttpSession session = request.getSession();

通過這句話等限,你可以得到一個與你的瀏覽器綁定的session對象爸吮,存在Tomcat里。這 個session對象只認(rèn)你這個瀏覽器望门,之后只要是你這個瀏覽器發(fā)出的請求形娇,無論跨越多少次請求響應(yīng),這個session對象就對它開放筹误,其它瀏覽器不能 訪問桐早。通過session.setAttribute()可以往session里面存值,session.getAttribute可以取值厨剪。

問題是 session是如何識別你的瀏覽器呢哄酝?靠Cookie或者URL改寫:如果瀏覽器支持Cookie,則使用Cookie祷膳;如果瀏覽器不支持Cookie或者Cookie功能被關(guān)閉陶衅,則自動使用URL改寫方法。拿cookie來說(通持背浚客戶很少見關(guān)閉cookie搀军,即使你關(guān)了,我也可以發(fā)現(xiàn)勇皇,之后提醒你打開或編程序重寫URL)罩句,服務(wù)器往客戶端寫東西時(shí),cookie會帶上sessionid敛摘。當(dāng)客戶端再次訪問服務(wù)器時(shí)的止,同一path下,會自動在html請求頭中帶上cookie信息,服務(wù)器可以在_COOKIE域中得取到想要的sessionid着撩。????

注意:跨應(yīng)用的Session:Session取不出來诅福。可以考慮用文件拖叙、數(shù)據(jù)庫氓润,URL傳值、隱藏表單傳遞session id等實(shí)現(xiàn)薯鳍。

5?咖气,從web.xml中獲取參數(shù)

1)用init-param獲取

在web.xml中加入:

??? <servlet>

??? ??? <servlet-name>ServletHello1</servlet-name>

??? ??? <servlet-class>com.ServletHello1</servlet-class>

??? ??? ???? <init-param>

???????????????? <param-name>zhangsan</param-name>

???????????????? <param-value>1000</param-value>

???????????? </init-param>

??? </servlet>

??? <servlet-mapping>

??? ??? <servlet-name>ServletHello1</servlet-name>

??? ??? <url-pattern>/MarkToWinServletHello1</url-pattern>

??? </servlet-mapping>

public class ServletHello1 extends HttpServlet {

??? protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

??? ??? String salary = getInitParameter("zhangsan");

??? ??? System.out.println("salary is "+salary);

??? }

2)用ServletConfig從init-param獲取

獲取init-param同getInitParameter

public class ServletHello1 extends HttpServlet {

??? protected void doGet(HttpServletRequest request, HttpServletResponse response)

??? ??? ??? throws ServletException, IOException {

??? ??? ServletConfig c = getServletConfig();

??? ??? System.out.println(c.getServletName()+c.getInitParameter("zhangsan"));

??? }

}

3)從context-param獲取

用context-param存放的參數(shù),整個web應(yīng)用中的任何servlet挖滤,jsp都可以獲得崩溪。

(因?yàn)閏ontext參數(shù)不屬于任何特定的servlet,屬于整個web應(yīng)用):

????<context-param>

??????? <param-name>zhangsan</param-name>

??????? <param-value>1000</param-value>

??? </context-param>

??? protected void doGet(HttpServletRequest request, HttpServletResponse response)

??? ??? ??? throws ServletException, IOException {

??????? ServletContext servletContext = getServletContext();

??????? String jd =? servletContext.getInitParameter("zhangsan");

??? ??? System.out.println(jd);

??? }

4)從env-entry獲取

用env-entry存放的參數(shù)斩松,整個web應(yīng)用中的任何servlet伶唯,jsp都可以獲得。和context-param相比惧盹,env-entry存放的參數(shù)不止為String類型乳幸。下面的comp是component的意思瞪讼。

public void doGet(HttpServletRequest request, HttpServletResponse response)

??? ??? ??? throws ServletException, IOException {

??? ??? Context ctx;

??? ??? boolean isReady = false;

??? ??? try {

??? ??? ??? ctx = new InitialContext();

??? ??? ??? Boolean b = (Boolean) ctx.lookup("java:comp/env/isReady");

??? ??? ??? isReady = b.booleanValue();

??? ??? } catch (NamingException e) {

??? ??? ??? e.printStackTrace();

??? ??? }

??? ??? System.out.println("" + isReady);

??? }

<env-entry>

???? <env-entry-name>isReady</env-entry-name>

???? <env-entry-type>java.lang.Boolean</env-entry-type>

???? <env-entry-value>true</env-entry-value>

</env-entry>

6,?Servlet中的跳轉(zhuǎn)問題

1)用RequestDispatcher跳轉(zhuǎn)

?javax.servlet.RequestDispatcher是Sun公司編寫的一個Interface粹断,

顧名思義符欠,它可以把用戶請求"a資源"的request派遣(dispatch)到"b資源"上,從而實(shí)現(xiàn)跳轉(zhuǎn)瓶埋。(本來人家要訪問'a資源"希柿,你的程序卻讓人家自動的跳轉(zhuǎn)到"b資源"上。)

注意:RequestDispatcher有兩種形式:這兩種形式都能達(dá)到跳轉(zhuǎn)的目的养筒。

一種是ServletRequest.getRequestDispatcher(String url)狡汉。

一種是ServletContext.getRequestDispatcher(String url)。

但正常來講闽颇,二者都只能訪問同一web應(yīng)用的資源盾戴。見下面理論論述和實(shí)驗(yàn)。

注意以下兩者的而區(qū)別:

ServletContext.getRequestDispatcher(String

url)中的url只能使用絕對路徑兵多;

而ServletRequest.getRequestDispatcher(String

url)中的url可以使用相對路徑(兩個資源在同一個目錄下尖啡,所以省去路徑),也可以絕對路徑剩膘。假如你寫成相對路徑時(shí)衅斩,比如

request.getRequestDispatcher("add").forward(request, response);

系統(tǒng)會在同一目錄下找add,見后面的例子怠褐。

但是假如你寫成request.getRequestDispatcher(/WebModule1/jsp1.jsp).forward

(request, response); 系統(tǒng)也會傻傻的變成:request.getRequestDispatcher(http://localhost:

8080/WebModule1/WebModule1/jsp1.jsp).forward(request, response);

當(dāng)然你更不要寫成:request.getRequestDispatcher(http://localhost:

8083/WebModule1/jsp1.jsp).forward(request, response).道理是一樣的畏梆。

public class DeleteCookie extends HttpServlet {

??? protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

??????? request.setAttribute("requestkey","requstvalue1");

??????? getServletContext().setAttribute("ServletContextKey","ServletContextValue");

/*下面任意一種方法都能正確執(zhí)行。*/????????

??????? request.getRequestDispatcher("/Cookie/AddCookie").forward(request, response);

?//?????? request.getRequestDispatcher("AddCookie").forward(request, response);

?//?????? request.getRequestDispatcher("/WEB-INF/1.html").forward(request, response);

?//?????? request.getRequestDispatcher("/Hello/MarkToWinServletHello1").forward(request, response);

?//?????? getServletContext().getRequestDispatcher("/Hello/MarkToWinServletHello1").forward(request, response);

?// ????? getServletContext().getRequestDispatcher("/WEB-INF/1.html").forward(request, response);

/*下面的寫法錯誤奈懒,找不到AddCookie*/

//????? request.getRequestDispatcher("/AddCookie").forward(request, response);

// getServletContext().getRequestDispatcher("http://localhost:8080/ServletHello/Hello/MarkToWinServletHello1").forward(request, response);

??? }

}

2)用setHeader("refresh"...跳轉(zhuǎn)

使用response對象的setHeader()方法可以實(shí)現(xiàn)在某個時(shí)間點(diǎn)跳轉(zhuǎn)到某個頁面的作用奠涌。比如response.setHeader("refresh",60);可以實(shí)現(xiàn)六十秒以后,又一次訪問當(dāng)前頁面磷杏。而response.setHeader("refresh","3;URL=http://localhost:8080/ServletHello/cookie.html");?實(shí)現(xiàn)3秒后訪問新頁面:http://localhost:8080/ServletHello/cookie.html溜畅。

3)用sendRedirect跳轉(zhuǎn)

response的方法:void sendRedirect(String url),將頁面重定向到指定的URL地址上极祸。

?protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

??????? response.sendRedirect("http://localhost:8080/ServletHello/cookie.html");

??? }

4)sendRedirect和RequestDispatcher的區(qū)別

response.sendRedirect()與request.getRequestDispatcher().forward()區(qū)別:response.sendRedirect(url)是先回到客戶端慈格,再重新請求url,和過去的請求沒關(guān)系遥金≡±Γ可以訪問任何地方。瀏覽器的地址欄也變成了新的url稿械。request.getRequestDispatcher().forward()就干脆沒回到客戶端选泻,就一直在服務(wù)器里,從本個web應(yīng)用的一個資源(servlet溜哮,jsp滔金,或html)跳到另一個資源色解。(所以不能隨便訪問什么地方)茂嗓。而且瀏覽器地址欄沒有變餐茵。同時(shí)可以用request.setAttribute("requestkey","requstvalue1");來傳遞參數(shù)。?

RequestDispatcher會block述吸,因?yàn)橥诜?wù)器端忿族。當(dāng)程序需要從資源1跳到資源2時(shí),資源1會等資源2運(yùn)行完蝌矛,回來以后道批,再繼續(xù)執(zhí)行下面沒執(zhí)行的部分。所謂的block入撒。

7隆豹,Servlet的其他相關(guān)問題

servlet與JDBC、servlet與Cookie茅逮、Servlet與Image

html的Header當(dāng)中有一個叫做Referer的鍵,用于追溯

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末璃赡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子献雅,更是在濱河造成了極大的恐慌碉考,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挺身,死亡現(xiàn)場離奇詭異侯谁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)章钾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門墙贱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贱傀,你說我怎么就攤上這事嫩痰。” “怎么了窍箍?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵串纺,是天一觀的道長。 經(jīng)常有香客問我椰棘,道長纺棺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任邪狞,我火速辦了婚禮祷蝌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帆卓。我一直安慰自己巨朦,他們只是感情好米丘,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糊啡,像睡著了一般拄查。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棚蓄,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天堕扶,我揣著相機(jī)與錄音,去河邊找鬼梭依。 笑死稍算,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的役拴。 我是一名探鬼主播糊探,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼河闰!你這毒婦竟也來了科平?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤淤击,失蹤者是張志新(化名)和其女友劉穎匠抗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體污抬,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡介劫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年挚瘟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了彰导。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞭衩。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖射赛,靈堂內(nèi)的尸體忽然破棺而出多柑,到底是詐尸還是另有隱情,我是刑警寧澤楣责,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布竣灌,位于F島的核電站,受9級特大地震影響秆麸,放射性物質(zhì)發(fā)生泄漏初嘹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一沮趣、第九天 我趴在偏房一處隱蔽的房頂上張望屯烦。 院中可真熱鬧,春花似錦、人聲如沸驻龟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翁狐。三九已至类溢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谴蔑,已是汗流浹背豌骏。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工龟梦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隐锭,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓计贰,卻偏偏與公主長得像钦睡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子躁倒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容