day16-Servlet05

来源:https://www.cnblogs.com/liyuelian/archive/2022/11/12/16884910.html
-Advertisement-
Play Games

Servlet05 14.HttpServletRequest HttpServletRequest對象代表客戶端的請求 當 客戶端/瀏覽器 通過HTTP協議訪問伺服器時,HTTP請求頭中的所有信息都封裝在這個對象中 通過這個對象的方法,可以獲取客戶端的信息 HttpServletRequest類圖 ...


Servlet05

14.HttpServletRequest

  1. HttpServletRequest對象代表客戶端的請求
  2. 當 客戶端/瀏覽器 通過HTTP協議訪問伺服器時,HTTP請求頭中的所有信息都封裝在這個對象中
  3. 通過這個對象的方法,可以獲取客戶端的信息
  • HttpServletRequest類圖
image-20221112160803071

image-20221112161006386 image-20221112161332903

14.1HttpServletRequest常用方法

  1. getRequestURI():獲取請求的資源路徑

    http://localhost:8080/servlet/loginServlet

  2. getRequestURL():獲取請求的統一資源定位符(絕對路徑)

    http://localhost:8080/servlet/loginServlet

  3. getRemoteHost():獲取客戶端的主機

  4. getRemoteAddr():獲取客戶端的ip

  5. getHeader():獲取請求頭

  6. getParameter():獲取請求的參數

  7. getParameterValues():獲取請求的參數(多個值的時候使用)

  8. getMethod():獲取請求的方式get或post

  9. setAttribute(key,value):設置域數據

  10. getAttribute(key):獲取域數據

  11. getRequestDispatcher():獲取請求轉發對象(請求轉發的核心對象)

14.2HttpServletRequest應用實例

需求:在一個表單提交數據給Servlet,在該Servlet中通過HttpServletRequest對象獲取相關數據

package com.li.servlet.request;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet(name = "HttpServletRequestMethods", value = "/requestMethods")
public class HttpServletRequestMethods extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //這裡我們使用request對象,獲取表單提交的各種數據
        //System.out.println("HttpServletRequestMethods doPost()被調用...");

        //1.獲取和http請求頭相關的信息
        System.out.println("請求的資源URI= " + request.getRequestURI());
        System.out.println("請求的統一資源定位符(絕對路徑)URL= " + request.getRequestURL());
        System.out.println("請求的客戶端ip地址= " + request.getRemoteAddr());
        /*
        getRemoteAddr()應用:發現某個ip在10s內訪問的次數超過100次,就封ip
        實現思路:1用一個集合concurrentHashMap[k=ip v=訪問次數] 2啟動線程定時掃描 3做出相應處理
        */
        //如果我們希望得到請求的頭的相關信息,可以直接使用request.getHeader("請求頭欄位名")
        System.out.println("http請求頭HOST= " + request.getHeader("Host"));
        System.out.println("該請求發起的地址是= " + request.getHeader("Referer"));
        //請獲取訪問網站的瀏覽器是什麼?
        String userAgent = request.getHeader("User-Agent");
        //User-Agent= Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
        String[] s = userAgent.split(" ");//使用空格分割
        //取最後一個字元,再用 /分割,取第一個字元
        System.out.println("瀏覽器的種類= " + s[s.length - 1].split("\\/")[0]);
        System.out.println("http請求方式= " + request.getMethod());

        //2.獲取和請求參數相關的信息,要去在返回數據前獲取參數
        //username=&pwd=&hobby=lb&hobby=cc
        //2.1獲取表單的數據[單個數據]
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String pwd = request.getParameter("pwd");
        //2.2獲取表單一組數據[多個數據]
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("username= " + username);
        System.out.println("pwd= " + pwd);
        //增強for迴圈的快捷鍵 iter->回車即可
        for (String hobby : hobbies) {
            System.out.println("hobby= " + hobby);
        }
        //推而廣之,如果是單選,下拉框等,獲取數據的方法大同小異
    }
}

