如果我理解你的话:
- 浏览器将
POST /insertdata发送到www.mypage.com
- 数据被插入,服务器回复
@987654321@
- 当用户刷新页面时,再次启动插入重复数据的过程
你可以通过这样的重定向来避免它:
response.sendRedirect("http://www.mypage.com/insertsuccessful");
将此代码放在处理 POST 的 servlet/JSP 的末尾。这就是将会发生的事情:
- 浏览器将
POST /insertdata发送到www.mypage.com
- 数据被插入,服务器响应
@987654322@,标头Location: @987654323@
- 浏览器自动发送
GET /insertsuccesful到www.mypage.com
注意:状态码 (302) 和位置标头由 @987654324@ 方法自动设置。
现在当用户刷新页面时,它将是www.mypage.com/insertsuccesful,它将不再发布重复的数据。
您还可以创建www.mypage.com/insertfailed 页面,并在您在 POST 处理程序中捕获异常时重定向到该页面。
tutorial
更新 2
为了跟进@JB Nizet 的 cmets(感谢您的小心),让我们假设您的 web 应用程序使用上下文路径进行部署,例如www.mypage.com/webapp,并查看以下场景:
- 插入页面的 URL (
@987654326@) 包含一个 query string 参数 redirectOnOk,它定义了成功插入后客户端将重定向到的位置 ->@987654328@
- webapp 使用URL rewriting
- 您正在使用Session 进行登录控制
第一种情况
首先要注意的是@987654331@ 不是valid URL。这是无效的,因为您不希望在问号 (?) 后出现斜杠 (/):
scheme://domain:port/path?query_string#fragment_id
有效的 URL 可以包含英文字母、数字、点 (.)、连字符 (-)、下划线 (_) 和波浪号 (~)。其他一些标点符号是reserved,其他每个字符(有时甚至是保留字符)都必须是URL-encoded:
http://www.mypage.com/webapp/insertdata?redirectOnOK=%2Finsertsuccessful
由于在保留字符问号 (?) 之后不需要保留字符斜杠 (/),因此必须对其进行编码。这是第一种情况的解决方案:
String redirectRelativeUrl = new URLDecoder().decode(request.getParameter("redirectOnOk"),"UTF-8");
response.sendRedirect(request.getContextPath() + redirectRelativeUrl)
-
@987654335@ 将 %2F 解码为 /
-
需要
@987654336@ 才能返回/webapp(在第一种情况下,由于没有上下文路径,它将返回一个空字符串)
-
/webapp/insertsuccessful进入@987654337@方法
- 浏览器被重定向到
/webapp/insertsuccessful
如果您在形成查询字符串时使用非英文字母字符,则keys and values 应始终为URL encoded:
String safe = new UrlEncoder().encode("ž@Š","UTF-8");
第二个场景
URL 重写是一种基于regular expressions 映射URL 的机制。换句话说,浏览器请求:
http://www.mypage.com/webapp/resource/someName/12
如果上下文根下有一个JSP页面resource.jsp,那么可以定义一个URL重写规则将上面映射到:
http://www.mypage.com/webapp/resource.jsp?name=someName&count=12
因此,如果您以编程方式从您的 serlvet/JSP 重定向,您还必须应用(出站)URL 重写规则。在上面的例子中,入站规则是:
-
/someName/12 -> ?name=someName&count=12
-
/webapp/resource -> /webapp/resource.jsp
从服务器以编程方式重定向时需要应用出站规则:
-
name=someName&count=12 -> /someName/12
-
/resource.jsp -> /resource
为了简单起见,规则以这种方式呈现,实际上并不是正则表达式。这种情况下的解决方案是:
response.sendRedirect(response.encodeRedirectURL(request.getRequestURI() + "?" + request.getQueryString())
-
@987654341@ 返回/webapp/resource.jsp
-
@987654342@ 返回name=someName&count=12
-
@987654343@ 有输入 /webapp/resource.jsp?name=someName&count=12
- 浏览器被重定向到
/webapp/resource/someName/12
第三种情况
Initiating HTTP session 真的很简单:
Session session = request.getSession();
这导致它设置了一个JSESSIONIDcookie:
jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
如果浏览器禁用了 cookie,则在程序化重定向时,用户将不再通过身份验证,这意味着他将不得不再次登录。这种情况下的解决方案是:
String relativeRedirectUrl="/insertSucessful";
response.sendRedirect(response.encodeURL(request.getContextPath() + relativeRedirectUrl));
-
@987654347@ 附加 ;jsessionid=9ADABC18DB58C4DA99896C6261D2DD25 以输入如果 cookie 被禁用
- 浏览器被重定向到
/webapp/insertSucessful;jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
结论
- 由无效 URL 语法产生的错误很难调试,也很难注意到。在重定向到它们之前记录 URL 是一种很好的做法。
- 最好使用相对 URL,因为这样您就可以在具有不同域名的多台服务器上以及不同的上下文路径上部署您的 webapp,而无需更改某些属性文件中的源代码或值。