毛片在线视频观看,一级日韩免费大片,在线网站黄色,澳门在线高清一级毛片

薈聚奇文、博采眾長(zhǎng)、見賢思齊
當(dāng)前位置:公文素材庫 > 公文素材 > 范文素材 > JavaWeb工作原理

JavaWeb工作原理

網(wǎng)站:公文素材庫 | 時(shí)間:2019-05-28 14:32:00 | 移動(dòng)端:JavaWeb工作原理

JavaWeb工作原理

[JavaWeb工作原理][第一章]一什么是JavaWeb?

JavaWeb是用Java技術(shù)來解決相關(guān)web互聯(lián)網(wǎng)領(lǐng)域的技術(shù)總和。web包括:web服務(wù)器和web客戶端兩部分,在第一個(gè)項(xiàng)目(貸款計(jì)息查詢服務(wù)器)的時(shí)候已經(jīng)知道在Web服務(wù)器的作用是接受客戶端請(qǐng)求,然后向客戶端返回一些結(jié)果.瀏覽器的作用是允許用戶請(qǐng)求服務(wù)器上的某個(gè)資源,并且向用戶顯示請(qǐng)求的結(jié)果,HTML用于告訴瀏覽器怎樣向用戶顯示內(nèi)容,HTTP是WEB上客戶端和服務(wù)器之間通信所用的協(xié)議

二HTTP協(xié)議

Http是一種超文本傳輸協(xié)議(HyperTextTransferProtocol),他是一套計(jì)算機(jī)在網(wǎng)中通信的一種規(guī)則,在TCP/IP體系結(jié)構(gòu)中,HTTP屬于應(yīng)用層協(xié)議,位于TCP/IP協(xié)議的頂層.HTTP是一種無狀態(tài)的協(xié)議,意思是指在WEB瀏覽器和WEB服務(wù)器之間不需要建立持久的連接,HTTP定義的事物處理由以下四步組成:

1.客戶端和WEB服務(wù)器建立連接

a)客戶端和服務(wù)器的連接就是與客戶端與服務(wù)器的一個(gè)TCPSocket套接字連接2.客戶端發(fā)送HTTP請(qǐng)求

a)請(qǐng)求包含:請(qǐng)求行--請(qǐng)求行是一個(gè)ACCII文本行,由請(qǐng)求的HTTP方法,請(qǐng)求的

URL,HTTP版本組成,中間用空格分開,

b)請(qǐng)求頭---HTTP協(xié)議使用HTTP頭來傳遞請(qǐng)求的元信息,

c)空行---發(fā)送回車符和退行,通知服務(wù)器以下不再有請(qǐng)求頭

d)消息體--HTTP請(qǐng)求中帶有查詢字符串時(shí),如果是GET方法,查詢字符串或表單數(shù)據(jù)附加在請(qǐng)求行中,那么消息體就沒有內(nèi)容,如果是POST方法,查詢字符串或表單數(shù)據(jù)就添加在消息體重

3.服務(wù)器端接收客戶端的HTTP請(qǐng)求,生成HTTP相應(yīng)回發(fā)

a)響應(yīng)包含:狀態(tài)行---每個(gè)HTTP響應(yīng)以一個(gè)狀態(tài)行開頭,它由HTTP協(xié)議版本,

響應(yīng)狀態(tài)碼,響應(yīng)描述組成,中間用空格分開b)響應(yīng)頭---響應(yīng)頭與請(qǐng)求頭一樣,也是一個(gè)用冒號(hào)分隔符的名稱/值對(duì),冒號(hào)前面

是HTTP頭得名稱,后面是HTTP頭得值c)空行---發(fā)送回車符和退行,通知服務(wù)器以下不再有響應(yīng)頭

d)消息體---要發(fā)送回客戶端的HTML文檔或其他要顯示的內(nèi)容等,WEB服務(wù)器

把要發(fā)送給客戶端的文檔信息放在消息體中

4.服務(wù)器端關(guān)閉連接,客戶端解析并回發(fā)響應(yīng),恢復(fù)頁面

a)HTTP響應(yīng)到達(dá)客戶端后,瀏覽器先解析HTTP響應(yīng)中的狀態(tài)行,查看請(qǐng)求是否

成功的狀態(tài)代碼,然后開始一步步解析響應(yīng)

三WEB服務(wù)器缺陷與CGI

WEB服務(wù)是被設(shè)計(jì)用來向客戶端提供HTTP服務(wù)的,它只是能向客戶端提供靜態(tài)網(wǎng)頁內(nèi)容.我們知道,靜態(tài)網(wǎng)頁只是原封不動(dòng)的待在WEB服務(wù)器目錄中,服務(wù)器知道靜態(tài)頁面,并把它原樣傳回到客戶端,每個(gè)客戶端看到的頁面都是一樣的,所以WEB服務(wù)器它本身并不具備動(dòng)態(tài)頁面,所以在最早有了解決辦法CGI,

CGI即通用網(wǎng)關(guān)接口(CommonGateWayInterface),是最早用于創(chuàng)建動(dòng)態(tài)服務(wù)器端內(nèi)容的一種技術(shù),使用CGI,WEB服務(wù)器可以將客戶端的請(qǐng)求傳遞給一個(gè)外部程序,這個(gè)外部程序可以執(zhí)行,創(chuàng)建內(nèi)容,并且將響應(yīng)傳遞給客戶端,

但是他在處理一個(gè)請(qǐng)求的時(shí)候還行,但是在處理對(duì)個(gè)請(qǐng)求的時(shí)候是沒有一個(gè)用戶請(qǐng)求就新開一個(gè)進(jìn)程,我們都知道進(jìn)程是有獨(dú)立的內(nèi)存空間的,如果請(qǐng)求用戶多的時(shí)候那么就會(huì)導(dǎo)致服務(wù)器的崩潰,

四Java的解決方案

在java里,Servlet以及web容器,被設(shè)計(jì)用來解決CGI的問題,為WEB開發(fā)者創(chuàng)建一個(gè)健壯的服務(wù)器環(huán)境,

