WEB應用與開發(fā)-08JAVA服務器小程序(ServLet)之Servlet鏈、編程應用_第1頁
WEB應用與開發(fā)-08JAVA服務器小程序(ServLet)之Servlet鏈、編程應用_第2頁
WEB應用與開發(fā)-08JAVA服務器小程序(ServLet)之Servlet鏈、編程應用_第3頁
WEB應用與開發(fā)-08JAVA服務器小程序(ServLet)之Servlet鏈、編程應用_第4頁
WEB應用與開發(fā)-08JAVA服務器小程序(ServLet)之Servlet鏈、編程應用_第5頁
已閱讀5頁,還剩64頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第八講課題JAVA效勞器小程序〔ServLet〕之Servlet鏈、編程應用目的要求掌握Servlet鏈的含義及編程應用教學重點ServLet鏈的構建與Shtml的使用教學難點ServLet鏈的構建教學課時4〔含2課時上機〕教學方法講解、例如與啟發(fā)式教學相結合教學內容和步驟8.1Servlet鏈8.1.1什么是servlet鏈

Servlet鏈,它是JvavServer體系結構的高級特征之一,與UNIX和DOS命令中的管道類似,你也可以將多個servlet以特定順序鏈接起來。在servlet鏈中,一個servlet的輸出被當作下一個servlet的輸入,而鏈中最后一個servlet的輸出被返回到瀏覽器。表過濾器(TableFilter)我們以表過濾器看看如何編寫一個可以被用于鏈接的servlet,這個表過濾器servlet將分析另一個servlet的輸出,查找含有特殊表格式指令的HTML注釋,這些指令包括表有多少列、是否顯示表頭等等。在該表格式指令之后的所有行將會被格式化成一個HTML表格。這樣,鏈中的前一個servlet只要簡單地將數(shù)據(jù)用逗號分割,數(shù)據(jù)就可以一行一行地直接輸出了,而無須將這些數(shù)據(jù)格式化成HTML表格。同樣,當你決定修改這個表格的格式時,你就不必修改產(chǎn)生數(shù)據(jù)的servlet,而直接修改這個表過濾器servlet就可以了。這個表過濾器servlet實現(xiàn)了HTTP效勞的方法。首先,它必須重復(echo)上一個servlet中設置的頭信息。這些信息包括內容類型、調用的URL、遠程主機等等。TableFilter.java顯示了設置這些頭信息的必要代碼。例1:TableFilter.javapackagejavaservlets.samples;importjavax.servlet.*;import.*;import;import;publicclassTableFilterextendsHttpServlet{/***<p>PerformsanHTTPservicerequest*@paramreqTherequestfromtheclient*@paramrespTheresponsefromtheservlet*/

publicvoidservice(HttpServletRequestreq,

HttpServletResponseresp)

throwsServletException,

{

//Getallheaderssetbythepreviousservletandechothem

e=req.getHeaderNames();

while(e.hasMoreElements()){

Stringheader=(String)e.nextElement();

Stringvalue=req.getHeader(header);

resp.setHeader(header,value);

}//如下述代碼所示,接下來的步驟是取得一個可以從前一個servlet的輸出流中講讀取數(shù)據(jù)的輸入流,如果該輸入流的內容類型是某種我們可以分析的類型(如HTML),我們就繼續(xù)下一步驟;否那么,我們就從輸入流中讀出所有字節(jié)并毫不修改地把它們寫回瀏覽器。//GettheinputandoutputstreamsServletInputStreamin=req.getInputStream();ServletOutputStreamout=resp.getOutputStream();//OnlyprocessifthisisarecognizedMIMEtypeStringtype=req.getContentType();if(type.equals("text/html")||

type.equals("text/table")||

type.equals("application/x-www-form-urlencoded")){

resp.setContentType("text/html");

//Createabufferedreaderthatwecanusetoread

//asinglelineatatime

BufferedReaderbr=

newBufferedReader(newInputStreamReader(in));

booleaninTable=false;

inttableCols=0;

booleanheaderRow=false;

//Readuntilnomoredataexists

while(true){

Strings=br.readLine();

//nullindicatesendoffile

if(s==null){

break;

}

//Ifweareinthemiddleofatablecommand,process

//theline

if(inTable){

//Searchfortheendofthetable

if(s.startsWith("<!--endtable")){

out.println("</table></center>");

inTable=false;

}

else{

//We'vegotarowofatable-formatit

s=formatRow(s,tableCols,headerRow);

headerRow=false;

}

}

else{

//Searchforthestartofatable

if(s.startsWith("<!--table")){

intpos=s.indexOf("columns=");

tableCols=0;

if(pos>=0){

//Getthenumberofcolumns

Stringcols=s.substring(pos+8);

intendPos=cols.indexOf("");

if(endPos>0){

cols=cols.substring(0,endPos);

}

tableCols=Integer.parseInt(cols);

}

//Gettheheaderflag.If'yes'thefirst

//rowofdataisactuallyaheader

pos=s.indexOf("header=");

if(pos>=0){

Stringflag=s.substring(pos+7);

headerRow=flag.startsWith("yes");

}

//Ifwehaveavalidnumberofcolumns,format

//thetable

if(tableCols>0){

out.println(s);

s="<center><tableborder>";

inTable=true;

}

}

}

out.println(s);

}

}else{

//UnsupportedMIMEtype;echothecontentsunchanged

while(true){

intb=in.read();

if(b==-1){

break;

}

out.write(b);

}

}

out.close();

}

