Servlet——HttpServletRequest對象詳解
HttpServletRequest對象代表客戶端的請求,當客戶端通過HTTP協議訪問服務器時,HTTP請求頭中的所有信息都封裝在這個對象中,開發人員通過這個對象的方法,可以獲得客戶的這些信息。
======================================================================================
HttpServletRequest常用方法
getRequestURL方法返回客戶端發出請求時的完整URL getRequestURI方法返回請求行中的資源名部分 getQueryString方法返回請求行中的參數部分(參數名+值) getRemoteAddr方法返回發出請求的客戶機的IP地址 getRemoteHost方法返回發出請求的客戶機的完整主機名 getRemotePort方法返回web服務器所使用的網絡端口號 getLocalPort方法返回web服務器所使用的網絡端口號 getLocalAddr方法返回web服務器的IP地址 getLocalName方法返回web服務器的主機名在Servlet中作如下測試:
// 得到URL String url = request.getRequestURL().toString(); System.out.println("URL:"+url); out.println("URL:"+url+"<br>"); // 得到URI String uri = request.getRequestURI(); System.out.println("URI:"+uri); out.println("URI:"+uri+"<br>"); // 得到參數字符串 String query_string = request.getQueryString(); System.out.println("QueryString:"+query_string); out.println("QueryString:"+query_string+"<br>"); // 得到請求方的IP地址 // 可以以此來封殺某些IP String remote_addr = request.getRemoteAddr(); System.out.println("RemoteAddr:"+remote_addr); out.println("RemoteAddr:"+remote_addr+"<br>"); // 得到請求方的完整主機名 String remote_host = request.getRemoteHost(); System.out.println("RemoteHost:"+remote_host); out.println("RemoteHost:"+remote_host+"<br>"); //得到請求方的網絡端口號 int remote_port = request.getRemotePort(); System.out.println("RemotePort:"+remote_port); out.println("RemotePort:"+remote_port+"<br>"); //得到服務器本機使用的網絡端口號 int local_port = request.getLocalPort(); System.out.println("LocalPort:"+local_port); out.println("LocalPort:"+local_port+"<br>"); //得到服務器本機的IP地址 String local_addr = request.getLocalAddr(); System.out.println("LocalAddr:"+local_addr); out.println("LocalAddr:"+local_addr+"<br>"); // 得到服務器本機的主機名 String local_name = request.getLocalName(); System.out.println("LocalName:"+local_name); out.println("LocalName:"+local_name+"<br>");
瀏覽器運行結果:
======================================================================================
HttpServletRequest的常見應用
----------------------------------------------------------------------------------------------------------------------------------------------------
1.獲取客戶機請求頭
getHeader方法獲取某一個header的內容 getHeaders方法(如果頭名字相同,返回Enumeration,用得比較少) getHeaderNames方法獲取所有的http消息頭
測試:
//getHeader 通過消息頭,來獲取信息 // 比如要獲取http請求的Host String host = request.getHeader("Host"); System.out.println("Host:"+host); System.out.println("-----------------"); //getHeaderNames方法獲取所有的消息頭 // 需求:請把整個http請求的消息全部獲取 Enumeration<String> headers= request.getHeaderNames(); while(headers.hasMoreElements()){ // 取出消息頭的名字 String headername = headers.nextElement(); System.out.println(headername+":"+ request.getHeader(headername)); }
服務器輸出結果:
Host:localhost:8080 ----------------- host:localhost:8080 connection:keep-alive cache-control:max-age=0 accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 upgrade-insecure-requests:1 user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36 accept-encoding:gzip, deflate, sdch accept-language:zh-CN,zh;q=0.8
---------------------------------------------------------------------------------------------------------------------------------------------------- 2.獲取客戶機請求參數
getParameter方法 getParameterValues(String name) getParameterNames()方法
在這里,getParameter方法返回一個只有一個值的參數,getParameterValues方法返回一個可以有多個值的參數,比如用於獲取復選框的選項。
案例:獲取用戶通過表單提交的內容。 界面部分:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>Form</TITLE></HEAD>"); out.println(" <BODY>"); out.println(" <form action='RegisterCL' method='post'>"); out.println(" 用戶名:<input type='text' name='username'/><br><br>"); out.println(" 密 碼:<input type='password' name='pwd'/><br><br>"); out.println(" 性 別:<input type='radio' name='sex' value='男'/>男<input type='radio' name='sex' value='女'/>女<br><br>"); out.println(" 愛 好:<input type='checkbox' name='hobby' value='音樂'/>音樂<input type='checkbox' name='hobby' value='籃球'/>籃球<input type='checkbox' name='hobby' value='電影'/>電影<br><br>"); out.println(" 所在城市:<select name='city'><option value='北京'>北京</option><option value='重慶'>重慶</option></select><br><br>"); out.println(" 你的介紹:<textarea cols='20' rows='10' name='intro'>請輸入介紹...</textarea><br><br>"); out.println(" 提交照片:<input type='file' name='photo'/><br><br>"); // hidden表單 // 什么時候使用hidden傳數據:1.不希望用戶看到該數據 2.不希望影響界面,同時業務邏輯又要使用該數據 out.println(" <input type='hidden' value='abc' name='hidden1'/>"); out.println(" <input type='submit' value='提交'/>"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
接收信息的Servlet代碼:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String u = request.getParameter("username"); String p = request.getParameter("pwd"); String sex = request.getParameter("sex"); // 如果接收復選框的內容,則應該使用getParameterValues // 如果復選框一個都沒有選擇,則會返回null,所以下面要進行判斷 String hobbies[] = request.getParameterValues("hobby"); String city = request.getParameter("city"); String intro = request.getParameter("intro"); String hidden1 = request.getParameter("hidden1"); out.println("用戶名:"+u+"<br>"); out.println("密 碼:"+p+"<br>"); out.println("性 別:"+sex+"<br>"); if(hobbies == null){ out.println("你沒有愛好<br>"); }else{ out.println("你的愛好有:<br>"); out.println("<ul>"); for(int i=0;i<hobbies.length;i++){ out.println("<li>"+hobbies[i]+"</li>"); } out.println("</ul>"); } out.println("所在城市:"+city+"<br>"); out.println("個人介紹:"+intro+"<br>"); out.println("隱藏控件傳遞的數據是:"+hidden1+"<br>"); }
運行結果:
提交之后:
---------------------------------------------------------------------------------------------------------------------------------------------------- 3.實現請求轉發
請求轉發指一個web資源收到客戶端請求后,通知服務器去調用另外一個web資源進行處理。 請求轉發一定要和HttpServletResponse.sendRedirect所表示的請求重定向區別開來!
一個web資源收到客戶端請求后,通知服務器去調用另外一個web資源進行處理,稱之為請求轉發 一個web資源收到客戶端請求后,通知瀏覽器去訪問另外一個web資源,稱之為請求重定向。 |
HttpServletRequest對象提供了一個getRequestDispatcher方法,該方法返回一個RequestDispatcher對象,調用這個對象的forword方法可以實現請求轉發。
那么什么叫做請求轉發呢?假如我們此時要通過request請求轉發的方式將數據帶到下一個頁面該怎么做?看下面一個案例:
假如我們的項目有三個Servlet,分別是Login、Servlet1和Servlet2,Servlet1接收Login表單post過來的數據,然后請求轉發到Servlet2進行處理。
Login的代碼:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //返回一個界面 out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>LoginServlet</TITLE></HEAD>"); out.println(" <BODY>"); out.println("<h1>用戶登錄</h1>"); //action 應該這樣寫 /web應用名稱/Servlet的url out.println("<form action='/requestForward/Servlet1' method='post'>"); out.println("用戶名:<input type='text' name='username'/><br><br>"); out.println("密 碼:<input type='password' name='password'><br><br>"); out.println("<input type='submit' value='登錄'><br>"); out.println("</form>"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
Servlet1的代碼:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); request.setCharacterEncoding("utf-8"); // 接收用戶名 String u = request.getParameter("username"); // 把u放入request域對象 request.setAttribute("username", u); // 表示使用轉發的方法把request和response對象傳遞給下一個Servlet // 這里不用帶web應用名稱 request.getRequestDispatcher("/Servlet2").forward( request, response); }
Servlet2的代碼:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String u = request.getAttribute("username").toString(); out.println("接收到的用戶名是:"+u); }
可以看到,Servlet1接收Login傳遞過來的數據,然后將數據放入了request域對象,然后將request對象和response對象使用轉發的方法傳遞給了Servlet2,也就是說,Servlet2中的request對象和response對象其實就是Servlet1中的。
可以通過下述時序圖了解這個交互過程:
從時序圖中可以看到,瀏覽器只發出了一次請求,接收到了一次結果。而從Servlet1到Servlet2的轉發過程只是發生在服務器內部的,瀏覽器並不知道。所以說,瀏覽器的地址欄此時應該停留在http://localhost:8080/RequestTest/Servlet1,其實不管服務器內部轉發多少次,瀏覽器都不會知道,它的地址欄也就不會發生變化,這一切都是發生在服務器內部的。
而sendRedirect請求重定向與此不同,請求重定向是服務器告訴瀏覽器接下來應該訪問的WEB資源,瀏覽器收到這個通知之后會去請求這個資源,這是發生在瀏覽器的兩次不同的請求,所以地址欄也會發生變化。
這里要注意的是:
1、使用forward不能轉發到該web應用之外的url。 2、因為forward是發生在web服務器的,不是瀏覽器,所以Servlet1和Servlet2使用的是同一個request和response對象。 3、使用sendRedirect()方法不能夠通過request.setAttribute()方法把屬性傳遞給下一個Servlet。很顯然,這是兩次不同的請求,request對象都不一樣,怎么可能通過request傳遞數據。
----------------------------------------------------------------------------------------------------------------------------------------------------
下面總結一下請求重定向(sendRedirect)和請求轉發的區別: 【1】RequestDispatcher.forward方法只能將請求轉發給同一個WEB應用中的組件;而HttpServletResponse.sendRedirect方法還可以重定向到同一個站點上的其他應用程序中的資源,甚至是使用絕對URL重定向到其他站點的資源。 【2】如果傳遞給HttpServletResponse.sendRedirect方法的相對URL以”/”開頭,它是相對於整個WEB站點的根目錄;如果創建RequestDispatcher對象時指定的相對URL以”/”開頭,它是相對於當前WEB應用程序的根目錄。 【3】調用HttpServletResponse.sendRedirect方法重定向的訪問過程結束后,瀏覽器地址欄中顯示的URL會發生變化,由初始的URL地址變成重定向的目標URL;調用RequestDispatcher.forward方法的請求轉發過程結束后,瀏覽器地址欄保持初始的URL地址不變。 【4】HttpServletResponse.sendRedirect方法對瀏覽器的請求直接作出響應,響應的結果就是告訴瀏覽器去重新發出對另外一個URL的訪問請求;RequestDispatcher.forward方法在服務器端內部將請求轉發給另外一個資源,瀏覽器只知道發出了請求並得到了響應結果,並不知道在服務器程序內部發生了轉發行為。 【5】RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬於同一個訪問請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和response對象,它們屬於兩個獨立的訪問請求和響應過程。