Http请求&Request


今日目标

  1. 0. http请求
  2. 1. Request概述
  3. 2. reuqest获取请求消息内容
  4. 请求行
  5. 请求头
  6. 请求参数(体)【重点】
  7. 3. request其他功能
  8. 请求转发
  9. 域对象
  10. 4. 案例:用户登录

1626502959827.png

零 Http协议

0.1 Http协议概述

超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议。

传输协议:在客户端和服务器端通信时,规范了传输数据的格式和内容

# 1. http协议的特点
        HyperText Transfer Protocol 超文本传输协议
    0). tcp/ip协议族: 链路层,网络层(ip), 传输层(tcp), 应用层(http)
    1). 基于tcp协议 : 传输层协议, 三次握手,保障数据安全,相对udp效率低
    2). 默认端口 80 (省略不写)
                协议://ip:port/资源位置?参数
            完整版: http://localhost:80/a.html
            省略版: http://localhost/a.html            
            https 的默认端口是443 (secure 安全, 对传输数据进行加密)        
                    https://www.baidu.com/?tn=88093251_21_hao_pg
                    https://www.baidu.com:443/?tn=88093251_21_hao_pg
    3). 基于请求-响应模型
        一次请求对应一次响应 / 先有请求,再有响应
    4). 无状态(多次请求之间相互独立,不记录状态)         
# 2. http协议版本发展
    1). http1.0 (1996) : 每次请求都有一个新的连接(开销大,比较慢)
    2). http1.1    (1999) : 长连接,多个请求共用一个连接(开销小一些,比较快) 
                         传输的数据都是文本(比较慢), 不支持推送
                         目前主流!!!
    3). http2.0 (2015) : 传输的数据经过压缩的,效率很高, 支持推送        
# 3. http协议的内容
    1). 请求报文: 浏览器发送给服务器的数据 
        请求行, 请求头, 请求体
    2). 响应报文: 服务器发送给浏览器的数据
        响应行, 响应头, 响应体

# 4. 抓包工具 (抓取基于http协议传输的数据包)
    1. 在浏览器和服务器交互的时候(发送请求,然后响应),我们可以使用工具抓取数据查看
    2. google浏览器内置开发者工具

使用 chrome(谷歌)抓包 ——按键f12

发送一个请求,观察开发者工具

1607830364675.png

记得点击view source 查看请求报文的原文

0.2 Http请求案例

http.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>get请求</h1>
    <form action="RequestServlet" method="get">
        <input type="text" name="username" placeholder="请输入用户名"> <br>
        <input type="password" name="password" placeholder="请输入密码"> <br>
        <input type="submit">
    </form>

    <h1>post请求</h1>
    <form action="RequestServlet" method="post">
        <input type="text" name="username" placeholder="请输入用户名"> <br>
        <input type="password" name="password" placeholder="请输入密码"> <br>
        <input type="submit">
    </form>
</body>
</html>
package com.itheima03.request;

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

@WebServlet("/RequestServlet")
public class RequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("RequestServlet被访问了");
    }
}

1649469264063.png

0.2.2 HTTP请求报文格式

① 请求行

* 格式
        请求方式 请求路径 协议/版本号

* 例如
        POST /day07_myapp/static/login.html HTTP/1.1
        GET /day07_myapp/static/login.html?username=jack&password=123 HTTP/1.1

* 请求方式区别
    get
        1.请求参数在地址栏显示(请求行)
        2.请求参数大小有限制
        3.数据不太安全
    post
        1.请求参数不在地址栏显示(请求体)
        2.请求参数大小没有限制
        3.数据相对安全
        (上传文件要用post,其他请求两种都可以)

② 请求头

* 格式
        请求头名称:请求头的值
* 例如   
        Host: localhost:8080

常见请求头

        ------------------------------------------(了解)
1. Host: localhost:8080         所访问的服务器地址(域名+端口)
2. Connection: keep-alive       长连接(http1.1协议)    
3. Upgrade-Insecure-Requests:1   客户端支持https加密协议  

        ---------------------------------------(重点)
4. Referer: http://baidu.com    上一次请求的地址    
        防盗链....        
5. User-Agent:        客户端系统和浏览器版本
        User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) Chrome/63.0 Safari/537.36
        浏览器兼容性
            判断 : 服务器根据用户的浏览器版本, 返回响应的数据
                谷歌方式一 : 发送google浏览器可以解析的数据
                IE方式二 : 发送ie浏览器可以解析的数据
                火狐方式三 :

