JAVA WEB DAY 02_请求对象(request)

request对象

01 HTTP 协议概述[★]

01_01 概念:

HyperText Transfer Protocol

超文本传输协议

01_02 作用:

  1. 用于浏览器和服务器之间的数据输出
  2. 规定了浏览器和服务器的传输格式

01_03 特点:

  1. 无状态:协议对客户端没有状态存储,对事务处理没有“记忆”能力。
  2. 无连接:HTTP/1.1之前,由于无状态特点,每次请求需要通过TCP三次握手四次挥手,和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户的请求,所以每次需要重新响应请求,需要耗费不必要的时间和流量。
  3. 基于请求和响应:基本的特性,由客户端发起请求,服务端响应
  4. 简单、快速、灵活
  5. 通信使用文明、请求和响应不会对通信方进行确认、无法保护数据的完整性

01_04 组成:

  • 请求:浏览器发送数据给服务器的过程
  • 响应:服务器返回数据给浏览器的过程

02 HTTP 请求概述[★★★★]

HTTP 请求:浏览器访问服务器的过程


HTTP 请求的组成:
 请求行
 请求头
 请求体

02_01 查看HTTP请求

  • HTML 代码
<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--login 是一个 servlet-->
<h2>GET 提交</h2>
<form action="login" method="get">
    用户名:
    <input type="text" name="username"><br/>
    密码:
    <input type="password" name="password"><br/>
    <input type="submit" value="登录">
</form>
<hr>
<h2>POST 提交</h2>
<form action="login" method="post">
    用户名:
    <input type="text" name="username"><br/>
    密码:
    <input type="password" name="password"><br/>
    <input type="submit" value="登录">
</form>
</body>
</html>
  • 查看浏览器与服务器的通讯

在这里插入图片描述

  • HTTP 请求:

在这里插入图片描述

03 请求行概述[★★★]

请求行格式:

  • POST 请求:POST /XXX/login HTTP/1.1
  • GET 请求:GET /XXX/login?username=xxx&password=xxx HTTP/1.1

请求行组成:
 请求方式
 请求地址
 协议和版本

03_01 POST & GET 区别

POSTGET
地址栏数据在请求体中发送,所以地址上不显示参数因为是请求行中发送数据,所以在地址栏上可以看参数
大小理论上没有限制大小4不同的浏览器有区别,1K
安全性安全性更高安全性更低
缓存POST 邮寄,发送数据不使用本地缓存GET 拿,从服务器上获取数据,会使用缓存。如果本地浏览器已经缓存页面,而且服务器的数据没有修改,不再从服务上得到数据。

04 请求头概述[★★★]

  • 常见请求头
常见请求头作用
Referer服务器端获取浏览器上一次访问地址
If-Modified-Since服务器端获取浏览器缓存页面的时间
User-Agent服务器获取客户端操作系统的类型和浏览器类型
Connection获取 HTTP 协议连接状态
1.1 保持连接 keep-alice
1.0 断开连接 close
Host获取服务器的地址和端口

05 请求体概述[★★★]

请求头:

  • 用户输入的内容
  • 只要用户输入并提交给服务器的数据都可以统称为请求参数

问题
POST 和 GET 请求都有请求体吗?

  • Post 才有,Get 没有请求体

06 HttpServletRequest 对象概述[★★★]

问题
HttpServletRequest 对象是谁创建的?

  • web 服务器:Tomcat

HttpServletRequest 对象的作用?

  • 用来封装浏览器发送给服务器的所有数据:请求行、请求头、请求体
    需要调用 request 对象的方法获得请求数据

07 获取请求行的相关方法[★★★]

  • 需求:将请求行相关信息输出到网页上
  • HttpServletRequest 对象的方法
HttpServletRequest对象的方法功能说明
String getMethod()获取请求方式
String getRequestURI()获得统一资源标识符
StringBuffer getRequestURL()获得统一资源定位符:网址
String getProtocol()获得协议和版本
String getContextPath()获得项目访问路径
String getRemoteAddr()获得客户端IP地址
  • Java 代码
