日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

一篇学会HttpServletRequest

發布時間:2023/11/28 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一篇学会HttpServletRequest 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

JavaWeb系列教程
JavaWeb—Servlet
模擬Servlet本質
使用IDEA開發Servlet程序
Servlet對象的生命周期
適配器(GenericServlet)改造Servlet
ServletConfig
Servlet–ServletContext
HTTP協議,get和post的區別
web站點歡迎頁
一篇學會HttpServletRequest
如果大家覺得有幫助的話,不妨動動小手,點贊收藏一波,也方便后面的復習哈


在學習一個東西之前,我們首先應該了解它是什么,接下來讓我們來認識一下它吧。

初識HttpServletRequest

  1. HttpServletRequest是一個接口,全限定名稱:jakarta.servlet.http.HttpServletRequest

  2. HttpServletRequest接口是Servlet規范中的一員。

  3. HttpServletRequest接口的父接口:ServletRequest

public interface HttpServletRequest extends ServletRequest {}

實現類

  1. HttpServletRequest接口的實現類誰寫的? HttpServletRequest對象是誰給創建的?

  2. 通過測試: org.apache.catalina.connector.RequestFacade 實現了 HttpServletRequest接口

      public class RequestFacade implements HttpServletRequest {}
    

    測試結果說明:Tomcat服務器(WEB服務器、WEB容器)實現了HttpServletRequest接口,還是說明了Tomcat服務器實現了Servlet規范。而對于我們javaweb程序員來說,實際上不需要關心這個,我們只需要面向接口編程即可。我們關心的是HttpServletRequest接口中有哪些方法,這些方法可以完成什么功能!!!!

封裝的信息

  • HttpServletRequest對象中都有什么信息?都包裝了什么信息?

    • HttpServletRequest對象是Tomcat服務器負責創建的。這個對象中封裝了什么信息? 封裝了HTTP的請求協議。
    • 實際上是用戶發送請求的時候,遵循了HTTP協議,發送的是HTTP的請求協議,Tomcat服務器將HTTP協議中的信息以及數據全部解析出來,然后Tomcat服務器把這些信息封裝到HttpServletRequest對象當中,傳給了我們javaweb程序員。
    • javaweb程序員面向HttpServletRequest接口編程,調用方法就可以獲取到請求的信息了。
  • request和response對象的生命周期?

    • request對象和response對象,一個是請求對象,一個是響應對象。這兩個對象只在當前請求中有效。
    • 一次請求對應一個request。
    • 兩次請求則對應兩個request。

HttpServletRequest接口中常用的方法

  • 怎么獲取前端瀏覽器用戶提交的數據?

      Map<String,String[]> getParameterMap() 這個是獲取MapEnumeration<String> getParameterNames() 這個是獲取Map集合中所有的keyString[] getParameterValues(String name) 根據key獲取Map集合的valueString getParameter(String name)  獲取value這個一維數組當中的第一個元素。這個方法最常用。以上的4個方法,和獲取用戶提交的數據有關系。
    

    下面是方法的測試


 Enumeration<String> parameterNames = request.getParameterNames();while (parameterNames.hasMoreElements()){String s = parameterNames.nextElement();writer.print(s+"<br>");}

   //獲取所有nameEnumeration<String> parameterNames = request.getParameterNames();while (parameterNames.hasMoreElements()){String s = parameterNames.nextElement();//通過name,獲取valueString[] parameterValues = request.getParameterValues(s);for (int i = 0; i < parameterValues.length; i++) {writer.print(s+"--->"+parameterValues[i]+"<br>");}}


思考:

為了幫助大家理解并且更好的記憶上面的方法,我們來思考一下,如果是我們自己,當前端form表單提交了數據以后,我們打算怎么存儲數據

前端提交的數據格式:username=abc&userpwd=111&aihao=s&aihao=d&aihao=tt

我會采用Map集合來存儲:

Map<String,String>key存儲Stringvalue存儲String這種想法對嗎?不對。如果采用以上的數據結構存儲會發現key重復的時候value覆蓋。key         value---------------------username    abcuserpwd     111aihao       saihao       daihao       tt這樣是不行的,因為map的key不能重復。
Map<String, String[]>key存儲Stringvalue存儲String[]key				value-------------------------------username		{"abc"}userpwd			{"111"}aihao			{"s","d","tt"}

注意:前端表單提交數據的時候,假設提交了120這樣的“數字”,其實是以字符串"120"的方式提交的, 所以服務器端獲取到的一定是一個字符串的"120",而不是一個數字。(前端永遠提交的是字符串,后端獲取的也永遠是字符串。)

請求域對象

request對象實際上又稱為“請求域”對象。
我們可以把請求域對象和應用域對象對比學習

