Servlet跳转页面的重定向和转发(深入解析)

一.前言
今天这里分享一下Servlet中的重定向和转发,具体作用看似两个都可以用作跳转页面,但是其中还是有很大的差别的,这里就为大家简单讲解原理及直观的测试一下。

二.重定向

1.原理

重定向

简单解释过程:
如图,浏览器A发送请求服务器B,B不能完全完成A想要的任务,所以B返回告诉A,让A去找服务器C完成接下来的任务,此时浏览器A重新发送新的请求给C,直到完成任务,这是一种直白的重定向解释。

实际整个重定向过程:
客户浏览器发送http请求—-》web服务器接受后发送302状态码响应及对应新的location给客户浏览器–》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址—-》服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。

2.特点

(1) 重定向是客户端行为。(浏览器重新请求)
(2)重定向是浏览器做了至少两次的访问请求的(当然也可以重定向多次)。
(3)定向浏览器地址改变
(4)重定向两次跳转之间传输的信息会丢失(request范围)。
(5)重定向可以指向任何的资源,包括当前应用程序中的其他资源,同一个站点上的其他应用程序中的资源,其他站点的资源(如自己工程重定向到百度)。注意:传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录。

3.代码实现

下面是具体实现代码:

package com.qjl.web.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 重定向
 * @author Joe
 *
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public LoginServlet() {
        super();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("text/html;charset=utf-8");

        String username = request.getParameter("username");
        String password = request.getParameter("pwd");

        System.out.println(username + "..." + password);
        //重定向
//      request.getContextPath();//获取上下文路径(/项目名称)
        //告诉浏览器重定向到index.html
        response.sendRedirect(request.getContextPath()+"/index.html");
    }


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

}

大家可以看到response.sendRedirect()这个方法可以重定向到index.html页面,这里是respone(重点哦),响应给浏览器的,当然这里写的是根路径也就是/项目名/index.html,这里说一下WebContent目录下的资源是可以直接访问的

request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("text/html;charset=utf-8");

这两行代码第一行:设置请求进来的数据成utf-8,第二行:设置服务器响应给浏览器的数据,让浏览器报头设置成utf-8。这样就不会中文乱码了。

4.实际过程测试(IE浏览器)

主要servlet代码如上,页面就不给代码了。
从login.html页面输入username和password参数,点击提交,数据提交到servlet中,页面会重定向到index.html页面,通过开发者工具可以看到如下过程:
重定向
图里有几点需要注意:
(1)请求login.html后,状态码是302,302代表服务器告诉浏览器需要重新请求其他页面,所以浏览器得到302码以及login.html告诉浏览器重定向的位置信息,重定向到index.html页面了,状态码200,整个过程完成。
(2)请求login.html时上图圈出部分,是带参数的,但是在重定向到index.html时就不会带参数了如下图:
这里写图片描述

这就是整个的重定向过程。

三.转发

  1. 原理
  2. 转发

    简单解释:
    浏览器A请求服务器B,B无法完成A所有的请求任务,所以直接将请求发送给服务器C了,这里不再经过A了,B发送给C的同时带着A给B的数据。

    实际整个转发过程:
    客户浏览器发送http请求—-》web服务器接受此请求–》调用内部的一个方法在容器内部完成请求处理和转发动作—-》将目标资源发送给客户。在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。

2.特点
1,转发是服务器行为(这是不经过浏览器的
2,转发是浏览器只做了一次访问请求
3,转发浏览器地址不变
4,转发两次跳转之间传输的信息不会丢失,所以可以通过request进行数据的传递
5,转发只能将请求转发给同一个WEB应用中的组件
注意:如果创建RequestDispatcher 对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。(只能是本工程下的,因为是服务器行为)

3.代码实现
具体实现代码如下:

package com.qjl.web.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 转发
 */
@WebServlet("/reg")
public class RegServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;


    public RegServlet() {
        super();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("text/html;charset=utf-8");

        String username = request.getParameter("username");
        String password = request.getParameter("pwd");

        System.out.println(username + "..." + password);
//      //1转发到login.html
//      //1.1获取转发器
//      RequestDispatcher dispatcher = request.getRequestDispatcher("/login.html");
//      //1.2转发
//      dispatcher.forward(request, response);
        request.getRequestDispatcher("/index2.html").forward(request, response);
    }


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

}

大家可以看到通过request.getRequestDispatcher(“index2.html”)方法再.forward(request,respone)将浏览器请求信息直接转发给index2.html页面,这就是转发过程,注意这里是request服务器直接请求了另一个服务器也就是login直接请求了index2并且通过forward传递给index2浏览器请求时的数据。

4.实际过程测试(IE浏览器)

主要servlet代码如上,页面就不给代码了。
从reg.html页面输入username和password参数,点击提交,数据提交到servlet中,页面会重定向到index2.html页面,通过开发者工具可以看到如下过程:
转发测试

图里有几点需要注意:
(1)这次转发过程浏览器只请求了一次,也就是对于reg.html页面的请求,服务器在内部直接请求了index2.html而不经过浏览器了。
(2)在reg.html直接转发到index2.html过程中,通过forward方法直接将浏览器请求的数据转发给index2了(封装在了request中)。

这就是整个转发过程。

四.总结

对于重定向和转发都是用来在servlet中直接跳转页面,但是其中有很大的差别,重定向时浏览器的行为,转发则是服务器的行为,所以重定向大大加大了带宽,但是转发也加大了服务器压力。对于参数传递也需要注意,重定向原来数据消失,而转发数据还在。对于跳转的页面,重定向可以跳转到其他项目或其他网站,而转发是不可以的只能自己工程下的。

对于可能有些人分不清跳转的url该怎么写,什么时候写根路径什么时候写绝对路径还有相对路径,这里说明:绝对路径一般用在跳转其他网站,相对路径尽量避免使用,根路径则大多数情况都适用。

最后在这里吐槽几句,今天开始强制十点半了心痛,以后没事就多写写博客分享吧。大家有什么问题也欢迎随时沟通交流。

猜你喜欢

转载自blog.csdn.net/a754895/article/details/82593559