基于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日

相关文章

  • java — 线程(二)

    死锁 死锁是指两个或两个以上的线程在执行过程中,由于竞争同步锁而产生的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程称为死锁。 死锁的案例 : 同步代码块的嵌套创建锁对象: public class Lock { public static final Lock lockA = new L…

    Java 2023年4月17日
    00
  • Java线程中断的本质深入理解

    Java线程中断的本质深入理解 Java中断是一种非常有用的工具,它可以停止正在运行的线程。然而,这个过程并不总是那么简单。 理解线程中断 线程中断可以被认为是设置一个标志,让线程知道它应该停止执行。线程可以使用isInterrupted()方法来检查标志是否被设置。也可以使用Thread.interrupted()方法来检查标志并清除它。 例如,以下代码段…

    Java 2023年5月26日
    00
  • Java axios与spring前后端分离传参规范总结

    Java axios与Spring前后端分离传参规范总结 本攻略主要介绍了在Java axios与Spring前后端分离的开发中,如何进行传参规范。 一、传参规范 在前后端分离的开发中,一般通过JSON格式传递参数。在发送请求时,需要规范JSON数据的格式,保证后端能够正确解析参数。 以axios请求为例,将参数封装在data属性中,如下: javascri…

    Java 2023年6月3日
    00
  • springBoot中的properties配置解析

    在Spring Boot中,可以使用properties文件来配置应用程序的属性。这些属性可以用于配置数据源、日志、缓存、安全等方面。本文将详细讲解Spring Boot中的properties配置解析,包括如何定义属性、如何使用属性、如何覆盖属性等。 定义属性 在Spring Boot中,可以使用application.properties或applica…

    Java 2023年5月15日
    00
  • Spring boot整合security详解

    Spring Boot整合Security详解 Spring Security是一个功能强大的安全框架,可以帮助我们保护Web应用程序。Spring Boot提供了与Spring Security的无缝集成,本文将详细介绍如何使用Spring Boot整合Security,并提供两个示例。 添加依赖 首先,我们需要在pom.xml文件中添加Spring Se…

    Java 2023年5月15日
    00
  • 利用Java实现调用http请求

    以下是利用Java实现调用HTTP请求的完整攻略。 简介 在Java中,我们可以使用HttpURLConnection或者Apache HttpClient来实现HTTP请求。两者区别在于HttpURLConnection是内置于Java SDK中的,而Apache HttpClient是第三方库。以下分别讲解这两种方式的使用方法。 使用HttpURLCon…

    Java 2023年5月19日
    00
  • java多版本共存

    原理 通过脚步改变path环境变量来实现java多版本切换.这里使用的是Win10. 一,删除原有的java搜索路径. 在安装高版本的java时,会添加一个路径到path环境变量中,如我的C:\Program Files\Common Files\Oracle\Java\javapath,在该目录下存有java.exe和javac.exe等.在用cmd执行命…

    Java 2023年4月17日
    00
  • Spring Security使用中Preflight请求和跨域问题详解

    Spring Security使用中Preflight请求和跨域问题详解 什么是Preflight请求 Preflight请求也被称为CORS预检请求,是跨域请求中的一种。在进行跨域请求时,客户端会自动发送Preflight请求到服务器来检查是否可以跨域请求。具体来说,Preflight请求是一个附带预检请求头信息的OPTIONS请求,用于检查实际请求是否可…

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