Request&Response

52 阅读6分钟

request和response这两个参数的作用

  • request:封装请求数据的对象

    • 浏览器会发送HTTP请求到后台服务器[Tomcat]
    • HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
    • 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
    • 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
    • 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
  • response:封装响应数据的对象

    • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
    • 把响应数据封装到response对象中
    • 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
    • 浏览器最终解析结果,把内容展示在浏览器给用户浏览

1. Request对象

1.1 Request继承体系:

image.png

Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的,所以Tomcat提供了方法参数接口的具体实现类,并完成了对象(RequestFacade)的创建。

小结

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

1.2 Request获取请求数据

获取请求行数据

image.png

获取请求头数据

image.png

获取请求体数据

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

  • 获取字节输入流,如果前端发送的是字节数据,如文件数据,用 ServletInputStream getInputStream()

  • 获取字符输入流,如果是纯文本数据,则使用该方法 BufferedReader getReader()
    BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,request对象被销毁后,BufferedReader流就会自动关闭,不需要手动关闭流。

请求参数和请求数据的关系是什么?

请求数据则是包含请求行、请求头和请求体的所有数据,请求参数是请求数据中的部分内容。
GET请求,请求参数在请求行中
POST请求,请求参数一般在请求体中

对于请求参数的获取

  • GET方式: String getQueryString()
  • POST方式: BufferedReader getReader();

request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可

  • 获取所有参数Map集合 Map<String,String[]> getParameterMap()
  • 根据名称获取参数值(数组) String[] getParameterValues(String name)
  • 根据名称获取参数值(单个值) String getParameter(String name)

中文乱码解决方案

  • POST请求和GET请求的参数中如果有中文,后台接收数据就会出现中文乱码问题

    GET请求在Tomcat8.0以后的版本就不会出现了

  • POST请求解决方案是:设置输入流的编码

    request.setCharacterEncoding("UTF-8");
    注意:设置的字符集要和页面保持一致
    
  • 通用方式(GET/POST):需要先解码,再编码

    new String(username.getBytes("ISO-8859-1"),"UTF-8");
    

1.3 Request请求转发

请求转发(forward):一种在服务器内部的资源跳转方式。
req.getRequestDispatcher("资源B路径").forward(req,resp);

image.png 3. 请求转发资源间共享数据:使用Request对象

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

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

  • 存储数据到request域[范围,数据是存储在request对象]中
void setAttribute(String name,Object o);
  • 根据key获取值
Object getAttribute(String name);
  • 根据key删除该键值对
void removeAttribute(String name);

请求转发的特点

  • 浏览器地址栏路径不发生变化

    虽然后台从/req5转发到/req6,但是浏览器的地址一直是/req5,未发生变化

  • 只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器

  • 一次请求,可以在转发资源间使用request共享数据

    虽然后台从/req5转发到/req6,但是这个只有一次请求

2. Response对象

2.1 Response设置响应数据功能介绍

  1. 响应行

image.png 对于响应头,比较常用的就是设置响应状态码:

void setStatus(int sc);
  1. 响应头

image.png

设置响应头键值对:

void setHeader(String name,String value);
  1. 响应体

image.png

对于响应体,是通过字符、字节输出流的方式往浏览器写,

获取字符输出流:

PrintWriter getWriter();

获取字节输出流

ServletOutputStream getOutputStream();

2.2 Respones请求重定向

一种资源跳转方式

image.png
resp.setStatus(302);
resp.setHeader("location","资源B的访问路径");
简化版写法:
resposne.sendRedirect("/request-demo/resp2")

重定向的特点

  • 浏览器地址栏路径发生变化
    当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化

  • 可以重定向到任何位置的资源(服务器内、外部均可)

  • 两次请求,不能在多个资源使用request共享数据
    因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据

image.png

2.3 路径问题

  • 浏览器使用:需要加虚拟目录(项目访问路径)
  • 服务端使用:不需要加虚拟目录

对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录
对于重定向来说,路径最终是由浏览器来发送请求,就需要添加虚拟目录。
可以动态获取项目访问的虚拟路径,从而降低代码的耦合度。

        //简化方式完成重定向
        //动态获取虚拟目录
        String contextPath = request.getContextPath();
        response.sendRedirect(contextPath+"/resp2");

2.4 Response响应字符数据

        // 返回一个简单的字符串`aaa`
        response.setContentType("text/html;charset=utf-8");
        //1. 获取字符输出流
        PrintWriter writer = response.getWriter();
		 writer.write("aaa");
// 返回一串html字符串,并且能被浏览器解析
PrintWriter writer = response.getWriter();
//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
response.setHeader("content-type","text/html");
writer.write("<h1>aaa</h1>");
// 返回中文字符串
//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");

2.5 Response响应字节数据

对于流的copy的代码是比较复杂的,所以我们可以导入依赖,使用别人提供好的方法来简化代码的开发。