HttpServletRequest

1、HttpServletRequest

web客戶端發送給web服務器的HTTP請求消息能夠分爲三個部分:請求行、請求消息頭、消息正文(也叫實體內容)。Servlet程序經過調用ServletRequest對象的方法能夠獲知客戶端的請求信息,以及客戶機和服務器的網絡環境信息,例如獲取客戶發送的請求消息的各個部分和客戶端IP地址。HttpServletRequest是專用於HTTP協議的ServletRequest子接口,它用於封裝HTTP請求消息,增長了獲取HTTP協議專有的頭信息的方法,以及獲取HTTP請求消息參數的功能。html

2、請求消息

一、獲取請求行的相關信息

HTTP請求消息的請求行能夠分爲三個部分:請求方式、資源路徑和HTTP協議版本,如:java

GET    /project/servlet/RequestURI?parm1=a&parm2=b    HTTP/1.1web

RequestLineServlet.java數組

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestLineServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=GB2312"); 
        PrintWriter out = response.getWriter();
        
        out.println("getMethod:" + request.getMethod() + "<br>");
        // 返回位於主機和端口以後、參數部分以前的那部份內容
        out.println("getRequestURI:" + request.getRequestURI() + "<br>");
        // 返回參數部分,無參數返回null
        out.println("getQueryString:" + request.getQueryString() + "<br>");
        // 返回協議名和版本號
        out.println("getProtocol:" + request.getProtocol() + "<br>");
        // 返回Web應用程序的路徑(虛擬目錄),這個路徑以「/」開頭
        out.println("getContextPath:" + request.getContextPath() + "<br>");
        // 返回servlet映射的路徑(web.xml的url-pattern屬性)
        out.println("getServletPath:" + request.getServletPath() + "<br>");
    }
}

 

注:URL和URI的區別,可看http://www.cnblogs.com/gaojing/archive/2012/02/04/2413626.html瀏覽器

二、獲取請求頭的信息

ServletRequest和HttpServletRequest接口中定義了若干用於讀取HTTP請求消息中的頭字段的方法,其中的getHeader方法是一個通用的方法,能夠讀取全部的頭字段。服務器

(1)、獲取全部請求頭信息網絡

RequestHeadersServlet.javaapp

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestHeadersServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=GB2312");
        PrintWriter out = response.getWriter();
        
        Enumeration<?> headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()) {
            String headerName = (String)headerNames.nextElement();
            // 同一個請求頭名可能出現屢次
            Enumeration<?> values = request.getHeaders(headerName);
            while(values.hasMoreElements()) {
                out.println(headerName + ":" + (String)values.nextElement() + "<br>");
            }
        }
    }
}

 

在瀏覽器輸入訪問地址:http://localhost:8888/requestHeadersServlet/servlet/RequestHeadersServletide

現增長一個html文件,從它連接到該Servlet,訪問referer.html:編碼

<a href="servlet/RequestHeadersServlet">referer test</a>

 

訪問referer.html:

點擊超連接,再次訪問RequestHeadersServlet

注意觀察:請求消息包含了referer請求頭。

(2)盜鏈

關於「盜鏈」:http://baike.baidu.com/link?url=UpFE0AJdwVL2ESHqD6aF1N28Zmwi47RwoKzs50NI2t1HKBR6paci_NFhbv78hW-x

爲了防止「盜鏈」,須要檢查請求的來路,只接受本站內的頁面連接進來的下載請求,而阻止其餘站點的頁面連接進來的下載請求。要實現這樣功能,就須要檢查請求消息的referer頭字段是否與本站匹配。

DownManagerServlet.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
    public class DownManagerServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=GB2312");
        String referer = request.getHeader("referer");
        String sitePart = "http://" + request.getServerName();
        PrintWriter out = response.getWriter();
        
        // 增長if判斷是爲了下載請求必須經過本站的下載頁面連接進來,也就是防止盜鏈
        if(referer != null && referer.startsWith(sitePart)) {
            // 處理正當的下載請求,這裏只是示意
            out.println("dealing download ...");
        } else {
            // 非法下載請求(即referer爲空或不匹配sitePart)跳轉到本站的下載說明頁
            response.sendRedirect("../down.html");
        }
    }
}

 