③ 请求体(正文)

* 格式
        参数名=参数值&参数名=参数值...
* 例如
        username=jack&password=123

* 注意:
        get方式没有请求体,post方式才有

一 Request概述

  • 由来: 用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中
  • 作用:开发人员可以通过request对象方法,来获取浏览器发送给服务器的所有信息.

1649471777466.png

Request体系结构

        ServletRequest  (接口: 兼容大部分协议)
            |
        HttpServletRequest (接口: 只支持HTTP协议)
            |
        org.apache.catalina.connector.RequestFacade(由tomcat厂商提供实现类,不关心)

面向接口编程: 省事

在javaEE中我们是面向接口编程 (面向对象的一种思想)

二 Request获取Http请求信息(核心功能)

2.1 获取请求行信息

* 例如:
        GET /day09_request/requestDemo1 HTTP/1.1
         请求方式     请求地址    协议/版本
* 相关API: (查阅文档: 是javaee文档)
    1. 获取请求方式 GET【掌握!!!】
            String getMethod()  

    2. 获取URI /day09_request/requestDemo1
            统一资源标识符
                (范围广,只要能唯一标识资源的: 本地路径,远程地址
                    url 是 uri 的子集
                )  
            String getRequestURI() 

    3. 获取URL http://localhost:8080/day09_request/requestDemo1
            统一资源定位符(确定某一个资源的地址:俗称网址) 
            StringBuffer getRequestURL()  

    4. 获取协议和版本号    HTTP/1.1
            String getProtocol()
package com.itheima04.api;

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

/*
    TODO: 通过request对象获取请求信息
    请求报文
        1. 请求行
                请求方式,请求地址,协议
        2. 请求头
        3. 请求体

  TODO 请求行
    * 例如:
        GET /day09_request/requestDemo1 HTTP/1.1
         请求方式     请求地址    协议/版本
    * 相关API: (查阅文档: 是javaee文档)
        1. 获取请求方式 GET【掌握!!!】
                String getMethod()

        2. 获取URI /day09_request/requestDemo1
                统一资源标识符
                    (范围广,只要能唯一标识资源的: 本地路径,远程地址
                        url 是 uri 的子集
                    )
                String getRequestURI()

        3. 获取URL http://localhost:8080/day09_request/requestDemo1
                统一资源定位符(确定某一个资源的地址:俗称网址)
                StringBuffer getRequestURL()

        4. 获取协议和版本号    HTTP/1.1
                String getProtocol()

    # 扩展
        uri : 统一资源标识符(Uniform Resource Identifier)
            0). 只要可以唯一标识一个资源的东西,就可以称之为uri
            1). 本地地址
                    c:/test/a.txt
            2). 远程地址 (网址)
                    http://www.xx.com/a.txt

        url : 统一资源定位器(Uniform Resource Locator)
            远程地址 (网址)
            url是uri的子集
 */
@WebServlet("/Demo01Servlet")
public class Demo01Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String method = request.getMethod();
        System.out.println("请求方式:" + method); // 请求方式:GET

        String requestURI = request.getRequestURI();
            // StringBuffer 是 StringBuilder 线程安全版
        StringBuffer requestURL = request.getRequestURL();
        // 请求地址 uri: /day16-demo01/Demo01Servlet (省略了三要素 http://localhost:80)
        System.out.println("请求地址 uri:" + requestURI);
        //请求地址 url: http://localhost/day16-demo01/Demo01Servlet (完整版)
        System.out.println("请求地址 url:" + requestURL);

        String protocol = request.getProtocol();
        //请求协议:HTTP/1.1
        System.out.println("请求协议:" + protocol);
    }
}

2.2 获取请求头信息

* 例如:
        Host: localhost:8080(主机: 指的就是tomcat访问地址)
        name(请求头属性名,固定不变的) : value(对应的属性值,动态改变)
         常见请求头: 
            user-agent (用户的系统版本和浏览器)
            referer(上一次地址) 
            如果在浏览器抓包中看不到某个头,就表示这个头所对应的值是null

* 相关API:
    1. 获取指定请求头名称对应的值,注:名称不区分大小写  (掌握)
            String value =  getHeader(String name)  

    2. 获取所有请求头的名称
            Enumeration<String> getHeaderNames()  
            注:是Iterator迭代器前身(JDK 枚举)
package com.itheima04.api;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;

