Request 和 Response详解(上):https://developer.aliyun.com/article/1491722
- 请求转发资源间共享数据:使用Request对象
此处主要解决的问题是把请求从/req5
转发到/req6
的时候,如何传递数据给/req6
。
需要使用request对象提供的三个方法:
- 存储数据到request域[范围,数据是存储在request对象]中
void setAttribute(String name,Object o);
- 根据key获取值
Object getAttribute(String name); • 1
- 根据key删除该键值对
void removeAttribute(String name);
接着上个需求来:
1.在RequestDemo5的doGet方法中转发请求之前,将数据存入request域对象中
2.在RequestDemo6的doGet方法从request域对象中获取数据,并将数据打印到控制台
3.启动访问测试
(1)修改RequestDemo5中的方法
@WebServlet("/req5") public class RequestDemo5 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo5..."); //存储数据 request.setAttribute("msg","hello"); //请求转发 request.getRequestDispatcher("/req6").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(2)修改RequestDemo6中的方法
/** * 请求转发 */ @WebServlet("/req6") public class RequestDemo6 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo6..."); //获取数据 Object msg = request.getAttribute("msg"); System.out.println(msg); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(3)启动测试
访问http://localhost:8080/request-demo/req5
,就可以在控制台看到如下内容:
此时就可以实现在转发多个资源之间共享数据。
- 请求转发的特点
- 浏览器地址栏路径不发生变化
虽然后台从/req5
转发到/req6
,但是浏览器的地址一直是/req5
,未发生变化
- 只能转发到当前服务器的内部资源
不能从一个服务器通过转发访问另一台服务器
- 一次请求,可以在转发资源间使用request共享数据
虽然后台从/req5
转发到/req6
,但是这个只有一次请求
3.HTTP响应详解(理解)
1.使用抓包查看响应报文协议内容
学习目标
- 能够使用抓包查看响应报文协议内容
内容讲解
注意:
http响应报文协议包括:
1.响应行 2.响应头 3.响应体
响应数据:是服务器响应给浏览器
【1】步骤
1.创建html页面 2.创建servlet
【2】实现
1.创建html页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h2>get请求</h2> <form action="/getServlet" method="get"> 用户名:<input type="text" name="username" value="suoge" /> <br/> 密码:<input type="text" name="password" value="1234" /> <br/> <input type="submit" value="get提交" /> </form> <h2>post请求</h2> <form action="/postServlet" method="post"> 用户名:<input type="text" name="username" value="suoge" /> <br/> 密码:<input type="text" name="password" value="1234" /> <br/> <input type="submit" value="post提交" /> </form> </body> </html>
2.创建servlet
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; @WebServlet("/getServlet") public class GetServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //响应给浏览器数据 response.getWriter().print("get...."); } }
package com.itheima.sh.a_http_01; 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; @WebServlet("/postServlet") public class PostServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //响应给浏览器数据 response.getWriter().print("post...."); } }
【3】抓包结果
内容小结
1.由于浏览器的原因,浏览器会把请求行和响应行信息放在了一起;
2.get和post请求的响应没有区别;
2.HTTP响应报文协议介绍
学习目标
- 理解响应报文协议的组成部分
内容讲解
【1】响应行
响应行格式:协议/版本 状态码
如:HTTP/1.1 200 ;
【2】响应头
响应头也是用的键值对key:value,服务器基于响应头通知浏览器的行为。
常见的响应头:
常见的MIME类型:就是文件在tomcat服务器中的文件类型:
windows tomcat(MIME类型) 超文本标记语言文本 .html text/html *** xml文档 .xml text/xml XHTML文档 .xhtml application/xhtml+xml 普通文本 .txt text/plain *** PDF文档 .pdf application/pdf Microsoft Word文件 .word application/msword PNG图像 .png image/png ** GIF图形 .gif image/gif JPEG图形 .jpeg,.jpg image/jpeg ** ......
【3】响应体
响应体,就是服务器发送给浏览器的数据。当前浏览器向服务器请求的资源是hello.html,所以服务器给浏览器响应的数据是一个html页面。
请求资源路径:
响应结果:
如果请求是servlet,那么浏览器的响应体接收到的是servlet响应的数据:
内容小结
1.响应行:
协议版本号 状态码 200(一切正常) 404(找不到资源路径) 500(服务器报异常) 302(和location一起使用,实现重定向) 304(从浏览器缓存中读取数据) 405(服务器的servlet没有重写doGet和doPost方法)
2.响应头:
location 指定响应的路径
content-type:告诉浏览器文件格式,告诉浏览器不要解析html文件(text/plain),解决中文乱码问题
refresh 定时刷新
content-disposition 以附件形式展示图片等资源
3.响应体:
服务器处理的结果响应到浏览器中
4.Response对象
1 Response对象介绍
前面讲解完Request对象,接下来我们回到刚开始的那张图:
- Request:使用request对象来获取请求数据
- Response:使用response对象来设置响应数据
Reponse的继承体系和Request的继承体系也非常相似:
介绍完Response的相关体系结构后,接下来对于Response我们需要学习如下内容:
- Response设置响应数据的功能介绍
- Response完成重定向
- Response响应字符数据
- Response响应字节数据
2 Response设置响应数据功能介绍
HTTP响应数据总共分为三部分内容,分别是响应行、响应头、响应体,对于这三部分内容的数据,respone对象都提供了哪些方法来进行设置?
- 响应行
对于响应行,比较常用的就是设置响应状态码:
void setStatus(int sc);
设置响应头键值对:
void setHeader(String name,String value); • 1
- 响应体
对于响应体,是通过字符、字节输出流的方式往浏览器写,
获取字符输出流:
PrintWriter getWriter(); • 1
获取字节输出流
ServletOutputStream getOutputStream();
介绍完这些方法后,后面我们会通过案例把这些方法都用一用,首先先来完成下重定向的功能开发。
3 Respones请求重定向
- Response重定向(redirect):一种资源跳转方式。
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向
- 重定向的实现方式:
resp.setStatus(302); resp.setHeader("location","资源B的访问路径");
具体如何来使用,我们先来看下需求:
针对上述需求,具体的实现步骤为:
1.创建一个ResponseDemo1类,接收/resp1的请求,在doGet方法中打印resp1....
2.创建一个ResponseDemo2类,接收/resp2的请求,在doGet方法中打印resp2....
3.在ResponseDemo1的方法中使用
response.setStatus(302);
response.setHeader(“Location”,“/request-demo/resp2”) 来给前端响应结果数据
4.启动测试
(1)创建ResponseDemo1类
@WebServlet("/resp1") public class ResponseDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("resp1...."); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(2)创建ResponseDemo2类
@WebServlet("/resp2") public class ResponseDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("resp2...."); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(3)在ResponseDemo1的doGet方法中给前端响应数据
@WebServlet("/resp1") public class ResponseDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("resp1...."); //重定向 //1.设置响应状态码 302 response.setStatus(302); //2. 设置响应头 Location response.setHeader("Location","/request-demo/resp2"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(4)启动测试
访问http://localhost:8080/request-demo/resp1
,就可以在控制台看到如下内容:
说明/resp1和/resp2都被访问到了。到这重定向就已经完成了。
虽然功能已经实现,但是从设置重定向的两行代码来看,会发现除了重定向的地址不一样,其他的内容都是一模一样,所以resposne对象给我们提供了简化的编写方式为:
resposne.sendRedirect("/request-demo/resp2")
所以第3步中的代码就可以简化为:
@WebServlet("/resp1") public class ResponseDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("resp1...."); //重定向 resposne.sendRedirect("/request-demo/resp2"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
Request 和 Response详解(下):https://developer.aliyun.com/article/1491742