一.前言
今天这里分享一下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时就不会带参数了如下图:
这就是整个的重定向过程。
三.转发
- 原理
-
简单解释:
浏览器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该怎么写,什么时候写根路径什么时候写绝对路径还有相对路径,这里说明:绝对路径一般用在跳转其他网站,相对路径尽量避免使用,根路径则大多数情况都适用。
最后在这里吐槽几句,今天开始强制十点半了心痛,以后没事就多写写博客分享吧。大家有什么问题也欢迎随时沟通交流。