/***<p>Formatsthegivenlineintoatablerow*/

privateStringformatRow(Stringline,intcols,booleanheader)

{

Strings="<tr>";

intpos=line.indexOf(",");

intlastPos=0;

//Loopforeachcolumn

for(inti=0;i<cols;i++){

if(pos<0){

pos=line.length();

}

//InserttheproperHTMLtag

if(header){

s+="<th>";

}

else{

s+="<td>";

}

//Findthenextcolumndata

if(pos>0){

s+=line.substring(lastPos,pos);

lastPos=pos;

if(pos<line.length()){

lastPos=pos+1;

pos=line.indexOf(",",lastPos);

}

else{

pos=0;

}

}

//InserttheproperHTMLtag

if(header){

s+="</th>";

}

else{

s+="</td>";

}}

//Returntheformattedline

returns;

}

/***<p>Initializetheservlet.Thisiscalledoncewhenthe*servletisloaded.Itisguaranteedtocompletebeforeany*requestsaremadetotheservlet**@paramcfgServletconfigurationinformation*/publicvoidinit(ServletConfigcfg)

throwsServletException

{

super.init(cfg);

}

/***<p>Destroytheservlet.Thisiscalledoncewhentheservlet*isunloaded.*/

publicvoiddestroy()

{

super.destroy();

}/***<p>Returnsinformationaboutthisservlet*/

publicStringgetServletInfo(){

return"TableFilterforChaining";

}

}

接下來的輸入流分析就簡單得多了。我們只要一行一行地讀入表格中的數(shù)據(jù),直至找到文件結束標記為止。對每一行,通過查找逗號來取得每一個域,然后將它們格式化成表格的一行。8.1.3觸發(fā)一個servlet鏈在將要鏈接在一起的servlet組織好之后,你可以通過別名、MIME類型或者HTML請求來觸發(fā)這個servlet鏈。每一種方式都其特殊的配置,下面分別看看如何用JavaWeb效勞器和LiveSoftware的JRun來配置這些觸發(fā)方法。其他效勞器的設置也大致相同。⑴servlet別名servlet別名使你可以設置一個servlet名字或別名來表示一個或多個servlet。servlet鏈可以用servlet列表表示,該列表中的servlet用逗號分開,并按調用次序的先后排列在一起。①JavaWebServer在配置servlet別名以觸發(fā)servlet鏈之前,一定要確認servlet鏈接功能已經(jīng)被啟動。圖4.4顯示了站點設置管理屏幕,這里,你可以啟用servlet鏈接功能。

