基于Struts2实现防止表单重复提交的攻略
在Web应用程序中,表单重复提交是一个非常常见和麻烦的问题。当用户多次点击提交按钮时,可能会导致数据被重复提交,从而引发一些严重的问题,例如重复加入订单、重复发送邮件、重复插入数据库等错误操作。因此,对于Web应用程序来说,采取措施防止表单重复提交是至关重要的。
本文将介绍使用Struts2框架来实现防止表单重复提交的方法。
思路
Struts2框架提供了一个名为TokenInterceptor的拦截器,它能够防止表单重复提交。具体的实现过程如下:
-
在Struts2配置文件中开启Token拦截器。
-
在表单中添加
<s:token/>
标签。 -
在Action类中添加对应的Token校验方法。
示例一
下面是一个简单的示例,演示如何在Struts2中使用Token来防止表单重复提交。
Struts2配置文件
在Struts2的配置文件struts.xml
中,我们需要开启Token拦截器。具体实现可以参考如下代码:
<interceptors>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor-stack name="defaultStack">
<interceptor-ref name="token"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
表单代码
<s:form action="submit">
<s:textfield name="name" label="姓名"/>
<s:textfield name="age" label="年龄"/>
<s:token/>
<s:submit/>
</s:form>
Action类代码
public class SubmitAction extends ActionSupport {
private String name;
private int age;
public void validate() {
if (hasErrors()) {
return;
}
HttpSession session = ServletActionContext.getRequest().getSession();
String token = (String) session.getAttribute("struts.tokens.token");
if (token == null || !token.equals(this.getToken())) {
addFieldError("","请勿重复提交");
}
}
public String submit() {
// TODO: 业务逻辑处理
return SUCCESS;
}
// getter and setter method...
}
在Action类中,我们需要添加一个名为validate
的校验方法,在该方法中进行Token的验证工作。具体实现如上所示。
示例二
下面是另外一个示例,演示如何在Struts2中使用拦截器来防止表单重复提交,同时在Action类中添加日志信息。
Struts2配置文件
在Struts2的配置文件中,我们需要添加一个名为DuplicateFormSubmitInterceptor
的自定义拦截器。具体实现可以参考如下代码:
<interceptors>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="duplicateFormSubmit" class="com.example.interceptor.DuplicateFormSubmitInterceptor"/>
<interceptor-stack name="defaultStack">
<interceptor-ref name="token"/>
<interceptor-ref name="duplicateFormSubmit"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
自定义拦截器代码
public class DuplicateFormSubmitInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
Object form = invocation.getAction();
String methodName = invocation.getProxy().getMethod();
Method method = form.getClass().getMethod(methodName, new Class[]{});
if (method.isAnnotationPresent(DuplicateFormSubmit.class)) {
DuplicateFormSubmit annotation = method.getAnnotation(DuplicateFormSubmit.class);
if (annotation != null && !annotation.ignore()) {
String tokenName = annotation.value();
String tokenValue = request.getParameter(tokenName);
if (tokenValue == null) {
return ERROR;
} else {
HttpSession session = request.getSession();
String previousToken = (String) session.getAttribute(tokenName);
if (previousToken == null) {
return ERROR;
} else {
if (!previousToken.equals(tokenValue)) {
return ERROR;
}
}
}
session.removeAttribute(tokenName);
}
}
return invocation.invoke();
}
}
表单代码
<s:form action="submit">
<s:textfield name="name" label="姓名"/>
<s:textfield name="age" label="年龄"/>
<input type="hidden" name="token" value="${token}" />
<s:submit/>
</s:form>
Action类代码
@DuplicateFormSubmit("token")
public class SubmitAction extends ActionSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(SubmitAction.class);
private String name;
private int age;
public String execute() {
LOGGER.info("执行业务逻辑");
return SUCCESS;
}
// getter and setter method...
}
在这个示例中,我们使用自定义拦截器DuplicateFormSubmitInterceptor
来防止表单重复提交。同时,在Action类上我们使用注解@DuplicateFormSubmit
来标注需要进行防重复提交操作的方法,该注解有一个参数value
,表示在表单中使用的Token名称。
在表单代码中,我们需要使用<input type="hidden" name="token"/>
标签来添加Token值,并使用${token}
来替换Token的值,这样就可以在提交表单时向服务器传递Token值了。
在Action类中,我们使用了日志框架来记录业务逻辑的执行情况,并使用了@DuplicateFormSubmit
注解来标注需要进行Token校验的方法。
结论
通过以上两个示例,我们可以看到,在Struts2框架中实现防止表单重复提交非常简单。只需要配置Token拦截器,并在表单中添加<s:token/>
标签,在Action类中实现对Token的校验即可。如果需要进一步提升防御能力,也可以使用自定义拦截器来实现防止表单重复提交。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于Struts2实现防止表单重复提交 - Python技术站