html頁面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊</title>
</head>
<body>
<h1>註冊用戶</h1>
<!--註意:這裡的requestMethods不是你的類名,是你在web.xml裡面(或者註解裡面)配置的<url-pattern>-->
<form action="http://localhost:8080/servlet_demo/requestMethods" method="post">
    u:<input type="text" name="username"/><br/><br/>
    p:<input type="password" name="pwd"/><br/><br/>
    選擇你最喜歡的三國人物:
    <input type="checkbox" name="hobby" value="lb">劉備
    <input type="checkbox" name="hobby" value="cc">曹操
    <input type="checkbox" name="hobby" value="sq">孫權<br/><br/>
    <input type="submit" value="註冊用戶">
</form>
</body>
</html>

瀏覽器中訪問html頁面,輸入數據,點擊註冊:

image-20221112173741298

後臺輸出如下:

image-20221112174008561

14.3HttpServletRequest註意事項和細節

  1. 獲取doPost參數中文亂碼解決方法,設置編碼類型request.setCharacterEncoding("UTF-8");

    註意要寫在獲取參數之前:

    image-20221112174621994
  2. 註意:如果通過PrintWriter writer,有返回數據給瀏覽器,建議將獲取參數的代碼寫在writer.print()之前,否則可能獲取不到參數值(post)

  3. 處理http響應數中文亂碼問題

    image-20221112175013837
  4. 再次理解HTTP協議響應Content-Type的含義,比如text/html,text/plain,application/x-tar

    Content-Type表示返回的數據類型,瀏覽器會根據這個類型來解析數據,詳見HTTP協議MIME類型

14.4請求轉發

14.4.1為什麼需要請求轉發

  1. 目前我們學習的都是一次請求,對應一個Servlet

    image-20221112181819875
  2. 在實際的開發中,往往業務比較複雜,需要在一次請求中,使用到多個Servlet完成一個任務(Servlet鏈,流水作業)

    image-20221112182014390

14.4.2請求轉發說明

  1. 實現請求轉發:請求轉髮指一個web資源收到客戶端請求後,通知伺服器去調用另外一個web資源進行處理

  2. HttpServletRequest對象(也叫request對象)提供了一個getRequestDispatcher方法,該方法返回一個RequestDispatcher對象,調用這個對象的forward方法可以實現請求轉發

  3. request對象同時也是一個域對象,開發人員通過request對象在實現轉發時,把數據通過request對象帶給其他web資源處理

    • setAttribute方法
    • getAttribute方法
    • removeAttribute方法
    • getAttributeNames方法

14.4.3請求轉發應用實例

例子

需求:瀏覽器在某html頁面輸入數據,checkServlet根據該數據對進行操作,如果輸入的數據為“tom”,就將其設置為“管理員”,如果不是,就設置為“普通用戶”,由managerServlet向伺服器返回數據

image-20221112192943227

CheckServlet:

package com.li.servlet.request;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet(urlPatterns = {"/checkServlet"})
public class CheckServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("CheckServlet doPost()被調用...");

        //根據用戶名來確定該用戶是什麼身份
        String username = request.getParameter("username");
        //註意:如果是同一個request對象(請求轉發),那麼可以在不同的Servlet中使用getParameter取出該參數
        if ("tom".equals(username)) {
            //分配許可權
            //request對象是一個域對象,通過request對象,在實現轉發時,
            // 把數據通過request對象帶給其他web資源處理
            request.setAttribute("role", "管理員");//k-v
        } else {
            request.setAttribute("role", "普通用戶");//k-v
        }

        //獲取分發器
        /**
         * 1. /managerServlet寫的是想轉發的Servlet的url-pattern
         * 2. / 會被解析成 /servlet_demo
         *      因此請求轉發是不可能轉發到外網去的
         * 3.forward(request,response)表示把當前的request和response對象傳遞給下一個Servlet使用,
         *      保證了下一個Servlet和當前的Servlet使用的是同一個request和response對象
         */
        RequestDispatcher requestDispatcher =
                request.getRequestDispatcher("/managerServlet");
        requestDispatcher.forward(request, response);

    }
}

ManagerServlet:

