標籤:
在上一篇《Servlet的學習(十)》中介紹了HttpServletRequest請求對象的一些常用方法,而從這篇起開始介紹和學習HttpServletRequest的常用功能。
使用HttpServletRequest可以防止盜鏈行為,什麼是盜鏈行為,比如說在一個別的網站上超連結,指向我們的網頁中的某個資料,這樣從他的網頁上就可以直接進入到我的某個頁面,無需從我的指定路口進入:
例如在一個簡單的1.html檔案中加入了我的【myservlet】web應用下的某個Servlet訪問的超連結:
如果我的Servlet中代碼僅僅為為訪問輸出資料,例如:
1 response.setContentType("text/html;charset=utf-8");2 String data ="銀魂真是一部好動漫";3 response.getWriter().write(data);
那麼點擊這個超連結肯定會訪問到這個Servlet:
那麼我們如果不想被比人直接通過地址訪問或者超連結訪問怎麼辦呢:
記得學習HTTP協議中的“referer”要求標頭嗎,這個要求標頭是告訴伺服器該請求是從哪個URL發來的,那麼我們就可以根據這個URL來判斷是否是我們允許的請求地址來控制伺服器是否將響應發送回去。
代碼如下:
1 String reqUrl = request.getHeader("referer");2 if(reqUrl==null || !reqUrl.startsWith("http://localhost:8080/myservlet/index.jsp")){3 response.sendRedirect("/myservlet/index.jsp");4 return ;5 }6 7 response.setContentType("text/html;charset=utf-8");8 String data ="銀魂真是一部好動漫";9 response.getWriter().write(data);
在if判斷中判斷是否為空白是防止直接將該web資源以輸入URL地址直接存取,而另一個判斷是防止訪問該web資源不是從指定的地方來訪問進來。
通過該代碼,如果我們繼續在1.html頁面中點擊超連結,則會自動跳轉到我們設定好的index.jsp中:
而如果我們直接在瀏覽器中訪問Servlet也是會跳到這個頁面的。
只有在index.jsp中點擊我們設定好的超連結,才能訪問到:
接下來,我們來討論的使用HttpServletRequest響應對象來擷取表單資料,這是非常重要的知識點,表單提交的資料根據提交方式的不同會放置在不同位置,例如採用POST方式則會將這些資料放置在HTTP請求資料實體中,無論採用哪種方式,都是可以用響應對象的getParameter(String)等等方式擷取,這點在《Servlet的學習(十)》中已經介紹。
現在,我們在需要新建立一個HTML頁面編寫我們的表單代碼,和一個Servlet作為伺服器端接收表單提交的資料,將Servlet命名為ServletRequest,而表單的傳送伺服器和選擇HTTP方式如下:
1 <form action="/myservlet/servlet/ServletRequest" method="post">
先來看
1 <input type="text" name="user" /> 2 <input type="password" name="password" />
這兩種常見的輸入字元情況。
當然還需要在表單中提供具有提交功能的標籤才能提交,我們選擇
1 <input type="submit" value="提交" >
這樣的提交方式,效果如下:
在表單中這兩個都可以直接通過getParameter(String)方法擷取使用者輸入的資料,代碼如下:
1 String username = request.getParameter("user");2 String password = request.getParameter("password");
只要我們在使用者名稱和密碼中輸入資料,再點擊提交,就可以將使用者名稱和密碼中的資料傳遞給伺服器:
同時,由原來的表單的HTML頁面會自動跳轉到該Servlet的頁面上。
對於text和password兩種表單方式的健壯性判斷:
依據:
1,如果表單中使用者名稱和密碼不填,那麼直接提交後會是傳遞給伺服器Null 字元串。
2,如果不是在表單,而是知道了平常表單提交後會跳轉的Servlet頁面,那麼直接輸入該Servlet地址則是傳遞Null給伺服器
因此必須加入健壯性語句:
1 String username = request.getParameter("user");2 if(username!=null && !username.trim().equals("")) {3 System.out.println("user:"+username);4 }
password部分代碼同理。
接下來是選項按鈕,比如性別選擇:
1 性別 <input type="radio" name="gender" value="male"/>男2 <input type="radio" name="gender" value="female"/>女
只有<input type=”radio”>標籤中的”name”屬性一樣,才能具有單選的功能,同時”name”屬性也是在Servlet中擷取使用者單選資料的重要參數,代碼:
1 String gender = request.getParameter("gender");
如果單選沒有選擇任何選項,則提交會返回null,所以需加入健壯性語句:
1 String gender = request.getParameter("gender");2 if(gender != null) {3 System.out.println(gender);4 }
接下來是下拉式清單,下拉式清單可以是作為選擇城市,如:
1 城市<select name="city">2 <option value="none">--選擇城市--</option>3 <option value="beijing">北京</option>4 <option value="shanghai">上海</option>5 <option value="hangzhou">杭州</option>6 <option value="amoy">廈門</option>7 </select>
由<select>標籤中的”name”屬性作為Servlet中伺服器擷取用戶端發來的下來列表資料的重要參數,代碼如下:
1 String city = request.getParameter("city");2 System.out.println(city);
由於下拉式清單會預設選擇其第一個<option>標籤的內容,所有即使我們沒有進行任何選擇,也是會傳遞值得,這裡可以無需健壯性判斷。
接下來是複選框,複選框可以是一些所學技能,或者興趣愛好,如:
1 愛好 <input type="checkbox" name="hobby" value="sing">唱歌2 <input type="checkbox" name="hobby" value="surf">衝浪3 <input type="checkbox" name="hobby" value="swim">遊泳
由<input type=”checkbox”>標籤中的name屬性決定了這些複選框是否屬於同一個複選框組,也是同時也是作為Servlet中擷取表單複選框的資料的重要參數,由於多個參數使用同一個參數名,所以必須使用getParameterValues(String)方法來擷取所有的被勾選的複選框,代碼如下(包含健壯性):
1 String[] hobbies = request.getParameterValues("hobby");2 for(int i=0;hobbies!=null&&i<hobbies.length;i++) {3 System.out.println(hobbies[i]);4 }
如果沒有勾選任何一個複選框,則不會向伺服器Servlet傳送任何資料。所以如果直接接收可能會發生null 指標異常,必須判斷是否接收到的字串數組有資料(hobbies!=null)。
重要:
現在,我們再重新回到<input type="text" name="user" /> 上,如果我們輸入的是中文資料,點擊提交之後會是怎樣?
在控制台看到的結果:
結果就是出現了中文亂碼問題。這是瀏覽器在發送時通常要看當時的編碼,如:
或者:
但是!!
在Servlet收到request請求對象發來的資料時,通過getParameter方法是預設查詢“ISO-8859-1”碼錶的,所以造成了編碼不一致!
解決方式也很簡單,只要在Servlet中將擷取的request對象選擇正確的解碼方式即可,只要在代碼前添加一句:
1 request.setCharacterEncoding("UTF-8");
就可以擷取表單中正確的中文資料了:
注意,對於響應對象的setCharacterEncoding方法只對HTTP協議的POST方式有效,對GET方式無效。
如果我們將表單提交方式改為GET,那麼提交表單中有中文資料的話依然在Servlet中會出現亂碼。
如果想使GET方式也不會出現中文亂碼,並沒有好的捷徑方法。先要通過getParameter擷取請求資料(這時在Servlet中以ISO8859碼錶進行解碼),然後再通過ISO8859進行編碼成位元組數組,最後通過建立字串對象的方式選擇UTF-8解碼錶解出最開始用戶端編碼的資料。
代碼如下:
1 String userTemp = request.getParameter("user");2 String username = new String(userTemp.getBytes("ISO8859-1"),"utf-8");
即可。
當然這種方式對POST方式也是有效。
另外一種對GET方式是修改Tomcat中的設定檔(這種方式只適合GET方式,用POST方式還是會亂碼)。通過Tomcat伺服器的首頁,選擇“Configuration”查看配置文檔,選擇“Connector”下的“HTTP”:
在這個文檔中有一個URIEncoding屬性,是指可以在server.xml檔案中配置這個屬性,如果沒有這個屬性,則Tomcat預設採用ISO8859-1編碼:
通過在server.xml檔案中的<connector>標籤中添加設定即可:
由於是在Tomcat中修改server.xml檔案,所以伺服器需要重啟。
經過這種方式,就無需在代碼中再設定任何編碼錶,所有在伺服器端都會採用“URIEncoding”屬性設定的碼錶。但這個方式不建議使用。
同樣在“Configuration”的配置文檔中的“Connector”下的“HTTP”說明文檔中,有useBodyEncodingForURI這麼個屬性:
當在server.xml檔案中的<connector>標籤中添加設定了這個屬性,還未完成:
還必須在Servlet中同時調用了響應對象的setCharacterEncoding方法,就能再次使GET方式不會出現亂碼:
1 request.setCharacterEncoding("utf-8");2 String username = request.getParameter("user");
同樣,這種配置server.xml檔案的方式依然不建議採用。
最後說明一點,在HTML編程中,我們也可以使用超連結來提交資料,當然這樣的方式屬於HTTP中的GET方式,原理類似於在瀏覽器地址URL後手動添加參數,比如如下代碼:
1 <a href="/myservlet/servlet/ServletRequest?user=銀魂" >使用者名稱為中文</a>
跟隨的參數為中文!!
兩種解決方式:
1,在這個超連結上必須將這個中文進行URL編碼,必須在JSP中進行編寫(在後面的篇章中會介紹如何使用);
2,或者使用上述GET處理中文亂碼的第一種方式,進行雙次編碼:
1 String userTemp = request.getParameter("user");2 String username = new String(userTemp.getBytes("ISO8859-1"),"utf-8");
也是可以的。
Servlet的學習(十一)