一、Servlet

a)Servlet是J2EE規(guī)范,

b)它是一個(gè)普通的JAVA類,集成于HttpServlet,用于處理動(dòng)態(tài)頁面的響應(yīng)

c)它是與平臺(tái)無關(guān)的JAVA類,能夠編譯成平臺(tái)中立的字節(jié)碼,從而被基于JAVA技術(shù)的WEB服務(wù)器動(dòng)態(tài)裝載和運(yùn)行

d)Servlet在服務(wù)器端得工作主要是執(zhí)行如下任務(wù)

i.

讀取客戶端發(fā)送的顯示和隱式數(shù)據(jù)

ii.生成結(jié)果

iii.向客戶端發(fā)送顯示數(shù)據(jù)(文檔)和隱式數(shù)據(jù)(HTTP響應(yīng)數(shù)據(jù))

二、WEB容器

a)WEB容器主要是如Tomcat,Jboss,WebLogic,WebSphere,Oracle9iAS等,其中Tomcat是一種用的很廣泛的Web容器,它是一個(gè)開放源代碼的免費(fèi)的中間件產(chǎn)品b)WEB容器必須對(duì)Servlet支持以下幾點(diǎn)

i.通信支持

ii.生命周期管理

iii.多線程支持iv.JSP支持v.處理安全性

三、Servlet與WEB容器配合處理請(qǐng)求和響應(yīng)

a)與GUI類似,Servlet允許一個(gè)請(qǐng)求被一個(gè)程序處理.并且使用同樣的程序產(chǎn)生動(dòng)態(tài)的

響應(yīng),此外,Servlet特別定義了一個(gè)有效的生命周期,使得用單個(gè)進(jìn)程管理所有請(qǐng)求成為可能,它消除了CGI的多進(jìn)程缺陷,允許主進(jìn)程在多個(gè)Servlet和多個(gè)請(qǐng)求之間共享內(nèi)存資源.b)Servlet運(yùn)行在一個(gè)主進(jìn)程或者一個(gè)父進(jìn)程中,每個(gè)用戶發(fā)送請(qǐng)求信息到服務(wù)器,就會(huì)在Servlet進(jìn)程里創(chuàng)建一個(gè)線程,它們共享一個(gè)資源c)最后,WEB容器和Servlet對(duì)請(qǐng)求和響應(yīng)的處理如下

i.客戶端向WEB服務(wù)器發(fā)起一個(gè)HTTP請(qǐng)求

ii.HTTP請(qǐng)求被WEB服務(wù)器幾首,如果請(qǐng)求的是靜態(tài)頁面,則由WEB服務(wù)器負(fù)責(zé)

處理,如果請(qǐng)求的是JAVAWEB組件(Servlet或者JSP),則移交給WEB容器,iii.WEB容器根據(jù)Servlet的配置文件(web.xml),確定調(diào)用的具體Servlet類,并把request對(duì)象,response對(duì)象傳給它

iv.Servlet通過request對(duì)象知道客戶端的使用者是誰,客戶的請(qǐng)求信息是什么和其

他的一些信息

v.一旦Servlet完成了請(qǐng)求的處理,WEB容器就會(huì)刷新response,把控制權(quán)返回給

WEB服務(wù)器

五JavaWeb應(yīng)用程序的組成

1.配置文件---每個(gè)WEB應(yīng)用程序包括一個(gè)配置文件,WEB.XML2.靜態(tài)文件和JSP

3.類文件和包---WEB應(yīng)用程序裝載和管理自定義的JAVA代碼

4.網(wǎng)頁可以放在WEB應(yīng)用程序的根目錄下,根據(jù)動(dòng)態(tài)網(wǎng)頁或者靜態(tài)網(wǎng)頁放在不同的目

錄里

5.圖像一般會(huì)放在images子目錄中,不過這是習(xí)慣,不是必須的

6.Servlet類,JavaBean類---編譯為Class文件后是防在WEB-INF/classes目錄的7.Lib目錄用來包含應(yīng)用程序任何所需要的jar文件8.標(biāo)記描述其放在WEB-INF目錄下

9.Applet程序放在應(yīng)用的目錄下

10.WEB-INF目錄下存放web.xml部署描述文件器

剩下的WEB容器Tomcat主要是在實(shí)踐中應(yīng)用,在這里不做總結(jié)

擴(kuò)展閱讀:JavaWeb工作原理

淺析基于Java的Web服務(wù)器工作原理

一個(gè)Web服務(wù)器也被稱為HTTP服務(wù)器,它通過HTTP協(xié)議與客戶端通信。這個(gè)客戶端通常指的是Web瀏覽器。一個(gè)基于Java的Web服務(wù)器用到二個(gè)重要的類,java.net.Socket與java.net.ServerSocket,并通過HTTP消息通信。因此,本文從討論HTTP與這二個(gè)類開始,然后我將解釋一個(gè)與本文相關(guān)的簡(jiǎn)單的Web應(yīng)用。

TheHypertextTransferProtocol(HTTP)

HTTP是一種讓W(xué)eb服務(wù)器與瀏覽器(客戶端)通過Internet發(fā)送與接收數(shù)據(jù)的協(xié)議。它是一個(gè)請(qǐng)求、響應(yīng)協(xié)議--客戶端發(fā)出一個(gè)請(qǐng)求,服務(wù)器響應(yīng)這個(gè)請(qǐng)求。HTTP運(yùn)用可靠的TCP連接,通常用的TCP80端口。它的第一個(gè)版本是HTTP/0.9,然后被HTTP/1.0取代。當(dāng)前的版本是HTTP/1.1,由RFC2616(.pdf)定義。

本節(jié)主要對(duì)應(yīng)HTTP1.1,足夠使你充分理解由Web服務(wù)器程序發(fā)出的消息。如果你對(duì)更加詳細(xì)的知識(shí)有興趣,可以參考RFC2616。

