【Servlet与JSP】请求转发与重定向

假设一个登陆系统,要求用户输入用户名和密码:

用户在上面表单当中输入了信息以后,点击登陆按钮(type="submit")将表单做为请求参数进行提交。html

这一提交就有两种形式:getpost
GET:显式获取,请求参数明晃晃地放入url(以?开始)中,经过TCP连接传给目标服务页。
POST:分邮获取,先向目标服务器发出请求首部,如得到确定答复(816 I'm a teapot! 100 Continue)以后向目标服务页发出请求体,请求体被暗含。前端

通常出于必定安全性和功能性考虑(URL的长度有限直接致使GET自身的局限性),像这种登陆请求通常都经过POST发送,并且POST能够进行请求信息的编码,而GET只有一种编码方式(也是由于URL的编码方式有限),但若是只是用于用户查询的这种临时性的信息出于速度考虑会使用GET(由于GET是直接发出一次请求)。安全

固然,这不是今天讨论的重点服务器

咱们使用POST(仅讨论这种方式)方式发出请求信息,服务端页面内部嵌入的JSP代码或服务端后台的Servlet代码(实际上,JSP严格说属于后台代码,由于JSP能够等价为一个Servlet,只不过一般处理前端业务)就开始处理请求,服务端处理请求以后就要进行验证处理,若是验证经过就会以这个用户信息登陆。less

因而咱们有了这样的局面:
jsp

若是登陆正确,则服务端将主页(index.jsp)呈现到用户(客户端)面前,不然将错误登陆的页面(error.jsp)提示给用户。post

然而,请求的处理方式就有了两种:请求转发(Request Dispatch)重定向(Redirection)编码

  1. 请求转发:服务端LoginServlet收到来自于login.jsp的请求,LoginServlet对请求的信息进行验证,根据验证结果,经过请求分发器(Request Dispatcher)将登陆的请求信息分发到index.jsperror.jsp(下文简称结果页
  2. 重定向:服务端LoginServlet收到来自于login.jsp的请求,LoginServlet对请求的信息进行验证,根据验证结果,服务端向客户端发出重定向到对应页面的响应(301 Redirect),客户端收到重定向响应以后进行第二次请求发送。

显然,这两个过程的事情是不同的,其结果也不同。url

请求转发

小明:李华,麻烦告诉物理老师一声,下节物理课改为体育了
李华:可是,我是英语课表明,你应该去找牛顿同窗,他知道物理老师的办公室,这样吧我帮你转告给他(默记:下节物理课改为体育了)。
李华找到了牛顿同窗
李华:牛顿,告诉物理老师一声,(回想到默记内容:下节物理课改为体育了),下节物理课改为体育了
牛顿:(默记:下节物理课改为体育了)好的,我把这个消息转告物理老师spa

请求转发正是这样的一个相似于传火的过程:

login.jsp将用户的登陆信息封成一个请求发送给LoginServletLoginServlet检查无误以后就把这个请求随手转发给了index.jsp,这样一来index.jsp可以知道:

啊,原来是那个该死的管理员登陆了呢,我真巴不得踢他的屁股呢。

也就是说,请求的信息在转发过程当中是被保留下来的,这当然是很好的。
请求转发经过Servlet的request内置对象(主要负责请求的处理)的getDispatcher(url).forward(requ,resp)方法实现。表示向url页面转发请求。requresp参数一般直接填写requestresponse这两个内置对象,表示对当前的请求和响应进行传递。

因为请求转发是在服务端完成的,服务端将结果页做为一个response总体返回,所以客户端根本察觉不到任何事情,地址栏指示为处理该请求的Servlet的URI。
这也无形中埋下了一个隐患,因为请求是一脉相承的,所以一旦用户在这个过程当中一个不当心按了一下F5(刷新),整个转发过程要从新走一遍,假设这个请求处理购买业务,那将是很是致命的(好比重复购买和重复支付)。

重定向

小明:李华,麻烦告诉物理老师一声,下节物理课改为体育了
李华:(心不在焉)我是英语课表明,你找错人了,本身跟物理课表明牛顿同窗说去。
吃了个闭门羹,小明一脸尴尬的找到了牛顿同窗
小明:牛顿同窗……
牛顿:嗯??怎么了??
小明:……(唉??我要说啥来着O.O……)

重定向是一种服务端的响应(Response),HTTP中规定的重定向的响应信息是3系的(301 Permanent moved302 Found)。
重定向,顾名思义,就是新确你的请求方,好比说,原本你在地址栏里敲的AAA.com(纯属虚构,若有雷同不胜荣幸),可是AAA.com因业务调整迁移到了BBB.com,这种状况下服务商一般会保留AAA.com的域名而后在此域名下提供一个重定向将你带到BBB.com。

重定向的响应服务端发出,但重定向以后的请求仍然由客户端发出。
重定向方式是经过内置对象responsesendRedirect(url)方法实现,由于根据HTTP的规定,一个规范的重定向响应必须包含一个重定向的目标地址[RFC 2616]。

The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).

HTTP/1.1 301 Moved Permanently
Location: http://www.example.org/index.asp

url就是规范中规定的目标地址。

可是,这个url自己也就表明了客户端的第二次访问请求,但一般重定向信息中仅仅包含目标页面的URL,将此URL做为新的访问请求时,本来的登陆信息就不复存在了(由于新的访问请求不包含这些内容)。
这样一来,即便登陆成功,index.jsp也无从知晓是谁登陆了,他只能知道的是:

好像有个很厉害的家伙登陆了耶,是谁呢,算了老实装死就行了。

综上,重定向的方式会致使请求丢失(Request Loss)

但这个问题应该有办法解决吧

确实如此,回顾一下上面的GET请求方式,

GET:显式获取,请求参数明晃晃地放入url(以?开始)中,经过TCP连接传给目标服务页。

这也就意味着,我能够把从POST获取的请求再从新以GET的方式塞入URL中,这样反馈给客户端从新发送的请求就再一次包含了以前的信息。

可是!

正如前面所说的,因为GET和POST之间的差别,这种作法可能会带来某种风险。

那么我看X度啦,X宝啦,都不会出现上面两种状况呢

其实,做为登陆功能,通常仍是青睐采用重定向的方式(其实教务处的CAS认证跳转也是重定向的方式),毕竟登陆了一溜十三招,发现地址栏仍是那个位置彷佛也是很是的古怪。
可是正如前面所说的,重定向有信息丢失的风险,由于重定向的内容每每不包含登陆信息。

因而乎另外一个内置对象就有了做用——会话(Sessions)

会话是服务端在服务器上建立的一个对象,专门用于对一个具体用户进行交互,能够简单理解为一个一对一服务员。 既然重定向会致使信息丢失,那么就在重定向以前在服务端建立一个会话,在会话中指明登陆的信息,这样重定向以后,会话内容在服务端天然是不会丢失的,而用户从新访问页面的时候直接从会话读取登陆信息就能够了。

相关文章
相关标签/搜索