JavaWeb—Request请求对象

  • Post author:
  • Post category:java



目录


一、概述


二、Request对象


2.1 Request继承体系


小结


2.2 Request获取请求数据


2.2.1 获取请求行数据


2.2.2 获取请求头数据


2.2.3 获取请求体数据


小结


2.2.4 获取请求参数的通用方式


小结


2.3 IDEA快速创建Servlet


2.4 请求参数中文乱码问题


2.4.1 POST请求解决方案


2.4.2 GET请求解决方案


小结


2.5 Request请求转发



一、概述



Request是请求对象,Response是响应对象。

  • request:


    获取请求数据

○浏览器会发送HTTP请求到后台服务器[Tomcat]

○HTTP的请求中会包含很多请求数据 [请求行+请求头+请求体]

○所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数

○获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务

  • response:


    设置响应数据

○业务处理完后,后台就需要给前端返回业务处理的结果,即响应数据

○把响应数据封装到response对象中

○后台服务器][Tomcat]会解析response对象,按照 [响应行+响应头+响应体]格式拼接结果

○浏览器最终解析结果,把内容展示在浏览器给用户浏览



小结:

  • request对象是用来封装请求数据的对象
  • response对象是用来封装响应数据的对象


二、Request对象



1. request原理:

  • request和response对象是由服务器创建的。我们来使用它们
  • request对象是来获取请求消息,response对象是来设置响应消息



2. request 对象继承体系结构:



3. request功能:

  • 获取请求消息数据

①获取请求行数据

②获取请求头数据


③获取请求体数据

  • 其他功能


2.1 Request继承体系

这个时候,我们就需要用到Request继承体系中的


RequestFacade


  • 该类实现了HttpServletRequest接口,也间接实现了ServletRequest接口。
  • Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat] 来调用的,所以Tomcat提供了方法参数接口的具体实现类,并完成了对象的创建
  • 要想了解RequestFacade中都提供了哪些方法,可以直接查看JavaEE的API文档中关于 ServletRequest和HttpServletRequest的接口文档,因为RequestFacade实现了其接口就 需要重写接口中的方法


小结

  • Request的继承体系为ServletRequest–>HttpServletRequest–>RequestFacade
  • Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法
  • 使用request对象,可以查阅JavaEE API文档的HttpServletRequest接口中方法说明


2.2 Request获取请求数据

HTTP请求数据总共分为三部分内容,分别是

请求行、请求头、请求体

,对于这三部分内容的数据,分别该如何获取

2.2.1 获取请求行数据

请求行包括三块内容,分别是

请求方式



请求资源路径



HTTP协议及版本

对于这三部分内容,request对象都提供了对应的API方法来获取,具体如下:

  • 获取请求方式:

    GET

String getMethod()

  • 获取虚拟目录(项目访问路径):

    /request-demo

String getContextPath()

  • 获取URL(统一资源定位符):

    http://localhost:8080/request-demo/req1

StringBuffer getRequestURL()

  • 获取URI(统一资源标识符):

    /request-demo/req1

String getRequestURI

  • 获取请求参数(GET方式):

    username=zhangsan&password=123

String getQueryString()

package com.learn.web;

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;

/**
 * @author 咕咕猫
 * @version 1.0
 */

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // String getMethod():获取请求方式: GET
        String method = req.getMethod();
        System.out.println(method);

        // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
        String contextPath = req.getContextPath();
        System.out.println(contextPath);

        // StringBuffer getRequestURL(): 获取URL(统一资源定位符)http://localhost:8080/request-demo/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url.toString());

        // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
        String uri = req.getRequestURI();
        System.out.println(uri);

        // String getQueryString():获取请求参数(GET方式): username=zhangsan
        String queryString = req.getQueryString();
        System.out.println(queryString);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

2.2.2 获取请求头数据

对于请求头的数据,格式为

key:value

如下:

  • 根据请求头名称获取对应值的方法为

String getHeader(String name)

**
* request 获取请求数据
*/
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

        //获取请求头: user-agent: 浏览器的版本信息
        String agent = req.getHeader("user-agent");
        System.out.println(agent);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
    }
}

2.2.3 获取请求体数据

浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST,请求体中的数据格式如下:

对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:

  • 获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法

ServletInputStream getInputStream()

该方法可以获取字节

  • 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法

BufferedReader getReader()

**
* request 获取请求数据
*/
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
        //获取post 请求体:请求参数
        //1. 获取字符输入流
        BufferedReader br = req.getReader();
        //2. 读取数据
        String line = br.readLine();
        System.out.println(line);
    }
}



小结


HTTP请求数据中包含了请求行、请求头、请求体,针对三部分内容,Request对象都提供了对应的API方法来获取对应的值:

2.2.4 获取请求参数的通用方式

对于请求参数的获取,常用的有以下两种

  • GET方式

String getQueryString()

  • POST方式

BufferedReader gerReader()

基于上述理论,request对象为我们提供了如下方法:

  • 获取所有参数Map集合

Map getParameterMap()

  • 根据名称获取参数值(数组)

String[] getParameterValues(String name)

  • 根据名称获取参数值(单个值)

String getParameter(String name)

通过案例来把上述的三个方法进行实例演示:

1.修改req.html页面,添加爱好选项,爱好可以同时选多个

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/request_demo/req2" method="get">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="checkbox" name="hobby" value="1">游泳
    <input type="checkbox" name="hobby" value="2">爬山<br>
    <input type="submit">

</form>

</body>
</html>

