Request&Response(1)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Request&Response

1,Request和Response的概述

==Request是请求对象,Response是响应对象。==这两个对象在我们使用Servlet的时候有看到:

此时,我们就需要思考一个问题request和response这两个参数的作用是什么?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-acHIJZYD-1686564906061)(null)]

  • request:获取请求数据
  • 浏览器会发送HTTP请求到后台服务器[[Tomcat&Servlet#Tomcat|Tomcat]]
  • HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
  • 后台服务器[[Tomcat&Servlet#Tomcat|Tomcat]]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
  • 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
  • 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
  • response:设置响应数据
  • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
  • 把响应数据封装到response对象中
  • 后台服务器[[Tomcat&Servlet#Tomcat|Tomcat]]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
  • 浏览器最终解析结果,把内容展示在浏览器给用户浏览

对于上述所讲的内容,我们通过一个案例来初步体验下request和response对象的使用。

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用request对象 获取请求数据
        String name = request.getParameter("name");//url?name=zhangsan
        //使用response对象 设置响应数据
        response.setHeader("content-type","text/html;charset=utf-8");
        response.getWriter().write("<h1>"+name+",欢迎您!</h1>");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Post...");
    }
}

启动成功后就可以通过浏览器来访问,并且根据传入参数的不同就可以在页面上展示不同的内容:

小结

在这节中,我们主要认识了下request对象和reponse对象:

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

目前我们只知道这两个对象是用来干什么的,那么它们具体是如何实现的,就需要我们继续深入的学习。接下来,就先从Request对象来学习,主要学习下面这些内容:

  • request继承体系
  • request获取请求参数
  • request请求转发

2,Request对象

2.1 Request继承体系

在学习这节内容之前,我们先思考一个问题,前面在介绍Request和Reponse对象的时候,比较细心的同学可能已经发现:

  • 当我们的Servlet类实现的是Servlet接口的时候,service方法中的参数是ServletRequest和ServletResponse
  • 当我们的Servlet类继承的是HttpServlet类的时候,doGet和doPost方法中的参数就变成HttpServletRequestHttpServletReponse

那么,

  • ServletRequest和HttpServletRequest的关系是什么?
  • request对象是有谁来创建的?
  • request提供了哪些API,这些API从哪里查?

首先,我们先来看下Request的继承体系:

从上图中可以看出,ServletRequest和HttpServletRequest都是Java提供的,所以我们可以打开JavaEE提供的API文档[参考: 资料/JavaEE7-api.chm],打开后可以看到:

所以ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法创建对象,这个时候就引发了下面这个问题:

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

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

对于上述结论,要想验证,可以编写一个Servlet,在方法中把request对象打印下,就能看到最终的对象是不是RequestFacade,代码如下:

@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(request);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

启动服务器,运行访问http://localhost:8080/request-demo/demo2,得到运行结果:

小结

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

2.2 Request获取请求数据

HTTP请求数据总共分为三部分内容,分别是请求行、请求头、请求体,对于这三部分内容的数据,分别该如何获取,首先我们先来学习请求行数据如何获取?

[!quote]

![[Tomcat&Servlet#HTTP请求数据格式|HTTP请求数据格式]]

2.2.1 获取请求行数据

请求行包含三块内容,分别是请求方式请求资源路径HTTP协议及版本

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

  • 获取请求方式: GET

String getMethod()

  • 获取虚拟目录(项目访问路径): /request-demo

[!tip]

因为是动态的所以灵活度高

String getContextPath()

  • 获取URL(统一资源定位符): http://localhost:8080/request-demo/req1

StringBuffer getRequestURL()

  • 获取URI(统一资源标识符): /request-demo/req1

String getRequestURI()

  • 获取请求参数(GET方式): username=zhangsan&password=123

[!tip]

请求参数:问号后面的那一串

String getQueryString()

介绍完上述方法后,咱们通过代码把上述方法都使用下:

/**  
 * request 获取请求数据  
 */  
@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);//GET  
        // 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 {  
    }  
}

启动服务器,访问http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123,获取的结果如下:

这里我设置了路径

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 {  
    }  
}  

重新启动服务器后,http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123,获取的结果如下:

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 {  
    }  
}  
```
重新启动服务器后,`http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123`,获取的结果如下:
![1628o769145524](http://wn.linghanwu.com/img/1628769145524.png)
#### 2.2.3 获取请求体数据
浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST,请求体中的数据格式如下:
![162876866p5185](http://wn.linghanwu.com/img/1628768665185.png)
对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:
-   获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
    
`ServletInputStream getInputStream()`  
该方法可以获取字节
-   获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
    
`BufferedReader getReader()`
接下来,大家需要思考,要想获取到请求体的内容该如何实现?
> 具体实现的步骤如下:
> 
> 1.准备一个页面,在页面中添加form表单,用来发送post请求
> 
> 2.在Servlet的doPost方法中获取请求体数据
> 
> 3.在doPost方法中使用request的`getReader()`或者`getInputStream()`来获取
> 
> 4.访问测试
1.  在项目的webapp目录下添加一个html页面,名称为:`req.html`
    
```java
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
<!--   
    action:form表单提交的请求地址  
    method:请求方式,指定为post  
-->  
<form action="/request-demo/req1" method="post">  
    <input type="text" name="username">  
    <input type="password" name="password">  
    <input type="submit">  
</form>  
</body>  
</html>
  1. 在Servlet的doPost方法中获取数据
/**  
 * 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 {  
        //在此处获取请求体中的数据  
    }  
}
  1. 调用getReader()或者getInputStream()方法,因为目前前端传递的是纯文本数据,所以我们采用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);  
    }  
}

注意

BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,request对象被销毁后,BufferedReader流就会自动关闭,所以此处就不需要手动关闭流了。

  1. 启动服务器,通过浏览器访问http://localhost:8080/request-demo/req.html

点击提交按钮后,就可以在控制台看到前端所发送的请求数据

小结

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

  • 请求行
  • getMethod()获取请求方式
  • getContextPath()获取项目访问路径
  • getRequestURL()获取请求URL
  • getRequestURI()获取请求URI
  • getQueryString()获取GET请求方式的请求参数
  • 请求头
  • getHeader(String name)根据请求头名称获取其对应的值
  • 请求体
  • 注意: 浏览器发送的POST请求才有请求体
  • 如果是纯文本数据:getReader()
  • 如果是字节数据如文件数据:getInputStream()
2.2.4 获取请求参数的通用方式

在学习下面内容之前,我们先提出两个问题:

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

1.什么是请求参数?

为了能更好的回答上述两个问题,我们拿用户登录的例子来说明

1.1 想要登录网址,需要进入登录页面

1.2 在登录页面输入用户名和密码

1.3 将用户名和密码提交到后台

1.4 后台校验用户名和密码是否正确

1.5 如果正确,则正常登录,如果不正确,则提示用户名或密码错误

上述例子中,用户名和密码其实就是我们所说的请求参数

[[Tomcat&Servlet#^64b46d|请求参数]]

2.什么是请求数据?

请求数据则是包含请求行请求头请求体的所有数据

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

3.1 请求参数是请求数据中的部分内容

3.2 如果是GET请求,请求参数在请求行中

3.3 如果是POST请求,请求参数一般在请求体中

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

  • GET方式:

String getQueryString()

  • POST方式:

BufferedReader getReader();

有了上述的知识储备,我们来实现一个案例需求:

(1)发送一个GET请求并携带用户名,后台接收后打印到控制台

(2)发送一个POST请求并携带用户名,后台接收后打印到控制台

Request&Response(2)https://developer.aliyun.com/article/1530549

相关文章
|
5月前
|
应用服务中间件 数据安全/隐私保护
|
5月前
response.setcontenttype详解
response.setcontenttype详解
|
5月前
|
前端开发 Java 应用服务中间件
Request&Response(4)
Request&Response
39 0
|
5月前
|
Java 数据库连接 数据库
Request&Response(5)
Request&Response
49 0
|
5月前
|
Java Maven 数据安全/隐私保护
Request&Response(2)
Request&Response
45 0
|
5月前
|
存储 Java 应用服务中间件
Request&Response(3)
Request&Response
53 0
|
6月前
|
Java 数据库连接 数据库
Request 和 Response详解(下)
Request 和 Response详解(下)
74 1
|
6月前
|
存储 缓存 前端开发
Request 和 Response详解(中)
Request 和 Response详解(中)
82 0
|
6月前
|
前端开发 Java 应用服务中间件
Request 和 Response详解(上)
Request 和 Response详解(上)
126 0
|
存储
Request和Response详解
Request和Response详解
115 0