重定向是一种资源跳转的方式


重定向的特点:注意其与转发的区别(forward和redirect区别)

1. 地址栏发生变化

2. 重定向可以访问其他站点(服务器)的资源

3. 重定向是两次请求,不能使用request对象来共享数据


回顾:转发的特点:

1. 转发地址栏路径不变

2. 转发只能访问当前服务器下的资源

3. 转发是一次请求,意味着可以使用request对象来共享数据

 


案例:

假设:

客户端向服务器访问A资源,但是A资源不能解决客户端的需求,他会返回给客户端一个状态码302,告诉客户端需要重定向,并且指定了重定向的资源路径

1. 服务器告诉浏览器重定向,设置状态码为302来完成

2. 告诉浏览器重定向指向的资源在服务器的路径:响应头Location:B资源的路径


写两个Servlet,responseDemo1重定向到responseDemo2资源,如下:

responseDemo1代码:

package zr.web.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("/responseDemo1")
public class ResponseDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("Demo1被访问了!!");
        //浏览器如果访问了服务器的这个/responseDemo1资源,服务器会告诉浏览器需要重定向,浏览器自动跳转到/responseDemo2资源上
        //1. 设置状态码为302
        response.setStatus(302);
        //2. 设置响应头Location
        response.setHeader("location","/day15/responseDemo2");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

 

responseDemo2代码如下:

package zr.web.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("/responseDemo2")
public class ResponseDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Demo2被访问了!!");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

运行结果

Demo1被访问了!!

Demo2被访问了!!


但是注意,这样去写不灵活,上面只能修改重定向的资源路径,下面介绍一个简单的重定向方法,只需要输入资源路径即可,其他的都是固定不变的

//补充:简单的重定向方法,只需要输入资源路径即可
response.sendRedirect("/day15/responseDemo2");

其内部实现原理

//1. 设置状态码为302
response.setStatus(302);
//2. 设置响应头Location
response.setHeader("location","/day15/responseDemo2");

路径写法:

                1. 路径分类
                    相对路径:通过相对路径不可以确定唯一资源
                        * 如:./index.html
                        * 不以/开头,以.开头路径

                        * 规则:找到当前资源和目标资源之间的相对位置关系
                            * ./:当前目录
                            * ../:后退一级目录

                          如一个页面:http://localhost:8080/day15/htmls/index.html,在这个页面里面访问下面那个路径只需要在超链接href值写上 ../responseDemo1 即可

                           http://localhost:8080/day15/responseDemo1

                    2. 绝对路径:通过绝对路径可以确定唯一资源
                        * 如:http://localhost/day15/responseDemo2        /day15/responseDemo2
                        * 以/开头的路径为绝对路径

                    3. 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
                            * 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
                                * 建议虚拟目录动态获取:request.getContextPath()
                                * <a> , <form> 重定向...

                            * 给服务器使用:不需要加虚拟目录
                                * 转发资源的时候所需要的路径


对于规则的理解     

判断请求将来从哪发出,需要判断是给服务器还是给客户端浏览器用的,比如在页面上创建了一个超链接,指向了服务器的一个资源,那么这个链接就是给客户端使用的,所以其路径需要加虚拟目录,而像前面提到的转发,就是服务器内部之间的访问,比如A转发到B,那么A里面的forward方法路径参数就不需要加虚拟路径,即可访问B资源;然而重定向需要加虚拟目录,因为它是服务器内部的资源发送给客户端的一个状态码和资源路径,所以最终还是服务器来访问这个地址,所以需要加虚拟目录


虚拟目录的动态获取

虚拟目录:需要动态获取,不能写死路径,因为如果以后修改了服务器的虚拟路径会导致修改工作过于复杂,可以向下面的这个重定向代码段一样,用getContextPath()来动态获取虚拟路径,防止了这个意外的发生

//动态获取虚拟目录,放置以后修改服务器的虚拟目录之后,所有的路径都要修改,太麻烦
String contextPath = request.getContextPath();
//补充:简单的重定向方法,只需要输入资源路径即可
response.sendRedirect(contextPath+"/responseDemo2");