增加一個servlet別名是非常直截了當?shù)氖隆.斝谄鹘邮盏綄Α?Elemetns”的請求,它將調用“javaservlets.samples.Elements”servlet,取得輸出后將其傳給”作為輸入,最后將TableFilter的輸出返回給瀏覽器。如圖4.5所示,你只要簡單地將servlet名用逗號分隔開來,就可以將任意數(shù)量的servlet鏈接在一起。注意,在本書寫作時,JavaWebServer1.1還不能完全正確地支持servlet鏈接。該問題將在后續(xù)版本中得到解決。②Jrun在JRun中,servlet鏈接的配置是通過設置servlet映射來實現(xiàn)的。JRun中servlet別名與servlet是一一對應的,一個servlet只能與惟一的別名對應,所以servlet別名不能支持servlet鏈接。而servlet映射可以讓你將一個名字與一系列servlet或者servlet別名項對應。圖4.6顯示了如何在JRun中使用servlet映射。⑵servlet別名鏈接的例子:Elements為了說明如何使用servlet別名來觸發(fā)servlet鏈接,我們先編一個用HTML表格列出元素周期表的servlet。ElementsServlet要實現(xiàn)doGet()來響應HTMLGET命令。我們還要設置內容類型然后輸出HTML首部信息。ElementsServlet沒有格式化輸出HTML表格,我們將讓它輸出表過濾器servlet所需的表格格式信息,并簡單地一行一行輸出用逗號分隔的數(shù)據(jù)。例2:elements

packagejavaservlets.samples;

importjavax.servlet.*;

import.*;

/***<p>Thisisasimpleservletthatwillreturnalistof*periodicelements.*/

publicvoiddoGet(HttpServletRequestreq,

HttpServletResponseresp)

throwsServletException,

{

//CreateaPrintWritertowritetheresponse

out=

newjava.io.PrintWriter(resp.getOutputStream());

//Setthecontenttypeoftheresponse

resp.setContentType("text/html");

//PrinttheHTMLheader

out.println("<html>");

out.println("<head>");out.println("<title>JavaServletsSample-"+

"PeriodicElements</title>");

out.println("</head>");

out.println("<h2><center>");

out.println("ThePeriodicElements</center></h2>");

out.println("<br>");

//Outputspecialtableformattinginstructionsfor

//theTableFilterservlet

out.println("<!--tablecolumns=2header=yes-->");

//Outputthetable

out.println("Symbol,Element");

out.println("Ac,Actinium");

out.println("Ag,Silver");

out.println("Al,Aluminum");

//Etc...

out.println("Y,Yttrium");

out.println("Yb,Ytterbium");

out.println("Zn,Zinc");

out.println("Zr,Zirconium");

out.println("<!--endtable-->");

//Wrapup

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

out.flush();

out.close();

}在你瀏覽器的URL中輸出“/Elements”調用我們在Jrun中配置的servlet映射。在刷新時,瀏覽器向Web效勞器發(fā)出URL請求,Web效勞器找到與這個URL信息對應的servlet映射,然后調用ElemetnsServlet。ElementsServlet處理GET請求并返回未格式化的元素周期表數(shù)據(jù)給Web效勞器。之后,Web效勞器發(fā)現(xiàn)存在servlet鏈接,于是將ElementsServlet的輸出重定向為servlet鏈接中下一個servlet,也就是表過濾器的輸入。表過濾器重新設置所有HTTP首部,以適應表過濾器的需要,然后讀入所有元素周期表數(shù)據(jù),表過濾器使用指定的表格格式信息來分析和處理這些數(shù)據(jù),最后生成一個格式化的元素周期表。⑶Mime類型觸發(fā)servlet鏈接的另外一種方法是將一個servlet與特定Mime類型聯(lián)系起來。當這種Mime類型的應答產(chǎn)生時,輸出就會被發(fā)送給與之相聯(lián)系的servlet。由于MIME類型是在servlet向輸出流中寫入時才確定的,所以用這種方法你可以輕易地將servlet的輸出重定向到其他servlet。①JavaWebServer如前所述,在所有的工作之前,你必須確認servlet鏈接功能已經(jīng)啟用(見圖4.4)。截止到本書發(fā)稿,還沒有可以管理MIME類型和servlet映射的圖形用戶接口(GUI),所以你不得不手工編輯“perties”文件。這個文件位于目錄“/<server_root>/properties/server/javawebserver/webpageservice”。下述代碼給出了根本的內容。值得注意的是,MIME類型所映射的servlet名字實際上是該servlet的別名。#Thisfilemapsmime-typestotheservletswhichprocessthem

