1. 程式人生 > 其它 >javaweb之request

javaweb之request

技術標籤:javawebhttpjavaservletweb

Request

一、說明

前面說了我們將專案釋出到Tomcat伺服器中去之後,外部可以通過網際網路來進行訪問我們的部署到服務中的資源。

訪問方式

http://ip地址:埠號/專案路徑/資源路徑

同時說了,還可以向伺服器中傳遞使用者傳遞的引數,然後伺服器接收到了引數之後,servlet可以用來進行處理。

那麼這章將詳細描述如何接收引數?如何進行處理?下一節講述如何去進行相應。

二、請求中的引數說明

當用戶傳送了請求之後,可以看到是通過HTTP的方式來進行請求訪問的,那麼通過抓包工具來獲取對應的請求

// 請求行
// 請求方式 專案名稱和請求路徑 什麼協議
POST /day16/req HTTP/1.1 // 請求頭:通過key-value的形式 // 傳送請求的主機IP地址 Host: localhost // 連線方式是短連線還是長連線 Connection: keep-alive // 請求的內容長度 Content-Length: 25 Cache-Control: max-age=0 // 請求是從哪裡傳送過來的 Origin: http://localhost Upgrade-Insecure-Requests: 1 // 請求的內容型別 Content-Type: application/x-www-form-urlencoded // 請求的瀏覽器型別,具體的版本和本機的系統型別
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36 // 本機中的瀏覽器可以接受的響應的響應格式:xml、text、image等等 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Referer: http://localhost/day16/index.jsp // 可以接受的壓縮格式 Accept-Encoding: gzip, deflate, br // 瀏覽器可以接受的語言型別 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,cs;q=0.7 // 當前瀏覽器訪問要請求的網址攜帶過去的cookie資料 Cookie: JSESSIONID=844ABB8A9F63FA147D8194E47C4BB1AF // 請求體 // post方式的請求引數。get方式的請求引數是直接在請求行中 username=tom&password=tom

三、Request簡介

request代表的是請求的物件,Tomcat伺服器利用request來封裝來自使用者的請求資料,包括上面所有的資料。

request是HttpServletRequest的例項物件。

面試題:

當用戶在瀏覽器端輸入了對應的URL之後,接下來會發生什麼?

http://localhost:8080/servletOne/index.html

第一步:

Tomcat伺服器會將上面的內容進行解析:
    專案名稱:/servletOne
    資源路徑:index.html(靜態資源)

第二步:

Tomcat去首先找到這個專案名稱進行對映到對應的專案名稱

第三步:

去資源路徑下尋找有沒有這個靜態資源index.html檔案,如果匹配了就可以利用response物件來進行展示了

注意:Tomcat伺服器在針對於一次請求的時候,會直接建立request物件和response物件

request物件可能不止一個,但是response物件只有一個。因為前面提到了一次請求必定會存在著一次響應,多次請求必然也存在著多次響應。
哪怕響應的內容是錯誤的,但是也是響應。

3.1、利用request來獲取請求行中的資料

方法說明引數返回值
getMethod()獲取請求方式String
getContextPath()獲取專案路徑String

java程式碼如下

@WebServlet(name = "Servlet2",urlPatterns = "/two")
public class TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取得到請求方式
        String method = request.getMethod();
        System.out.println(method);
        // 獲取得到請求的專案路徑
        String contextPath = request.getContextPath();
        System.out.println(contextPath);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
    }
}

在瀏覽器端輸入:

http://localhost:8080/servlet/two

檢視控制檯:

GET               -----------請求方式是get
/servlet		  -----------專案名稱

3.2、利用request來獲取請求體中的引數

方法說明引數返回值
getParameter(name)獲取一個表單項的值name:表單項名稱String
getParameterValues(name)獲取一個表單項的值String[]
getParameterMap()獲取所有表單項的值Map<String,String[]>

1、既然是請求體,那麼需要來根據表單來進行提交;

2、根據返回值的型別可以看到獲取單個引數、多個引數的值;

3、從瀏覽器中傳送到Tomcat伺服器中的資料首先都是經過二進位制流的,所以在對二進位制流解析的時候也是需要進行注意的。