/*
    TODO: 请求头信息 (格式 -> name : value)
* 例如:
        Host: localhost:8080(主机: 指的就是tomcat访问地址)
        name(请求头属性名,固定不变的) : value(对应的属性值,动态改变)
         常见请求头:
            user-agent (用户的系统版本和浏览器)
            referer(上一次地址)
            如果在浏览器抓包中看不到某个头,就表示这个头所对应的值是null

* 相关API:
    1. 获取指定请求头名称对应的值,注:名称不区分大小写  (掌握)
            String value =  getHeader(String name)

    2. 获取所有请求头的名称
            Enumeration<String> getHeaderNames()
            注:是Iterator迭代器前身(JDK 枚举)
 */
@WebServlet("/Demo02Servlet")
public class Demo02Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String host = request.getHeader("host");
        // 主机:localhost:8080
        System.out.println("主机:" + host);
        String referer = request.getHeader("referer");
        //上一次访问的地址:http://localhost:8080/day16-demo01/
            //注意: 如果你在浏览器地址栏中不是通过链接跳转到当前Servlet
            // 而是直接访问,打印将是null(表示没有上一次地址)
        System.out.println("上一次访问的地址:" +referer);
        String header = request.getHeader("user-agent");
        //用户系统和浏览器:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36
        System.out.println("用户系统和浏览器:" + header);

        System.out.println("--------------");
       /* HashMap<String, String> map = new HashMap<>();
        //获取map的key这一列集合的迭代器
        Iterator<String> it = map.keySet().iterator();
        while(it.hasNext()){
            String key = it.next();
            String value = map.get(key);
        }*/
        /*
        * Enumeration 接口 : 被Iterator替代了 (迭代器)
        * */
        //把request看成一个map,name是请求头的属性名,value是请求头对应的值
        //获取request 请求头集合的迭代器
        Enumeration<String> headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()){ // 有没更多元素
            String name = headerNames.nextElement(); // 获取下一个元素
            String value = request.getHeader(name);
            System.out.println(name + ":" + value);
        }
    }
}

案例:视频防盗链

  • referer : 请求来源

1626511739914.png

index.html

 <!--
            网址首页 http://localhost:8080/day16-demo01
        -->
        <a href="Demo03Servlet">防盗链: 爱奇艺官网,观看&lt;我的恶魔妻子&gt; </a>
package com.itheima04.api;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
      //模拟资源库
@WebServlet("/Demo03Servlet")
public class Demo03Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //TODO: 防盗链

        //获取上一次访问的地址
        String referer = request.getHeader("referer");
        if(referer != null && referer.startsWith("http://localhost:8080")){
            //说明: 是爱奇艺的官网

            response.setContentType("text/html;charset=utf-8"); //防止网页显示中文乱码
            response.getWriter().print("正在播放: 我的恶魔妻子"); //会在网页上输出
        }else{
            //说明: 是其他网站过来的
            response.setContentType("text/html;charset=utf-8"); //防止网页显示中文乱码
            response.getWriter().print("请到爱奇艺官网观看"); //会在网页上输出
        }
    }
}

zs.html

需要写在别的模块中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h1>张三看看</h1>
        <a href="http://localhost:8080/day16-demo01/Demo03Servlet">观看&lt;我的恶魔妻子&gt;</a>

</body>
</html>

2.3 获取请求参数(体)【重点….】

  • 不论get还是post请求方式,都可以使用下列方法来获取请求参数

    get请求参数放在 请求行 url中(get没有请求体)

    post请求参数放在 请求体

  • 在web课程里面,get和post处理的业务逻辑都是一样的….
* 参数
        username=jack&password=123&hobby=drink&hobby=perm
        格式: name1=value1&name2=value2... (name是可以重复)
* API
    1. 获取指定参数名的值  username=jack
            String getParameter(String name)            
    2. 获取指定参数名的值数组  hobby=drink&hobby=perm
            String[] getParameterValues(String name)
    3. 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
            Map<String,String[]> getParameterMap()
                 name , value
* 中文乱码【重点】
1. get请求没有乱码
    1). tomcat7以及之前,get请求存在乱码:maven的tomcat插件是7版本
    2). tomcat8没有get请求乱码了
