今天重新认识了Post/Redirect/Get pattern, 感谢hip-hop的session, 一下帮助我理清了概念和思路.

谈到pattern,首先要清楚它为了什么而产生: PRG (参见链接1)是为了解决web页面的double submit问题而提供的一种方案.

1. double submit problem

上下文: 用户在browser中的pageA页面完成输入,点击了提交按钮,进入pageB页面,提示"提交成功". 这时, 若分别出现下列三种case:

1> 重新载入或刷新pageB;

2> 点击浏览器的后退按钮,接着点击前进按钮;

3> 点击浏览器的后退按钮退回到pageA,再点一回提交按钮;

对于没有考虑过这种问题而直接开发的网站,会出现什么情况呢?

case 1和case 2会由浏览器弹出一个小窗口,提示大意如"可能重复提交页面,是否继续?"的询问,如果选择了yes,那么前面的提交行为会再做一次;而case 3属于你主动地再一次提交. 也就是说,如果是买东西的话,那你已经重复买到了第二份! 这就是所谓的double submit.

究起实质, 是由于submit pageA和点击提交按钮共用了同一个服务器请求, 而这恰恰是一个POST请求, 在页面被重复提交的背后, POST请求也被多次发送, 导致server上错误地多次执行了添加或更改数据的行为. 图1解释了double submit问题.

图 1 Double Submit Problem

2. PRG solusion

应该想到,用户的这类如"后退再前进"或刷新的行为, 应当视为对历史结果或页面的查看, 并无再次提交之意.

解决问题的一种思路就是将用户点击提交按钮从而发出POST请求, 页面提交跳转和显示结果页面这三个行为分离开. PRG正是遵循这种思路, Client用POST方法请求Server响应数据变更, Server用Redirect方法将response指定到另一个URL上的结果页面, Client所有对页面显示的请求都用GET方法告知Server. 解决方案如图2所示. 这样, "后退再前进"或刷新页面的行为都发出的是GET请求, 从而不会对server产生任何数据更改的影响, double submit problem得以解决.

图2  PRG solusion

Basic principles:

* 不要用一个页面直接作为POST请求的响应结果, 你会给习惯"后退再前进"的人留下resubmit难题.

* 在处理完POST请求之后, redirect到另一个URL页面, 刷新页面的人就只能看到它.

* 用GET而不是POST去请求一个页面的显示, 当你需要的仅仅是显示的结果.

请注意:

* 后退到页面内再点击提交按钮来提交页面的行为,依然被认为是用户自愿的提交.

* 第一次提交后, Server的response正常完成之前的再次提交若未被所应用的框架阻止的话, 它会被Server认为是另一个正常提交.

3. IsPostBack

值得一提的是, .Net WebForm中, 常在Page_Load方法中使用Page.IsPostBack属性来判断对当前Form的请求是第一次or非第一次, 这和本文讨论的问题不完全一致: Asp.net提供了支持服务器端事件的控件, 同时还支持控件的AutoPostBack行为, 故会多次发出对当前Form的请求, 而IsPostBack提供了加载页面时的一个逻辑分支. IsPostBack属性在多种情况下的取值规则可参见链接2 .

附参考链接:

[1]  http://en.wikipedia.org/wiki/Post/Redirect/Get

[2]  http://www.cnblogs.com/hobe/archive/2008/04/06/1139031.html

http://blog.csdn.net/shaobo_wu/article/details/5854448