@WebServlet(urlPatterns = "/line")
public class RequestLineServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置内容类型和编码
        response.setContentType("text/html;charset=utf-8");
        // 获得字符打印流
        PrintWriter out = response.getWriter();

        // 请求方式 192.168.32.166
        out.println("请求方式:" + request.getMethod() + "<br/>");
        
        // 统一资源标识符: /day02/line   isbn 唯一 
        out.println("统一资源标识符:" + request.getRequestURI() + "<br/>" );
        // 统一资源定位符: http://localhost:8080/day02/line
        out.println("统一资源定位符:" + request.getRequestURL()+ "<br/>");
        
        // 协议和版本
        out.println("协议和版本:" + request.getProtocol() + "<br/>" );
        // 上下文路径:项目的访问路径
        out.println("项目的访问路径:" + request.getContextPath() + "<br/>");
        // 客户端IP地址
        out.println("客户端IP地址:" + request.getRemoteAddr()+ "<br/>");
    }
}
  • 网页显示如下

在这里插入图片描述

08 获取请求头相关方法[★★★]

  • 需求:获取请求头信息并输出
  • HttpServletRequest 对象的方法
HttpServletRequest 对象的方法功能描述
String getHeader(String headName)根据请求头名字获得值
Enumeration getHeaderNames()获得所有请求头的名字
返回的一个迭代器
hasMoreElement:判断是否有下一个元素
nextElement:获得下一个元素
  • Java 代码
@WebServlet(urlPatterns = "/header")
public class RequestHeaderServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         // 设置内容类型和编码
         response.setContentType("text/html;charset=utf-8");
         // 获得字符打印流
         PrintWriter out = response.getWriter();

        // 根据请求头名字获得值
        String host = request.getHeader("host");
        out.println("host = " + host + "<hr>");

        // 获得所有请求头名字
        // Enumeration 是迭代器的前身  Iterator
        Enumeration<String> it = request.getHeaderNames();
        // 判断是否有下一个元素
        while (it.hasMoreElements()){
            // 获得下一个元素
            String headerName = it.nextElement();
            // 根据请求头名获取值
            String headerValue = request.getHeader(headerName);
            out.println(headerName+":"+headerValue + "<br>");
        }
    }

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

09 获取请求参数相关方法[★★★]

  • 需求:用户注册得到表单提交的参数
  • HttpServletRequest对象的方法
HttpServletRequest对象的方法描述
String getParameter(String name)根据参数名获得参数值
String[] getParameterValues(String name)根据参数名获得多个参数值
返回是数组
Enumeration getParameterNames()获得所有请求参数的名字
返回迭代器对象
Map<String,String[]> getParameterMap()获得所有请求参数信息
返回map集合
key:参数名 value:参数值
  • HTML 代码
<h2>用户注册</h2>
<form action="register" method="post">
    用户名: <input type="text" name="name"><br/>
    性别: <input type="radio" name="gender" value="" checked="checked"/><input type="radio" name="gender" value=""/><br/>
    城市:
    <select name="city">
        <option value="广州">广州</option>
        <option value="深圳">深圳</option>
        <option value="珠海">珠海</option>
    </select>
    <br/>
    爱好:
        <input type="checkbox" name="hobby" value="上网"/>上网
        <input type="checkbox" name="hobby" value="上学"/>上学
        <input type="checkbox" name="hobby" value="上车"/>上车
        <input type="checkbox" name="hobby" value="上吊"/>上吊
    <br/>
    <input type="submit" value="注册"/>
</form>
  • Java 代码