我在之前的博客已經說過相關內容了,大家可能忘記了

先來復習一下之前講過的應用域對象

應用域對象

  • 應用域對象是什么?

    • ServletContext (Servlet上下文對象。)

    • 什么情況下會考慮向ServletContext這個應用域當中綁定數據呢?

      • 第一:所有用戶共享的數據。—假設現在有一張數據庫表,我們把查詢好的數據放在ServletContext中,那么以后如果我們還想要獲得這些數據,就直接從ServletContext當中去取出來,而不需要每次都去連接數據庫,去和數據庫交互,和數據庫的交互,需要使用IO流,大量的IO流,效率很低,IO讀的是硬盤,硬盤上有磁針,它再快也是機械型的行為,通常我們優化系統的時候使用緩存機制
      • 第二:這個共享的數據量很小。—ServletContext是應用域,服務器啟動的時候創建,服務器關閉的時候銷毀,它會一直占用內存
      • 第三:這個共享的數據很少的修改操作。—如果經常修改,會有線程安全問題,為了避免這樣的問題出現,就會使用鎖機制,這樣就導致效率降低
      • 在以上三個條件都滿足的情況下,使用這個應用域對象,可以大大提高我們程序執行效率。
      • 實際上向應用域當中綁定數據,就相當于把數據放到了緩存(Cache)當中,然后用戶訪問的時候直接從緩存中取,減少IO的操作,大大提升系統的性能,所以緩存技術是提高系統性能的重要手段。

你見過哪些緩存技術呢?

  • 字符串常量池
  • 整數型常量池 [-128~127],但凡是在這個范圍當中的Integer對象不再創建新對象,直接從這個整數型常量池中獲取。大大提升系統性能。
    - 數據庫連接池(提前創建好N個連接對象,將連接對象放到集合當中,使用連接對象的時候,直接從緩存中拿。省去了連接對象的創建過程。效率提升。)
    - 線程池(Tomcat服務器就是支持多線程的。所謂的線程池就是提前先創建好N個線程對象,將線程對象存儲到集合中,然后用戶請求過來之后,直接從線程池中獲取線程對象,直接拿來用。提升系統性能)
    - 后期你還會學習更多的緩存技術,例如:redis、mongoDB…
  • ServletContext當中有三個操作域的方法:
         void setAttribute(String name, Object obj); // 向域當中綁定數據。Object getAttribute(String name); // 從域當中根據name獲取數據。void removeAttribute(String name); // 將域當中綁定的數據移除// 以上的操作類似于Map集合的操作。Map<String, Object> map;map.put("name", obj); // 向map集合中放key和valueObject obj = map.get("name"); // 通過map集合的key獲取valuemap.remove("name"); // 通過Map集合的key刪除key和value這個鍵值對。

請求域”對象

請求域”對象要比“應用域”對象范圍小很多。生命周期短很多。請求域只在一次請求內有效。

一個請求對象request對應一個請求域對象。一次請求結束之后,這個請求域就銷毀了。

執行原理

請求域對象方法:

  void setAttribute(String name, Object obj); // 向域當中綁定數據。Object getAttribute(String name); // 從域當中根據name獲取數據。void removeAttribute(String name); // 將域當中綁定的數據移除

請求域和應用域的選用原則

盡量選擇使用小的域對象,這樣占用的資源比較少

轉發

  第一步:獲取請求轉發器對象
RequestDispatcher dispatcher = request.getRequestDispatcher("/b");第二步:調用轉發器的forward方法完成跳轉/轉發
dispatcher.forward(request,response);轉發是一次請求第一步和第二步代碼可以聯合在一起。
request.getRequestDispatcher("/b").forward(request,response);

兩個Servlet共享數據

  1. 將數據放到ServletContext應用域當中,當然是可以的,但是應用域范圍太大,占用資源太多。不建議使用。

  2. 可以將數據放到request域當中,然后AServlet轉發到BServlet,保證AServlet和BServlet在同一次請求當中,這樣就可以做到兩個Servlet,或者多個Servlet共享同一份數據。

  3. 只要是服務器的合法資源都可以轉發,可以是html,servlet等

  4. 注意:轉發的時候,路徑的寫法要注意,轉發的路徑以“/”開始,不加項目名。

容易混淆的方法

uri?username=zhangsan&userpwd=123&sex=1
String username = request.getParameter(“username”);

之前一定是執行過:request.setAttribute(“name”, new Object())
Object obj = request.getAttribute(“name”);

以上兩個方法的區別是什么
第一個方法:獲取的是用戶在瀏覽器上提交的數據.
第二個方法:獲取的是請求域當中綁定的數據。

其他方法和亂碼問題