在HTTP中,客戶端總是通過建立一個(gè)連接與發(fā)送一個(gè)HTTP請(qǐng)求來發(fā)起一個(gè)事務(wù)。服務(wù)器不能主動(dòng)去與客戶端聯(lián)系,也不能給客戶端發(fā)出一個(gè)回叫連接。客戶端與服務(wù)器端都可以提前中斷一個(gè)連接。例如,當(dāng)用一個(gè)瀏覽器下載一個(gè)文件時(shí),你可以通過點(diǎn)擊“停止”鍵來中斷文件的下載,關(guān)閉與服務(wù)器的HTTP連接。

HTTP請(qǐng)求

一個(gè)HTTP請(qǐng)求包含三個(gè)部分:

Method-URI-Protocol/Version方法-地址-版本

Requestheader請(qǐng)求頭

Entitybody請(qǐng)求實(shí)體

下面是一個(gè)HTTP請(qǐng)求實(shí)例:

POST/servlet/default.jspHTTP/1.1

Accept:text/plain;text/htmlAccept-Language:en-gb

Connection:Keep-Alive

Host:localhost

Referer:

User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)

Content-Length:33

Content-Type:application/x-www-form-urlencoded

Accept-Encoding:gzip,deflate

LastName=Franks&FirstName=Michael

TheMethod-URI-Protocol/Version在這個(gè)請(qǐng)求的第一行:

POST/servlet/default.jspHTTP/1.1

其中POST是請(qǐng)求的類型。每個(gè)客戶端HTTP請(qǐng)求可以是HTTP規(guī)范中指定的許多請(qǐng)求類型中的一種。HTTP1.1支持七種類型的請(qǐng)求,它們是GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE。其中GET與POST是Internet應(yīng)用中經(jīng)常用到的二種請(qǐng)求類型。

URI完整地指定了Internet資源。一個(gè)URI通常被解析為相對(duì)服務(wù)器的根目錄。這樣,它應(yīng)該總是以一個(gè)"/"前綴開始。一個(gè)URL實(shí)際上是URI的一種類型。

Version指的是該HTTP請(qǐng)求所用到的HTTP協(xié)議版本。

請(qǐng)求頭包含了客戶端環(huán)境與請(qǐng)求實(shí)體的一些有用的信息。例如它包含瀏覽器設(shè)定的語言、實(shí)體的長(zhǎng)度等等。每條請(qǐng)求頭用回車換行符(CRLF)分開。一個(gè)非常重要的空行分開了請(qǐng)求頭與實(shí)體,它標(biāo)志著實(shí)體內(nèi)容的開始。一些Internet開發(fā)書籍認(rèn)為這個(gè)CRLF空行是HTTP請(qǐng)求的第四個(gè)部分。

在上面的HTTP請(qǐng)求中,實(shí)體只是簡(jiǎn)單以下的一行:

LastName=Franks&FirstName=Michael

在一個(gè)典型的HTTP請(qǐng)求中,請(qǐng)求實(shí)體內(nèi)容會(huì)長(zhǎng)得多。

HTTP響應(yīng)

與請(qǐng)求相似,HTTP響應(yīng)也由三部分組成:

Protocol-Statuscode-Description協(xié)議狀態(tài)描述代碼

Responseheaders響應(yīng)頭

Entitybody響應(yīng)實(shí)體

以下是一個(gè)HTTP響應(yīng)的實(shí)例:

HTTP/1.1200OK

Server:Microsoft-IIS/4.0

Date:Mon,3Jan199813:13:33GMT

Content-Type:text/html

Last-Modified:Mon,11Jan199813:23:42GMT

Content-Length:1

WelcometoBrainySoftware

響應(yīng)頭的第一行類似請(qǐng)求頭的第一行,告訴你所用的協(xié)議是HTTP1.1,請(qǐng)求成功(200=success),以及沒有任何問題。

響應(yīng)頭類似請(qǐng)求頭也包含了一些有用的信息。響應(yīng)的實(shí)體響應(yīng)本身的HTML內(nèi)容。頭與實(shí)體之間由回車換行的空行(CRLF)分開。

Socket類

一個(gè)socket是一個(gè)網(wǎng)絡(luò)連接的端點(diǎn),它使得一個(gè)應(yīng)用可以從網(wǎng)絡(luò)讀與寫。在不同電腦上的二個(gè)應(yīng)用軟件能夠通過收發(fā)字節(jié)流而彼此通信。要發(fā)一個(gè)信息到另一個(gè)應(yīng)用程序,你需要知道它的IP地址,以及它的socket端口號(hào)。在Java中,一個(gè)socket用java.net.Socket來實(shí)現(xiàn)。

要?jiǎng)?chuàng)建一個(gè)socket,你可以用Socket類中幾個(gè)構(gòu)建方法中的一個(gè)。其中一個(gè)接受主機(jī)名與端口號(hào)作為參數(shù):

newSocket("yahoo.com",80);

一旦你成功地創(chuàng)建了一個(gè)Socket類的實(shí)例,你就可以用它去發(fā)送與接收字節(jié)流了。要發(fā)送字節(jié)流,你需要呼叫Socket類的getOutputStream方法來得到一個(gè)java.io.OutputSteam對(duì)象。要發(fā)送文本到遠(yuǎn)程的程序,你通常需要從返回的OutputStream創(chuàng)建一個(gè)java.io.PrintWriter對(duì)象。要從連接的另一端接收字節(jié)流,你需要呼叫Socket類的getInputStream方法,它返回一個(gè)java.io.InputStream對(duì)象。

以下代碼創(chuàng)建一個(gè)可以與本地HTTP服務(wù)器通信的socket(127.0.0.1表示一個(gè)本地的主機(jī)),發(fā)送一個(gè)HTTP請(qǐng)求,并接收從服務(wù)器的響應(yīng)。它還創(chuàng)建一個(gè)StringBuffer對(duì)象來接受響應(yīng),并打印到控制臺(tái)。

Socketsocket=newSocket("127.0.0.1","8080");OutputStreamos=socket.getOutputStream();

booleanautoflush=true;

PrintWriterout=newPrintWriter(socket.getOutputStream(),

autoflush);

