基于Struts2实现防止表单重复提交

基于Struts2实现防止表单重复提交的攻略

在Web应用程序中,表单重复提交是一个非常常见和麻烦的问题。当用户多次点击提交按钮时,可能会导致数据被重复提交,从而引发一些严重的问题,例如重复加入订单、重复发送邮件、重复插入数据库等错误操作。因此,对于Web应用程序来说,采取措施防止表单重复提交是至关重要的。

本文将介绍使用Struts2框架来实现防止表单重复提交的方法。

思路

Struts2框架提供了一个名为TokenInterceptor的拦截器,它能够防止表单重复提交。具体的实现过程如下:

  1. 在Struts2配置文件中开启Token拦截器。

  2. 在表单中添加<s:token/>标签。

  3. 在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技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • JS文本框不能输入空格验证方法

    确保JS文本框输入内容不包含空格可以通过验证输入内容的方法来实现。以下是实现JS文本框不能输入空格的完整步骤: 第一步:获取文本框中用户输入的内容 使用 JavaScript 获取该文本框中用户输入的内容,可以使用 document.getElementById() 方法或其他选择器。 let userInput = document.getElementB…

    Java 2023年6月15日
    00
  • springboot启动后卡住无日志的几种情况小结

    下面是关于“SpringBoot启动后卡住无日志的几种情况小结”完整攻略: 问题背景 在使用SpringBoot开发JavaWeb应用时,有时候可能会遇到启动后卡住无日志的情况,导致我们无法知道整个启动过程的具体信息。这种情况通常有以下几种原因: 应用启动卡在某个点,等待某个线程执行完成 应用启动时出现了未捕获的异常 应用启动时依赖的外部服务出现了故障 接下…

    Java 2023年6月2日
    00
  • XML与HTML的结合(上)

    下面我来为您详细讲解“XML与HTML的结合(上)”的完整攻略。 首先,让我们先明确一下XML和HTML的区别。HTML(Hypertext Markup Language)是一种用于创建网页的标记语言,而XML(Extensible Markup Language)则是一种通用的标记语言,用于描述数据。 因为XML具有更加灵活的结构和语法,所以可以用来描述…

    Java 2023年5月23日
    00
  • springboot多数据源使用@Qualifier自动注入无效的解决

    这里是 springboot多数据源使用@Qualifier自动注入无效的解决 的完整攻略,按照以下步骤进行操作即可。 问题描述 在 Spring Boot 中使用多数据源时,我们通常会在每个数据源的配置类上使用 @Qualifier 注解来标识不同的数据源,以便在注入时进行区分。但是在有些情况下,这种方式可能会导致注入失败,无法自动注入需要的数据源对象。 …

    Java 2023年5月20日
    00
  • Win2003平台上jsp虚拟主机环境的架设(IIS6+J2SDK+resin)

    这里提供Win2003平台上jsp虚拟主机环境的架设攻略,该环境采用IIS6+J2SDK+Resin,具体步骤如下: 准备工作 下载并安装J2SDK(Java SE Development Kit) 下载Resin,并解压到指定目录下。 下载并安装IIS6。 安装Resin 进入Resin解压后的主目录,找到bin目录。 右键点击resin.exe,选择“以…

    Java 2023年6月15日
    00
  • Java中关于char类型变量能够输出中文的问题

    Java中的char类型变量能够输出中文,是因为Java使用的是Unicode字符编码标准,其中全球所有的字符都有唯一的码位,包括中文字符。在Java中,char类型变量以16位无符号整数形式存储字符。由于Unicode字符集在编码范围内包含了中文字符,所以Java的char类型变量和String类型能将中文字符完美输出。 在Java中,对于char类型变量…

    Java 2023年5月26日
    00
  • java 实现KMP算法

    Java实现KMP算法完整攻略 什么是KMP算法 KMP算法全称是Knuth-Morris-Pratt算法,是一个字符串查找算法,用于在一个字符串S中查找一个模式串P出现的位置。 KMP算法思想 KMP算法的思想是通过一个”部分匹配”的概念,当部分匹配发生后,可以知道一部分字符是匹配的,从而充分利用这个已知信息,避免从头再去比较已经比较过的字符。 KMP算法…

    Java 2023年5月18日
    00
  • java使用jar包生成二维码的示例代码

    下面是Java使用jar包生成二维码的完整攻略: 1. 引入Jar包 在Java中使用二维码需要引入第三方Jar包,可以使用Zxing或者QrCode这两个常用的Jar包。这里以Zxing为例,可以从官网或者Maven库中下载获取。 2. 生成二维码 import java.awt.Color; import java.awt.Graphics2D; imp…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部