目录
1,Request和Response
Request是请求对象,Response是响应对象。
-
request:获取请求数据
-
浏览器会发送HTTP请求到后台服务器[Tomcat]
-
HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
-
后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
-
所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
-
获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
-
-
response:设置响应数据
-
业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
-
把响应数据封装到response对象中
-
后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
-
浏览器最终解析结果,把内容展示在浏览器给用户浏览
-
2,Request对象
2.1 Request继承体系
Request的继承体系:
- ServletRequest和HttpServletRequest都是Java提供的,
- ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法创建对象,
- RequestFacade继承自ServletRequest和HttpServletRequest,是tomcat服务器定义的接口实现类,Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用。
2.2 Request获取请求数据
HTTP请求数据中包含了请求行
、请求头
和请求体
,针对这三部分内容,Request对象都提供了对应的API方法来获取对应的值:
-
请求行
-
getMethod()获取请求方式
-
getContextPath()获取项目访问路径
-
getRequestURL()获取请求URL
-
getRequestURI()获取请求URI
-
getQueryString()获取GET请求方式的请求参数
-
-
请求头
-
getHeader(String name)根据请求头名称获取其对应的值
-
-
请求体
-
注意: 浏览器发送的POST请求才有请求体
-
如果是纯文本数据:getReader()
-
如果是字节数据如文件数据:getInputStream()
-
2.2.1 获取请求参数的通用方式
-
获取所有参数Map集合
Map<String,String[]> getParameterMap()
-
根据名称获取参数值(数组)
String[] getParameterValues(String name)
-
根据名称获取参数值(单个值)
String getParameter(String name)
2.3 请求参数中文乱码问题
不管是GET还是POST请求,在发送的请求参数中如果有中文,在后台接收的时候,都会出现中文乱码的问题。
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("/req4")
public class RequestDemo4 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请求解决方案
1. 乱码原因:
编码:
java.net.URLEncoder.encode("需要被编码的内容","字符集(UTF-8)")
解码:
java.net.URLDecoder.decode("需要被解码的内容","字符集(UTF-8)")
2. 解决步骤:
1.按照ISO-8859-1编码获取乱码
å¼ ä¸
对应的字节数组2.按照UTF-8编码获取字节数组对应的字符串
实现代码如下:
//3. 转换为字节数据,编码
byte[] bytes = decode.getBytes("ISO-8859-1");
for (byte b : bytes) {
System.out.print(b + " ");
}
//此处打印的是:-27 -68 -96 -28 -72 -119
//4. 将字节数组转为字符串,解码
String s = new String(bytes, "utf-8");
System.out.println(s); //此处打印的是张三
简化代码
new String(username.getBytes("ISO-8859-1"),"UTF-8");
注意
-
把
request.setCharacterEncoding("UTF-8")
代码注释掉后,会发现GET请求参数乱码解决方案同时也可也把POST请求参数乱码的问题也解决了 -
只不过对于POST请求参数一般都会比较多,采用这种方式解决乱码起来比较麻烦,所以对于POST请求还是建议使用设置编码的方式进行。
另外需要说明一点的是Tomcat8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
2.4 Request请求转发
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发
-
请求转发的实现方式:
req.getRequestDispatcher("资源B路径").forward(req,resp);
2. 请求转发资源间共享数据:使用Request对象
此处主要解决的问题是把请求从/req5
转发到/req6
的时候,如何传递数据给/req6
。
需要使用request对象提供的三个方法:
-
存储数据到request域[范围,数据是存储在request对象]中
void setAttribute(String name,Object o);
-
根据key获取值
Object getAttribute(String name);
-
根据key删除该键值对
void removeAttribute(String name);
3. 请求转发的特点
-
浏览器地址栏路径不发生变化
-
只能转发到当前服务器的内部资源
-
不能从一个服务器通过转发访问另一台服务器
-
一次请求,可以在转发资源间使用request共享数据
虽然后台从
/req5
转发到/req6
,但是这个只有一次请求
3,Response对象
Reponse的继承体系和Request的继承体系也非常相似:
3.1 Response设置响应数据功能介绍
HTTP响应数据分别是响应行、响应头、响应体
-
设置响应状态码:
void setStatus(int sc);
-
设置响应头键值对:
void setHeader(String name,String value);
-
响应体:
获取字符输出流:
PrintWriter getWriter();
获取字节输出流
ServletOutputStream getOutputStream();
3.2 Respones请求重定向
一种资源跳转方式。
-
重定向的实现方式:
//重定向
//1.设置响应状态码 302
response.setStatus(302);
//2. 设置响应头 Location
response.setHeader("Location","/request-demo/resp2");
2. 简化的编写方式为:
//重定向
resposne.sendRedirect("/request-demo/resp2");
3.3 路径问题
-
浏览器使用:需要加虚拟目录(项目访问路径)
-
服务端使用:不需要加虚拟目录
例:
-
<a href='路劲'>
-
<form action='路径'>
-
req.getRequestDispatcher("路径")
-
resp.sendRedirect("路径")
答案:
1.超链接,从浏览器发送,需要加 2.表单,从浏览器发送,需要加 3.转发,是从服务器内部跳转,不需要加 4.重定向,是由浏览器进行跳转,需要加。
-
后期通过Tomcat插件配置了项目的访问路径,那么所有需要重定向的地方都需要重新修改,需要借助request对象中的getContextPath()方法,修改后的代码如下
//简化方式完成重定向
//动态获取虚拟目录
String contextPath = request.getContextPath();
response.sendRedirect(contextPath+"/resp2");
3.4 Response响应字符数据
-
通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();
-
通过字符输出流写数据: writer.write("aaa");
实用:
-
返回一个简单的字符串
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对象就会被销毁掉,所以不要手动关闭流。
-
返回一个中文的字符串
你好
,需要注意设置响应数据的编码为utf-8
//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");
3.3 Response响应字节数据
要想将字节数据写回到浏览器,我们需要两个步骤:
-
通过Response对象获取字节输出流:
-
ServletOutputStream outputStream = resp.getOutputStream();
-
-
通过字节输出流写数据: 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);
}
}
上述代码中,对于流的copy的代码还是比较复杂的,所以我们可以使用别人提供好的方法来简化代码的开发,具体的步骤是:
(1)pom.xml添加依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
(2)调用工具类方法
//fis:输入流
//os:输出流
IOUtils.copy(fis,os);
优化后的代码:
/**
* 响应字节数据:设置字节数据的响应体
*/
@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);
}
}