BufferedReaderin=newBufferedReader(

newInputStreamReader(socket.getInputStream()));

//sendanHTTPrequesttothewebserver

out.println("GET/index.jspHTTP/1.1");

out.println("Host:localhost:8080");

out.println("Connection:Close");

out.println();

//readtheresponse

booleanloop=true;

StringBuffersb=newStringBuffer(8096);

while(loop){

if(in.ready()){inti=0;

while(i!=-1){

i=in.read();

sb.append((char)i);}

loop=false;}

Thread.currentThread().sleep(50);}

//displaytheresponsetotheoutconsole

System.out.println(sb.toString());

socket.close();

注意要從web服務(wù)器得到正確的響應(yīng),你必須要發(fā)送用HTTP協(xié)議編譯了的HTTP請(qǐng)求。如果你看了上面的HTTP部分,你應(yīng)該能夠理解上面代碼中的HTTP請(qǐng)求。

編者注:這篇文章節(jié)選自budi自己出版的書<Tomcat內(nèi)幕>。你可以在他的網(wǎng)站得到更多的相關(guān)資料。

基于Java的Web服務(wù)器工作原理2

作者:fajaven譯發(fā)文時(shí)間:201*.09.1217:00:38

ServerSocket類

Socket類描述的是“客戶端”socket,當(dāng)你需要?jiǎng)?chuàng)建與遠(yuǎn)程服務(wù)程序連接時(shí)需要用到它。如果你想實(shí)現(xiàn)一個(gè)服務(wù)程序,如HTTP服務(wù)器或者FTP服務(wù)器,則需要另外不同的方法。這是因?yàn)槟愕姆⻊?wù)器必須隨時(shí)服務(wù),它不知道什么時(shí)候會(huì)有一個(gè)客戶端程序需要連接它。

因?yàn)檫@個(gè)目的,你需要用到j(luò)ava.net.ServerSocket這個(gè)類,它是服務(wù)器端socket的一個(gè)實(shí)現(xiàn)。服務(wù)器端socket等待來自客戶端的連接請(qǐng)求。一旦它收到一個(gè)連接請(qǐng)求,它創(chuàng)建一個(gè)socket實(shí)例來與客戶端進(jìn)行通信。

要?jiǎng)?chuàng)建服務(wù)器端socket,需要用到ServerSocket類提供的四個(gè)構(gòu)建方法中的一個(gè)。你需要指定服務(wù)器端socket偵聽的IP地址與端口號(hào)。比較典型地,這個(gè)IP地址可以是127.0.0.1,意思是該服務(wù)器端socket偵聽的是本地機(jī)器。服務(wù)器端socket偵聽的IP地址指的是綁定地址。服務(wù)器端socket另一個(gè)重要的屬性是隊(duì)列長(zhǎng)度,即它拒絕請(qǐng)求前所接受的最大請(qǐng)求排隊(duì)長(zhǎng)度。

ServerSocket類的構(gòu)建方法之一如下:

publicServerSocket(intport,intbackLog,InetAddressbindingAddress);

對(duì)于這個(gè)構(gòu)建方法,綁定地址必須是java.net.InetAddress類的實(shí)例。創(chuàng)建一個(gè)InetAddress類的對(duì)象的簡(jiǎn)單方法是呼叫其靜態(tài)方法getByName,傳遞一個(gè)包含主機(jī)名的字符串。

InetAddress.getByName("127.0.0.1");

以下行的代碼創(chuàng)建了一個(gè)服務(wù)器端socket,它偵聽本地機(jī)器的8080端口,限制隊(duì)列長(zhǎng)度為1。

newServerSocket(8080,1,InetAddress.getByName("127.0.0.1"));

一旦有了一個(gè)ServerSocket實(shí)例,就可以通過呼叫其accept方法來讓它等待進(jìn)來的鏈接請(qǐng)求。這個(gè)方法只有當(dāng)接收到請(qǐng)求時(shí)才返回,它返回的是Socket類的實(shí)例。這個(gè)Socket對(duì)象就可以用來從客戶端應(yīng)用程序發(fā)送與接收字節(jié)流,正如上節(jié)據(jù)說的那樣。實(shí)際上,accept方法是本文例子中用到的唯一方法。

應(yīng)用實(shí)例

我們的web服務(wù)器程序是ex01.pyrmont包的一部分,它包含三個(gè)類:HttpServer;Request;Response。

整個(gè)程序的入口(靜態(tài)main方法)是HttpServer類。它創(chuàng)建一個(gè)HttpServer的實(shí)例,并呼叫其await方法。正如名字表達(dá)的,await在一個(gè)特定的端口等待HTTP請(qǐng)求,處理它們,并返回響應(yīng)給客戶端。它保持等待狀態(tài),直到收到停止命令。(用方法名await代替wait,是因?yàn)镾ystem中有一個(gè)重要的與線程相關(guān)的方法)

這個(gè)程序只從一個(gè)特定的目錄發(fā)送靜態(tài)資源,如HTML與圖像文件。它只支持沒有文件頭(如日期與cookie)的情況,F(xiàn)在我們將在如下的幾節(jié)中看一下這三個(gè)類。

HttpServer類

HttpServer實(shí)現(xiàn)了一個(gè)web服務(wù)器,它可以提供(serve)特定目錄及其子目錄下的靜態(tài)資源。這個(gè)特定的目錄由publicstaticfinalWEB_ROOT指定。

WEB_ROOT初始化如下:

publicstaticfinalStringWEB_ROOT=

System.getProperty("user.dir")+File.separator+"webroot";

代碼列表中包含了一具叫做webroot的目錄,里面有一些靜態(tài)的資源,你可以用來測(cè)試本應(yīng)用。你也可以看到一個(gè)servlet,在我的下一篇文章將會(huì)被用到:“Servlets容器是怎樣工作的”。

為了請(qǐng)求一個(gè)靜態(tài)的資源,在瀏覽器的地址欄輸入如是地址::port/staticResources

