关键字:页面重定向(跳转,page redirection)、实现方式

写完标题,我突然想到了孔乙己,鲁迅先生嘲笑他以知道茴香豆的茴字有四种写法而感到自豪。不过我想我和孔乙己还是不同的,因为茴香豆的茴字会写一种即可,但本文总结的四种页面重定向的方式应用的场景不尽相同,产生的页面效果也不同。是有必要加以理解并选择合适的方式处理不同的场景的。

四种方式:

  • 在Server端sendRedirect
  • 在Server端使用jsp或RequestDispatcher进行forward
  • 在Browser端使用Javascript进行重定向
  • 在Browser端使用html标签进行重定向

以下是对四种方式进行的详解。

在Server端sendRedirect

示例代码

//HttpServletResponse response
response.sendRedirect("some url");

特点

1. 执行该语句后server会发送一个没有body的http response。状态码(Status Code)为302,在response header中有Location属性,值为:some url。浏览器接到该response后会自动读取Location的信息,并向指向的URL发出请求,所以你可以在地址栏看到some url了。

值得一提的是,如果第一个请求为Post请求时,现在很多浏览器会在第二个请求中转换为Get请求,这种处理方式并没有严格遵守HTTP协议。HTTP协议对重定向的状态码作了细分,增加了303(第二个请求转换为Get请求)和307码(第二个请求和第一个请求方法相同)。Eric Law在他的博文中有更详细的解释。

2. 由于浏览器发出的第二个请求,因此Location中的some url可以跨域(Cross domain),为任意URL。

3. 由于是两次独立的请求,所以两次请求不能共享request里面的数据。

4. 为访问目的资源,事实上浏览器发出了两个请求,效率较低。

页面效果

  1. 浏览器地址栏发生变化;
  2. 由于第一次请求返回的response body为空,所以页面不会发生闪烁。

使用场景

  1.  期望让用户知道最终的URL,以便加入书签(Bookmark);
  2. 在web.xml的welcome file配置中只能指定一个页面的Location,可以使用一个简单的页面,比如jsp,重定向到期望的servlet;
  3. 在dispatcher中根据用户身份重定向到各自的系统。
在Server端使用jsp或RequestDispatcher进行forward

示例代码

JSP中

<jsp:forward page={"relativeurl" | "<%= expression %>"} >
	<jsp:param name="parametername" value="{parametervalue | <%= expression %>}" /><%--如果没有参数可以移除该语句 --%>
</jsp:forward>

Java Code

request.getSession().getServletContext().getRequestDispatcher("Some url").forward(request, response);



特点

1. 在Server内部把请求转发给另一个资源,处理后把结果返回给浏览器,该操作对浏览器透明,因此地址栏的URL不会发生变化;

2. 两个资源共享request里的数据;

3. 转发到的Some url是本系统内部的资源,不能跨域。

页面效果

  1. 浏览器地址栏的URL不会发生变化;
  2. 不会出现页面闪烁。

使用场景

  1. 服务器不期望用户了解服务器内部的资源结构信息;
  2. 不跨域,以期更高的效率。
在Browser端使用Javascript进行重定向

示例代码

<script type="text/javascript">
window.location="Some URL";
</script>


特点

1. 浏览器已经成功得到所请求的页面了,浏览器在执行JavaScript时将地址栏的URL改变,以致向新的URL发出请求。

页面效果

  1. 浏览器地址栏的URL发生变化;
  2. 如果第一次请求得到的页面不是空白,可以看到页面的闪烁。

使用场景

  1. 有的框架,比如Apache Tiles,不支持response.sendRedirect,只好用其他的办法了。。。
在Browser端使用html标签进行重定向


示例代码


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
  <head>
      <title>Welcome to Radic's Blog</title>
      <meta http-equiv="refresh" content="0;url=<c:url value="/authenticate.html"/>" />
  </head>
  <body>Redirecting...</body>
</html>

0表示页面被加载后发生跳转的时间,以毫秒为单位,0毫秒表示立即执行跳转。后面的url指定跳转的目标URL。参考文档了解更多meta http-equiv的用途。

特点

1. 浏览器已经成功得到所请求的页面了,浏览器发现meta http-equiv="refresh"时将地址栏的URL改变,以致向新的URL发出请求。

页面效果

  1. 浏览器地址栏的URL发生变化;
  2. 如果第一次请求得到的页面不是空白,可以看到页面的闪烁。

使用场景


  1. 有人会问,浏览器禁用了JavaScript,我又不幸使用了Tile框架,怎么办呢?那就用这种方式把!