@WebServlet(urlPatterns = "/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         request.setCharacterEncoding("utf-8");
         // 设置内容类型和编码
         response.setContentType("text/html;charset=utf-8");
         // 获得字符打印流
         PrintWriter out = response.getWriter();

        // 根据参数名获得参数值
        String username = request.getParameter("username");
        out.println("username = " + username + "<br>");

        // 根据参数名获得多个参数值
        String[] hobbies = request.getParameterValues("hobby");
        out.println("hobbies = " + Arrays.toString(hobbies) + "<hr>");

        // 获得所有请求参数的名字
        Enumeration<String> it = request.getParameterNames();
        // 遍历所有名字
        while (it.hasMoreElements()) {
            // 获得参数名字
            String name = it.nextElement();
            // 根据参数名获得值
            String[] values = request.getParameterValues(name);
            out.println(name + " = " + Arrays.toString(values) + "<br>");
        }

        out.println("<hr>");
        // 获得所有请求参数信息:封装到map集合中
        // key:参数名  value:参数的值
        Map<String, String[]> map = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : map.entrySet()) {
            out.println(entry.getKey() + " = " + Arrays.toString(entry.getValue()) + "<br>");
        }
    }
}

10 BeanUtils 工具使用-封装参数[★★★]

  • 需求:使用 BeanUtils 封装请求参数到 JavaBean 对象中
  • BeanUtils常用方法
BeanUtils常用方法作用
void populate(Object bean, Map<String, Object> properties)将map集合的数据封装到指定的bean对象
简单记忆:后付钱(后面的参数赋值给前面的对象)
  • Java JavaBean/entity User 代码
public class User {
    // 成员变量
    private String username;
    private String gender;
    private String[] hobby;
    private String city;

    public String getUsername() {return username;}

    public void setUsername(String username){this.username = username;}

    public String getGender() {return gender;}

    public void setGender(String gender) {this.gender = gender;}

    public String[] getHobby() {return hobby;}

    public void setHobby(String[] hobby) {this.hobby = hobby;}

    public String getCity() {return city;}

    public void setCity(String city) {this.city = city;}

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", gender='" + gender + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                ", city='" + city + '\'' +
                '}';
    }
}
  • 利用 BeanUtils 将表单参数封装到 User 对象中
import org.apache.commons.beanutils.BeanUtils;

@WebServlet(urlPatterns = "/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try{
            request.setCharacterEncoding("utf-8");
            // 设置内容类型和编码
            response.setContentType("text/html;charset=utf-8");

            // 获得请求参数信息
            Map<String, String[]> map = request.getParameterMap();

            // 创建User对象
            User user = new User();
            System.out.println("封装前:" + user);
            // 使用BeanUtils工具类的方法封装请求参数
            // populate:将map集合的数据封装到指定的对象中
            // 参数1:Object bean 自定义的JavaBean对象
            // 参数2:Map<String, ? extends Object> properties map集合
            // map集合的key和对象的成员变量名要一致才会封装
            BeanUtils.populate(user,map);

            System.out.println("封装后:" + user);
        } catch(Exception e){
            e.printStackTrace();
        }

只要满足三个条件的类就是一个 JavaBean

  1. 类必须是 public 修饰的
  2. 类必须有 public 的无参数构造方法
  3. 成员变量必须提供对应的 setter & getter 方法

11 参数的乱码问题[★★★]

请求参数乱码的原因:编码和解码使用的码表不一样

  • 编码:将文本内容转换为二进制数据的过程 utf8或gbk
  • 解码:将二进制数据转换为文本的过程

Tomcat 默认使用的码表是欧洲码表:iso-8859-1 不支持汉字
解决:设置请求参数的(编码)码表,通过请求对象的方法设置
request.setcharacterEncoding("utf-8")
注意: 设置请求参数的编码方法不能在获取请求参数之后设置
Tomcat8.0开始,GET方式请求不需要考虑乱码问题了,如果使用Tomcat8.0之前的版本,则也需要手动处理乱码问题,详情参考:https://blog.csdn.net/lxf512666/article/details/52939573/