如果你從不同的機(jī)器上發(fā)送請(qǐng)求到運(yùn)行本應(yīng)用的機(jī)器,則machinename是運(yùn)行應(yīng)用機(jī)器的機(jī)器名或IP地址,port是8080,staticResources是被請(qǐng)求的文件名稱,它必須包含在WEB_ROOT目錄內(nèi)。

例如,如果你用同一臺(tái)電腦來測(cè)試這個(gè)應(yīng)用,你想要HttpServer發(fā)送index.html這個(gè)文件,用以下的地址::8080/index.html

要停止服務(wù),只需要從瀏覽器發(fā)送一個(gè)停止(shutdown)命令,即在瀏覽器的地址欄輸入host:port字段后,加上預(yù)先定義好的字符串。在我們的HttpServer類中,停止命令被定義為SHUTDOWN,一個(gè)staticfinal變量。

privatestaticfinalStringSHUTDOWN_COMMAND="/SHUTDOWN";

因此,要停止服務(wù),你可以這樣::8080/SHUTDOWN現(xiàn)在,讓我們看一下列表1.1中給出的await方法。代碼列表后面將對(duì)這段代碼做一些解釋。

Listing1.1.TheHttpServerclass"awaitmethod

publicvoidawait(){

ServerSocketserverSocket=null;

intport=8080;try{

serverSocket=newServerSocket(port,1,

InetAddress.getByName("127.0.0.1"));}

catch(IOExceptione){

e.printStackTrace();

System.exit(1);}

//Loopwaitingforarequest

while(!shutdown){

Socketsocket=null;

InputStreaminput=null;

OutputStreamoutput=null;try{

socket=serverSocket.accept();

input=socket.getInputStream();

output=socket.getOutputStream();

//createRequestobjectandparse

Requestrequest=newRequest(input);

request.parse();

//createResponseobject

Responseresponse=newResponse(output);

response.setRequest(request);

response.sendStaticResource();

//Closethesocket

socket.close();

//checkifthepreviousURIisashutdowncommand

shutdown=request.getUri().equals(SHUTDOWN_COMMAND);}

catch(Exceptione){

e.printStackTrace();

continue;}}}

await方法以創(chuàng)建一個(gè)ServerSocket實(shí)例開始,然后進(jìn)入一個(gè)while的循環(huán)。

serverSocket=newServerSocket(

port,1,InetAddress.getByName("127.0.0.1"));...

//Loopwaitingforarequest

while(!shutdown){...}

在while循環(huán)中的代碼,運(yùn)行到ServerSocket的accept方法即停止。這個(gè)方法只有在8080端口接收到HTTP請(qǐng)求才返回:

socket=serverSocket.accept();

收到請(qǐng)求后,await方法從accept方法返回的Socket實(shí)例中等到j(luò)ava.io.InputStream與java.io.OutputStream:

input=socket.getInputStream();

output=socket.getOutputStream();

然后await方法創(chuàng)建一個(gè)Request對(duì)象,呼叫它的parse方法來解析這個(gè)原始的HTTP請(qǐng)求:

//createRequestobjectandparse

Requestrequest=newRequest(input);

request.parse();

下一步,await方法創(chuàng)建一個(gè)Response對(duì)象并把Request對(duì)象設(shè)置給它,呼叫它的sendStaticResource方法:

//createResponseobject

Responseresponse=newResponse(output);

response.setRequest(request);

response.sendStaticResource();

最后,await方法關(guān)閉Socket,呼叫Request的getUri方法來檢查HTTP請(qǐng)求的地址是否是一個(gè)停止命令。如果是,則shutdown變量被設(shè)置為true,程序退出while循環(huán):

//Closethesocket

socket.close();

//checkifthepreviousURIisashutdowncommand

shutdown=request.getUri().equals(SHUTDOWN_COMMAND);

基于Java的Web服務(wù)器工作原理3

作者:fajaven發(fā)文時(shí)間:201*.09.1217:11:54

Request類

Request類對(duì)應(yīng)HTTP請(qǐng)求。創(chuàng)建這個(gè)類的實(shí)例,并傳給它從Socket獲得的InputStream對(duì)象,從而捕獲與客戶端的通信。呼叫InputStream對(duì)象的read方法中的一個(gè)就可以得到HTTP請(qǐng)求的原始數(shù)據(jù)。

Request類有二個(gè)public方法parse與getUri。parse方法解析HTTP請(qǐng)求的原始數(shù)據(jù)。它做的事情不多--唯一它使之有效的信息是HTTP請(qǐng)求的URI,這個(gè)通過呼叫私有方法parseUri來獲得。parseUri方法把URI作為一個(gè)變量。調(diào)用getUri方法可以得到HTTP請(qǐng)求的URI。

要明白parse與parseUri的工作原理,你需要知道HTTP請(qǐng)求的結(jié)構(gòu),由RFC2616定義。

一個(gè)HTTP請(qǐng)求包括三個(gè)部分:Requestline;Headers;Messagebody。

現(xiàn)在,我們只需要關(guān)注HTTP請(qǐng)求的第一部分--請(qǐng)求行。請(qǐng)求行以方法記號(hào)開始,接著是請(qǐng)求的URI與協(xié)議版本,以回車換行符結(jié)束。請(qǐng)求行的元素之間以空格分開。例如,一個(gè)用GET方法的index.html文件的請(qǐng)求行如下:

GET/index.htmlHTTP/1.1

parse方法從socket的InputStream傳遞給Request對(duì)象中讀取字節(jié)流,把這個(gè)字節(jié)數(shù)組存在緩沖里。然后,它把buffer字節(jié)數(shù)組里的字節(jié)放入叫做request的StringBuffer對(duì)象中,再把StringBuffer替換成String傳遞給parseUri方法。

parse方法的代碼如列表1.2

Listing1.2.TheRequestclass"parsemethod

publicvoidparse(){

//ReadasetofcharactersfromthesocketStringBufferrequest=newStringBuffer(2048);inti;

byte[]buffer=newbyte[2048];try{

i=input.read(buffer);}

catch(IOExceptione){

e.printStackTrace();i=-1;}

for(intj=0;jrequest.append((char)buffer[j]);}

System.out.print(request.toString());

uri=parseUri(request.toString());}