package com.li.servlet.request;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(urlPatterns = {"/managerServlet"})
public class ManagerServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ManagerServlet doPost()被調用...");

        //因為是同一個request對象,因此可以用request.getParameter("username")獲取username
        String username = request.getParameter("username");
        String role = (String) request.getAttribute("role");//k-v
        //輸出信息
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("用戶名:" + username + "<br/>");
        writer.print("role:" + role);
        writer.flush();
        writer.close();
    }
}

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄</title>
</head>
<body>
<form action="http://localhost:8080/servlet_demo/checkServlet" method="post">
    u:<input type="text" name="username"><br/>
    <input type="submit" value="登錄">
</form>
</body>
</html>

redeployTomcat,在瀏覽器中訪問http://localhost:8080/servlet_demo/login.html,輸入數據,點擊登錄,可以看到地址欄變為http://localhost:8080/servlet_demo/checkServlet,但沒有變為managerServlet(地址會保留在第一個Servlet的URL)

image-20221112202633137 image-20221112202743178

image-20221112202907968 image-20221112202925282

14.4.4請求轉發註意細節

  1. 瀏覽器地址不會變化(地址會保留在第一個Servlet的URL)

  2. 在同一次HTTP請求中,進行多次轉發,仍然是一次HTTP請求

  3. 在同一次HTTP請求中,進行多次轉發,多個Servlet可以共用request域/對象的數據,即request域/對象的數據(參數,屬性)的作用域,是在一次HTTP請求有效

    因為是同一個request對象(數據上來講)

  4. 可以轉發到WEB-INF目錄下

  5. 不能訪問當前WEB工程外的資源

  6. 因為瀏覽器地址欄會停留在第一個Servlet,如果你刷新頁面,會再次發出請求(並且會帶數據)。

    所以在支付頁面情況下,不要使用請求轉發,否則會造成重覆支付 [解決方案可以使用重定向]

image-20221112205005615

14.5習題

14.5.1習題一

通過HttpServletRequest對象獲取到訪問服務的的瀏覽器名稱

通過字元串分割,14.2已完成

14.5.2習題二

請想辦法獲取到 JSESSIONID的值

image-20221112180402215

//獲取 JSESSIONID的值
String cookie = request.getHeader("Cookie");
String[] s1 = cookie.split(";");
String[] strings = s1[0].split("=");
System.out.println("JSESSIONID的值= "+strings[1]);
image-20221112181501739

14.5.3習題三

下麵是一個表單,完成如下功能

(1)編寫一個RegisterServlet,能夠接收到提交的各種數據,並獲取瀏覽器所在電腦的操作系統和位數

(2)並把接收到的數據返回給瀏覽器顯示

(3)註意處理中文亂碼問題

(4)暫不處理文件提交

image-20221112205321403

RegisterServlet:

package com.li.servlet.request.homework;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(urlPatterns = {"/registerServlet"})
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.獲取表單提交的數據

        //先設置編碼類型
        request.setCharacterEncoding("utf-8");
        //單個數據使用 getParameter
        String username = request.getParameter("username");
        String pwd = request.getParameter("pwd");
        String pwd2 = request.getParameter("pwd2");
        //多個數據使用getParameterValues
        String[] sports = request.getParameterValues("sport");
        String gender = request.getParameter("gender");
        String city = request.getParameter("city");
        String introduce = request.getParameter("introduce");

        //2.獲取用戶瀏覽器所在電腦的操作系統和位數
        //Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
        String User_Agent = request.getHeader("User-Agent");
        String[] s = User_Agent.split(" ");//使用空格分割
        //s[1]="(Windows" 取出索引為1及之後的字元串
        String OS = s[1].substring(1);
        //s[5]=x64;
        String OSNum = s[5].substring(1, 3);

        //3.返回輸出
        //設置編碼類型
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("你的用戶名稱:" + username + "<br/>");
        writer.print("你的用戶密碼:" + pwd + "<br/>");
        writer.print("你的確認密碼:" + pwd2 + "<br/>");
        writer.print("喜歡的運動:");
        for (String sport : sports) {
            writer.print(sport + " ");
        }
        writer.print("<br/>你的性別:" + gender + "<br/>");
        writer.print("喜歡的城市:" + city + "<br/>");
        writer.print("自我介紹:" + introduce + "<br/>");
        writer.print("電腦操作系統:" + OS + "<br/>");
        writer.print("位數:" + OSNum + "<br/>");
        writer.flush();
        writer.close();
    }
}