转---Post/Redirect/Get pattern的更多相关文章

  1. Post/Redirect/Get pattern | PRG 模式

    Post/Redirect/Get 是一种 web 开发设计模式,用于防止表单的重复提交. 默认情况,提交 Post 请求到服务器后,如果直接刷新浏览器,会重新在提交一次 Post 请求.在访问电商网 ...

  2. Go web开发初探

    2017年的第一篇博客,也是第一次写博客,写的不好,请各位见谅. 本人之前一直学习java.java web,最近开始学习Go语言,所以也想了解一下Go语言中web的开发方式以及运行机制. 在< ...

  3. A real ROCA using Bootstrap, jQuery, Thymeleaf, Spring HATEOAS and Spring MVC

    http://www.tuicool.com/articles/ENfe2u https://github.com/tobiasflohre/movie-database What is the be ...

  4. ASP.NET MVC:4 Ways To Prevent Duplicate Form Submission(转载)

    原文地址:http://technoesis.net/prevent-double-form-submission/. Double form submission in a multi-user w ...

  5. Go 源码学习之--net/http

    其实自己不是很会看源码,但是学习优秀的源码是提升自己代码能力的一种方式,也可以对自己以后写代码有一个很好的影响,所以决定在之后的时间内,要有一个很好的习惯,阅读优秀的源码.刚开始自己会觉得看源码很痛苦 ...

  6. Go Revel - Session / Flash(会话与flash)

    ##Session / Flash 作用域 revel提供了两种cookies存储机制: // 一个加密签过的cookie (限制为4kb). // 限制: Key 中不能有冒号 type Sessi ...

  7. springmvc DispatchServlet初始化九大加载策略(三)

    7. initRequestToViewNameTranslator 请求视图名 它主要与视图解析有关,如果对ViewResolvers.ModelAndView.View等没有多大印象,可以先看第8 ...

  8. Golang构建HTTP服务(一)--- net/http库源码笔记

    搭建一个简单的Go Web服务器 Go语言标准库 - net/http 在学习Go语言有一个很好的起点,Go语言官方文档很详细,今天我们学习的Go Web服务器的搭建就需要用到Go语言官方提供的标准库 ...

  9. Spring 4 官方文档学习(十一)Web MVC 框架之Flash Attributes

    接上一篇中的重定向. http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-fl ...

随机推荐

  1. Android开发——LinearLayout和RelativeLayout的性能对比

    0. 前言 我们都知道新建一个Android项目自动生成的Xml布局文件的根节点默认是RelativeLayout,这不是IDE默认设置,而是由android-sdk\tools\templates\ ...

  2. 银行业务-Excel文件的拆分逻辑

    一.问题: 随着银行业务数据量的急剧增加,原始的人力统计数据已经不能满足要求, 需要开发一款可以实现自动化数据统计的系统平台,进行数据的采集.加工.过滤.统计.预测 其中数据采集方式又以[Excel] ...

  3. 基于MapReduce的(用户、物品、内容)的协同过滤推荐算法

    1.基于用户的协同过滤推荐算法 利用相似度矩阵*评分矩阵得到推荐列表 已经推荐过的置零 2.基于物品的协同过滤推荐算法 3.基于内容的推荐 算法思想:给用户推荐和他们之前喜欢的物品在内容上相似的物品 ...

  4. C#入门经典第十章例题 - - 卡牌

    1.库 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ...

  5. TW实习日记:第六天

    今日的一整天都是在开发微信相关的接口,因为项目的系统是嵌在企业微信中,所以不可避免的要产生微信UserID和企业系统ID的匹配关系,那么就需要用手机号或是邮箱这种两边都存在的唯一参数进行匹配.然后再将 ...

  6. 高可用Kubernetes集群-10. 部署kube-proxy

    十二.部署kube-proxy 1. 创建kube-proxy证书 1)创建kube-proxy证书签名请求 # kube-proxy提取CN作为客户端的用户名,即system:kube-proxy. ...

  7. vsftpd安装配置虚拟用户

    原文发表于cu:2016-03-11 参考文档: FTP原理:http://vbird.dic.ksu.edu.tw/linux_server/0410vsftpd_1.php FTP配置:http: ...

  8. 做程序开发的你如果经常用Redis,这些问题肯定会遇到

    分布式缓存Redis是一种支持Key-Value等多种数据结构的存储系统.可用于缓存.事件发布或订阅.高速队列等多种场景.Redis使用ANSI C语言编写,提供字符串(String).哈希(Hash ...

  9. Python mutilprocessing Processing 父子进程共享文件对象?

    multiprocessing python多进程模块, 于是, Processing也是多进程的宠儿. 但今天讨论的问题, 似乎也能引起我们一番重视 直接上代码:     1 2 3 4 5 6 7 ...

  10. Scrum立会报告+燃尽图(十一月十七日总第二十五次):设计调查问卷;修复上一阶段bug

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...