parseUri方法查找請(qǐng)求行的第一個(gè)與第二個(gè)空格,從而從請(qǐng)求行獲得了URI。列表1.3展示了parseUri方法的代碼。

Listing1.3.TheRequestclass"parseUrimethod

privateStringparseUri(StringrequestString){intindex1,index2;

index1=requestString.indexOf("");

if(index1!=-1){

index2=requestString.indexOf("",index1+1);

if(index2>index1)

returnrequestString.substring(index1+1,index2);}

returnnull;}

Response類

Response類描述HTTP響應(yīng)。它的構(gòu)建方法接受OutputStream對(duì)象,如下:

publicResponse(OutputStreamoutput){

this.output=output;}

Response對(duì)象通過傳遞從socket獲得的OutputStream對(duì)象到HttpServer類的await方法而創(chuàng)建。

Response類有二個(gè)公共方法setRequest與setStaticResource。setRequest用來傳遞Request對(duì)象到Response對(duì)象。它比較簡(jiǎn)單,代碼如列表1.4所示:

Listing1.4.TheResponseclass"setRequestmethod

publicvoidsetRequest(Requestrequest){

this.request=request;}

sendStaticResource方法用來發(fā)送靜態(tài)的資源,例如HTML文件。它的實(shí)現(xiàn)如列表1.5所示:

Listing1.5.TheResponseclass"sendStaticResourcemethod

publicvoidsendStaticResource()throwsIOException{

byte[]bytes=newbyte[BUFFER_SIZE];

FileInputStreamfis=null;try{

Filefile=newFile(HttpServer.WEB_ROOT,request.getUri());

if(file.exists()){

fis=newFileInputStream(file);

intch=fis.read(bytes,0,BUFFER_SIZE);

while(ch!=-1){

output.write(bytes,0,ch);

ch=fis.read(bytes,0,BUFFER_SIZE);}}else{

//filenotfound

StringerrorMessage="HTTP/1.1404FileNotFound\\r\\n"+

"Content-Type:text/html\\r\\n"+

"Content-Length:23\\r\\n"+"\\r\\n"+"

FileNotFound";

output.write(errorMessage.getBytes());}}

catch(Exceptione){

//thrownifcannotinstantiateaFileobject

System.out.println(e.toString());}finally{

if(fis!=null)

fis.close();}}

SendStaticResource方法非常簡(jiǎn)單。它首先通過傳遞父與子目錄到File類的構(gòu)建方法從而實(shí)例化java.io.File類。

FilefilenewFile(HttpServer.WEB_ROOT,request.getUri());

然后檢查這個(gè)文件是否存在。如果存在,則sendStaticResource方法傳遞File對(duì)象創(chuàng)建java.io.FileInputStream對(duì)象。然后調(diào)用FileInputStream的read方法,并把字節(jié)數(shù)組寫到OutputStream對(duì)象output。就這樣,靜態(tài)資源的內(nèi)容作為原始數(shù)據(jù)被發(fā)送到瀏覽器。

if(file.exists()){

fis=newFileInputStream(file);

intch=fis.read(bytes,0,BUFFER_SIZE);

while(ch!=-1){

output.write(bytes,0,ch);

ch=fis.read(bytes,0,BUFFER_SIZE);}}

如果文件不存在,sendStaticResource發(fā)送一個(gè)錯(cuò)誤信息到瀏覽器。

StringerrorMessage="HTTP/1.1404FileNotFound\\r\\n"+

"Content-Type:text/html\\r\\n"+

"Content-Length:23\\r\\n"+"\\r\\n"+"

FileNotFound";

output.write(errorMessage.getBytes());

編譯與運(yùn)行應(yīng)用程序

要編輯與運(yùn)行本文的應(yīng)用,首先你需要解壓源碼zip文件。直接解壓出來的目錄被稱為工作目錄,它有三個(gè)子目錄:src/,classes/,lib/。要編譯應(yīng)用,從工作目錄輸入如下命令:

javac-d.src/ex01/pyrmont/*.java

-d選項(xiàng)把結(jié)果寫到當(dāng)前目錄,而不是src/目錄。

要運(yùn)行應(yīng)用,在當(dāng)前工作目錄輸入如下命令:

javaex01.pyrmont.HttpServer

測(cè)試這個(gè)應(yīng)用,打開你的瀏覽器,在地址欄輸入如下地址::8080/index.html

你將在你的瀏覽器看到index.html顯示出來,如圖1所示。

圖1:web服務(wù)器的輸出顯示

在控制臺(tái),你看到如下的內(nèi)容:

GET/index.htmlHTTP/1.1

Accept:*/*Accept-Language:en-us

Accept-Encoding:gzip,deflate

User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)

Host:localhost:8080

Connection:Keep-Alive

GET/images/logo.gifHTTP/1.1