#Thisisusedbythefiltermanagertosetupchainsofservlets

#wheretheouputofoneservletgetspipedtotheinputof

#anotherservletbasedonthemime-typethattheservletspecifies

#withsetContentType("mime-type")

#

#Thedefaultservletforallmime-typesisfile.Donotsetthis

#explicitly.

##Entriesinthisfileshouldbeoftheform

#mime-type/servletname

#ie.

#foo/bar=fooServlet

#wherefooServletisdefinedinperties

java-internal/parsed-html=ssi

java-internal/template-content=template②Jrun在JRun中,你可以通過系統(tǒng)管理應用程序設置MIME類型映射。如圖4.10所示,你可以把一個servlet和特定的MIME類型聯(lián)系起來。MIME類型鏈接的例子:Indy500為了說明如何通過MIME類型來觸發(fā)servlet鏈接,讓我們編寫一個列出Indianapolis500自1911年起的所有優(yōu)勝者。就像ElementsServlet一樣,我們直接將輸入用逗號分隔的各行數(shù)據(jù),并用表過濾器將其格式化成HTML表格形式輸出。惟一的不同在于我們設置了一個不同的MIME類型,通過這個MIME類型,Web效勞器將Indy500Servlet的輸出重定向為表過濾器servlet的輸入(見例3)。例3Indy500.java

packagejavaservlets.samples;

importjavax.servlet.*;

import.*;

/**<p>Thisisasimpleservletthatwillreturnalistof

*pastIndianapolis500winners*/

publicclassIndy500extendsHttpServlet

{

/**

*<p>PerformstheHTTPGEToperation*@paramreqTherequestfromtheclient*@paramrespTheresponsefromtheservlet*/

publicvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)

throwsServletException,{

//CreateaPrintWritertowritetheresponse

out=

newjava.io.PrintWriter(resp.getOutputStream());

//Setthecontenttypeoftheresponse

resp.setContentType("text/table");

//PrinttheHTMLheader

out.println("<html>");

out.println("<head>");

out.println("<title>JavaServletsSample-"+

"PastIndianapolis500Winners</title>");

out.println("</head>");

out.println("<h2><center>");

out.println("PastIndianapolis500Winners</center></h2>");

out.println("<br>");

//Outputspecialtableformattinginstructionsfor

//theTableFilterservlet

out.println("<!--tablecolumns=3header=yes-->");

out.println("Year,Driver,AverageSpeed");

out.println("1997,ArieLuyendyk,145.827");

out.println("1996,BuddyLazier,147.956");

out.println("1995,JacquesVillenueve,153.616");

//Etc...out.println("1912,JoeDawson,78.719");

out.println("1911,RayHarroun,74.602");

out.println("<!--endtable-->");

//Wrapup

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

out.flush();

out.close();

}通過使用JRun中配置的MIME類型映射,調用Indy500Servlet的結果將會是格式化了的Indianapolis500優(yōu)勝者列表(如圖4.12所示)。值得注意的是,我們只要設置servlet的別名就可以了,而無須指定它的全名。再次重申,Web瀏覽器向Web效勞器發(fā)送的是含有servlet名字的HTTP請求,Web效勞器調用了servlet(Indy500),servlet設置了MIME類型“text/table”,而我們已經(jīng)將這個MIME類型映射到表過濾器servlet。于是,Indy500所產(chǎn)生的輸出將被重定向為表過濾器servlet的輸入,表過濾器servlet將數(shù)據(jù)格式化為HTML表格的形式,并將輸出返回給Web效勞器。最后Web效勞器把這些HTML頁發(fā)送給瀏覽器。⑷HTTP請求觸發(fā)servlet鏈接的另一種方法是在HTTP請求中指定servlet鏈接。不過不是所有的Web效勞器都支持這種方法。為了說明HTTP請求中的servlet鏈接,我們再來編寫一個簡單的servlet(SolarSystem),它將返回我們太陽系中所有行星的信息。例4給出了SolarSystemServlet的代碼。例4:SolarSystem.java

