web项目
1、重定向
Response对象在请求头中设置转发属性
//把响应头中的状态码改为302 response.setStatus(302); //在请求头中设置location属性为要转发的路径 response.setHeader("location","http://www.sohu.com");
(1)这类请求首先客户端发起初始请求 http://localhost:8080/abc 这个我们配置的请求Servlet
GET /abc HTTP/1.1
Host: localhost:8080 User-Agent: insomnia/6.5.4 Accept: /
(2)Servlet通过response修改了状态码为302,并在响应头中添加转发路径 location属性,下面的响应信息发送到了客户端浏览
HTTP/1.1 302 < Content-Type: text/html;charset=utf-8 < Content-Language: zh-CN
< location:http://www.sohu.com
< Content-Length: 1072 < Date: Wed, 14 Aug 2019 07:18:10 GMT
(3)浏览器接收到响应消息后,发现响应是302,就在头属性中找出location属性,重新封装下面的Http请求 http://www.sohu.com ,再次发出请求
GET / HTTP/1.1
Host:http://www.sohu.com User-Agent: insomnia/6.5.4 Accept: /
因为直接操作响应头的代码有点麻烦,所以response把上面的两行代码封装成了sendRedirect()方法
特点:可以实现跨域转发(从localhost转到sohu.com)
response.sendRedirect("http://www.sohu.com");//重定向的过程
//等同于
//把响应头中的状态码改为302
response.setStatus(302);
//在请求头中设置location属性为要转发的路径
response.setHeader("location","http://www.sohu.com");
辨析重定向与请求转发:
转发是服务器行为,重定向是客户端行为。为什么这样说呢,这就要看两个动作的工作流程:
转发过程:客户浏览器发送http请求----》web服务器接受此请求--》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户;在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
重定向过程:客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器--》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。
2、请求转发(服务器端)
(1)创建请求派发对象(ps:请求派发就是请求转发)
RequestDispatcher dispatcher = request.getRequestDispatcher("/bbc");//得到请求派发对象
(2)forWard(request,response)
dispatcher.forward(request,response);//转发
说明:用forward()方法转发,第一个Servlet无法向客户端响应,只有转给的第二个Servlet可以向客户端响应
(3)include(request,response)
dispatcher.include(request,response);//包含
说明:用include方法转发,第一个Servlet和第二个Servlet均可向客户端响应,响应顺序按代码顺序响应,形成一种第一个Servlet的响应信息包含第二个Servlet的响应信息效果。
code:
servlet1:
//请求转发
// response.setStatus(302);
// response.setHeader("location","http://www.sohu.com");
// response.sendRedirect("http://www.sohu.com");//重定向
response.getWriter().println("Hi every body!");
RequestDispatcher dispatcher = request.getRequestDispatcher("/bbc");//得到请求派发对象
// dispatcher.forward(request,response);//转发
dispatcher.include(request,response);//包含
response.getWriter().println("Hi every body!");
System.out.println("asdfsdasdafafdsa");
servlet2:
public class OtherServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("Hello World !");
response.getWriter().flush();
}
}
补充:
服务器修改响应码跳转:
Redirect的实现
将response的状态码设为302
通过头部的"Location"指定重定向的路径
注:302是临时跳转
301是永久跳转,即每次访问都会跳转
302每次访问时都会先到达原路径,然后经过一次跳转后达到新的路径
301只有第一次访问时,会有一个有原路径跳转新路径的过程,之后在访问原路径是,就会直接到达新路径,而不再经过原路径跳转的过程
但301的使用要慎重,因为使用301后,重定向的路径会缓存到用户的浏览器中,用户访问时会只会从缓存中读取重定向的路径,而这个缓存没有过期时间的指定.如果用户不主动清缓存,则这个跳转会一直进行,此时在服务端是不可控的.