前言:了解了Servlet的快速入门,这里开始正式学习Request&Response对象
一、Request和Response介绍
- Request是请求对象
在后台服务器接收到请求后,后台服务器会对HTTP请求[请求行+请求头+请求体] 中的数据进行解析并把解析结果存入到一个对象中,这个对象就是Request对象
- Response是响应对象
在处理完逻辑后,会把响应数据封装到Response对象中,后台服务器会解析Response对象,按照HTTP请求[响应行+响应头+响应体]格式拼接结果;在前端页面中,我们可以通过response.data拿到其中的数据。
二、Request
2.1 HTTP请求报文的组成
2.2 Request继承体系
-
当Servlet类实现的是Servlet接口的时候,service方法中的参数是ServletRequest和ServletResp
-
当Servlet类继承的是HttpServlet类的时候,doGet和doPost方法中的参数就变成HttpServletRequest和HttpServletReponse
这里说一下Request的继承体系:ServletRequest -> HttpServletRequest -> RequestFacade
2.3 Request获取请求数据
这里讲下通过Request获取请求行数据、请求头数据、请求体数据。
2.3.1 获取请求行数据
-
获取请求方式: GET
String getMethod()
-
获取虚拟目录(项目访问路径): /json
String getContextPath()
-
获取URL(统一资源定位符):http://localhost:8080/json/a.html
StringBuffer getRequestURL()
-
获取URI(统一资源标识符):/json/a.html
String getRequestURI()
-
获取请求参数(GET方式): username=ls&password=123
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():获取虚拟目录(项目访问路径):/json
String contextPath = req.getContextPath();
System.out.println(contextPath);
// StringBuffer getRequestURL():
//获取URL(统一资源定位符):http://localhost:8080/json/a.html
StringBuffer url = req.getRequestURL();
System.out.println(url.toString());
// String getRequestURI():获取URI(统一资源标识符):/json/a.html
String uri = req.getRequestURI();
System.out.println(uri);
// String getQueryString():获取请求参数(GET方式):username=ls&password=123
String queryString = req.getQueryString();
System.out.println(queryString);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
2.3.2 获取请求头数据
在请求头中,数据的存储方式为键值对格式,当我们获取值的时候需要用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.3.3 获取请求体数据
-
获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
ServletInputStream getInputStream()
- 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
BufferedReader getReader()
下面是代码实现
/**
* request 获取请求数据
*/
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取post 请求体:请求参数
//1. 获取字符输入流
BufferedReader br = req.getReader();
//2. 读取数据
String line = br.readLine();
System.out.println(line);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
2.3.4 请求转发
请求转发是一种在服务器内部的资源跳转方式,其流程如下
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发
代码实现:
req.getRequestDispatcher("资源B路径").forward(req,resp);
在请求转发的过程中,也可以共享数据,这里需要用到三个方法。
-
存储数据到request域中
void setAttribute(String name,Object o);
-
根据key获取值
Object getAttribute(String name);
-
根据key删除该键值对
void removeAttribute(String name);
2.3.5 乱码问题
乱码出现的原因是在请求发送到服务器时,在获取流的时候采用的编码是ISO-8859-1,而且ISO-8859-1编码是不支持中文的,所以会出现乱码。
所以需要在获取流数据之前的编码设置为UTF-8。
代码实现为:
request.setCharacterEncoding("UTF-8");
2.3.6 小结
-
请求行
-
getMethod()获取请求方式
-
getContextPath()获取项目访问路径
-
getRequestURL()获取请求URL
-
getRequestURI()获取请求URI
-
getQueryString()获取GET请求方式的请求参数
-
-
请求头
-
getHeader(String name)根据请求头名称获取其对应的值
-
-
请求体
-
注意: 浏览器发送的POST请求才有请求体
-
如果是纯文本数据:getReader()
-
如果是字节数据如文件数据:getInputStream()
-
三、Response
3.1 Response体系结构
Reponse的继承体系和Request的继承体系也非常相似
3.2 Response
HTTP响应数据总共分为三部分内容,分别是响应行、响应头、响应体。respone对象分别提供了三种方法,分别来设置这三部分。
- 响应行
响应头为:HTTP/1.1 200 OK
HTTP协议/及版本 响应状态码 状态码描述
设置的方法为:
void setStatus(int sc);
- 响应头
响应头为:Content-Type:text/html
键 值
设置的方法为:
void setHeader(String name,String value);
- 响应体
响应体为:<html></html>
设置的方法为:
获取字符输出流:
PrintWriter getWriter();
获取字节输出流:
ServletOutputStream getOutputStream();
3.2 Respones请求重定向
Response重定向是一种资源跳转方式,实现步骤如下
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向
代码实现:
response.setStatus(302);
response.setHeader("Location","/request-demo/resp2");
3.3 请求转发和重定向的特点
具体如下
3.4 Response响应数据
- 响应字符数据
步骤为:
1)通过Response对象获取字符输出流:
PrintWriter writer = resp.getWriter();
2)通过字符输出流写数据:
writer.write("aaa");
***当返回html字符串的时候,需要在字符输出流输出前写
***一次请求响应结束后,response对象就会被销毁掉,所以不要手动关闭流。
response.setHeader("content-type","text/html");
- 响应字节数据
1)通过Response对象获取字节输出流:
ServletOutputStream outputStream = resp.getOutputStream();
2)通过字节输出流写数据:
outputStream.write(字节数据);
这里举个例子:返回一个图片文件到浏览器
/**
* 响应字节数据:设置字节数据的响应体
*/
@WebServlet("/resp4")
public class ResponseDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 读取文件
FileInputStream fis = new FileInputStream("d://a.jpg");
//2. 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
//3. 完成流的copy
byte[] buff = new byte[1024];
int len = 0;
while ((len = fis.read(buff))!= -1){
os.write(buff,0,len);
}
fis.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
***我们可以导入jar包,把步骤进行化简
步骤为
(1)pom.xml添加依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
(2)调用工具类方法
//fis:输入流
//os:输出流
IOUtils.copy(fis,os);
3)优化后的代码为
/**
* 响应字节数据:设置字节数据的响应体
*/
@WebServlet("/resp4")
public class ResponseDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 读取文件
FileInputStream fis = new FileInputStream("d://a.jpg");
//2. 获取response字节输出流
ServletOutputStream os = response.getOutputStream();
//3. 完成流的copy
IOUtils.copy(fis,os);
fis.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
三、总结
这篇文章主要讲Request和Response对象的介绍、以及内部的API,我觉得这些知识是学习后面知识的基础,建议多看多练。(今天学校停电,用电脑仅剩的电量写完的...)