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

相关文章

  • servlet+JSP+mysql实现文件上传的方法

    实现文件上传功能需要前端页面、服务端servlet程序以及后台mysql数据库的支持。下面是使用servlet+JSP+mysql实现文件上传的完整攻略。 前端页面 首先,我们需要在前端页面上添加文件上传的表单,通过提交表单将文件传输到服务端。此处提供一段基本的表单代码: <form method="post" enctype=&q…

    Java 2023年6月15日
    00
  • Java如何搭建一个个人网盘

    搭建个人网盘是一项不错的技术挑战,如果你有一定的Java编程经验,那么就可以利用Java来完成个人网盘的搭建。以下是一个简单的Java搭建个人网盘的攻略: 开发环境准备 首先,你需要一个完整的Java开发环境。安装JDK并配置相应的环境变量,建议使用JDK 8或以上版本。其次,你需要一个开发工具,例如Eclipse或IntelliJ IDEA等IDE。当然,…

    Java 2023年5月26日
    00
  • jsp页面中如何将时间戳字符串格式化为时间标签

    在 JSP 页面中使用时间戳字符串,需要进行格式化为时间标签。下面是如何将时间戳字符串格式化为时间标签的完整攻略。 步骤1:导入时间函数库 首先,需要引入 JSP 内置的时间函数库,以便使用日期和时间相关的函数。 <%@ page import="java.text.SimpleDateFormat" %> <%@ pa…

    Java 2023年6月15日
    00
  • java实现斐波那契数列的3种方法

    以下是详细讲解“Java实现斐波那契数列的3种方法”的完整攻略。 一、斐波那契数列简介 斐波那契数列(Fibonacci Sequence)是一个非常经典的数学问题,它的定义如下: 斐波那契数列是一列数字,第一和第二项为 1,之后的每一项都是前两项之和。 数列的前几项为:1,1,2,3,5,8,13,21,34,55,89,144,… … 二、Java实现斐…

    Java 2023年5月19日
    00
  • Java后端Cookie实现(时间戳)代码实例

    请看下面的详细讲解: Java后端Cookie实现(时间戳)代码实例 一、Cookie介绍 Cookie是指服务器通过HTTP响应发送给客户端的一小段文本信息。浏览器会将这些信息存储在客户端,并在下一次访问相同的服务器时发送回服务器。 Cookie可以用于实现在客户端保留数据的功能,比如记住登陆状态、保存浏览历史等。 二、创建Cookie 在Java后端开发…

    Java 2023年6月1日
    00
  • Java中字符串中连续相同字符去重方法

    在Java中,要去除字符中连续相同的字符,可以使用正则表达式或者递归的方式实现。以下是实现方法的详细攻略。 使用正则表达式 正则表达式是一种用于匹配字符串的模式,可以用来查找、替换和拆分字符串。Java中使用Pattern和Matcher两个类来进行正则表达式的匹配操作。 在去除字符串中连续相同的字符时,可以使用正则表达式来进行匹配和去重操作。具体步骤如下:…

    Java 2023年5月27日
    00
  • Java构造函数通透理解篇

    Java构造函数通透理解篇 什么是构造函数 构造函数是一种特殊的函数,用于在创建对象时进行初始化操作。在Java语言中,构造函数名称必须与类名称完全一致,且没有返回值类型,因为构造函数的返回值类型就是类本身。 构造函数的作用 构造函数的主要作用是用于在创建对象时进行初始化操作,它会被自动调用,并设置类的初始状态。在构造函数中,可以进行对对象的属性进行初始化,…

    Java 2023年5月26日
    00
  • 使用BindingResult 自定义错误信息

    下面是关于使用BindingResult自定义错误信息的完整攻略。 一、BindingResult简介 在Spring MVC框架中,接受前端数据的方法一般会使用@ModelAttribute或@RequestBody注解对参数进行声明,此时也可以添加BindingResult类型的参数,用于接收数据绑定时产生的错误信息。 BindingResult是Spr…

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