2. post请求中文乱码
    0). 乱码: 编码和解码所使用的编码表不一致
        ASCII : 128个字符    0110 0001(10进制97) -> a
        ISO-8859-1 : 256个字符 (拉丁码,欧码)
        GBK : 2个字节表示一个汉字 
        utf-8 : 国际码 (3个字节中文)
    1). 编码: 浏览器编码用的是utf-8
    2). 解码: tomcat解码用的是ISO-8859-1 (拉丁码,欧码)
    3). 解决方案: tomcat解码要使用utf-8编码
         //告诉tomcat,用utf-8解码请求信息
        //必须获取参数之前,设置
        request.setCharacterEncoding("utf-8");
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h1>get请求方式</h1>
        <form action="ParamServlet" method="get">
            用户 <input type="text" name="username" placeholder="请输入用户名"> <br>
            密码 <input type="password" name="password" placeholder="请输入密码"> <br>
            性别 <input type="radio" name="sex" value="male"> 男
            <input type="radio" name="sex" value="female"> 女
                <br>
            爱好
            <input type="checkbox" name="hobby" value="smoke"> 抽烟
            <input type="checkbox" name="hobby" value="drink"> 喝酒
            <input type="checkbox" name="hobby" value="firehead"> 烫头
            <br>
            <input type="submit">
        </form>

        <h1>post请求方式</h1>
        <form action="ParamServlet" method="post">
            用户 <input type="text" name="username" placeholder="请输入用户名"> <br>
            密码 <input type="password" name="password" placeholder="请输入密码"> <br>
            性别 <input type="radio" name="sex" value="male"> 男
            <input type="radio" name="sex" value="female"> 女
            <br>
            爱好
            <input type="checkbox" name="hobby" value="smoke"> 抽烟
            <input type="checkbox" name="hobby" value="drink"> 喝酒
            <input type="checkbox" name="hobby" value="firehead"> 烫头
            <br>
            <input type="submit">
        </form>
</body>
</html>
package com;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

/*
    url格式:
            协议://ip:port/资源位置?参数

            参数格式: name=value&name=value...
  * API
    1. 获取指定参数名的值  username=jack
            String getParameter(String name)
    2. 获取指定参数名的值数组  hobby=drink&hobby=perm
            String[] getParameterValues(String name)
    3. 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
            Map<String,String[]> getParameterMap()
                 name , value

    # 问题: post请求参数乱码
        1. get请求没有乱码
            tomcat8以前是有乱码,tomcat8以及之后版本就没有了
        2. post请求有乱码
            0). 乱码原因: 编码和解码所使用的字符集(编码表)不一样
            1). 编码 : 浏览器在编码 (utf-8)
            2). 解码     : 服务器在解码
                    tomcat  (默认使用iso-8859-1 欧码)
                    servlet

                    servlet没有设置,会使用tomcat的默认设置,如果设置了就使用servlet设置的

           解决:
                 request.setCharacterEncoding("utf-8");
                 注意: 一定要写在获取请求参数之前
 */
@WebServlet("/ParamServlet")
public class ParamServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求参数编码为utf-8
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String[] hobbies = request.getParameterValues("hobby");

        //zs,110,female,[drink, firehead]
        System.out.println(username + "," + password + "," + sex + "," + Arrays.toString(hobbies));

        Map<String, String[]> map = request.getParameterMap();
        Iterator<String> it = map.keySet().iterator();
        while(it.hasNext()){
            String key = it.next();
            String[] value = map.get(key);
            /*
            *   username--[ls]
                password--[110]
                sex--[male]
                hobby--[smoke, drink]
            * */
            System.out.println(key + "--" + Arrays.toString(value));
        }

    }

}

三 Request其他功能

3.1 请求转发

  • 一种在服务器内部的资源跳转方式

1630634168866.png

* API
    1. 通过request对象,获得转发器对象(邮递员)
             //path是要跳转的资源路径
            RequestDispatcher getRequestDispatcher(String path)

    2. 通过转发器对象,实现转发功能
             // 要记得携带请求和响应
            void forward(ServletRequest request, ServletResponse response)  

* 请求转发特点
    1. 浏览器:发了一次请求
    2. 地址栏:没有发生改变
    3. 只能转发到服务器内部资源....

* 链式编程
        request.getRequestDispatcher("bServlet").forward(request,response)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <!--
            TODO:
                URL格式 -> http://localhost:8080/AServlet?name=value
                a标签是get请求,所以参数可以直接拼接在url中
        -->
    <a href="AServlet?msg=汉堡">请求转发_要汉堡</a>
</body>
</html>
package com.itheima01.dispatch;