12 转发和重定向概述[★★★]

转发和重定向的作用:实现页面的跳转

实现转发和重定向的方法

  • 转发方法
    request.getRequestDispatcher("转发的页面地址").forward(request,response);
  • 重定向方法
    response.sendRedirect("转发地址")
  • 需求:使用转发和重定向实现页面跳转
  • Java 代码
@WebServlet(urlPatterns = "/one")
public class OneServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 实际开发会先处理业务逻辑

        // 转发到TwoServlet
        // 获得转发器对象
       	RequestDispatcher requestDispatcher = request.getRequestDispatcher("two");
        // 调用转发器的方法执行转发操作:页面跳转
        requestDispatcher.forward(request, response);

        // 简化代码
        request.getRequestDispatcher("two").forward(request, response);

        // 重定向到TwoServlet
        response.sendRedirect("two");
    }
}

13 转发和重定向的区别[★★★★]

区别转发重定向
地址栏不会变化会变成重定向的页面地址
跳转位置服务器内部执行的跳转浏览器端执行的跳转
请求次数1次2次
请求域数据不会丢失会丢失

面试题:
转发或重定向后续代码还会执行吗?

  • 会执行,但没有意义了,一般不会再后面编写代码

什么时候使用转发?什么时候使用重定向?

  • 如果需要请求域的数据,则只能只用转发,否则可以随便选择

14 Servlet 作用域概述[★★★]

作用域:
  服务器端的一小块内存区,底层结构就是一个map集合,用于 Servlet 之间共享数据
Servlet 的三个作用域:
  请求域、会话域、上下文域

  • 作用域相关方法
请求域相关方法作用
Object getAttribute(“键”)根据键从请求域中获得值
void setAttribute(“键”,Object数据)往请求域中存储键值对数据
void removeAttribute(“键”)根据键从请求域中删除键值对数据

15 请求域概述和演示[★★★]

请求域的作用范围:在同一次请求中有效

在这里插入图片描述

  • 需求:FirstServlet 创建一个键和值,转发到另一个 SecondServlet,从 SecondServlet 中取出键和值,并且输出。

  • FirstServlet 代码

@WebServlet(urlPatterns = "/first")
public class FirstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        // 往请求域中存储键值对数据
        request.setAttribute("username", "lily");
        // 转发到second
        request.getRequestDispatcher("second").forward(request, response);

        // 重定向second
        // response.sendRedirect("second");
    }
}
  • SecondServlet 代码
@WebServlet(urlPatterns = "/second")
public class SecondServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
         // 设置内容类型和编码
         response.setContentType("text/html;charset=utf-8");
         // 获得字符打印流
         PrintWriter out = response.getWriter();
         
         // 从请求域中获取数据
        Object username = request.getAttribute("username");
        out.println("用户名:" + username);
    }
}

16 案例:实现登陆功能-功能分析和环境搭建[★★★]

  • 需求
    1.用户名和密码正确,将用户信息保存再请求域中,转发到另一个 Servlet,显示用户登陆成功
    2.用户名和密码错误,重定向到另一个 html 页面,显示登陆失败
    3.使用表示层,业务层,数据访问层的三层结构实现
  • 案例流程图
    在这里插入图片描述
  • 登陆页面 HTML 代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
<h2>用户登录</h2>
<form action="login" method="post">
    <table>
        <tr>
            <td>用户名</td>
            <td><input type="text" name="username"/></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="登录"/></td>
        </tr>
    </table>
</form>
</body>
</html>

17 案例:实现登录功能-控制器[★★★]

  • 步骤:
    1.接收请求参数:用户名和密码
    2.判断用户名和密码是否正确
    3.用户名密码正确跳转转发到欢迎页面(Servlet),获取用户名显示信息
    4.不正确跳转重定向到失败页面(html)

  • LoginServlet 代码