packagejavaservlets.samples;

importjavax.servlet.*;

import.*;

/***<p>Thisisasimpleservletthatwillreturnalistof*theplanetsinoursolarsystem*/publicclassSolarSystemextendsHttpServlet{

/***<p>PerformstheHTTPGEToperation*@paramreqTherequestfromtheclient*@paramrespTheresponsefromtheservlet*/

publicvoiddoGet(HttpServletRequestreq,

HttpServletResponseresp)

throwsServletException,{

//Setthecontenttypeoftheresponse

resp.setContentType("text/html");

//CreateaPrintWritertowritetheresponseout=newjava.io.PrintWriter(resp.getOutputStream());

//PrinttheHTMLheader

out.println("<html>");

out.println("<head>");

out.println("<title>JavaServletsSample-"+"PlanetsInOurSolarSystem</title>");out.println("</head>");out.println("<h2><center>");out.println("PlanetsInOurSolarSystem</center></h2>");out.println("<br>");//Outputspecialtableformattinginstructionsfor//theTableFilterservletout.println("<!--tablecolumns=5header=yes-->");out.println("Planet,Avg.DistancefromSun,"+

"Timetoorbit,Timetospin,Moons");out.println("Mercury,58millionkm,88days,58.6days,0");out.println("Venus,108millionkm,225days,243days,0");out.println("Earth,150millionkm,365.25days,24hours,1");out.println("Mars,228millionkm,687days,24.62hours,2");out.println("Jupiter,778millionkm,11.9years,9.83hours,16");out.println("Saturn,1427millionkm,29.5years,10.65hours,19");out.println("Uranus,2870millionkm,84years,17.23hours,15");out.println("Neptune,4497millionkm,164.8years,16hours,8");out.println("Pluto,5913millionkm,248years,6.375days,1");out.println("<!--endtable-->");//Wrapupout.println("</html>");out.flush();out.close();

}

/***<p>Initializetheservlet.Thisiscalledoncewhenthe*servletisloaded.Itisguaranteedtocompletebeforeany*requestsaremadetotheservlet**@paramcfgServletconfigurationinformation*/publicvoidinit(ServletConfigcfg)

throwsServletException{

super.init(cfg);

}

/***<p>Destroytheservlet.Thisiscalledoncewhentheservlet*isunloaded.*/

publicvoiddestroy()

super.destroy();

}

}和前面的servlet一樣,SolarSystemServlet將直接輸出無格式的數(shù)據(jù)而將格式化的工作交由表過濾器servlet來完成。由于JavaWebServer不支持用HTTP請求觸發(fā)servlet鏈接,我們將使用JRun。圖4.14顯示了SolarSystemServlet和表過濾器servelt鏈接起來以后的輸出結果。請注意調用servlet時使用的URL,在這種情況下,URL中包含了一個鏈接在一起的servlet名字,它們之間用逗號來間隔。8.2JavaServlet編程及應用效勞器端包含效勞器端包含(Server-SideIncludes)是Web頁面設計中的一種常用技術,在一個輸出很多網(wǎng)頁的系統(tǒng)中,經(jīng)常會有一些網(wǎng)頁的組成局部在多個網(wǎng)頁中同時出現(xiàn)。Server-SideIncludes是JavaServer體系結構的一個高級特征,它可以在HTML文檔中嵌入servlet,這樣就可以利用一個或多個servlet來組成最終的HTML文檔,這種特殊的包含了Servlet輸出和HTML標記的文件用擴展名.shtml表示。Servlet標記的語法:<servletname=Servlet_namecode=Servlet.classcodebase=類路徑名稱1=參數(shù)值1名稱2=參數(shù)值2

