javaWeb中的Request对象

220 阅读9分钟

Request对象概述

方向: 浏览器 -> 服务器

负责获取客户端的请求数据

request对象是从客户端向服务器发出请求,包括用户提交的信息以及客户端的一些信息。客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据,然后服务器通过request对象的相关方法来获取这些数据。

  • 查看Servlet中的service方法得知, Servlet中使用的ServletRequest接口, 而我们使用的是ServletRequest的子接口HttpServletRequest, 它继承自ServletRequest, 是与HTTP协议相关的Request请求对象
  • 我们使用的子接口HttpServletRequest, 此接口对象由Tomcat引擎提供
  • 可以实现客户端向服务器发出请求, 请求内容包括: 请求行,请求头,请求体

http请求
在这里插入图片描述

Request对象获取请求行

  • API
方法返回值描述
getMethod()String获取提交的方式 (GET,POST)
getRequestURI()String获取请求的参数,请求服务器路径
getRequestURL()StringBuffer获取请求的参数,请求服务器路径
getQueryString()String获取请求行 问号后面的参数 (GET)
getContextPath()String获取WEB应用名称
  • 代码演示
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //request对象方法 getMethod()获取客户端的请求方式
    String method = request.getMethod();
    System.out.println(method);
    //方法 String getRequestURI() 获取请求服务器路径
    //方法 StringBuffer getRequestURL() 获取请求服务器路径
    String URI = request.getRequestURI();
    StringBuffer URL = request.getRequestURL();
    System.out.println("URI=="+URI);//   /web04/line
    System.out.println("URL=="+URL);//  http://localhost:8080/web04/line

    //方法 String getQueryString()获取请求行,?后面的所有参数
    String query = request.getQueryString();
    System.out.println(query);//user=tom&pass=123&

    //获取WEB应用名称  String getContextPath()
    String path = request.getContextPath();
    System.out.println(path);//   /web04
    //获取WEB应用名称, 结合重定向使用
    //response.sendRedirect(request.getContextPath()+"/ddd");
}

Request对象获取请求头

​ 请求头数据格式键值对, k:v

​ 指导性信息,指导服务器

方法返回值描述
getHeader(String name)String获得一个key对应一个value的请求头
getHeaderNames()Enumeration获取所有的请求头的键
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     * Enumeration getHeaderNames() 获取所有的请求头的键
     * 返回值Enumeration接口 (向量枚举)
     * 集合:1.0-1.1 Enumeration    集合1.2  迭代器
     * Iterator迭代器接口:  hasNext()   next()
     * Enumeration接口:  hasMoreElement()  nextElement()
     */
    Enumeration<String> enums  = request.getHeaderNames();
    while (enums.hasMoreElements()){
         key = enums.nextElement();
         String value = request.getHeader(key);
        System.out.println(key+"=="+value);
    }
}

Request获取请求参数

方法返回值描述
getParameter(表单中的name值)String获得提交的参数(一个name对应一个value)
getParameterValues(表单中的name值)String[]获得提交的参数(一个name对应多个value)
getParameterMap()Map<String,String[]>获得提交的参数,将提交的参数名称和对应值存入到一个Map集合中
<body>
    <form action="/web02/param" method="post">
        用户名:<input type="text" name="username"><br/>
        密 码:<input type="password" name="password"><br/>
        爱 好:<input type="checkbox" name="hobby" value="Basketball">篮球
                <input type="checkbox" name="hobby" value="football">足球
                <input type="checkbox" name="hobby" value="pingpang">乒乒球 <br/>
        <input type="submit">
    </form>
</body>
@WebServlet(urlPatterns = "/param")
public class ParamServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获得提交的参数(一个name对应一个value)
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println(username +" == " +password);
        //获得提交的参数(一个name对应多个value)
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("hobbies = " + Arrays.toString(hobbies));
        //获得提交的参数,将提交的参数名称和对应值存入到一个Map集合中
        Map<String, String[]> map = request.getParameterMap();
        for(String key : map.keySet()){
            String[] values = map.get(key);
            System.out.println(key + " == " + Arrays.toString(values));
        }
    }