國內的瀏覽器中是支援utf-8的,但是在進行解析二進位制流之後,在伺服器端進行解析的時候,伺服器根據不同的請求方式(get/post)來進行解析。在Tomcat8之後,對get解析是utf-8,對於post請求方式採用的是iso8859-1方式解析。所以如果說我們利用post方式來進行請求的時候,我們需要在程式碼中指定對瀏覽器中傳送過來的資料使用什麼樣的格式來解析二進位制流。

index.html頁面中的程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表單請求</title>
</head>
<body>
<form action="/servlet/three" method="post">
    使用者名稱:<input type="text" name="username"><br>
    愛好:
    <input type="checkbox" name="hobby" value="eat"><input type="checkbox" name="hobby" value="drink"><input type="checkbox" name="hobby" value="play"><br>
    <input type="submit" value="post提交">
</form>
</body>
</html>

對應的servlet程式碼如下:

@WebServlet(name = "Servlet3",urlPatterns = "/three")
public class ThreeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 設定針對於post方式的請求來說將二進位制流解析成utf-8的方式
            request.setCharacterEncoding("utf-8");
            // 獲取表單中的引數
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<String> parameterKeys = parameterMap.keySet();
        for (String parameterKey : parameterKeys) {
            String[] strings = parameterMap.get(parameterKey);
            System.out.print(parameterKey+"對應的value有:");
            for (String string : strings) {
                System.out.print(string+" ");
            }
            System.out.println();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
    }
}

在瀏覽器中訪問:

http://localhost:8080/servlet/index.html

在這裡插入圖片描述

填寫對應資料,去看下後端響應:

username對應的value有:李廣 
hobby對應的value有:eat drink play 

可以看到可以使用getParameterMap來進行接收之前,指定對應的二進位制流解析方式

3.3、request其它作用

  • 域物件:由Servlet規範提供的,能臨時儲存資料的物件;在其作用範圍裡,資料可以共享。

  • 所有域物件都可以儲存資料:

    • 存資料:setAttribute(String name, Object value)
    • 取資料:getAttribute(String name)
    • 刪資料:removeAttribute(String name)
  • 使用域物件進行資料共享的原則:在滿足要求的情況下,使用小的域物件

  • 不同域物件的區別是:作用範圍不同

    • ServletContxt:

      • 何時建立:伺服器啟動時
      • 何時銷燬:伺服器關閉時
      • 作用範圍:整個web專案

      但是這個是不常用的,因為在啟動之後,就開啟往裡面儲存資料,那麼最終匯入伺服器記憶體消耗過大,影響效率。

    • request:

      • 何時建立:一次請求開始
      • 何時銷燬:一次請求結束(開始響應時)
      • 作用範圍:一次請求中

四、請求轉發和重定向區別

參照下面的API來進行操作:

//請求轉發,是服務端跳轉
request.getRequestDispatcher("/資源路徑").forward(request, response);

//回顧:重定向,是瀏覽器跳轉
response.sendRedirect("/專案路徑/資源路徑");

在靜態頁面中向servlet傳送轉發,需要帶上專案路徑;

servlet向servlet之間傳送請求,不需要帶上路徑;

請求轉發:

1、位址列中不會發生變化;【最直觀的區別】
2、請求轉發是一次請求;
3、伺服器間發生變化;    

重定向:

1、位址列中會發生變化;【最直觀的區別】
2、重定向是兩次請求;
3、瀏覽器間發生請求;    

對於請求轉發和重定向之間如何進行選擇?

請求轉發是一次請求中,在伺服器之間轉發,可能會攜帶資料;
重定向之間是瀏覽器請求伺服器之後,然後伺服器響應了瀏覽器之後,瀏覽器向其他伺服器傳送請求。此時攜帶的資料沒有太大的意義;

例子如下:

------------------------------------------請求轉發-----------------------------------------------------------
@WebServlet(name = "Servlet4",urlPatterns = "/four")
public class FourServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 設定請求轉發
        request.getRequestDispatcher("/five").forward(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}



@WebServlet(name = "Servlet5",urlPatterns = "/five")
public class FiveServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("hello,world");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}
--------------------------------------------重定向-----------------------------------------------------------
@WebServlet(name = "Servlet6",urlPatterns = "/six")
public class SixServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 設定重定向
        response.sendRedirect("http://www.baidu.com");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

輸入以下路徑:

http://localhost:8080/servlet/four

會發現瀏覽器端不會發生變化

輸入以下路徑:

http://localhost:8080/servlet/six
回車之後,會發現跳轉到了
https://www.baidu.com/