名稱n=參數(shù)值n><paramname=名稱1value=參數(shù)值1

paramname=名稱2value=參數(shù)值2

paramname=名稱nvalue=參數(shù)值n></servlet>編程思路及技巧:下面是一個完整的簡單的效勞器包含(SSI)的實例,整個shtml頁面由2個Servlet組成,第1個Servlet是Header.java,代表頁頭,主要功能是顯示標題信息;第2個Servlet是Footer.java,代表頁腳,主要功能是顯示頁腳的版權信息;Together.shtml是將2個Servlet組合在一起顯示的效勞器包含,它應當從文檔根目錄(如root)中加載。例5:Header.javaimportjavax.servlet.*;importjava.io.*;publicclassHeaderextendsGenericServlet{

publicvoidservice(ServletRequestreq,ServletResponseresp)

throwsServletException,IOException

{res.setContentType("text/html;charset=gb2312");

PrintWriterout=res.getWriter();

//Getthetitleofthepage.Settoemptystringif

//notitleparameterwasgiven

Stringtitles[]=req.getParameterValues("title");

Stringtitle="";

if(titles!=null){

if(titles.length>0){

title=titles[0];

}

}Footer.javaimportjavax.servlet.*;importjava.io.*;publicclassFooterextendsGenericServlet{

publicvoidservice(ServletRequestreq,ServletResponseresp)

throwsServletException,IOException

{res.setContentType("text/html;charset=gb2312");

PrintWriterout=res.getWriter();

//Formatthestandardheader

out.println("<hr>"=;

out.println("<palign='center'><i>版權所有,信息公司</i></p>"=;

//Wrapup

out.flush();

out.close();

}

/***<p>Returnsinformationaboutthisservlet*/

publicStringgetServletInfo(){

return"Footer";

}

publicvoidinit(ServletConfigcfg)

throwsServletException

{

super.init(cfg);

}

publicvoiddestroy()

{

super.destroy();

}}使用JavaServletAPI進行會話管理接口封裝了HTTP會話的細節(jié),該會話與一段時間內特定的Web客戶對Web效勞器的多個請求相關。管理會話數(shù)據(jù)主要涉及到3個方面:會話交換、會話重定位和會話持久性,只有實現(xiàn)了接口的數(shù)據(jù)對象才能夠被交換、重定位和保持。這個接口主要是讓對象具有序列化的能力,它可以將對象的狀態(tài)信息寫入任意的輸出流中如:文件、網(wǎng)絡連接等。編程思路:下面是實現(xiàn)一個簡單在商場購物的例子,當用戶選購商品(糖果、收音機和練習簿)放入購物袋中,保存選購的商品信息。編程技巧說明:在Servlet中進行會話管理時,首先要獲得會話對象。HttpServletRequest.getSession()對象返回與請求相關的當前HttpSession對象,并且當該對象不存在時就新創(chuàng)立一個對象;HttpServletRequest.getSession(true)實現(xiàn)相同的功能。如果參數(shù)是false,當不存在會話對象時,將返回一個null值。

8.3小結在本講中,我們討論了servlet鏈及編程應用,這是JavaServer體系結構的高級特征之一。servlet鏈接提供了將一個servlet的輸出重定向為另一個servlet的輸入的能力。這樣,你就可以劃分工作,從而使用一系

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論