我已经浏览了同样问题的答案,但是Struts中没有任何默认方法来防止重新提交吗?另外,就我而言,如果我重置表单字段,它仍然会保存旧值(但是,如何获取这些值)?
我有一个调度操作类:
public class QrcAction extends DispatchAction
{
public ActionForward waiverPage( final ActionMapping inMapping,
final ActionForm inForm,
final HttpServletRequest inRequest,
final HttpServletResponse inResponse )
{
QrcForm qrcForm = (QrcForm) inForm;
if ( StringUtils.isEmpty( qrcForm.getCustomerId() ) )
{
ActionMessages errors = getErrors( inRequest );
errors.add( IAppConstants.APP_ERROR, new ActionMessage( IPropertiesConstant.ERROR_INVALID_CUSTOMER_ID ) );
saveErrors( inRequest, errors );
return inMapping.findForward( IActionForwardConstant.QRC_SEARCH_CUSTOMER_PAGE );
}
qrcForm.setCustWaiverPojo( new CrmCustWaiverPojo() );
qrcForm.setRemarksPojo( new RemarksPojo() );
return inMapping.findForward( IActionForwardConstant.WAIVER_PAGE );
}
public ActionForward applyWaiver( final ActionMapping inMapping,
final ActionForm inForm,
final HttpServletRequest inRequest,
final HttpServletResponse inResponse )
{
String forward = IActionForwardConstant.WAIVER_PAGE;
QrcForm qrcForm = (QrcForm) inForm;
ActionMessages messages = getMessages( inRequest );
ActionMessages errors = getErrors( inRequest );
CrmuserDetailsDto userDto = (CrmuserDetailsDto) inRequest.getSession( false )
.getAttribute( IAppConstants.CRM_USER_OBJECT );
double waiverLimit = 0;
if ( StringUtils.isNotEmpty( userDto.getWaiverLimitAmmount() ) )
waiverLimit = Double.parseDouble( userDto.getWaiverLimitAmmount() );
if ( waiverLimit < qrcForm.getCustWaiverPojo().getWaiverAmount().doubleValue() )
{
errors.add( IAppConstants.APP_ERROR, new ActionMessage( IPropertiesConstant.ERROR_INVALID_WAIVER_LIMIT,
waiverLimit ) );
}
QrcFormHelper.validateWaiver( errors, qrcForm ); // validates pojo fields
if ( errors.isEmpty() )
{
// saving data to database
if ( success )
{
messages.add( IAppConstants.APP_MESSAGE, new ActionMessage( "success.msg.key" ) );
// resetting the form fields
qrcForm.setCustWaiverPojo( new CrmCustWaiverPojo() );
qrcForm.setRemarksPojo( new RemarksPojo() );
qrcForm.setSrTicketNo( null );
}
else
errors.add( IAppConstants.APP_ERROR, new ActionMessage( "error.msg.key" ) );
}
saveErrors( inRequest, errors );
saveMessages( inRequest, messages );
return inMapping.findForward( forward );
}
}
调用
waiverPage()
来显示表单,并且它已提交给 applyWaiver()
。在 applyWaiver()
中,成功保存值后,我将重置表单字段并将其转发到同一页面。提交并获得成功结果后,会显示一条消息并清除表单,之后,如果我再次刷新它,则会在数据库中创建一个具有相同的先前输入值的条目。
这个问题有办法解决吗?
更新:
waiver.jsp:
<html:form action="manageQrc.do?method=applyWaiver">
<html:hidden property="custWaiverPojo.customerId" name="qrcForm" value="${ qrcForm.customerId }"/>
<label class="label_radio">
<html:radio property="custWaiverPojo.waiverType" value="Goodwill Wavier" name="qrcForm" styleClass="waiverType">Goodwill</html:radio>
</label>
<label class="label_radio">
<html:radio property="custWaiverPojo.waiverType" value="Process Wavier" name="qrcForm" styleClass="waiverType">Process</html:radio>
</label>
<strong> Select Category </strong>
<span class="LmsdropdownWithoutJs">
<html:select property="custWaiverPojo.waiverHead" name="qrcForm" styleId="waiverHead">
<html:option value="">Please Select</html:option> <!-- options are filled after radio button selection -->
</html:select>
</span>
<strong>Amount</strong>
<html:text property="custWaiverPojo.waiverAmount" name="qrcForm" styleClass="textbox" styleId="waiverAmount" maxlength="10"></html:text>
<strong>Bill No. </strong>
<span class="LmsdropdownWithoutJs">
<html:select property="custWaiverPojo.billNo" name="qrcForm" styleId="waiverBill">
<html:option value="0">Please Select</html:option>
<html:option value="20140101">20140101</html:option>
<html:option value="20140201">20140201</html:option>
<html:option value="20140301">20140301</html:option>
<html:option value="20140401">20140401</html:option>
</html:select>
</span>
<strong>Ticket ID</strong>
<html:text property="srTicketNo" name="qrcForm" maxlength="20" styleClass="textbox" styleId="waiverSRT"></html:text>
<strong> Remarks</strong>
<html:textarea property="remarksPojo.remarks" name="qrcForm" styleClass="LmsRemarkstextarea" styleId="waiverRemarks"></html:textarea>
<html:submit />
</html:form>
本博客中的解决方案使用token来标识请求为:
第1步:
使用
saveToken()
方法在会话中保存令牌,该方法在 Action
类中实现。
public class EmployeeLoadAction extends Action{
private final static String SUCCESS = "success";
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ActionForward forward;
forward = mapping.findForward(SUCCESS);
saveToken(request);
return forward;
}
}
第2步:
在JSP文件中。在这个例子中是
employee.jsp
。
使用 JSP 文件中的
hidden
变量存储令牌,如下所示。
不要忘记在 JSP 文件中导入
Globals
和 Constants
类以避免 Jasper Exception
TRANSACTION_TOKEN_KEY
内部的 Action class
变量已被弃用,因此请使用 Globlas class
中的变量。
<%@ page import="org.apache.struts.Globals" %>
<%@ page import="org.apache.struts.taglib.html.Constants" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form name="employee" action="EmployeeSubmit.do" method="POST">
<input type="hidden" name="<%= Constants.TOKEN_KEY %>" value="<%= session.getAttribute(Globals.TRANSACTION_TOKEN_KEY) %>">
<TABLE>
<TR>
<TD>Name</TD>
<TD>
<input type="text" name="empName">
</TD>
</TR>
<TR>
<TD>ID</TD>
<TD>
<input type="text" name="empId">
</TD>
</TR>
<TR>
<TD colspan="2">
<input type="submit" value="Submit">
</TD>
</TR>
</TABLE>
</form>
</body>
</html>
第三步:
现在,重复提交的实际逻辑位于
EmployeeSubmit
操作类中。
方法
isTokenValid()
将验证令牌并返回 boolean
。
据此,我们可以决定是否重新提交表单。
public class EmployeeSubmitAction extends Action{
private final static String SUCCESS = "success";
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ActionForward forward;
forward = mapping.findForward(SUCCESS);
EmployeeSubmitForm frm = (EmployeeSubmitForm) form;
if (isTokenValid(request)) {
System.out.println("frm.getName() : " + frm.getEmpName());
resetToken(request);
} else {
System.out.println("frm.getName() : " + frm.getEmpName());
System.out.println("Duplicate Submission of the form");
}
return forward;
}
}
在
成功保存值后,我正在重置表单字段并将其转发到同一页面。applyWaiver()
这是一个问题,因为提交后您应该重定向到将显示页面的操作。在操作中,您还可以填充表单 bean(如果它不是会话范围内的)。因此,在代码中使用重定向到操作的转发
public ActionForward applyWaiver( final ActionMapping inMapping,
final ActionForm inForm,
final HttpServletRequest inRequest,
final HttpServletResponse inResponse )
{
...
if (! errors.isEmpty() )
{
errors.add( IAppConstants.APP_ERROR, new ActionMessage( "error.msg.key" ) ;
// resetting the form fields
qrcForm.setCustWaiverPojo( new CrmCustWaiverPojo() );
qrcForm.setRemarksPojo( new RemarksPojo() );
qrcForm.setSrTicketNo( null );
saveErrors( inRequest, errors );
saveMessages( inRequest, messages );
return inMapping.findForward( forward );
}
MessageResources mr = (MessageResources) inRequest.getAttribute(Globals.MESSAGES_KEY);
// saving data to database
if ( success )
inRequest.setAttribute( IAppConstants.APP_MESSAGE, mr.getMessage( "success.msg.key" ) );
else
inRequest.setAttribute( IAppConstants.APP_MESSAGE, mr.getMessage( "error.msg.key" ) );
return new ActionForward(inMapping.findForward( forward ).getPath(), true ); //true is for redirect
}