import javax.servlet.RequestDispatcher;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/AServlet")
public class AServlet extends HttpServlet {

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

    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        //1. 接收请求
        String msg = request.getParameter("msg");
        System.out.println("AServlet:" + msg);
        //2. 业务处理: 请求转发
//        RequestDispatcher dispatcher = request.getRequestDispatcher("BServlet");
//        dispatcher.forward(request, response);
        request.getRequestDispatcher("BServlet").forward(request, response);
    }

}
package com.itheima01.dispatch;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/BServlet")
public class BServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收请求
        String msg = request.getParameter("msg");
        System.out.println("BServlet:" + msg);
        //2. 业务处理
        System.out.println("BServlet:做汉堡");
        //3. 响应
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("给你汉堡,慢点吃");
    }

}

3.2 域对象(共享数据)

  • 域对象:一个有作用范围的对象,开发者可以通过域对象在其作用范围内共享/传递数据

    快递员 : 一个有作用范围的对象, 客户可以通过快递员在其作用范围传递物件

  • request域对象:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

    request的本职工作是请求数据的封装, 它兼职送快递

    request的作用范围: 一次请求(一次请求到一次响应之间)

1630635775992.png

* API (request域对象可以看成一个map)
    1. 设置数据
            void setAttribute(String name, Object o)
                -> map.put(key,value)
    2. 获取数据
            Object getAttribute(String name)
                -> value = map.get(key)
    3. 删除数据
            void removeAttribute(String name)
                ->  map.remove(key)
package com.itheima01.dispatch;

import javax.servlet.RequestDispatcher;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/AServlet")
public class AServlet extends HttpServlet {

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

    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        //1. 接收请求
        String msg = request.getParameter("msg");
        System.out.println("AServlet:" + msg);
        request.setAttribute("extra", "今晚看电影");
        //2. 业务处理: 请求转发
//        RequestDispatcher dispatcher = request.getRequestDispatcher("BServlet");
//        dispatcher.forward(request, response);
        request.getRequestDispatcher("BServlet").forward(request, response);
    }

}
package com.itheima01.dispatch;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/BServlet")
public class BServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收请求
        String msg = request.getParameter("msg");
        System.out.println("BServlet:" + msg);
        //2. 业务处理
        System.out.println("BServlet:做汉堡");

        Object extra = request.getAttribute("extra");
        System.out.println("BServlet:" + extra);
        //3. 响应
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("给你汉堡,慢点吃");
    }

}

四 案例:用户登录

需求

实现用户的登录功能

登录成功跳转到SuccessServlet展示:登录成功!xxx,欢迎您

登录失败跳转到FailServlet展示:登录失败,用户名或密码错误

需求分析

1590997016531.png

代码实现

① 创建web项目

1630637932865.png

② 编写index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h1>登录页面</h1>
        <form action="LoginServlet" method="post">
            <input type="text" name="username" placeholder="请输入用户名"> <br>
            <input type="text" name="password" placeholder="请输入密码"> <br>
            <!--<input type="submit" value="登录">-->
            <button>登录</button>
        </form>
</body>
</html>

③ LoginServlet

package com.itheima.login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        //1. 获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //2. 业务处理
            //理论上要查询数据库 jar包放 web/web-if/lib
            //用伪数据
            // 常量写前面是为了避免空指针异常
        if("admin".equals(username) && "123".equals(password)){
            //登录成功
            request.getRequestDispatcher("SuccessServlet").forward(request, response);
        }else{
            //登录失败
            request.setAttribute("errorMsg", "用户名不存在或密码错误");
            request.getRequestDispatcher("FailedServlet").forward(request, response);
        }
    }

}

④ SuccessServlet

package com.itheima.login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/SuccessServlet")
public class SuccessServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("登录成功!");
    }

}

⑤ FailedServlet

package com.itheima.login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/FailedServlet")
public class FailedServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object errorMsg = request.getAttribute("errorMsg");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("登录失败: " + errorMsg);
    }

}

总结

# request
1. 是什么
    1). 概念: 请求是浏览器发送给服务器的数据
        a. B/S架构 (浏览器, 服务器:tomcat+servlet)
        b. http协议 (请求报文! + 响应报文)
            I. 请求行
            II. 请求头
            III. 请求体
            (google浏览器的抓包工具)
    2). API: request对象
        a. 位置 : 式servlet-service方法的参数
        b. 含义 : tomcat接收到浏览器的请求报文之后,将数据封装到此对象中  
2. 为什么

3. 怎么办
        开发者可以在servlet中通过request对象获取请求内容

        BeanUtils
            1). 知道MyBatis 的 ORM
            2). 反射