register_form.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶註冊</title>
</head>
<body>
<form action="http://localhost:8080/servlet_demo/registerServlet" method="post">
    用戶註冊信息<br/>
    用戶名稱:<input type="text" name="username"/><br/>
    用戶密碼:<input type="password" name="pwd"/><br/>
    確認密碼:<input type="password" name="pwd2"/><br/>
    請選中你喜歡的運動項目<br/>
    <input type="checkbox" name="sport" value="lq">籃球<br/>
    <input type="checkbox" name="sport" value="zq">足球<br/>
    <input type="checkbox" name="sport" value="sq">手球<br/>
    請選中你的性別<br/>
    <input type="radio" name="gender" value="men">男<br/>
    <input type="radio" name="gender" value="women">女<br/>
    請選中你喜歡的城市
    <select name="city">
        <option>--請選中--</option>
        <option value="gz">廣州</option>
        <option value="bj">北京</option>
        <option value="sh">上海</option>
    </select><br/>
    自我介紹<textarea name="introduce"></textarea><br/>
    <input type="submit" value="提交">
    <input type="reset" value="重置">
</form>
</body>
</html>

image-20221112224256688 image-20221112224304878


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • C#11添加了文件作用域類型功能:一個新的file修飾符,可以應用於任何類型定義以限制其只能在當前文件中使用。 這樣,我們可以在一個項目中擁有多個同名的類。 通過下麵的項目顯示,該項目包含兩個名為Answer的類。 文件File1.cs中 namespace ConsoleApp11 { file ...
  • 1、前言 對於簡單的系統而言模型與數據可以進行直接的映射,比如說三層模型就足夠支撐項目的需求了。對於這種簡單的系統我們過度設計說白了無異於增加成本,因為對於一般的CRUD來說我們不用特別區分查詢和增刪改的程式結構。高射炮打蚊子那就有點大材小用了。但是我們的系統具有一定複雜性的時候,可能源於訪問頻次、 ...
  • .NET for Apache Spark 入門演練 微軟官方文檔: .NET for Apache Spark 入門 | Microsoft Learn 註意:由於本次在windows平臺下進行演練,以下在未標註操作系統平臺處,預設為windows。 1. 環境準備 推薦安裝工具: visual ...
  • 什麼是Path環境變數? 在探討這個問題之前,我們需要瞭解什麼是環境變數。 “環境變數”和“path環境變數”其實是兩個東西,這一點大家一定要區分開,不要混為一談。 “環境變數”是操作系統工作環境設置的一些選項或屬性參數。每個環境變數由變數名和文件路徑組成的,可以設置很多個環境變數。 我們一般使用環 ...
  • GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 本文來源:原創投稿;作者:YeJinrong/葉金榮 MySQL 8.0.30動態redo log初探 MySQL 8.0.30全新的動態redo lo ...
  • 背景 https://github.com/MobilityDB/MobilityDB https://www.citusdata.com/download/ https://www.postgresql.org/ https://www.citusdata.com/blog/2020/11/09/ ...
  • 一、查詢表、模式及欄位信息 1、查詢指定模式下的所有表 select tablename,* from pg_tables where schemaname = 'ods'; 2、查詢指定模式下的表名及欄位 SELECT C.relname, A.attname AS NAME, format_ty ...
  • 好家伙, 本篇內容為《JS高級程式設計》第三章學習筆記 1.Number類型 從名稱中我們可以得出,這是一個存放數值的類型, 不同的數值類型相應地也有不同的數值字面量格式 Number類型可以儲存不同進位的數(不常用就是了) 八進位:在數前加一個零("0"),後續的數字中不能有大於7的數值,否則八進 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...