HttpServletRequest**對象表明客戶端的請求,當客戶端經過HTTP協議訪問服務器時,**HTTP請求頭中的全部信息都封裝在這個對象中,開發人員經過這個對象的方法,能夠得到客戶這些信息。javascript
簡單來講,要獲得瀏覽器信息,就找HttpServletRequest對象css
什麼是防盜鏈呢?好比:我如今有海賊王最新的資源,想要看海賊王的要在個人網頁上看。如今別的網站的人看到我有海賊王的資源,想要把個人資源粘貼在他本身的網站上。這樣我獨家的資源就被一個CTRL+C和CTRL+V搶走了?而反盜鏈就是不能被他們CRTL+C和CRTL+Vhtml
這樣我就划不來啦【個人廣告你來沒看呢!】。想要看個人資源,就必須通過個人首頁點進去看。java
想要實現這樣的效果,就要獲取Referer這個消息頭,判斷Referer是否是從個人首頁來的。若是不是從個人首頁來的,跳轉回個人首頁。web
//獲取到網頁是從哪裏來的 String referer = request.getHeader("Referer"); //若是不是從個人首頁來或者從地址欄直接訪問的, if ( referer == null || !referer.contains("localhost:8080/zhongfucheng/index.jsp") ) { //回到首頁去 response.sendRedirect("/zhongfucheng/index.jsp"); return; } //能執行下面的語句,說明是從個人首頁點擊進來的,那沒問題,照常顯示 response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("路飛作了XXXXxxxxxxxxxxxxxxxx");
\瀏覽器
<form action="/zhongfucheng/Servlet111" method="post"> <table> <tr> <td>用戶名</td> <td><input type="text" name="username"></td> </tr> <tr> <td>密碼</td> <td><input type="password" name="password"></td> </tr> <tr> <td>性別</td> <td> <input type="radio" name="gender" value="男">男 <input type="radio" name="gender" value="女">女 </td> </tr> <tr> <td>愛好</td> <td> <input type="checkbox" name="hobbies" value="游泳">游泳 <input type="checkbox" name="hobbies" value="跑步">跑步 <input type="checkbox" name="hobbies" value="飛翔">飛翔 </td> </tr> <input type="hidden" name="aaa" value="my name is zhongfucheng"> <tr> <td>你的來自於哪裏</td> <td> <select name="address"> <option value="廣州">廣州</option> <option value="深圳">深圳</option> <option value="北京">北京</option> </select> </td> </tr> <tr> <td>詳細說明:</td> <td> <textarea cols="30" rows="2" name="textarea"></textarea> </td> </tr> <tr> <td><input type="submit" value="提交"></td> <td><input type="reset" value="重置"></td> </tr> </table>
//設置request字符編碼的格式 request.setCharacterEncoding("UTF-8"); //經過html的name屬性,獲取到值 String username = request.getParameter("username"); String password = request.getParameter("password"); String gender = request.getParameter("gender"); //複選框和下拉框有多個值,獲取到多個值 String[] hobbies = request.getParameterValues("hobbies"); String[] address = request.getParameterValues("address"); //獲取到文本域的值 String description = request.getParameter("textarea"); //獲得隱藏域的值 String hiddenValue = request.getParameter("aaa"); ....各類System.out.println().......
常見的get方式提交數據有:使用超連接,sendRedirect()服務器
格式以下:markdown
sendRedirect("servlet的地址?參數名="+參數值 &"參數名="+參數值);
<a href="/zhongfucheng/Servlet111?username=xxx">使用超連接將數據帶給瀏覽器</a>
//接收以username爲參數名帶過來的值 String username = request.getParameter("username"); System.out.println(username);
細心的朋友會發現,我在獲取表單數據的時候,有這句代碼request.setCharacterEncoding("UTF-8");
,若是沒有這句代碼,會發生什麼事呢?咱們看看。網絡
來這裏咱們來分析一下亂碼的緣由,在前面的博客中我已經介紹了,Tomcat服務器默認編碼是ISO 8859-1,而瀏覽器使用的是UTF-8編碼。瀏覽器的中文數據提交給服務器,Tomcat以ISO 8859-1編碼對中文編碼,當我在Servlet讀取數據的時候,拿到的固然是亂碼。而我設置request的編碼爲UTF-8,亂碼就解決了。app
接下來使用get方式傳遞中文數據,把表單的方式改爲get便可
當咱們訪問的時候,又出現亂碼了!
request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name");
結果仍是亂碼。這是爲何呢?我明明已經把編碼設置成UTF-8了,按照post方式,亂碼問題已經解決了!。咱們來看看get和post方式的區別在哪?爲何post方式設置了request編碼就能夠解決亂碼問題,而get方式不能呢。
首先咱們來看一下post方法是怎麼進行參數傳遞的。當咱們點擊提交按鈕的時候,數據封裝進了Form Data中,http中多了一個上傳請求頭,既然request對象封裝了http請求,因此request對象能夠解析到發送過來的數據,因而只要把編碼設置成UTF-8就能夠解決亂碼問題了。
//此時獲得的數據已是被ISO 8859-1編碼後的字符串了,這個是亂碼 String name = request.getParameter("username"); //亂碼經過反向查ISO 8859-1獲得原始的數據 byte[] bytes = name.getBytes("ISO8859-1"); //經過原始的數據,設置正確的碼錶,構建字符串 String value = new String(bytes, "UTF-8");
上面的代碼有些難理解,我畫張圖說明一下:
咱們都知道Tomcat默認的編碼是ISO 8859-1,若是在Tomcat服務器的配置下改爲是UTF-8的編碼,那麼就解決服務器在解析數據的時候形成亂碼問題了
在8080端口的Connector上加入URIEncoding="utf-8"
,設置Tomcat的訪問該端口時的編碼爲utf-8,從而解決亂碼,這種改法是固定使用UTF-8編碼的
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8"/>
、
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" useBodyEncodingForURI="true" />
request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name");
手寫超連接若是附帶中文參數問題,要URL重寫,在JSP博客中會講到
總結:
以前講過使用response的sendRedirect()能夠實現重定向,作到的功能是頁面跳轉,使用request的getRequestDispatcher.forward(request,response)實現轉發,作到的功能也是頁面跳轉,他們有什麼區別呢?如今我先來講下轉發
//獲取到requestDispatcher對象,跳轉到index.jsp RequestDispatcher requestDispatcher = request.getRequestDispatcher("/index.jsp"); //調用requestDispatcher對象的forward()實現轉發,傳入request和response方法 requestDispatcher.forward(request, response);
上面已經說了,能夠經過sendRedirect()重定向能夠在資源尾部添加參數提交數據給服務器。那麼轉發能不能提交數據給服務器呢?
答案明顯是能夠的,而且使用這種方法很是頻繁
//以username爲關鍵字存zhongfucheng值 request.setAttribute("username", "zhongfucheng"); //獲取到requestDispatcher對象 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Servlet222"); //調用requestDispatcher對象的forward()實現轉發,傳入request和response方法 requestDispatcher.forward(request, response);
//獲取到存進request對象的值 String userName = (String) request.getAttribute("username"); //在瀏覽器輸出該值 response.getWriter().write("i am :"+userName);
如上圖所示,Servlet222成功拿到了request對象在Servlet111存進的數據。
如今問題又來了,咱們能夠使用ServletContext和request實現Servlet之間的通信,那麼咱們用哪種呢?通常的原則:可使用request就儘量使用request。由於ServletContext表明着整個web應用,使用ServletContext會消耗大量的資源,而request對象會隨着請求的結束而結束,資源會被回收。使用request域進行Servlet之間的通信在開發中是很是頻繁的。
若是在調用forward方法以前,在Servlet程序中寫入的部份內容已經被真正地傳送到了客戶端,forward方法將拋出IllegalStateException異常。 也就是說:不要在轉發以前寫數據給瀏覽器
咱們來試試是否是真的會出現異常。
OutputStream outputStream = response.getOutputStream(); outputStream.write("--------------------------------------------".getBytes()); //關閉流,確保讓數據到瀏覽器中 outputStream.close(); //跳轉 request.getRequestDispatcher("/Foot").forward(request, response);
不少人都搞不清楚轉發和重定向的時候,資源地址究竟怎麼寫。有的時候要把應用名寫上,有的時候不用把應用名寫上。很容易把人搞暈。記住一個原則:給服務器用的直接從資源名開始寫,給瀏覽器用的要把應用名寫上
根據上面說明了轉發和重定向的區別也能夠很容易歸納出來。轉發是帶着轉發前的請求的參數的。重定向是新的請求。
典型的應用場景:
RequestDispatcher對象調用forward()能夠實現轉發上面已經說過了。RequestDispatcher還有另一個方法include(),該方法能夠實現包含,有什麼用呢?
咱們在寫網頁的時候,通常網頁的頭部和尾部是不須要改變的。若是咱們多個地方使用Servlet輸出網頭和網尾的話,須要把代碼從新寫一遍。而使用RequestDispatcher的include()方法就能夠實現包含網頭和網尾的效果了。
request.getRequestDispatcher("/Head").include(request, response); response.getWriter().write("--------------------------------------------"); request.getRequestDispatcher("/Foot").include(request, response);