今天在研究人人网的Ouath认证时,里面使用了重定向,突然想到servlet中重定向实现的原理是什么,只记得response.sendRedirect()可以实现吧URL重新发送到浏览器进行重定向,RequestDispatcher有forword和include方法可以实现服务器内的重定向,底层的实现还真没研究过。时间比较晚了,就google了一下,有几篇讲解记录一下:
1. 坛子里面的精华:http://www.iteye.com/topic/557980, 值得好好看看
2. 网上搜来的,讲的比较全,
一 问题:
在servlet/JSP编程学习中,发现有两种方法可以实现服务端输出重定向,一种是通过forward方法(例如JSP中
的<jsp:forward
page=”OtherPage.jsp”/>),另一种则是通过运用
javax.servlet.http.HttpServletResponse接口的sendRedirect方法(例如
response.sendRedirect(“OtherPage.jsp”);这两种方法有什么区别和联系呢?让我们看下面的分析。
二 分析:(1)<JSP:FORWORD>
该
方法是利用服务器端先将数据输出到缓冲区的机制,在把缓冲区(buffer)的内容发送到客户端之前,原来的不发送,改为发送该页面的内容,如果
在<JSP:FORWORD>之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意.
补充知识:输出缓冲区
缺省情况下:服务端要输出到客户端的内容,不直接写到客户端,而是先写到一个输出缓冲区中.只有在下面三中情况下,才会把该缓冲区的内容输出到客户端上:
1该JSP网页已完成信息的输出
2输出缓冲区已满
3JSP中调用了out.flush()或response.flushbuffer()
输出缓冲区的大小可以用:<%@page
buffer="none"|"nkb"%>或response.setBufferSize()设置,如下:
1设置输出缓冲区的大小为1KB。<%@page
buffer="1kb"%>或response.setBufferSize(1);
2设置输出缓冲区的大小为0,即不缓冲。<%@page
buffer="none" %>或response.setBufferSize(0);
用response.getBufferSize()或out.getBufferSize()可取的输出缓冲区的大小,单位为字节.
用response.isCommitted()可检查看服务端是否已将数据输出到客户端. 如果返回值是TRUE则已将数据输出到客户端,是FALSE则还没有。
(2)response.sendRedirect(“OtherPage.jsp”)
该
方法通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,让浏览器对在location中指定的URL提出请求,使浏览器显示重定向网页
的内容。该方法可以接受绝对的或相对的URLs。如果传递到该方法的参数是一个相对的URL,那么Web container在将它发送到客户端前会把它
转换成一个绝对的URL。如果地址是相对的,没有一个’/’,那么Web container就认为它是相对于当前的请求URI的。
因为这个方法是通过修改HTTP协议的HEADER实现的重定义功能,而下面的方法也能改变HTTP HEADER属性,他们的原理是一样的.
<%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
String newLocn="/index.html";
response.setHeader("Location",newLocn);
%>
补充知识:HTTP应答头
Web服务器响应浏览器或其他客户程序的请求时,其应答一般由以下几个部分组成:一个状态行,几个应答头,一个空行,内容文档。下面是一个最简单的应答:
HTTP/1.1 200 OK
Content-Type: text/plain
Hello World
1设置状态信息
状
态行包含HTTP版本、状态代码、与状态代码对应的简短说明信息。在大多数情况下,除了Content-Type之外的所有应答头都是可选的。
Servlet可以利用状态代码来实现许多功能。例如,可以把用户重定向到另一个网站,就像我们上边所看到的那个例子。下面我们就通过这个机会具体讨论各
种状态代码的含义以及利用这些代码可以做些什么。
如前所述,HTTP应答状态行包含HTTP版本、状态代码和对应的状态信息。由于状态信息直接和状态代码相关,而HTTP版本又由服务器确定,因此需要Servlet设置的只有一个状态代码。
先给出常见的HTTP 1.1状态代码以及它们对应的状态信息和含义,具体的使用方法我们接下来再做详细的介绍。
100 Continue 初始的请求已经接受,客户应当继续发送请求的其余部分。(HTTP 1.1新)
101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议(HTTP 1.1新)
200 OK 一切正常,对GET和POST请求的应答文档跟在后面。如果不用setStatus
设置状态代码,Servlet默认使用202状态代码。
201 Created 服务器已经创建了文档,Location头给出了它的URL。
202 Accepted 已经接受请求,但处理尚未完成。
203 Non-Authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝(HTTP 1.1新)。
204 No Content 没有新文档,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content 没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容(HTTP 1.1新)。
206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它(HTTP 1.1新)。
300 Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明。
301 Moved Permanently 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
302
Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。注意,在HTTP1.0中对应的状态信息是“Moved
Temporatily”,而HttpServletResponse中相应的常量是SC_MOVED_TEMPORARILY,而不是
SC_FOUND。
出现该状态代码时,浏览器能够自动访问新的URL,因此它是一个很有用的状态代码。为此,Servlet提供了一个专用的方
法,即sendRedirect。使用response.sendRedirect(url)比使用
response.setStatus(response.SC_MOVED_TEMPORARILY)和
response.setHeader("Location",url)更好。这是因为:
首先,代码更加简洁。
第二,使用sendRedirect,Servlet会自动构造一个包含新链接的页面(用于那些不能自动重定向的老式浏览器)。
最后,sendRedirect能够处理相对URL,自动把它们转换成绝对URL。
注意这个状态代码有时候可以和301替换使用。例如,如果浏览器错误地请求http://host/~user
(缺少了后面的斜杠),有的服务器返回301,有的则返回302。
严格地说,我们只能假定只有当原来的请求是GET时浏览器才会自动重定向。请参见307。
303 See Other 类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取(HTTP 1.1新)。
304 Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取(HTTP 1.1新)。
307
Temporary Redirect
和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是POST,即使它实际上只能在POST请求的应答是303时
才能重定向。由于这个原因,HTTP
1.1新增了307,以便更加清除地区分几个状态代码:当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只
能跟随对GET请求的重定向。
注意,HttpServletResponse中没有为该状态代码提供相应的常量。(HTTP 1.1新)
400 Bad Request 请求出现语法错误。
401 Unauthorized 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。
403 Forbidden 资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。
404 Not Found 无法找到指定位置的资源。这也是一个常用的应答,HttpServletResponse专门提供了相应的方法:sendError(message)。
405 Method Not Allowed 请求方法(GET、POST、HEAD、DELETE、PUT、TRACE等)对指定的资源不适用。(HTTP 1.1新)
406 Not Acceptable 指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容(HTTP 1.1新)。
407 Proxy Authentication Required 类似于401,表示客户必须先经过代理服务器的授权。(HTTP 1.1新)
408 Request Timeout 在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。(HTTP 1.1新)
409 Conflict 通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。(HTTP 1.1新)
410 Gone 所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址。它和404的不同在于,返回407表示文档永久地离开了指定的位置,而404表示由于未知的原因文档不可用。(HTTP 1.1新)
411 Length Required 服务器不能处理请求,除非客户发送一个Content-Length头。(HTTP 1.1新)
412 Precondition Failed 请求头中指定的一些前提条件失败(HTTP 1.1新)。
413 Request Entity Too Large 目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头(HTTP 1.1新)。
414 Request URI Too Long URI太长(HTTP 1.1新)。
416 Requested Range Not Satisfiable 服务器不能满足客户在请求中指定的Range头。(HTTP 1.1新)
500 Internal Server Error 服务器遇到了意料不到的情况,不能完成客户的请求。
501 Not Implemented 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求。
502 Bad Gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。
503 Service Unavailable 服务器由于维护或者负载过重未能应答。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头。
504 Gateway Timeout 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答。(HTTP 1.1新)
505 HTTP Version Not Supported 服务器不支持请求中所指明的HTTP版本。(HTTP 1.1新)
如前所述,HTTP应答状态行包含HTTP版本、状态代码和对应的状态信息。由于状态信息直接和状态代码相关,而HTTP版本又由服务器确定,因此需要Servlet设置的只有一个状态代码。拿我们上边的例子来看。其中有一句就是设置HTTP应答头的状态代码的,是:
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
Servlet
设置状态代码一般使用HttpServletResponse的setStatus方法。setStatus方法的参数是一个整数(即状态代码),不过为
了使得代码具有更好的可读性,可以用HttpServletResponse中定义的常量来避免直接使用整数。这些常量根据HTTP
1.1中的标准状态信息命名,所有的名字都加上了SC前缀(Status
Code的缩写)并大写,同时把空格转换成了下划线。也就是说,与状态代码301对应的状态信息是“Moved
Permanently”,则HttpServletResponse中的对应常量名字为SC_MOVED_PERMANENTLY。但有两个例外:和状
态代码302对应的常量根据HTTP 1.0命名为SC_MOVED_TEMPORARILY,而不是SC_FOUND,而307没有对应的常量。
虽然设置状态代码一般使用的是response.setStauts(int)方法,但为了简单起见,HttpServletResponse为两种常见
的情形提供了专用方法:sendError方法生成一个404应答,同时生成一个简短的HTML错误信息文档;sendRedirect方法生成一个
302应答,同时在Location头中指示新文档的URL。这种方法就是我们前边提到的
response.sendRedirect(“OtherPage.jsp”)实现重定向的方法的原理。它与301应答,既
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY)的区别请看上边状态列表的
红色标记部分,这里不再重复。
2设置HTTP应答头
设置HTTP应答头往往和设置状态行
中的状态代码结合起来。例如,有好几个表示“文档位置已经改变”的状态代码都伴随着一个Location头,而401(Unauthorized)状态代
码则必须伴随一个WWW-Authenticate头。这些都在相应的状态代码的状态信息说明中都提到了。
然而,即使在没有设置特殊含义的状态代码时,指定应答头也是很有用的。应答头可以用来完成:设置Cookie,指定修改日期,指示浏览器按照指定的间隔刷
新页面,声明文档的长度以便利用持久HTTP连接,……等等许多其他任务。还拿我们上边的例子来看,其中有一句就是设置HTTP应答头的,是:
response.setHeader("Location",newLocn);
设置应答头最常用的方法是HttpServletResponse的setHeader,该方法有两个参数,分别表示应答头的名字和值。和设置状态代码相似,设置应答头应该在发送任何文档内容之前进行。
应答头 说明
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding
文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档
的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE
4、IE
5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-
Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length
表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入
ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过
byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type
表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置
Content-Type,因此HttpServletResponse提供了一个专用的方法setContentTyep。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified
文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文
档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。
注
意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh"
CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的
HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。
注意Refresh的意义是“N秒之后刷新本页面或访问指定页面”,而不是“每隔N秒刷新本页面或访
问指定页面”。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是
<META HTTP-EQUIV="Refresh" ...>。
注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
Server 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie
设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie",
...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
WWW-Authenticate
客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例
如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。
注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。
到此我们应该可以理解用下面代码实现重定向的原理:修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,让浏览器对在location中指定的URL提出请求,使浏览器显示重定向网页的内容。
<%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 设置HTTP应答头状态代码
String newLocn="/index.html";
response.setHeader("Location",newLocn); 设置HTTP应答头
%>
三 总结:
通过上边的分析,我们清楚了这两种服务器端重
定向方法的原理,<jsp:forward>是利用服务器端先将数据输出到缓冲区的机制,在把缓冲区的内容发送到客户端之前,通过停止调用页
的处理,将执行转向响应的页面,从而实现的重定位功能,原调用页的输出缓冲区中任何尚未在浏览器中显示(刷新)的内容将被清楚,不再显示。
而response.sendRedirect(“OtherPage.jsp”)是通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,让浏览器对在location中指定的URL提出请求,使浏览器显示重定向网页的内容的。
四 对比:
1 forward方法是在Web container内部工作的。SendRedirect方法需要到客户端的一个往返。所以forward方法要比sendreRirect要快
2 forward方法只能重定向到同一个Web应用程序中的一个资源。而sendRedirect方法可以重定向到任何URL
3 forward方法还将原始的HTTP请求对象(request)转到目录页。而sendRedirect方法的功能是触发浏览器转向指定的URL,并不会将原始请求对象转发。
在例:C:\Tomcat 5.0\webapps\test\regiester10中我们可以看到在WELCOME。JSP中有:
<tr><td>姓名:<%=request.getParameter("userName")%></td></tr>
当在LOGIN.JSP中用response.sendRedirect("welcome.jsp");重定向到WELCOME.JSP时,输出为:
姓名:null
当在LOGIN.JSP中用<jsp:forward page = "welcome.jsp"/>重定向到WELCOME.JSP时,输出为:
姓名:wangjian
4.sendRedirect能够处理相对URL,自动把它们转换成绝对URL。
分享到:
相关推荐
"windows目录重定向源码"指的是实现这一功能的编程代码,可能是用C++或其他语言编写的,用于开发或理解Windows系统如何处理目录重定向的底层逻辑。 目录重定向通常涉及到以下几个核心知识点: 1. **注册表设置**:...
这种方法提供了更底层的控制,但实现起来相对复杂。 4. 实现步骤 - **安装必要的工具**:如iptables,可能还需要dnsmasq或bind等DNS服务器软件。 - **配置iptables规则**:根据需求编写iptables规则,设定匹配...
英飞凌4300单片机在进行printf函数串口重定向时,与常见的STM32单片机处理方式存在差异。...通过阅读和分析这个工程文件,可以深入理解嵌入式系统中如何实现特定硬件的I/O操作,并掌握printf函数的底层工作原理。
2. 实践编程:通过编写实际的Servlet或Filter来实现请求转发和重定向,这能帮助你更好地掌握它们的用法和区别。 3. 分析案例:研究不同应用场景下,何时选择请求转发,何时选择重定向,这有助于你在实际工作中做出...
标题中的“IP拦截重定向.rar”表明这是一个关于网络流量控制的技术,主要是在Windows 10系统上实现IP级别的拦截和重定向。这种技术通常用于网络安全、网络调试或者测试环境中,以便对特定的IP通信进行监控或模拟不同...
在本案例中,描述了如何在STM32的C++项目中实现`printf`函数的重定向,使其能够通过UART(通用异步收发传输器)发送串口数据。 首先,`printf`是C标准库中的一个函数,它用于格式化输出字符串。在嵌入式系统中,...
### 多态的编译器实现原理 #### 概述 多态是面向对象编程中的一个重要概念,它允许程序员在不指定具体类型的情况下处理不同类型的对象。本文将深入探讨多态在编译器层面是如何实现的,特别是关注虚拟函数表...
这个C语言实现的shell项目提供了学习和实践这些知识的平台,对于理解操作系统原理和提高编程技巧非常有帮助。通过阅读和分析源代码,开发者可以更深入地了解操作系统如何工作,以及如何使用C语言构建这样的系统工具...
本资料主要探讨的是Shell解释器的实现原理,通过源码分析来深入理解其工作方式。 首先,Shell的主要任务是读取用户的输入,解析命令,然后执行这些命令。这个过程包括了以下步骤: 1. **命令行输入解析**:当用户...
通过阅读和理解这些源码,开发者不仅可以学习到重定向输出的基本原理,还能进一步掌握易语言与API交互的方法,提升自身的编程技能。 在实际应用中,曙光重定向输出模块可用于各种场景。例如,它可以用于开发日志...
通过理解这些基本概念和工作原理,用户不仅可以更高效地使用Linux Shell,还能编写自己的Shell脚本,实现自动化任务,提高工作效率。对于系统管理员和开发者来说,掌握Shell的工作原理至关重要。
在实际项目中,你可能会使用现成的库如PJSIP或Mozart来简化开发,但理解底层原理仍然是必要的。编写C++ SIP协议栈是一个挑战性的任务,它要求对网络编程、协议解析和多线程有深入理解。同时,遵循SIP标准(RFC 3261...
4. **Detouring**:Microsoft Detours库提供了一种高级的API Hook实现方式,它可以在运行时透明地重定向函数调用,无需篡改IAT或EAT。这种方法灵活且易于使用,但可能引入额外的性能开销。 5. **VTable Hook**:...
下面将详细介绍redir的实现原理及其在Windows环境中的应用。 首先,我们需要理解redir的核心功能:输入重定向(<)和输出重定向(>)。输入重定向允许我们将文件内容作为程序的输入,而输出重定向则把程序的输出...
尽管如此,Python通过其底层的bytecode机制提供了一种间接实现类似功能的方法。这个主题涉及到Python的内部工作原理,包括编译器和虚拟机(VM)的概念。 标题所提到的"Python-pythongoto函式修饰符"可能是指一种...
深入理解ASP.NET的底层架构和工作原理,不仅能提升开发者的技能水平,还能在遇到问题时快速定位和解决,特别是在面对复杂的应用场景时。掌握ASP.NET的这些核心概念,将使开发者能够在创建Web应用程序时做出更加明智...
理解SIP协议的工作原理对于构建和维护VoIP(Voice over IP)系统、多媒体通信平台以及实现下一代网络(NGN)服务至关重要。SIP不仅适用于传统的电话服务,还广泛应用于物联网、智能家居等领域,是现代通信技术中的...
这个框架广泛应用于各种在线服务,如社交媒体、云存储和API接口等。在这个"纯Java实现的OAuth2流程"中,我们将深入...这个实现对于学习和理解OAuth2的底层机制非常有价值,同时也可以作为自定义授权解决方案的基础。