Response
今日目标
0. http响应
1. response【重点】
零 Http响应
之前我们已经学习过Http请求, 现在我们一起再来学习Http响应
0.1 浏览器查看Http响应协议
抓包的代码
<a href="ResponseServlet">03_查看响应报文</a> <br>
package com.itheima03.response;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/ResponseServlet")
public class ResponseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().print("hello");
}
}
0.2 HTTP响应消息格式
① 响应行
* 格式
协议/版本号 状态码
* 例如
HTTP/1.1 200
* 常见状态码
--------------- 用户可以正常访问页面
200 :表示成功
302 :重定向(response学习)
304 :从缓存中读取数据
(如果这个资源没有变化,浏览器是会缓存的,下次请求,就直接从缓存中读取,提高效率)
--------------- 用户无法正常访问页面
404:请求资源未找到(not found)
405:请求的方法未找到(明天讲了servlet给大家演示....)
500:服务器内部错误(java代码写错了.....)
② 响应头
* 格式
响应头名称:响应头的值
* 例如
Last-Modified: Mon, 13 Apr 2020 06:11:24 GMT
常见响应头:
1. Location:通常与状态码302一起使用,实现重定向操作
Location:http://www.itcast.cn
2. Content-Type:服务器告诉客户端,返回响应体的数据类型和编码方式
Content-Type:text/html;charset=utf-8
3. Refresh:在指定间隔时间后,跳转到某个页面
Refresh:5;http://www.itcast.cn
③ 响应体(正文)
* 服务器返回的数据,由浏览器解析后展示给用户
用户看到页面所有的内容,都是在响应体中返回的
一 Response【重点】
1.1 概述
- response对象表示web服务器给浏览器返回的响应信息
response是由tomcat创建的
- 作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息
注意: tomcat + servlet (服务端)
在response中但凡不是Servlet设置的信息,就是tomcat设置的, 我们可以用Servlet中设置覆盖tomcat的设置
ServletResponse 接口 (理论上兼容大部分协议)
|
HttpServletResponse 接口 (专门指的是http协议的响应)
|
org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)
1.2 设置Http响应行
* 格式
协议/版本号 状态码(status code)
* 例如
HTTP/1.1 200
* API
1. 设置状态码(status code)
void setStatus(int sc)
2. 常见响应状态码:
200:请求和响应都OK(顺利)
302:重定向 (待会)
304:浏览器从缓存中加载数据
404:请求的路径错误或请求的资源不存在(自己开发的时候,路径有问题)
405: 在HttpServlet的子类中, doGet或doPost方法没有重写
500:服务器内部异常
3. 注意事项:上述常见的响应状态码,通常是由tomcat服务器自动响应给浏览器。我们一般是不需要手动设置的;
浏览器缓存(304)
package com.itheima03.response;
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;
/*
TODO response
1. 响应: 服务器发送给浏览器的数据
2. 服务器 : tomcat + servlet
响应的内容不是servlet设置的就是tomcat设置
TODO:
响应报文
1. 响应行
1). 协议 : tomcat8默认使用 HTTP/1.1 (固定)
2). 状态码 (status code) : 表示当前响应的状态
I. 200 : 响应成功
II. 302 : 重定向 (待会)
III. 304 : 读取缓存 ,没有从服务器读取数据
浏览器的缓存机制 (提高效率)
可能给开发带来麻烦,以后更新网页出问题记得清除缓存
IV. 404 : not found , 资源不存在
开发碰到这个问题: 网址写错了
生活碰到这个问题: 网址写错了/资源下架了
V. 500 : 服务器错误
开发碰到这个问题: 服务器程序有bug
(查看bug信息 要么在server控制台,要么就在tomcat localhost log)
生活碰到这个问题: 服务器崩溃了
注意: 状态码一般由tomcat自动设置即可!!!!
目前,只有用到重定向功能,我们才会主动设置状态码
response.setStatus(302);
2. 响应头
3. 响应体
*/
@WebServlet("/ResponseDemo01Servlet")
public class ResponseDemo01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// int i = 1/0;
response.setStatus(302);
}
}
1.3 设置Http响应头
* 格式
响应头名称:响应头的值
(name : value)
* 例如
Content-Length : 5 (指的是响应体内容长度5个字符)
* API
1. 设置指定头名称和对应的值
void setHeader(String name, String value)
2. value值可以由多个参数组成,不同参数之间使用分号隔开:
response.setHeader(key,"value1;value2");
3. 常用响应头:
refresh:定时刷新;
content-type:设置响应数据的数据类型和编码格式; (内容类型)
location:配合302响应状态码完成重定向;(位置)
1.4 设置Http响应体
响应体中包含 响应数据的正文
响应是服务器给浏览器发送数据: 输出流
* API(输出流对象)
1. 字符输出流 : 用于向浏览器输出字符数据(文本)
PrintWriter getWriter()
2. 字节输出流 : 用于向浏览器输出二进制数据(比如文件下载)
ServletOutputStream getOutputStream()
注意:在同一个servlet中,二种类型的输出流不能同时存在,互斥
package com.itheima03.response;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.io.PrintWriter;
/*
TODO response
1. 响应: 服务器发送给浏览器的数据
2. 服务器 : tomcat + servlet
响应的内容不是servlet设置的就是tomcat设置
TODO:
响应报文
1. 响应行
1). 协议 : tomcat8默认使用 HTTP/1.1 (固定)
2). 状态码 (status code) : 表示当前响应的状态
2. 响应头
3. 响应体
0). 响应: 服务器发送给浏览器的数据
response中用输出流来给浏览器发送数据
1). 字节输出流
ServletOutputStream os = response.getOutputStream();
用来响应文件数据
2). 字符输出流
response.getWriter().print("hello world");
一般用来响应文本内容
注意: 两个流只能用一个,同时使用会冲突!!!
扩展:
浏览器获取到响应数据
1). 如果响应数据是文本内容: 浏览器会默认显示在网页上
2). 如果响应数据是文件 : 浏览器具体看情况(可能显示,也可能下载)
*/
@WebServlet("/ResponseDemo01Servlet")
public class ResponseDemo01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// int i = 1/0;
//设置状态码 : 重定向(再说)
// response.setStatus(302);
//字符输出流: 响应体
// PrintWriter writer = response.getWriter();
// writer.print("hello world");
// response.getWriter().print("hello world");
//字节输出流: 响应体
ServletOutputStream os = response.getOutputStream();
os.write("hello".getBytes());
}
}
二. 响应头的功能【重点】
2.1 响应定时刷新(refresh)
需求
在当前页面停留3秒钟之后,跳转到传智播客首页
步骤分析
1. 通过response设置响应头 Refresh
response.setHeader("Refresh","间隔时间(秒);跳转页面");
<a href="ResponseDemo02Servlet">05_定时刷新_响应头refresh(付款)</a> <br>
package com.itheima03.response;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/*
TODO 响应头 (格式 name : value)
* API
1. 设置指定头名称和对应的值
void setHeader(String name, String value)
2. value值可以由多个参数组成,不同参数之间使用分号隔开:
response.setHeader(key,"value1;value2");
3. 常用响应头:
refresh:定时刷新;
content-type:设置响应数据的数据类型和编码格式; (内容类型)
location:配合302响应状态码完成重定向;(位置)
*/
@WebServlet("/ResponseDemo02Servlet")
public class ResponseDemo02Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//TODO: 重点
/*
* 响应头: refresh
* 服务器告诉浏览器, 5秒之后跳转到百度
* */
response.setHeader("refresh","5;http://www.baidu.com");
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("付款成功,5秒之后跳转到主页");
}
}
2.2 响应体中文乱码(content-type)
需求
向页面输出中文数据没有乱码
原因分析
1. 通过response获取字符输出流
PrintWriter pw = response.getWriter();
2. 通过字符输出输出中文字符
pw.write("中文....");
3. 浏览器访问,网页出现中文乱码
4. 解决 : 统一浏览器和服务器编码(utf-8)
response.setContentType("text/html;charset=utf-8");
解决中文乱码
package com.itheima03.response;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/*
TODO 响应头 (格式 name : value)
* API
1. 设置指定头名称和对应的值
void setHeader(String name, String value)
2. value值可以由多个参数组成,不同参数之间使用分号隔开:
response.setHeader(key,"value1;value2");
3. 常用响应头:
refresh:定时刷新;
content-type:设置响应数据的数据类型和编码格式; (内容类型)
location:配合302响应状态码完成重定向;(位置)
TODO
1. 问题: 响应体中文乱码
1). 根本原因: tomcat默认编码表是ISO-8859-1,不支持中文
默认告诉浏览器的解码表: ISO-8859-1
Content-Type: text/html;charset=ISO-8859-1
服务器告诉浏览器,用ISO-8859-1进行解码
2). 解决问题: 告诉浏览器用utf-8解码
2. 服务器告诉浏览器,应该用什么语法解析响应体
MIME type : text/plain text/html application/json
windows文件类型: txt(纯文本) html(超文本) json
TODO 常用
response.setContentType("text/html;charset=utf-8");
*/
@WebServlet("/ResponseDemo03Servlet")
public class ResponseDemo03Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// response.setHeader("content-type","text/html");
// response.setHeader("content-type","text/html;charset=utf-8"); //完整写法
response.setContentType("text/html;charset=utf-8");// 省略写法
response.getWriter().print("<h1>你好,世界</h1>");
}
}
2.3 响应重定向(location+302)
需求
用户访问CServlet后,服务器告诉浏览器重定向到DServlet
步骤分析
* 方式一
// 1.设置状态码
response.setStatus(302);
// 2.设置响应头 Location
response.setHeader("Location","重定向网络地址");
* 方式二
// 1.response这哥们封装专门处理重定向的方法 (掌握)
response.sendRedirect("重定向网络地址");
重定向特点
# 重定向是浏览器行为
1. 起码发起两次请求
2. 浏览器地址栏的url被修改了(指向最后访问的地址)
3. 可以访问服务器外部资源
4. 不能通过request域对象共享数据
<a href="CServlet?msg=shengjian">07_重定向</a> <br>
package com.itheima04.redirect;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/CServlet")
public class CServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 接收请求
String msg = request.getParameter("msg");
System.out.println("CServlet:" + msg);
//2. 业务处理
System.out.println("CServlet: 收钱,打单...");
//3. 响应: 重定向
// 告诉浏览器准备再次发起请求
// response.setStatus(302);
// 告诉浏览器重定向的地址
// response.setHeader("location","DServlet");
//等价于以上两行
response.sendRedirect("DServlet");
}
}
package com.itheima04.redirect;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/DServlet")
public class DServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 接收请求 (因为这是一个全新的请求,没有携带参数,所以这就不获取了)
System.out.println("接收到请求啦");
//2. 业务处理
System.out.println("开始装生煎");
//3. 响应
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("生煎给你,慢点吃");
}
}
请求转发与重定向的区别
从最终效果来看,请求转发和重定向非常相似
1. 哪个对象的方法
1). 请求转发 : request
request.getRequestDispatcher(转发地址).forward(request,response)
2). 重定向 : response
response.sendRedirect(重定向地址); // 302状态码 + location头
2. 行为人
请求转发 : 服务器内部行为,浏览器不知道服务器内部发生了什么
重定向 : 浏览器行为
可以定向到其他服务器,但是请求转发只能在本服务器内
3. 请求次数
请求转发 : 1次
重定向: 起码2次
浏览器会限制重定向的次数,比如 google浏览器不超过20次
4. 数据共享 (重要)
请求转发: request域对象可以传递数据
重定向 : 不可以用request域对象传递数据
重定向涉及多次请求, 超出一个request作用范围
5. 地址栏指向
请求转发: 一开始设置的路径 AServlet
一次请求
重定向: 最终指向最后一次请求的地址 DServlet
多次请求,后续请求地址覆盖前面请求地址
6. 总结
请求转发: 就一次请求, 可以使用request域传递数据,不可以转发到其他服务器
重定向: 涉及多次请求,不可以用request域传递数据,但是可以定向到其他的服务器
7. 使用
a. 如果用request域对象传递数据,并且两个资源在同服务器内 -> 请求转发
b. 如果不需要request传递数据,或两个资源在不同服务器上 -> 重定向