其他方法

  1. 獲取客戶端的IP地址
    String remoteAddr = request.getRemoteAddr();

  2. 獲取應用的根路徑
    String contextPath = request.getContextPath();

  3. 獲取請求方式
    String method = request.getMethod();

  4. 獲取請求的URI
    String uri = request.getRequestURI(); // /aaa/testRequest

  5. 獲取servlet path
    String servletPath = request.getServletPath(); // /testRequest

亂碼問題

有時候,我們程序寫好以后,滿心歡喜,開啟服務器,期待在瀏覽器上的運行結果,結果卻出現了亂碼問題,那我們怎么解決呢

get請求在請求行上提交數據。
post請求在請求體中提交數據。

設置請求體的字符集。(顯然這個方法是處理POST請求的亂碼問題。這種方式并不能解決get請求的亂碼問題。)
Tomcat10之后,request請求體當中的字符集默認就是UTF-8,不需要設置字符集,不會出現亂碼問題。
Tomcat9前(包括9在內),如果前端請求體提交的是中文,后端獲取之后出現亂碼,怎么解決這個亂碼?執行以下代碼。
request.setCharacterEncoding(“UTF-8”);

在Tomcat9之前(包括9),響應中文也是有亂碼的,怎么解決這個響應的亂碼?
response.setContentType(“text/html;charset=UTF-8”);
在Tomcat10之后,包括10在內,響應中文的時候就不在出現亂碼問題了。以上代碼就不需要設置UTF-8了。

注意一個細節
在Tomcat10包括10在內之后的版本,中文將不再出現亂碼。(這也體現了中文地位的提升。)

get請求亂碼問題怎么解決?
get請求發送的時候,數據是在請求行上提交的,不是在請求體當中提交的。
get請求亂碼怎么解決
方案:修改CATALINA_HOME/conf/server.xml配置文件

注意:從Tomcat8之后,URIEncoding的默認值就是UTF-8,所以GET請求也沒有亂碼問題了。

轉發和重定向(重要)

在代碼上的區別

轉發

獲取請求轉發器對象

RequestDispatcherdispatcher=request.getRequestDispatcher("/dept/list")

調用請求轉發器對象的forward方法完成轉發

dispatcher.forward(request, response);

合并一行代碼

request.getRequestDispatcher("/dept/list").forward(request,
response);
轉發的時候是一次請求,不管你轉發了多少次。都是一次請求。
AServlet轉發到BServlet,再轉發到CServlet,再轉發到DServlet,不管轉發了多少次,都在同一個request當中。
這是因為調用forward方法的時候,會將當前的request和response對象傳遞給下一個Servlet。


重定向

注意:路徑上要加一個項目名。為什么?
瀏覽器發送請求,請求路徑上是需要添加項目名的。
以下這一行代碼會將請求路徑“/oa/dept/list”發送給瀏覽器
瀏覽器會自發的向服務器發送一次全新的請求:/oa/dept/list
response.sendRedirect("/oa/dept/list");

形式上的區別

轉發(一次請求)

在瀏覽器地址欄上發送的請求是:http://localhost:8080/servlet10/a ,最終請求結束之后,瀏覽器地址欄上的地址還是這個。沒變。

重定向(兩次請求)

  • 在瀏覽器地址欄上發送的請求是:http://localhost:8080/servlet10/a ,最終在瀏覽器地址欄上顯示的地址是:http://localhost:8080/servlet10/b
  • 在瀏覽器輸入:localhost:8080/servlet09/a結果直接跳轉到b

本質區別

  • 轉發:是由WEB服務器來控制的。A資源跳轉到B資源,這個跳轉動作是Tomcat服務器內部完成的。

  • 重定向:是瀏覽器完成的。具體跳轉到哪個資源,是瀏覽器說了算。

二者如何選擇

  • 轉發和重定向應該如何選擇?什么時候使用轉發,什么時候使用重定向?

    • 如果在上一個Servlet當中向request域當中綁定了數據,希望從下一個Servlet當中把request域里面的數據取出來,使用轉發機制。
    • 剩下所有的請求均使用重定向。(重定向使用較多。)
  • 跳轉的下一個資源有沒有要求呢?必須是一個Servlet嗎?

    • 不一定,跳轉的資源只要是服務器內部合法的資源即可。包括:Servlet、JSP、HTML…
  • 轉發會存在瀏覽器的刷新問題。
    比如說我們把數據保存到數據庫中,希望跳轉到成功頁面,當我們使用轉發的時候,只要瀏覽器刷新一次,數據庫就會多出一條數據,這樣是不可取的,所以可以使用重定向

這里推薦一篇關于轉發和重定向的文章:轉發和重定向(完整理解及總結)

總結

以上是生活随笔為你收集整理的一篇学会HttpServletRequest的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。