2.在Servlet代码中获取页面传递GET请求的参数值

  • 获取GET方式的所有请求参数
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求逻辑
        System.out.println("get...");

        //1. 获取所有参数的map
        Map<String, String[]> map = req.getParameterMap();
        for (String key : map.keySet()) {
            //username:zhangsan
            System.out.print(key + ":");

            //获取值
            String[] values = map.get(key);
            for (String value : values) {
                System.out.print(value + " ");
            }

            System.out.println();
        }

  • 获取GET请求参数中的爱好,结果是数组值
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求逻辑
        //2.根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
    }

  • 获取GET请求参数中的用户名和密码,结果是单个值
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求逻辑
        //3.根据key获取单个参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username);
        System.out.println(password);
    }



小结


  • req.getParameter()方法使用的频率会比较高
  • 再写代码的时候,就只需要按照如下格式来编写
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
        //采用request提供的获取请求参数的通用方式来获取请求参数
        //编写其他的业务代码...
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

完整代码

package com.learn.web;

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.Map;

/**
 * @author 咕咕猫
 * @version 1.0
 */
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求逻辑
        System.out.println("get...");

        //1. 获取所有参数的map
        Map<String, String[]> map = req.getParameterMap();
        for (String key : map.keySet()) {
            //username:zhangsan
            System.out.print(key + ":");

            //获取值
            String[] values = map.get(key);
            for (String value : values) {
                System.out.print(value + " ");
            }

            System.out.println();
        }

        System.out.println("----------------------");

        //2.根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }

        //3.根据key获取单个参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username);
        System.out.println(password);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //POST请求逻辑
        this.doGet(req,resp);

        /*System.out.println("post...");
        //1. 获取所有参数的map
        Map<String, String[]> map = req.getParameterMap();
        for (String key : map.keySet()) {
            //username:zhangsan
            System.out.print(key + ":");

            //获取值
            String[] values = map.get(key);
            for (String value : values) {
                System.out.print(value + " ");
            }

            System.out.println();
        }

        System.out.println("----------------------");

        //2.根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }

        //3.根据key获取单个参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username);
        System.out.println(password);*/

    }
}


2.3 IDEA快速创建Servlet


2.4 请求参数中文乱码问题

2.4.1 POST请求解决方案

  • 分析出现中文乱码的原因:

○POST的请求参数是通过request的getReader()来获取流中的数据

○TOMCAT在获取流的时候采用的编码是ISO-8859-1

○ISO-8859-1编码是不支持中文的,所以会出现乱码

  • 解决方案:

○页面设置的编码格式为UTF-8

○把TOMCAT在获取流数据之前的编码设置为UTF-8

○通过request.setCharacterEncoding(“UTF-8”)设置编码,UTF-8也可以写成小写

@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 解决乱码:POST,getReader()
        request.setCharacterEncoding("UTF-8");//设置字符输入流的编码

        //2. 获取username
        String username = request.getParameter("username");
        System.out.println(username);
    }

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

2.4.2 GET请求解决方案

package com.itheima.web.request;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

public class URLDemo {

    public static void main(String[] args) throws UnsupportedEncodingException {
        String username = "张三";

        //1. URL编码
        String encode = URLEncoder.encode(username, "utf-8");
        System.out.println(encode);

        //2. URL解码
        //String decode = URLDecoder.decode(encode, "utf-8");
        String decode = URLDecoder.decode(encode, "ISO-8859-1");

        System.out.println(decode);

        //3. 转换为字节数据,编码
        byte[] bytes = decode.getBytes("ISO-8859-1");
      /*  for (byte b : bytes) {
            System.out.print(b + " ");
        }*/

        //4. 将字节数组转为字符串,解码
        String s = new String(bytes, "utf-8");

        System.out.println(s);


    }
}

GET请求中文参数出现乱码的原因

1. 浏览器把中文参数按照UTF-8进行URL解码

2. Tomcat对获取到的内容进行了ISO-8859-1的URL解码

3. 在控制台就会出现类上å¼ ä¸ 的乱码

package com.learn.web; /**
 * @author 咕咕猫
 * @version 1.0
 * 中文乱码解决方案
 */

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 解决乱码:POST,getReader()
//        request.setCharacterEncoding("UTF-8");//设置字符输入流的编码

        //2. 获取username
        String username = request.getParameter("username");
        System.out.println("解决乱码前:"+username);


        //3. GET,获取参数的方式:getQueryString
        // 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
//        //3.1 先对乱码数据进行编码:转为字节数组
//        byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
//        //3.2 字节数组解码
//        username = new String(bytes, StandardCharsets.UTF_8);

        username = new String(username.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        System.out.println("解决乱码后:"+username);
    }

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



小结


1. 中文乱码解决方案

  • POST请求和GET请求的参数中如果有中文,后台接受数据就会出现中文乱码问题,GET请求在Tomcat8.0以后的版本就不会出现了
  • POST请求解决的方法是:设置输入流的编码

request.setCharacterEncoding(“UTF-8”);

注意:设置的字符集要和页面保持一致

  • 通用方式(GET/POST):需要先解码,再编码

new String(username.getBytes(“ISO-8859-1″),”UTF-8”);

2. URL编码实现方式

  • 编码:

URLEncoder.encode(str,”UTF-8″);

  • 解码:

URLDecoder.decode(s,”ISO-8859-1″);


2.5 Request请求转发

  • 请求转发(forward):一种在服务器内部的资源跳转方式

  • 请求转发的实现方式:



req.getRequestDispatcher(“资源B路径”).forward(request,response);

  • 请求转发资源间共享数据:使用Request对象

此处主要解决的问题是把请求从/req5转发到/req6的时候,如何传递数据给/req6。

需要使用request对象提供的三个方法:

存储数据到request域[范围,数据是存储在request对象]中

void setAttribute(String name,Object o);

根据key获取值

Object getAttribute(String name);

根据key删除该键值对

void removeAttribute(String name);



版权声明:本文为weixin_61843013原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。