down.html

<a href="servlet/DownManagerServlet">down</a>

 

在瀏覽器輸入訪問地址:localhost:8888/downManagerServlet/servlet/DownManagerServlet

由於請求消息不含referer請求頭,即DownManagerServlet代碼中的referer爲空,跳轉到down.html

點擊超連接,再次訪問DownManagerServlet,因爲這時的請求消息包含有referer請求且值與DownManagerServlet位於同一Web站點,DownManagerServlet接受下載請求。

三、獲取請求消息的實體內容

以POST方式提交HTML的FORM表單時,其中的表單字段元素信息都將做爲HTTP消息的實體內容(消息正文)發送給Web服務器。對應HTTP請求消息的中的實體內容,ServletRequest以輸入流的方式提供給Servlet程序讀取,ServletRequest接口中定義了一個getInputStream方法來返回這個字節輸入流對象。爲了方便讀取純文本形式的實體內容,ServletRequest接口也定義了一個getReader方法,以返回一個表明實體內容的字符輸入流對象。

getInputStream與getReader方法

  • getInputStream返回輸入流對象類型爲ServletInputStream,若是實體內容中包含二進制數據,那麼只能使用getInputStream方法返回的輸入流對象來讀取實體內容。

  • getReader則返回一個BufferedReader對象。

  • 調用了二者任意一個方法後,就不能再調用另外一方法。

3、獲取請求參數

HttpServletRequest對象的最基本和最普遍應用就是獲取瀏覽器傳遞給Web服務器的參數信息,這些參數信息既能夠是HTTP請求消息的請求行中的URL地址後的附加信息,又能夠是Post方式下application/x-www-form-urlencoded編碼格式的實體內容。那麼,如何獲取這兩種參數?

ServletRequest和HttpServletRequest接口中定義了若干方法,這些方法除了能讀取HTTP請求消息的請求行的URL地址後的附件信息外,還能讀取Post方式下的application/x-www-form-urlencoded編碼格式的實體內容。

  • getParameter方法:若是請求消息中沒有包含指定名稱的參數,該方法返回null,即getParameter("firstname"),不存在這個參數返回null;若是指定名稱的參數存在但沒有設置值,返回一個空串;若是包含多個指定名稱相同的參數,返回第一個出現的參數值。另外,該方法對參數名大小寫敏感。

  • getParameterValues方法:該方法用於獲取某個指定名稱的全部參數的值,並以一個String數組的形式返回這些參數值。若是參數值只有一個,返回的數組的長度就爲1,其中包含的元素值與getParameter方法返回的值同樣。

  • getParameterNames方法:返回一個包含請求消息中全部參數名的Enumeration對象。

  • getParameterMap方法:返回一個將請求消息中全部參數名和值裝進Map的Map對象

問:何爲隱藏表單字段?

答:在form表單中可使用隱藏表單字段元素向服務器傳遞參數信息,瀏覽器在網頁上不會顯示出隱藏表單字段元素,但當提交表單時,瀏覽器會將這個隱藏表單字段元素的name屬性和value屬性做爲參數傳遞給web服務器。

4、利用請求域屬性傳遞消息

ServletRequest接口的實現類一般都是採用一個HashMap對象來存儲某些對象,setAttribute方法就是向這個HashMap對象中增長與某個名稱綁定的對象,getAttribute方法則是根據名稱從這個HashMap對象中檢索對象。這種存儲在ServletRequest對象中的對象稱之爲請求域屬性。

  • setAttribute(String name, Object o),若是ServletRequest對象中已經存在指定名稱的屬性,若屬性值對象爲null則至關於removeAttribute,不然即覆蓋原來對象。

  • getAttribute(String name),返回指定名稱的屬性對象。

  • removeAttribute(String name),刪除指定名稱的屬性對象。

  • getAttributeNames(),返回一個包含ServletRequest對象中全部屬性名的Enumeration對象。

相關文章
相關標籤/搜索