@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置请求参数的编码
        request.setCharacterEncoding("utf-8");

        // 接收请求参数:用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 判断用户名和密码是否正确:admin  123
        if ("admin".equals(username) && "123".equals(password)) {

            // 往请求域中存储数据:用户数据(用户对象)
            request.setAttribute("username", username);
            // 用户名和密码正确则跳转到欢迎页面(Servlet):获取用户信息显示
            request.getRequestDispatcher("welcome").forward(request,response);

            return;
        }

        // 用户名和密码不正确则跳转到失败页面(html)
        response.sendRedirect("login.html");
    }
}

  • WelcomeServlet 代码
@WebServlet(urlPatterns = "/welcome")
public class WelcomeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置内容类型和编码
        response.setContentType("text/html;charset=utf-8");
        // 获得打印字符流
        PrintWriter out = response.getWriter();

        // 从请求域获得用户名
        Object username = request.getAttribute("username");
        out.println("欢迎你回来:" + username);
    }
}

18 关于根目录使用说明[★★]

18_01 根目录 /

  • 需求:当浏览器访问OneServlet时转发或重定向到TwoServlet

/:代表根目录
/:如果使用在客户端(浏览器)则代表浏览器端的根目录
/:如果使用在服务器端则代表服务器端的根目录

浏览器端的根目录:http://localhost:8080/
服务器端的根目录:http://localhost:8080/项目访问地址/

总结

HTTP 协议的作用:用于浏览器和服务器之间数据传输


HTTP 协议的组成内容:请求(浏览器访问服务器)和响应(服务器返回数据给浏览器)


请求的组成:请求行、请求头、请求体


请求行的组成:请求方式、请求地址、协议和地址


请求头的含义:

  • referer:浏览器上一个访问的页面地址
  • If-Modified-Since:浏览器缓存页面的时间
  • user-agent:客户端的系统类型和浏览器类型

HTTPServletRequest 对象的作用:

  • 用来封装浏览器发送给服务器的所有数据

HTTPServletRequest 对象的常用方法:

  • 请求行方法:
      获取请求方式:String getMethod();
      获得项目访问地址:String getContextPath();
      获得协议版本:String getProtocol();
      获得统一资源标识符:String getRequestURL();
      获得统一资源定位符:StringBuffer getRequestURL();
      获取客户端 IP 地址:String getRemoteAddr();
  • 请求头方法:
      根据请求头名获得值:String getHeader(String headerName)
      获取所有请求头名字,返回迭代器对象:Enumeration getHeaderNames();
  • 请求参数方法(用户提交数据):
      根据参数名获得参数值:String getParameter(String name)
      根据参数名获得多个参数值:String[] getParameterValues(String name);
      获得所有请求参数名字:Enumeration getParameterNames();
      获得所有请求参数信息,返回Map集合:Map<String,String[]> getParameterMap();

BeanUtils工具类常用方法:
void populate(Object bean,Map<String,String[]> map);

  • 将map集合数据封装到指定的bean对象中
  • 要求:map键的名称和对象的成员变量名要一致

请求参数乱码的原因和解决方案:

  • 原因:Tomcat默认使用欧洲码表:iso-8859-1 不支持汉字
  • 解决:在获取请求参数之前设置请求参数编码:request.setCharacterEncoding("utf8");

转发和重定向:

  • 作用:用于页面跳转
  • 方法:
     转发:request.getRequestDispatcher("要跳转的页面地址").forward(request,response);
     重定向:response.sendRedirect("要跳转的页面地址");

Servlet 的作用域:

  • 概念:服务器内部的一小块内存区
  • 作用:用于 servlet 之间共享数据,底层是map结构
  • 分类:请求域、会话域、上下文域

Request 域对象(三个方法)

  • 往作用域中存储数据:request.setAttribute(String key,Object value)
  • 根据键从作用域中获取数据:request.getAttribute(String key)
  • 根据键从作用域删除键值对:request.removeAttribute(String key)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值