Request对象接收表单请求参数的中文乱码处理

POST方式接收中文

  • 产生乱码的原因:

    • post方式提交的数据是在请求体中,request对象接收到数据之后,放入request的缓冲区中。缓冲区就有编码(默认ISO-8859-1:不支持中文).
  • 解决方案:

    • 将request的缓冲区的编码修改了即可。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //将request的缓冲区的编码修改
    request.setCharacterEncoding("utf-8");

    //获取请求参数
    String user = request.getParameter("user");
    System.out.println("user = " + user);
}

GET方式接收中文

Tomcat8.5版本之后, Tomcat自动处理了get请求的中文乱码问题

但在Tomcat8.5之前的版本中, get请求的中文乱码需要自行处理

  • 产生乱码原因:

    • get方式提交的数据在请求行的url后面,在地址栏上其实就已经进行了一次URL的编码了。
  • 解决方案:

    • 将存入到request缓冲区中的值以ISO-8859-1的方式获取到,以UTF-8的方式进行解码。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     get方式提交的数据在 请求行中
     Tomcat8.5之后, Tomcat自动处理了get请求的中文乱码问题, 但在之前的Tomcat版本中,get请求的中文乱码需要自行处理
     老版本Tomcat中文乱码的解决:将存入到request缓冲区中的值以ISO-8859-1的方式获取到,以UTF-8的方式进行解码。
     */
    String user = request.getParameter("username"); //

    //将存入到request缓冲区中的值以ISO-8859-1的方式获取到
    byte[] bytes = user.getBytes("iso-8859-1");
    //以UTF-8的方式进行解码
    String value = new String(bytes, "utf-8");

    System.out.println("user = " + user);
}

BeanUtils 将 map中的数据封装到 pojo类中

导包

在这里插入图片描述

pojo类

package cn.itcast.pojo;

import java.util.Arrays;

public class User {
    private String username;
    private String password;
    private String[] hobby;

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

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

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

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }
}

页面

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/web0202/demo15" method="post">
    用户名:<input type="text" name="username"><br/>
    密 码:<input type="password" name="password"><br/>
    爱 好:<input type="checkbox" name="hobby" value="Basketball">篮球
    <input type="checkbox" name="hobby" value="football">足球
    <input type="checkbox" name="hobby" value="pingpang">乒乒球 <br/>
    <input type="submit">
</form>
</body>
</html>

servlet

package cn.itcast.web;

import cn.itcast.pojo.User;
import org.apache.commons.beanutils.BeanUtils;

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.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/demo15")
public class ServletDemo15 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决服务器给浏览器的数据中文乱码问题
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        Map<String, String[]> parameterMap = request.getParameterMap();
        User user = new User();
        try {
            BeanUtils.populate(user, parameterMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(user);

    }

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

原理

通过map的key值得到set方法的名字,利用反射技术调用set方法,将value值传入
在这里插入图片描述

Request域对象

Request作为域对象的API

Request作为域对象作用范围

Request对象其实就是从客户端浏览器向服务器发送的一次请求信息的封装。那么实质上向Request中所保存的数据有效期也是一次请求范围。

一次请求范围:从客户端浏览器向服务器发送一次请求,服务器针对这次请求对浏览器作出响应。当服务器作出响应之后,请求对象就销毁了,保存在其中的数据就无效了。

如果是两次请求,那么两个request对象是不一样的,所以一个里面存储的内容另外一个是获取不到的
但是如果是一次请求,而这个请求,服务器进行转发的之后,依然是一个request对象,那么他们中存储的对象则是可以被获取到的

每次请求都会创建新的request对象, 当响应结束后立刻销毁request对象.

  • API
方法返回值描述
setAttribute(String name, Object obj)void向Request域中保存数据
getAttribute(String name)Object从Request域中获取数据
removeAttribute(String name)void从Request域中移除数据
  • 代码演示

servlet1

@WebServlet(urlPatterns = "/my1")
public class MyServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //向request域对象中 存值
        request.setAttribute("language","java");
        //从request域对象中 取值
        Object value = request.getAttribute("language");
        System.out.println("MyServlet1 value = " + value);
    }

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