Accept:*/*

Referer::8080/index.html

Accept-Language:en-us

Accept-Encoding:gzip,deflate

User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)

Host:localhost:8080

Connection:Keep-Alive總結(jié)

在這篇文章中(分為三個(gè)部分),你看到了一個(gè)簡(jiǎn)單的web服務(wù)器的工作原理。本文相關(guān)的應(yīng)用只包括了三個(gè)類,功能是不全面的。然而,它仍不失為一個(gè)好的學(xué)習(xí)工具。

(責(zé)任編輯:張明燕)

Java的網(wǎng)絡(luò)編程:用Java實(shí)現(xiàn)Web服務(wù)器

作者:谷和啟發(fā)文時(shí)間:201*.12.2615:35:57

HTTP協(xié)議

超文本傳輸協(xié)議(HTTP)是位于TCP/IP協(xié)議的應(yīng)用層,是最廣為人知的協(xié)議,也是互連網(wǎng)中最核心的協(xié)議之一,同樣,HTTP也是基于C/S或B/S模型實(shí)現(xiàn)的。事實(shí)上,我們使用的瀏覽器如Netscape或IE是實(shí)現(xiàn)HTTP協(xié)議中的客戶端,而一些常用的Web服務(wù)器軟件如Apache、IIS和iPlanetWebServer等是實(shí)現(xiàn)HTTP協(xié)議中的服務(wù)器端。Web頁由服務(wù)端資源定位,傳輸?shù)綖g覽器,經(jīng)過瀏覽器的解釋后,被客戶所看到。

Web的工作基于客戶機(jī)/服務(wù)器計(jì)算模型,由Web瀏覽器(客戶機(jī))和Web服務(wù)器(服務(wù)器)構(gòu)成,兩者之間采用超文本傳送協(xié)議(HTTP)進(jìn)行通信。HTTP協(xié)議是Web瀏覽器和Web服務(wù)器之間的應(yīng)用層協(xié)議,是通用的、無狀態(tài)的、面向?qū)ο蟮膮f(xié)議。

一個(gè)完整的HTTP協(xié)議會(huì)話過程包括四個(gè)步驟:

◆連接,Web瀏覽器與Web服務(wù)器建立連接,打開一個(gè)稱為Socket(套接字)的虛擬文件,此文件的建立標(biāo)志著連接建立成功;

◆請(qǐng)求,Web瀏覽器通過Socket向Web服務(wù)器提交請(qǐng)求。HTTP的請(qǐng)求一般是GET或POST命令(POST用于FORM參數(shù)的傳遞);

◆應(yīng)答,Web瀏覽器提交請(qǐng)求后,通過HTTP協(xié)議傳送給Web服務(wù)器。Web服務(wù)器接到后,進(jìn)行事務(wù)處理,處理結(jié)果又通過HTTP傳回給Web瀏覽器,從而在Web瀏覽器上顯示出所請(qǐng)求的頁面;

◆關(guān)閉連接,應(yīng)答結(jié)束后Web瀏覽器與Web服務(wù)器必須斷開,以保證其它Web瀏覽器能夠與Web服務(wù)器建立連接。

Java實(shí)現(xiàn)Web服務(wù)器功能的程序設(shè)計(jì)

編程思路

根據(jù)上述HTTP協(xié)議的會(huì)話過程,本實(shí)例中實(shí)現(xiàn)了GET請(qǐng)求的Web服務(wù)器程序的方法,方法如下:

通過創(chuàng)建ServerSocket類對(duì)象,偵聽用戶指定的端口(為8080),等待并接受客戶機(jī)請(qǐng)求到端口。創(chuàng)建與Socket相關(guān)聯(lián)的輸入流和輸出流,然后讀取客戶機(jī)的請(qǐng)求信息。若請(qǐng)求類型是GET,則從請(qǐng)求信息中獲取所訪問的HTML文件名;如果HTML文件存在,則打開HTML文件,把HTTP頭信息和HTML文件內(nèi)容通過Socket傳回給Web瀏覽器,然后關(guān)閉文件,否則發(fā)送錯(cuò)誤信息給Web瀏覽器。最后關(guān)閉與相應(yīng)Web瀏覽器連接的Socket。

用Java編寫Web服務(wù)器httpServer.java文件的源代碼如下:

//httpServer.java

importjava.net.*;

importjava.io.*;

importjava.util.*;

importjava.lang.*;

publicclasshttpServer{

publicstaticvoidmain(Stringargs[]){intport;

ServerSocketserver_socket;

//讀取服務(wù)器端口號(hào)try{

port=Integer.parseInt(args[0]);}

catch(Exceptione){

port=8080;}try{

//監(jiān)聽服務(wù)器端口,等待連接請(qǐng)求

server_socket=newServerSocket(port);

System.out.println("httpServerrunningonport"+

server_socket.getLocalPort());

//顯示啟動(dòng)信息

while(true){

Socketsocket=server_socket.accept();

System.out.println("Newconnectionaccepted"+

socket.getInetAddress()+

":"+socket.getPort());

//創(chuàng)建分線程try{

httpRequestHandlerrequest=

newhttpRequestHandler(socket);

Threadthread=newThread(request);

//啟動(dòng)線程

thread.start();}

catch(Exceptione){

System.out.println;}}}

catch(IOExceptione){

System.out.println;}}}

classhttpRequestHandlerimplementsRunnable{

finalstaticStringCRLF="\\r\\n";

Socketsocket;

InputStreaminput;

OutputStreamoutput;

BufferedReaderbr;

//構(gòu)造方法

publichttpRequestHandler(Socketsocket)throwsException{

this.socket=socket;

this.input=socket.getInputStream();

this.output=socket.getOutputStream();

this.br=

newBufferedReader(newInputStreamReader(socket.getInputStream()));}

//實(shí)現(xiàn)Runnable接口的run()方法

publicvoidrun(){try{

processRequest();}

catch(Exceptione){

System.out.println;}}

privatevoidprocessRequest()throwsException{

while(true){

//讀取并顯示W(wǎng)eb瀏覽器提交的請(qǐng)求信息

StringheaderLine=br.readLine();

System.out.println("Theclientrequestis"+headerLine);

if(headerLine.equals(CRLF)||headerLine.equals(""))break;

StringTokenizers=newStringTokenizer(headerLine);

Stringtemp=s.nextToken();

if(temp.equals("GET")){

StringfileName=s.nextToken();

fileName="."+fileName;

//打開所請(qǐng)求的文件

FileInputStreamfis=null;

booleanfileExists=true;try{

fis=newFileInputStream(fileName);}

catch(FileNotFoundExceptione){

fileExists=false;}

//完成回應(yīng)消息

StringserverLine="Server:asimplejavahttpServer";

StringstatusLine=null;

StringcontentTypeLine=null;

StringentityBody=null;

StringcontentLengthLine="error";

if(fileExists){

statusLine="HTTP/1.0200OK"+CRLF;

contentTypeLine="Content-type:"+

contentType(fileName)+CRLF;

contentLengthLine="Content-Length:"

+(newInteger(fis.available())).toString()

+CRLF;}else{

statusLine="HTTP/1.0404NotFound"+CRLF;

contentTypeLine="text/html";

entityBody=""+""+

"404NotFound"+"

usage::port/"

+"fileName.html";}

//發(fā)送到服務(wù)器信息

output.write(statusLine.getBytes());

output.write(serverLine.getBytes());

output.write(contentTypeLine.getBytes());

output.write(contentLengthLine.getBytes());

output.write(CRLF.getBytes());//發(fā)送信息內(nèi)容

if(fileExists){

sendBytes(fis,output);

fis.close();}else{

output.write(entityBody.getBytes());}}}

//關(guān)閉套接字和流try{

output.close();

br.close();

socket.close();}

catch(Exceptione){}}

privatestaticvoidsendBytes(FileInputStreamfis,OutputStreamos)

throwsException{

//創(chuàng)建一個(gè)1Kbuffer

byte[]buffer=newbyte[1024];

intbytes=0;

//將文件輸出到套接字輸出流中

while((bytes=fis.read(buffer))!=-1){

os.write(buffer,0,bytes);}}

privatestaticStringcontentType(StringfileName){

if(fileName.endsWith(".htm")||fileName.endsWith(".html")){

return"text/html";}

return"fileName";}}

編程技巧說明◆主線程設(shè)計(jì)

主線程的設(shè)計(jì)就是在主線程httpServer類中實(shí)現(xiàn)了服務(wù)器端口的偵聽,服務(wù)器接受一個(gè)客戶端請(qǐng)求之后創(chuàng)建一個(gè)線程實(shí)例處理請(qǐng)求,代碼如下:

importjava.net.*;

importjava.io.*;

importjava.util.*;

importjava.lang.*;

publicclasshttpServer{

publicstaticvoidmain(Stringargs[]){port;

ServerSocketserver_socket;

//讀取服務(wù)器端口號(hào)try{

port=Integer.parseInt(args[0]);}

catch(Exceptione){

port=8080;}try{

//監(jiān)聽服務(wù)器端口,等待連接請(qǐng)求

server_socket=newServerSocket(port);

System.out.println("httpServerrunningonport"

+server_socket.getLocalPort());....................

◆連接處理分線程設(shè)計(jì)

在分線程httpRequestHandler類中實(shí)現(xiàn)了HTTP協(xié)議的處理,這個(gè)類實(shí)現(xiàn)了Runnable接口,代碼如下:

classhttpRequestHandlerimplementsRunnable{

finalstaticStringCRLF="\\r\\n";

Socketsocket;

InputStreaminput;

OutputStreamoutput;

BufferedReaderbr;

//構(gòu)造方法

publichttpRequestHandler(Socketsocket)throwsException{

this.socket=socket;

//得到輸入輸出流

this.input=socket.getInputStream();

this.output=socket.getOutputStream();

this.br=

newBufferedReader(newInputStreamReader(socket.getInputStream()));}

//實(shí)現(xiàn)Runnable接口的run()方法

publicvoidrun(){try{

processRequest();}

catch(Exceptione){

System.out.println;}}

◆構(gòu)建processRequest()方法來處理信息的接收和發(fā)送

作為實(shí)現(xiàn)Runnable接口的主要內(nèi)容,在run()方法中調(diào)用processRequest()方法來處理客戶請(qǐng)求內(nèi)容的接收和服務(wù)器返回信息的發(fā)送,代碼如下:

privatevoidprocessRequest()throwsException{

while(true){

//讀取并顯示W(wǎng)eb瀏覽器提交的請(qǐng)求信息

StringheaderLine=br.readLine();

System.out.println("Theclientrequestis"+headerLine);

if(headerLine.equals(CRLF)||headerLine.equals(""))break;

//根據(jù)請(qǐng)求字符串中的空格拆分客戶請(qǐng)求

StringTokenizers=newStringTokenizer(headerLine);

Stringtemp=s.nextToken();

if(temp.equals("GET")){

StringfileName=s.nextToken();

fileName="."+fileName;

.............

.............

在processRequest()方法中得到客戶端請(qǐng)求后,利用一個(gè)StringTokenizer類完成了字符串的拆分,這個(gè)類可以實(shí)現(xiàn)根據(jù)字符串中指定的分隔符(缺省為空格)將字符串拆分成為字串的功能。利用nextToken()方法依次得到這些字串;sendBytes()方法完成信息內(nèi)容的發(fā)送,contentType()方法用于判斷文件的類型。

顯示W(wǎng)eb頁面

顯示W(wǎng)eb頁面的index.html文件代碼如下:

*********歡迎你的到來!*********

這是一個(gè)用Java語言實(shí)現(xiàn)的Web服務(wù)器

--------------------------------------------------------------------------------

運(yùn)行實(shí)例

為了測(cè)試上述程序的正確性,將編譯后的httpServer.class、httpRequestHandler.class和上面的index.html文件置于網(wǎng)絡(luò)的某臺(tái)主機(jī)的同一目錄中。

首先運(yùn)行服務(wù)器程序javahttpServer8080,服務(wù)器程序運(yùn)行后顯示端口信息“httpServerruningonport8080”,然后在瀏覽器的地址欄中輸入:8080/index.html,就可以正確顯示網(wǎng)頁,同時(shí)在顯示“httpServerruningonport8080”窗口中服務(wù)器會(huì)出現(xiàn)一些信息。

友情提示:本文中關(guān)于《JavaWeb工作原理》給出的范例僅供您參考拓展思維使用,JavaWeb工作原理:該篇文章建議您自主創(chuàng)作。

來源:網(wǎng)絡(luò)整理 免責(zé)聲明:本文僅限學(xué)習(xí)分享,如產(chǎn)生版權(quán)問題,請(qǐng)聯(lián)系我們及時(shí)刪除。


JavaWeb工作原理》由互聯(lián)網(wǎng)用戶整理提供,轉(zhuǎn)載分享請(qǐng)保留原作者信息,謝謝!
鏈接地址:http://m.seogis.com/gongwen/585498.html
相關(guān)文章