深入體驗javaweb開發(fā)內(nèi)幕——關(guān)于httpservletrequestrequest對象
httpservletrequest對象代表客戶端的請求,當(dāng)客戶端通過http協(xié)議訪問服務(wù)器時,http請求頭中的所有信息都封裝在這個對象中,開發(fā)人員通過這個對象的相關(guān)方法,即可以獲得客戶的這些信息。
一、通過request常用方法獲得相關(guān)信息:
1、通過request常用方法獲得客戶機(jī)信息
getrequesturl方法返回客戶端發(fā)出請求時的完整url。
getrequesturi方法返回請求行中的資源名部分。
getquerystring 方法返回請求行中的參數(shù)部分。
getremoteaddr方法返回發(fā)出請求的客戶機(jī)的ip地址
getremotehost方法返回發(fā)出請求的客戶機(jī)的完整主機(jī)名
getremoteport方法返回客戶機(jī)所使用的網(wǎng)絡(luò)端口號
getlocaladdr方法返回web服務(wù)器的ip地址。
getlocalname方法返回web服務(wù)器的主機(jī)名
getmethod得到客戶機(jī)請求方式
例如在request.java中加入如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//返回相關(guān)請求的信息 string uri=request.getrequesturi(); stringrad = request.getremoteaddr(); stringrh = request.getremotehost(); stringru = request.getremoteuser(); intrp = request.getremoteport(); stringcp = request.getcontextpath(); stringla = request.getlocaladdr(); stringce = request.getcharacterencoding(); stringgm = request.getmethod(); stringqs = request.getquerystring(); system.out.println(uri); system.out.println(rad); system.out.println(rh); system.out.println(ru); system.out.println(rp); system.out.println(cp); system.out.println(la); system.out.println(ce); system.out.println(gm); system.out.println(qs); |
即可獲取相關(guān)信息。
2、通過request常用方法獲得客戶機(jī)請求頭信息
gethead(name)方法
getheaders(string name)方法
getheadernames方法
如:
1
2
3
4
5
6
7
8
9
10
|
private void getrequestvalue(httpservletrequest request) { //獲得客戶機(jī)請求頭及請求頭的值 system.out.println(request.getheader( "method" )); enumeration e = request.getheadernames(); while (e.hasmoreelements()){ string name = (string)e.nextelement(); string value = request.getheader(name); system.out.println(name+ ":" +value); } } |
3.獲得客戶機(jī)請求參數(shù)(客戶端提交的數(shù)據(jù))
getparameter(name):獲取指定名稱的參數(shù)值。這是最為常用的方法之一。
getparametervalues(string name):獲取指定名稱參數(shù)的所有值數(shù)組。它適用于一個參數(shù)名對應(yīng)多個值的情況。如頁面表單中的復(fù)選框,多選列表提交的值。
getparameternames():返回一個包含請求消息中的所有參數(shù)名的enumeration對象。通過遍歷這個enumeration對象,就可以獲取請求消息中所有的參數(shù)名
getparametermap():返回一個保存了請求消息中的所有參數(shù)名和值的map對象。map對象的key是字符串類型的參數(shù)名,value是這個參數(shù)所對應(yīng)的object類型的值數(shù)組。
二、request的常見應(yīng)用
1、 各種表單輸入項數(shù)據(jù)的獲取
如可以獲取form表單中的text、password、radio、checkbox、 file、select、textarea、 hidden、image、button等組件的值進(jìn)行數(shù)據(jù)庫操作或其他處理操作。
來看一個具體應(yīng)用:
界面代碼主體部分如下:
register.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<!doctype html public "-//w3c//dtd html 4.01transitional//en" > <html> <head> <title>register.html</title> <metahttp-equivmetahttp-equiv= "keywords" content= "keyword1,keyword2,keyword3" > <metahttp-equivmetahttp-equiv= "description" content= "this is my page" > <meta http-equiv= "content-type" content= "text/html;charset=utf-8" > <!--<link rel= "stylesheet" type= "text/css" href= "./styles.css" rel= "external nofollow" >--> </head> <body> <form action = "requestlogin" method = "post" > 用戶名:<input type= "text" name = "username" ><br/> 密碼: <inputtypeinputtype= "password" name = "password" ><br/> 性別:<input type= "radio" name = "sex" value = "male" >男 <input type= "radio" name = "sex" value= "female" >女<br/> 籍貫: <select name= "city" > <option value = "hebei" >河北</option> <opton value = "hubei" >湖北</opton> <option value = "shanxi" >山西</option> </select><br/> 簡歷:<br/> &nsp;<textarea rows= "5" cols= "20" name= "intro" ></textarea> <br/> 愛好:<br/> <input type= "checkbox" name= "hobbies" value = "sing" />唱歌 <input type= "checkbox" name= "hobbies" value = "dance" />跳舞 <input type= "checkbox" name= "hobbies" value = "readbook" />讀書 <input type= "checkbox" name= "hobbies" value = "readnewspaper" />看報<br/> 上傳頭像:<br/> <input type= "file" value= "image" name = "browser" ><br/> <input type= "submit" value= "提交" /> </form> </body> </html> |
然后,定義一個requestlogin.java類通過request對象獲取表單中組件的值:
如調(diào)用自定義方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
private void getinformation(httpservletrequest request) throws unsupportedencodingexception { //取出參數(shù)值 string name = request.getparameter( "username" ); string pass = request.getparameter( "password" ); string sex = request.getparameter( "sex" ); string city = request.getparameter( "city" ); string intro = request.getparameter( "intro" ); string [] hobbies = request.getparametervalues( "hobbies" ); string hobby = "" ; //hobbies!=null對所取值為空時進(jìn)行設(shè)置 for ( int i= 0 ;hobbies!= null &&i<hobbies.length;i++) { string hovalue = hobbies[i]; hobby += hovalue; } //獲取頭像信息 // string image = request.getparameter("image"); system.out.println( "username:" +name); system.out.println( "password:" +pass); system.out.println( "sex:" +sex); system.out.println( "city:" +city); system.out.println( "intro:" +intro); system.out.println( "hobby:" +hobby);} |
即可獲取表單中組件的值。
2、請求參數(shù)的中文亂碼問題
前面我們提到了response對象中出現(xiàn)亂碼問題及相應(yīng)的解決措施,那么在request中如何解決編碼問題呢?
下面來看具體的例子:
例如我想將一個form表單中的信息提取到并在控制臺輸出如圖:
假設(shè)在服務(wù)端并未request對象給指定編碼時即服務(wù)器端接收請求的字符編碼為iso8859-1,這時你在客戶端添加信息如:
當(dāng)填入的信息有中文時,假設(shè)設(shè)置表單的提交方式為post方式提交
則在服務(wù)端輸出如下:
此時輸出結(jié)果出現(xiàn)亂碼。
客戶端主體代碼同上:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
register.html <body> <form action = "requestlogin" method = "post" > 用戶名:<input type= "text" name = "username" ><br/> 密碼: <input type= "password" name = "password" ><br/> 性別:<input type= "radio" name = "sex" value = "male" >男 <input type= "radio" name = "sex" value = "female" >女<br/> 籍貫: <select name = "city" > <option value = "hebei" >河北</option> <opton value = "hubei" >湖北</opton> <option value = "shanxi" >山西</option> </select><br/> 簡歷:<br/> &nsp;<textarea rows= "5" cols= "20" name = "intro" ></textarea> <br/> 愛好:<br/> <input type= "checkbox" name = "hobbies" value = "sing" />唱歌 <input type= "checkbox" name = "hobbies" value = "dance" />跳舞 <input type= "checkbox" name = "hobbies" value = "readbook" />讀書 <input type= "checkbox" name = "hobbies" value = "readnewspaper" />看報<br/> 上傳頭像:<br/> <input type= "file" value = "image" name = "browser" ><br/> <input type= "submit" value = "提交" /> </form> </body> |
服務(wù)端主體代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
requestlogin.java package net.csdn.request; import java.io.ioexception; import java.io.printwriter; importjava.io.unsupportedencodingexception; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; importjavax.servlet.http.httpservletrequest; importjavax.servlet.http.httpservletresponse; public class requestlogin extendshttpservlet { public void doget(httpservletrequest request,httpservletresponse response) throws servletexception, ioexception { getinformation(request); } private voidgetparameter(httpservletrequest request) throws unsupportedencodingexception { private voidgetinformation(httpservletrequest request) throws unsupportedencodingexception { //取出參數(shù)值 string name =request.getparameter( "username" ); string pass =request.getparameter( "password" ); string sex =request.getparameter( "sex" ); string city =request.getparameter( "city" ); string intro = request.getparameter( "intro" ); string [] hobbies =request.getparametervalues( "hobbies" ); string hobby = "" ; //hobbies!=null對所取值為空時進(jìn)行設(shè)置 for (inti= 0 ;hobbies!= null &&i<hobbies.length;i++) { string hovalue = hobbies[i]; hobby +=hovalue; } //獲取頭像信息 // string image = request.getparameter("image"); system.out.println( "username:" +name); system.out.println( "password:" +pass); system.out.println( "sex:" +sex);system.out.println( "city:" +city); system.out.println( "intro:" +intro);system.out.println( "hobby:" +hobby);} public void dopost(httpservletrequestrequest, httpservletresponse response) throws servletexception, ioexception{doget(request, response);}} |
這里會出現(xiàn)亂碼問題,是因為你在registerlogin.java中并沒有給request對象設(shè)置編碼集,而request對象的默認(rèn)編碼集是iso8859-1是不支持漢字的,所以你只需要在此類中為其指明相應(yīng)的編碼即可:
改正:在doget方法中加入如下代碼指明接收請求的編碼方式:
request.setcharacterencoding("utf-8");
即可輸出:
但是這種修改方式只在提交方式為post時才有效。當(dāng)提交方式為get時是不起作用的。
即;
<form action ="requestlogin" method ="get">
時即便在
requestlogin.java
中再設(shè)置
request.setcharacterencoding("utf-8");
也不會起任何作用了程序還會輸出如圖所示信息:
這時就需要在
requestlogin.java
中含有中文的地方進(jìn)行如下設(shè)置了即在doget方法中加入如下代碼:
1
2
3
4
|
string username = new string(name.getbytes( "iso8859-1" ), "utf-8" ); string introduction = new string(intro.getbytes( "iso8859-1" ), "utf-8" ); system.out.println( "username:" +username); system.out.println( "password:" +introduction); |
此時再度測試時就ok了!如圖
好了到這里,你大概已經(jīng)知道該如何對response和request對象中的亂碼問題進(jìn)行操作了吧!
3、防盜鏈
所謂的防盜鏈就是當(dāng)你以一個非正常渠道去訪問某一個web資源的時候,服務(wù)器會將你的請求忽略并且將你的當(dāng)前請求變?yōu)榘凑G涝L問時的請求并返回到相應(yīng)的頁面,用戶只有通過該頁面中的相關(guān)操作去訪問想要請求的最終資源。
例如,你有一個訪問某資源的網(wǎng)址,但是你事先不知道這個網(wǎng)址是有防盜鏈的,那么當(dāng)你輸入該網(wǎng)址時你可能會發(fā)現(xiàn),并沒有馬上跳轉(zhuǎn)到你想要的資源頁面而是一些無關(guān)的信息頁面,但是就是在這些信息頁面中你發(fā)現(xiàn)有一個超鏈接或是其他操作可以跳轉(zhuǎn)到你所訪問的最終資源頁面。
這就是防盜鏈技術(shù)了,好了來看一個具體應(yīng)用:
rquest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class request extends httpservlet { public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {getdoorchain(request, response);} private void getdoorchain(httpservletrequest request, httpservletresponse response) throws ioexception { //通過request獲取請求頭參數(shù) string referer = request.getheader( "referer" ); if (referer== null || !referer.endswith( "http://localhost:8080/request/index.jsp" )){ response.sendredirect( "http://localhost:8080/request/index.jsp" ); return ; } response.setcharacterencoding( "utf-8" ); response.setcontenttype( "text/html;charset =utf-8" ); printwriter pw = response.getwriter(); pw.write( "喜劇片《東成西就》" ); } public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } } |
index.jsp部分的主體代碼:
1
2
3
4
5
|
<body> 這里是防盜鏈技術(shù)的應(yīng)用檢測! <br> <a href = "/request/request" >喜劇片 </a> </body> </html> |
效果如圖:
例如我最終想要通過http://lcoalhost:8080/request/request這個網(wǎng)址獲取到我想要的《東成西就》
的資源可是當(dāng)我真正的輸入這個網(wǎng)址時,卻轉(zhuǎn)到了:
http://localhost:8080/request/index.jsp這個頁面
只有當(dāng)你點擊“喜劇片”這個超鏈接時才會真正的得到你想要的資源頁面即:
好了趕快自己動手試一試吧!
4、request對象實現(xiàn)請求轉(zhuǎn)發(fā):
servlet api中定義了一個requestdispatcher接口,俗稱請求分派器。它定義了如下兩個方法: public void forward(servletrequest request, servletresponseresponse) 、public void include(servletrequest request,servletresponse response) ,
獲取requestdispatcher實例的方式主要有兩種:
調(diào)用servletcontext接口提供的getrequestdispatcher(stringurl)方法。
調(diào)用servletrequest接口提供的getrequestdispatcher(stringurl)方法。
requestdispatcher:
被包含的servlet程序不能改變響應(yīng)消息的狀態(tài)碼和響應(yīng)頭,如果它里面存在這樣的語句,這些語句的執(zhí)行結(jié)果將被忽略。
例:
request.getrequestdispatcher("./welcome.jsp").forward(request,response);即可從當(dāng)前應(yīng)用跳轉(zhuǎn)到相應(yīng)的"./welcome.jsp"頁面。
request對象提供了一個getrequestdispatcher方法,該方法返回一個requestdispatcher對象,調(diào)用這個對象的forward方法可以實現(xiàn)請求轉(zhuǎn)發(fā)。
request對象同時也是一個域?qū)ο螅_發(fā)人員通過request對象在實現(xiàn)轉(zhuǎn)發(fā)時,把數(shù)據(jù)通過request對象帶給其它web資源處理。
可通過如下方法對request中的數(shù)據(jù)對象進(jìn)行操作:
setattribute方法 ;
getattribute方法 ;
removeattribute方法;
getattributenames方法;
三、關(guān)于請求轉(zhuǎn)發(fā)的一些細(xì)節(jié)
forward方法用于將請求轉(zhuǎn)發(fā)到requestdispatcher對象封裝的資源。
如果在調(diào)用forward方法之前,在servlet程序中寫入的部分內(nèi)容已經(jīng)被真正地傳送到了客戶端,forward方法將拋出illegalstateexception異常。
如果在調(diào)用forward方法之前向servlet引擎的緩沖區(qū) (response)中寫入了內(nèi)容,只要寫入到緩沖區(qū)中的內(nèi)容還沒有被真正輸出到客戶端,forward方法就可以被正常執(zhí)行,原來寫入到輸出緩沖區(qū)中的 內(nèi)容將被清空,但是,已寫入到httpservletresponse對象中的響應(yīng)頭字段信息保持有效。
四、請求重定向和請求轉(zhuǎn)發(fā)的區(qū)別
一個web資源收到客戶端請求后,通知服務(wù)器去調(diào)用另外一個web資源進(jìn)行處理,稱之為請求轉(zhuǎn)發(fā)。
一個web資源收到客戶端請求后,通知瀏覽器去訪問另外一個web資源,稱之為請求重定向。
注意:
requestdispatcher.forward方法只能將請求 轉(zhuǎn)發(fā)給同一個web應(yīng)用中的組件;而httpservletresponse.sendredirect方法還可以重定向到同一個站點上的其他應(yīng)用程序中的資源,甚至是使用絕對url重定向到其他站點的資源。 如果傳遞httpservletresponse.sendredirect方法的相對url以“/”開頭,它是相對于整個web站點的根目錄;如果創(chuàng)建requestdispatcher對象時指定的相對url以“/”開頭,它是相對于當(dāng)前web應(yīng)用程序的根目錄。
調(diào)用httpservletresponse.sendredirect方法重定向的訪問過程結(jié)束后,瀏覽器地址欄中顯示的url會發(fā)生改變,由初始的url 地址變成重定向的目標(biāo)url;調(diào)用requestdispatcher.forward 方法的請求轉(zhuǎn)發(fā)過程結(jié)束后,瀏覽器地址欄保持初始的url地址不變。
httpservletresponse.sendredirect 方法對瀏覽器的請求直接作出響應(yīng),響應(yīng)的結(jié)果就是告訴瀏覽器去重新發(fā)出對另外一個url的訪問請求;requestdispatcher.forward方法在服務(wù)器端內(nèi)部將請求轉(zhuǎn)發(fā)給另外一個資源,瀏覽器只知道發(fā)出了請求并得到了響應(yīng)結(jié)果,并不知道在服務(wù)器程序內(nèi)部發(fā)生了轉(zhuǎn)發(fā)行為。
requestdispatcher.forward方法的調(diào)用者與 被調(diào)用者之間共享相同的request對象和response對象,它們屬于同一個訪問請求和響應(yīng)過程;而 httpservletresponse.sendredirect方法調(diào)用者與被調(diào)用者使用各自的request對象和response對象,它們屬于 兩個獨立的訪問請求和響應(yīng)過程。
關(guān)于請求消息頭我們在以后的學(xué)習(xí)中還會經(jīng)常用到request對象是我們目前在javaweb開發(fā)中學(xué)到的三個作用域即servletcontext、request和session域之一,是非常重要的一個請求對象,希望以上的相關(guān)介紹對能你有所幫助!
原文鏈接:http://blog.csdn.net/redarmy_chen/article/details/8157053#