我在 jsp 中使用jsp和servlet,方法类型为 POST 。但是在插入记录后再次刷新页面创建新记录。任何人都可以帮助我在 php 中使用替代标题吗?
或任何其他解决方案,我尝试了很多,但我的问题没有解决,所以再次发布这个问题。
谢谢
假设有 3 页
(1) Registration.jsp :具有注册表<form action="AddUser.jsp" >,用户可以在其中输入数据。
(2) AddUser.jsp(或者更好的是servlet):接受“Registration.jsp”提交的数据。
(3) Welcome.jsp : 注册后会出现这个页面。
所以在page2(AddUser.jsp)中写下如下代码
由于浏览器 URL 将被更改。因此,如果用户刷新页面,那么它也不会创建重复的条目。
如果我理解你的话:
POST /insertdata
到www.mypage.com
OK 200
您可以通过这样的重定向来避免它:
response.sendRedirect("http://www.mypage.com/insertsuccessful");
将此代码放在处理 POST 的 servlet/JSP 的末尾。这将发生:
POST /insertdata
到www.mypage.com
MOVED_TEMPORARILY 302
以标头响应Location: http://www.mypage.com/insertsuccesful
GET /insertsuccesful
到www.mypage.com
注意:状态码 (302) 和位置标头由该sendRedirect
方法自动设置。
现在,当用户刷新页面时
,它将不再发布重复数据。www.mypage.com/insertsuccesful
www.mypage.com/insertfailed
如果您在 POST 处理程序中捕获异常,您还可以创建页面并重定向到它。
更新 2
为了跟进@JB Nizet 的评论(感谢您的小心),我们假设您的 web 应用程序使用上下文路径部署,例如www.mypage.com/webapp
,并查看以下场景:
http://www.mypage.com/webapp/insertdata?redirectOnOK=/insertsuccessful
) 包含一个查询字符串参数redirectOnOk
,该参数定义成功插入后客户端将重定向到的位置 ->http://www.mypage.com/webapp/insertsuccessful
首先要注意的是这http://www.mypage.com/webapp/insertdata?redirectOnOK=/insertsuccessful
不是一个有效的 URL。这是无效的,因为您不希望/
在问号 ( ) 后出现斜线 ( ?
):
scheme://domain:port/path?query_string#fragment_id
有效的 URL 可以包含英文字母、数字、点 ( .
)、连字符 ( -
)、下划线 ( _
) 和波浪号 ( ~
)。其他一些标点符号是保留的,并且每个其他字符(有时甚至是保留字符)都必须是URL 编码的:
http://www.mypage.com/webapp/insertdata?redirectOnOK=%2Finsertsuccessful
由于在保留/
字符问号 ( ?
) 之后不需要保留字符斜线 ( ),因此必须对其进行编码。这是第一种情况的解决方案:
String redirectRelativeUrl = new URLDecoder().decode(request.getParameter("redirectOnOk"),"UTF-8");
response.sendRedirect(request.getContextPath() + redirectRelativeUrl)
URLDecoder#decode
解码%2F
为/
HttpServletRequest#getContextPath
需要返回 /webapp
(在第一种情况下,它会返回一个空字符串,因为没有上下文路径)/webapp/insertsuccessful
进入sendRedirect
方法/webapp/insertsuccessful
如果您在形成查询字符串时使用非英文字母字符,则键和值应始终为URL 编码:
String safe = new UrlEncoder().encode("ž@Š","UTF-8");
URL 重写是一种基于正则表达式映射 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())
getRequestURI
返回/webapp/resource.jsp
getQueryString
返回name=someName&count=12
encodeRedirectURL
有输入/webapp/resource.jsp?name=someName&count=12
/webapp/resource/someName/12
Session session = request.getSession();
这样做的结果是它设置了一个JSESSIONID
cookie:
jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
如果浏览器禁用了 cookie,则在程序化重定向时,用户将不再被验证,这意味着他将不得不再次登录。这种情况下的解决方案是:
String relativeRedirectUrl="/insertSucessful";
response.sendRedirect(response.encodeURL(request.getContextPath() + relativeRedirectUrl));
encodeURL
如果 cookie 被禁用,则附加;jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
到输入/webapp/insertSucessful;jsessionid=9ADABC18DB58C4DA99896C6261D2DD25
我认为您已经通过“linski”和“Rakesh”详细说明了答案的最重要部分。为此,我对他们都投了赞成票。
然而,我想指出一件事。
两个答案中都提到了已经存在一段时间的 PRG(Post-Redirect-Get)模式。这将解决大多数重复发布问题,但失败的一个领域是存在“服务器滞后”。如果您的后端工作在启动重定向之前有一些明显的滞后时间,则用户可能会通过再次单击提交按钮(假设您正在使用发布数据的按钮)来启动多个发布操作。
一个简单的前端解决方案是在第一次单击后暂时禁用按钮(或您用来启动发布操作的任何按钮)。
您当然可以在后端发挥创意,以确保同一用户在重定向发生之前不会发布重复的帖子,但这需要更多的工作。