servlet2

@WebServlet(urlPatterns = "/my2")
public class MyServlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从request域对象中 取值
        Object value = request.getAttribute("language");
        System.out.println("MyServlet2 value = " + value);
    }

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

请求转发

请求转发的写法

通过ServletRequest对象获得RequestDispatcher对象

方法返回值描述
getRequestDispatcher(String path)RequestDispatcher获得RequestDispatcher对象

再根据RequestDispatcher中的方法进行请求转发

方法返回值描述
forward(ServletRequest request, ServletResponse response)void进行请求转发

转发的实现步骤

  • request对象方法获取转发器 RequestDispatcher getRequestDispatcher(“转发地址”)返回值就是转发器
  • 使用转发器对象的方法 forward

代码实现

servlet1

@WebServlet(urlPatterns = "/my1")
public class MyServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //向request域对象中 存值
        request.setAttribute("language","java");
        //从request域对象中 取值
        Object value = request.getAttribute("language");
        System.out.println("MyServlet1 value = " + value);

        //进行请求转发
        request.getRequestDispatcher("/my2").forward(request, response);
    }

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

servlet2

@WebServlet(urlPatterns = "/my2")
public class MyServlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从request域对象中 取值
        Object value = request.getAttribute("language");
        System.out.println("MyServlet2 value = " + value);

        //响应回浏览器
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("我是MyServlet2 页面数据");
    }

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

9 请求转发和重定向区别

  • 请求转发是一次请求一次响应,而重定向是两次请求两次响应。
  • 请求转发地址栏不会变化的,重定向地址栏发生变化。
  • 请求转发路径不带工程名,重定向需要带工程名路径。
  • 请求转发只能在本网站内部,重定向可以定向到任何网站。

9.2 代码演示

MyServlet1

@WebServlet(urlPatterns = "/my1")
public class MyServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //向request域对象中 存值
        request.setAttribute("language","java");
        //从request域对象中 取值
        Object value = request.getAttribute("language");
        System.out.println("MyServlet1 value = " + value);

        //进行请求转发
        //request.getRequestDispatcher("/my2").forward(request, response);
        //进行重定向
        response.sendRedirect("/web02/my2");
    }

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

MyServlet2

@WebServlet(urlPatterns = "/my2")
public class MyServlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从request域对象中 取值
        Object value = request.getAttribute("language");
        System.out.println("MyServlet2 value = " + value);

        //响应回浏览器
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("我是MyServlet2 页面数据");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 注意:

    • 如果需要使用request进行值传递,需要通过请求转发完成。
    • 如果页面需要跳转到其他网站上必须使用重定向, 不能使用request进行值传递。

客户端与服务器端地址的写法

  • 什么是客户端地址:客户端直接访问服务器的地址是客户端地址

    • 通过客户端访问web应用 地址必须加上web应用的名称
  • 什么是服务器端地址:web应用内部访问的地址是服务器端地址

    • 特点,访问时,不用写web应用名称
  • 写地址时, 怎么区分是否加上web应用的名称

    • 看在web应用内, 还是外

      • 客户端地址

        • 直接在地址栏中写url地址 — 客户端地址
        • 标签的href — 客户端地址
        • form表单的action-----客户端地址
        • location.href ---- 客户端地址
        • response响应对象的重定向 sendRedirect( 地址) -----客户端地址
      • 目前记住一个服务器端地址:

        • Request请求对象的请求转发getRequestDispatcher(转发地址) — 服务器端地址
        • servlet的映射路径— 也是服务端地址