关键字:页面重定向(跳转,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. 为访问目的资源,事实上浏览器发出了两个请求,效率较低。
页面效果
- 浏览器地址栏发生变化;
- 由于第一次请求返回的response body为空,所以页面不会发生闪烁。
使用场景
- 期望让用户知道最终的URL,以便加入书签(Bookmark);
- 在web.xml的welcome file配置中只能指定一个页面的Location,可以使用一个简单的页面,比如jsp,重定向到期望的servlet;
- 在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是本系统内部的资源,不能跨域。
页面效果
- 浏览器地址栏的URL不会发生变化;
- 不会出现页面闪烁。
使用场景
- 服务器不期望用户了解服务器内部的资源结构信息;
- 不跨域,以期更高的效率。
在Browser端使用Javascript进行重定向
示例代码
<script type="text/javascript">
window.location="Some URL";
</script>
特点
1. 浏览器已经成功得到所请求的页面了,浏览器在执行JavaScript时将地址栏的URL改变,以致向新的URL发出请求。
页面效果
- 浏览器地址栏的URL发生变化;
- 如果第一次请求得到的页面不是空白,可以看到页面的闪烁。
使用场景
- 有的框架,比如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发出请求。
页面效果
- 浏览器地址栏的URL发生变化;
- 如果第一次请求得到的页面不是空白,可以看到页面的闪烁。
使用场景
- 有人会问,浏览器禁用了JavaScript,我又不幸使用了Tile框架,怎么办呢?那就用这种方式把!