`
szlxh002
  • 浏览: 34952 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

避免重复提交表单

 
阅读更多

重复提交表单原因:

1.前台多次按了“提交”接钮;

通过在前台按钮的onclick事件来避免

 <script language="javascript">
            <!--
                var checkSubmitFlg=true; 
                function checkSubmit()
                {
                    if(true==checkSubmitFlg)
                    {
                        document.theForm.submit();
                        checkSubmitFlg=false;
                    }
                    else
                    {
                        alert("你已经提交了表单,请不要重复提交!");
                    }
                }
            //-->
        </script>

 

 

 

2.在浏览器按“刷新”按钮

在相关的页面的表单上增加TokenProcessor隐藏域(input type="hidden")。

(1)在后台建立TokenProcessor类

package com.cjg.servlet;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * TokenProcessor类是一个单例类。
*/
public class TokenProcessor
{
    static final String TOKEN_KEY="org.sunxin.token";
   
    private static TokenProcessor instance = new TokenProcessor();

    /**
     * getInstance()方法得到单例类的实例。
     */
    public static TokenProcessor getInstance()
    {
        return instance;
    }

    /**
     * 最近一次生成令牌值的时间戳。
     */
    private long previous;

    /**
     * 判断请求参数中的令牌值是否有效。
     */
    public synchronized boolean isTokenValid(HttpServletRequest request)
    {
        //得到请求的当前Session对象。
        HttpSession session = request.getSession(false);
        if (session == null)
        {
            return false;
        }
        
        //从Session中取出保存的令牌值。
        String saved = (String) session.getAttribute(TOKEN_KEY);
        if (saved == null) {
            return false;
        }
        
        //清除Session中的令牌值。
        resetToken(request);
        
        
        //得到请求参数中的令牌值。
        String token = request.getParameter(TOKEN_KEY);
        if (token == null) {
            return false;
        }
        
        return saved.equals(token);
    }

    /**
     * 清除Session中的令牌值。
     */
    public synchronized void resetToken(HttpServletRequest request)
    {

        HttpSession session = request.getSession(false);
        if (session == null) {
            return;
        }
        session.removeAttribute(TOKEN_KEY);
    }

    /**
     * 产生一个新的令牌值,保存到Session中,
     * 如果当前Session不存在,则创建一个新的Session。
     */
    public synchronized void saveToken(HttpServletRequest request)
    {

        HttpSession session = request.getSession();
        String token = generateToken(request);
        if (token != null) {
            session.setAttribute(TOKEN_KEY, token);
        }

    }

    /**
     * 根据用户会话ID和当前的系统时间生成一个唯一的令牌。
     */
    public synchronized String generateToken(HttpServletRequest request)
    {

        HttpSession session = request.getSession();
        try
        {
            byte id[] = session.getId().getBytes();
            long current = System.currentTimeMillis();
            if (current == previous)
            {
                current++;
            }
            previous = current;
            byte now[] = new Long(current).toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(id);
            md.update(now);
            return toHex(md.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            return null;
        }
    }

    /**
     * 将一个字节数组转换为一个十六进制数字的字符串。
     */
    private String toHex(byte buffer[])
    {
        StringBuffer sb = new StringBuffer(buffer.length * 2);
        for (int i = 0; i < buffer.length; i++)
        {
            sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
            sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
        }
        return sb.toString();
    }
    
    /**
     * 从Session中得到令牌值,如果Session中没有保存令牌值,则生成一个新的令牌值。
     */
    public synchronized String getToken(HttpServletRequest request)
    {
        HttpSession session = request.getSession(false);
        if(null==session)
            return null;
        String token=(String)session.getAttribute(TOKEN_KEY);
        if(null==token)
        {
           token = generateToken(request);
            if (token != null)
            {
                session.setAttribute(TOKEN_KEY, token);
                return token;
            }
            else
                return null;
        }
        else
            return token;
    }
}

 (2)在表单加入TokenProcessor隐藏域

 <body>
        <%
            TokenProcessor processor=TokenProcessor.getInstance(); 
			String token=processor.getToken(request);
        %>
        <form method="post" action="handler" name="theForm">
            <table>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username"></td>
                </tr>
                <tr>
                    <td>密码:</td>
    	            <td>
    	                <input type="password" name="password">
                        <input type="hidden" name="org.sunxin.token" value="<%=token%>"/>
    	            </td>
    	        </tr>
    	        <tr>
    	            <td><input type="reset" value="重填"></td>
    	            <td><input type="button" name="btnSubmit" value="提交" onClick="checkSubmit();"/></td>
    	        </tr>
	        </table>
	        
        </form>
    </body>

 (3)处理form的Servlet

 

package com.cjg.servlet;

import javax.servlet.*;
import java.io.*;
import javax.servlet.http.*;
import java.util.*;

import com.cjg.servlet.TokenProcessor;

public class HandlerServlet extends HttpServlet
{
    int count=0;
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException,IOException
    {
        resp.setContentType("text/html;charset=GBK");
        PrintWriter out=resp.getWriter();
        
        TokenProcessor processor=TokenProcessor.getInstance();
        if(processor.isTokenValid(req))
        {
            try
            {
                Thread.sleep(5000);
            }
            catch(InterruptedException e)
            {
                System.out.println(e);
            }
                
            System.out.println("submit : "+count);
            if(count%2==1)
                count=0;
            else
                count++;
            out.println("success");
        }
        else
        {
            processor.saveToken(req);
            out.println("你已经提交了表单,同一表单不能提交两次。");
        }
        out.close();
    }
}

 

 

 

 

分享到:
评论

相关推荐

    WPF框架在MES系统中的应用:涵盖AGV调度、多线程、数据库及工业组态技术

    内容概要:本文详细介绍了基于WPF框架构建MES(制造执行系统)的经验和技术要点。主要内容包括:使用C#和WPF进行AGV(自动导引车)调度的多线程编程,采用Entity Framework和Dapper进行数据库操作,以及通过TCP/IP Socket和OPC UA协议实现工业组态和数据通信。此外,还探讨了Excel数据导出、PLC通信、路径规划、缓存机制等具体应用场景的技术实现。 适合人群:对WPF框架、MES系统开发感兴趣的软件工程师,尤其是那些希望深入了解工业自动化领域的开发者。 使用场景及目标:适用于需要快速开发高效稳定的MES系统的团队。主要目标是提高生产效率,优化资源配置,增强系统的实时性和稳定性。文中提供的代码片段和实践经验可以帮助开发者更好地理解和解决实际开发中遇到的问题。 其他说明:文章不仅提供了详细的代码示例,还分享了许多实用的开发技巧和优化建议,如多线程处理、异步编程、内存管理和UI更新等。对于想要深入研究WPF框架及其在工业自动化领域应用的人来说,是一份宝贵的参考资料。

    3dmax插件020-一键橱柜.ms

    3dmax插件

    西门子Smart200 PLC与威伦触摸屏三轴螺丝机控制系统解析及应用

    内容概要:本文详细介绍了基于西门子Smart200 PLC和威伦触摸屏的三轴螺丝机控制系统。首先,阐述了系统的硬件配置,包括PLC型号、步进驱动器和触摸屏的选择。接着,深入讲解了核心控制流程,如原点回归、点动控制和任意坐标定位的具体实现方法。文中还展示了如何利用PLC自带的高速脉冲输出进行精确的运动控制,以及如何通过触摸屏实现坐标管理和实时监控。此外,文章分享了一些实用技巧,如状态机架构的应用、运动控制框架的设计思路和常见问题的解决方案。 适合人群:自动化控制领域的工程师和技术人员,尤其是对PLC编程和运动控制感兴趣的初学者和有一定经验的研发人员。 使用场景及目标:适用于工业自动化生产线中需要精密定位和控制的设备开发,如螺丝机、贴标机、点胶机等。目标是帮助读者掌握PLC编程技巧,提高运动控制系统的稳定性和效率。 其他说明:文中提供了详细的代码示例和调试建议,有助于读者快速理解和应用相关技术。同时,强调了系统设计中的注意事项,如脉冲当量计算、机械结构优化等,确保系统的可靠运行。

    宣宇-美团万亿级对象存储挑战和实践探索.pdf

    Con北京站聚焦技术落地与前沿趋势,核心方向包括: ​​AI工程化​​:端侧推理、RAG增强、多模态生成成为主流; ​​云原生深水区​​:混合云治理、湖仓一体架构、可观测性技术持续迭代; ​​安全与效能​​:大模型安全防御、研发流程标准化、平台工程价值凸显; ​​行业融合​​:物流、金融、社交等领域的技术跨界创新案例丰富。 大会为开发者提供了从理论到实践的全景视角,推动技术向生产力转化。

    电动汽车内置式永磁同步电机(MTPA/MTPV)查表控制算法及自动生成程序

    内容概要:本文详细介绍了用于电动汽车内置式永磁同步电机(IPMSM)的基于查询表的矢量控制算法及其自动生成程序。文章首先解释了IPMSM的凸极特性和MTPA(最大转矩每安培)、MTPV(最大功率每伏特)之间的关系,强调了电流分配表在两者间平滑切换的重要性。随后展示了核心代码结构,包括遍历转速-转矩工作点、求解最优dq轴电流、电压电流约束检查以及弱磁补偿策略。此外,文章还讨论了数据输出方式,提供了C语言二维数组和Excel两种格式,并分享了一些实战经验和常见问题解决方法。最后提到了弱磁仿真的重要性,特别是在应对电池电压波动时的表现。 适合人群:从事电动汽车电机控制系统开发的技术人员,尤其是熟悉MATLAB编程并有一定电机控制背景的研发人员。 使用场景及目标:适用于需要高效生成IPMSM电流参考值表的工程项目,旨在提高电机控制系统的性能和稳定性,减少手动计算带来的错误和时间成本。 其他说明:文中提供的MATLAB源码已开源,可在GitHub上获取。同时,作者提醒使用者根据实际情况调整电机参数,以确保生成的查表能够正确应用于具体项目。

    信号处理领域中小波降噪、小波包降噪与滤波降噪的Python实现及应用场景

    内容概要:本文详细介绍了三种常用的信号降噪方法:滤波降噪、小波降噪和小波包降噪。滤波降噪通过设计滤波器来分离信号和噪声,适用于频率特性明确的噪声。小波降噪基于小波变换,能够自适应地捕捉信号的局部特征,尤其适合非平稳信号。小波包降噪则进一步细化了信号的频率分解,提供了更好的降噪效果,尤其在处理复杂信号时表现出色。文中通过Python代码展示了每种方法的具体实现,并进行了效果对比。 适用人群:从事信号处理领域的研究人员和技术人员,以及对信号降噪感兴趣的开发者。 使用场景及目标:① 对于频率特性明确的噪声,可以选择滤波降噪;② 处理非平稳信号时,推荐使用小波降噪;③ 在追求极致降噪效果,特别是面对复杂信号时,优先考虑小波包降噪。 其他说明:文中提供的Python代码可以帮助读者更好地理解和实践这三种降噪方法。同时,强调了在实际应用中需要根据具体的信号特点和需求选择最适合的降噪方法。

    李志伟-端侧大模型的安全建设:如何在算力与保障之间找到平衡.pdf

    Con北京站聚焦技术落地与前沿趋势,核心方向包括: ​​AI工程化​​:端侧推理、RAG增强、多模态生成成为主流; ​​云原生深水区​​:混合云治理、湖仓一体架构、可观测性技术持续迭代; ​​安全与效能​​:大模型安全防御、研发流程标准化、平台工程价值凸显; ​​行业融合​​:物流、金融、社交等领域的技术跨界创新案例丰富。 大会为开发者提供了从理论到实践的全景视角,推动技术向生产力转化。

    三菱FX系列PLC模拟量输入输出转换FB功能块设计与应用

    内容概要:本文详细介绍了三菱FX系列PLC的模拟量输入输出转换功能块(FB)的设计与应用。作者将常见的模拟量处理逻辑封装成即插即用的功能块,极大提高了开发效率。文中详细解释了功能块的接口设计、核心转换逻辑、量程适配方法以及抗干扰措施。同时,提供了多个实际项目的应用案例,如注塑机温度控制、真空炉控制等,展示了功能块的稳定性和易用性。 适合人群:从事工业自动化控制系统的工程师和技术人员,特别是对三菱PLC有一定了解的从业者。 使用场景及目标:适用于需要快速实现模拟量处理的工程项目,如温度、压力、流量等物理量的测量与控制。主要目标是提高开发效率,减少重复劳动,确保系统稳定可靠。 其他说明:文中提到的功能块不仅简化了编程流程,还增加了错误检测和抗干扰能力,使得即使是新手也能轻松应对复杂的模拟量处理任务。此外,功能块支持多种量程和硬件版本,适应性强。

    基于深度学习的口罩佩戴检测,Keras-YOLOv3 实现.zip

    基于深度学习的系统

    前端开发_浏览器扩展_Vite框架_Vue3_模板_适配_M_1744167663.zip

    前端开发_浏览器扩展_Vite框架_Vue3_模板_适配_M_1744167663.zip

    【计算机专业】求职面试全流程解析:技术题型、系统设计与行为面试技巧及资源推荐

    内容概要:本文详细介绍了计算机专业求职面试的内容与技巧,旨在帮助求职者高效准备。面经内容涵盖技术面试、系统设计面试、行为面试和其他类型面试。技术面试包括算法与数据结构、计算机基础、编程语言与框架等高频考点;系统设计面试强调高并发、高可用等设计目标,涉及短链系统、分布式缓存等典型题目;行为面试关注项目中的挑战解决、团队协作等问题,提倡使用STAR法则作答。技巧分享方面,技术面试准备建议刷题、复习基础知识;系统设计采用分层设计法,推荐相关书籍和资源;行为面试注重项目包装,强调量化成果和技术术语的使用;面试实战技巧包括良好沟通、拆解难题等。此外,文章还提供了资源与工具推荐、避坑指南以及不同公司面试侧重点分析,并指出短期冲刺和长期积累对提升面试通过率的重要性。; 适合人群:计算机专业学生和从业者,尤其是有求职需求的人员。; 使用场景及目标:①帮助求职者了解面试常见题型与考察点,进行有针对性的准备;②提供有效的面试技巧,提高求职成功率;③根据不同公司特点调整准备方向,增强竞争力。; 其他说明:通过系统化准备和反复练习,求职者能显著提升面试通过率。技术能力决定下限,而沟通表达与思维逻辑决定上限。

    西门子博图时间加密程序块解析:1212C PLC & KTP700触摸屏应用

    内容概要:本文详细介绍了西门子博图时间加密程序块的应用,特别是在1212C DC/DC/DC PLC和KTP700 Basic PN触摸屏中的实现。文章分为加密算法块和解密算法块两大部分,通过具体的代码示例展示了加密和解密的具体过程。加密算法采用了循环右移和异或运算,确保了加密的高效性和安全性。解密则通过逆向操作恢复原始时间数据。此外,文中还讨论了密钥更新策略、时间戳精度、硬件时钟同步等问题,并提供了实际应用中的注意事项和优化建议。 适合人群:从事工业自动化控制系统的工程师和技术人员,尤其是熟悉西门子PLC和触摸屏编程的人员。 使用场景及目标:① 提供一种可靠的时间加密方法,保护关键时间数据和逻辑不被轻易破解;② 增强项目的保密性和安全性;③ 提供实际项目中的应用案例和优化建议,便于快速移植到其他项目中。 其他说明:文章强调了加密和解密过程的透明度,使得维护人员能够直观理解加密逻辑,有助于快速定位和解决问题。同时,文中提到的一些技巧如动态密钥生成、时间戳精度调整等,也为实际应用提供了宝贵的实践经验。

    三相步进电机开环矢量控制与SVPWM实现的技术解析及应用场景

    内容概要:本文详细介绍了三相步进电机的开环矢量控制方案及其源码实现,尤其是坐标变换(Clarke变换和Park变换)和空间矢量脉宽调制(SVPWM)的具体实现方法。文中不仅解释了理论背景,还提供了具体的代码片段,展示了如何通过坐标变换将三相电流映射到旋转坐标系,并通过SVPWM生成合适的PWM信号来控制电机。此外,文章还讨论了一些实际应用中的技巧和注意事项,如角度生成策略、扇区判断优化以及启动时的斜坡函数设置。 适合人群:从事电机控制领域的工程师和技术爱好者,尤其是对步进电机矢量控制感兴趣的初学者和有一定基础的研发人员。 使用场景及目标:适用于需要提高步进电机控制精度和响应速度的场合,如工业自动化设备、搬运机械手等。目标是通过理解和应用开环矢量控制技术,使步进电机表现出接近伺服电机的性能,同时降低成本和复杂度。 其他说明:文章强调了在资源有限的嵌入式系统中进行优化的重要性,如使用查表法替代实时计算、利用位运算提高效率等。此外,还提到了一些调试技巧,如通过示波器观察波形、调整角度积分环节等,有助于解决实际应用中的常见问题。

    基于STM32F031的FOC有感电机控制代码解析与应用

    内容概要:本文详细介绍了基于STM32F031的FOC有感电机控制代码的功能特点及其应用场景。代码不仅涵盖了原理图、PCB设计,还包括详细的程序代码和注释。主要功能包括转把控制、刹车、助力、欠压检测、巡航、铁塔王通讯、一键通、隐形限速、霍尔修复和故障显示等。文中还展示了多个关键代码片段,如ADC采样、PWM生成、霍尔信号处理、故障检测和通讯协议处理等,强调了代码的稳定性和实用性。 适合人群:从事电机控制领域的工程师和技术爱好者,尤其是对FOC算法感兴趣的开发者。 使用场景及目标:适用于电动自行车、滑板车等需要高效电机控制的应用场景。目标是帮助开发者理解和应用成熟的FOC控制代码,提升产品的稳定性和功能性。 其他说明:代码经过量产验证,具有较高的可靠性和灵活性,能够适配多种国产芯片平台。文中还提供了丰富的实战经验和优化技巧,有助于解决实际开发中的常见问题。

    浅析电子商务环境下物流的特点.docx

    浅析电子商务环境下物流的特点.docx

    曾臻-Al+Vision+Shape+the+Future.pdf

    Con北京站聚焦技术落地与前沿趋势,核心方向包括: ​​AI工程化​​:端侧推理、RAG增强、多模态生成成为主流; ​​云原生深水区​​:混合云治理、湖仓一体架构、可观测性技术持续迭代; ​​安全与效能​​:大模型安全防御、研发流程标准化、平台工程价值凸显; ​​行业融合​​:物流、金融、社交等领域的技术跨界创新案例丰富。 大会为开发者提供了从理论到实践的全景视角,推动技术向生产力转化。

    欧姆龙FH系列机器视觉系统的高效开发与应用:加速工业自动化检测项目落地

    内容概要:本文详细介绍了欧姆龙FH系列机器视觉系统的独特优势及其应用场景。FH系列通过提供强大的仿真软件、优化的PLC通信接口以及先进的深度学习模块,显著提高了工业视觉项目的开发效率和准确性。具体而言,FH系列的仿真环境允许开发者在虚拟环境中调试算法,减少了现场调试的时间;其PLC通信接口支持多种工业协议并实现了自动寄存器映射,降低了设备工程师的沟通成本;深度学习模块则提供了预训练模型和自动ROI聚焦等功能,大幅提升了缺陷检测的精度和速度。此外,FH系列还集成了智能标定向导和动态标定功能,使得尺寸测量更加精确和便捷。 适用人群:从事工业自动化、机器视觉、智能制造等领域的一线工程师和技术管理人员。 使用场景及目标:适用于需要快速开发和部署视觉检测系统的工业生产线,尤其是汽车制造、电子产品、制药等行业。主要目标是缩短项目周期、提高检测精度、降低开发难度。 其他说明:相比于传统的视觉检测工具如Halcon,FH系列以其易用性和高效性脱颖而出,成为现代工业视觉项目的首选解决方案。文中提到的具体案例展示了FH系列在实际生产中的卓越表现,证明了其在提升工作效率方面的巨大潜力。

    高效机房控制系统:基于先进算法的多维节能优化方案

    内容概要:本文详细介绍了高效机房控制系统的先进控制算法及其多维节能优化方案。系统通过predictive_optimizer模块进行智能决策,优化冷水机组的组合和负荷分配,采用预测负荷、设备损耗和切换成本等多因素评估,实现最优能耗管理。此外,系统还利用三维建模和可视化工具,如PyQt和Three.js,提供直观的设备管理和故障排查。系统不仅能在常规情况下节省大量能源,还能在异常工况下迅速响应,确保稳定运行。文中提到的具体应用案例展示了该系统在多个项目的显著节能效果,如深圳项目中实现8%的能耗降低,以及某数据中心年能耗减少23%。 适合人群:从事机房管理、暖通空调系统设计与维护的技术人员,对工业自动化和节能优化感兴趣的工程师。 使用场景及目标:适用于新建或改造的大型数据中心、医院、工厂等场所,旨在提高能源利用效率,降低运营成本,增强系统的可靠性和灵活性。 其他说明:系统的核心优势在于其强大的自适应能力和丰富的实战经验,能够根据不同应用场景灵活调整控制策略,实现持续节能。

    基于Matlab的分位数长短期记忆网络(QRLSTM)用于时序数据预测与不确定性评估

    内容概要:本文详细介绍了如何利用Matlab实现分位数长短期记忆网络(QRLSTM)进行时序数据分析与预测。相较于传统LSTM仅提供单点预测,QRLSTM能够同时输出多个分位数的预测结果,从而提供预测不确定性的量化评估。文中首先展示了如何生成带有噪声的正弦波数据作为示例,并进行了数据预处理步骤,包括标准化和滑窗处理。接着,文章深入探讨了QRLSTM的网络架构设计,特别是自定义分位数损失层的实现细节。训练过程中采用了Adam优化器,并设置了学习率衰减机制以提高收敛速度。为了确保预测的有效性和稳定性,作者还分享了一些实用技巧,如GPU加速、梯度裁剪以及早停策略的应用。最终,通过对比实验验证了QRLSTM在处理具有异方差性的时序数据(如风速预测)方面的优越性能。 适合人群:对机器学习尤其是深度学习感兴趣的科研工作者和技术开发者,熟悉Matlab编程环境,希望深入了解时序数据预测及其不确定性估计的人群。 使用场景及目标:适用于需要对时序数据进行精准预测并且关心预测结果可靠性的应用场景,例如金融市场的价格走势预测、气象预报、能源消耗量预测等领域。主要目标是帮助用户掌握QRLSTM的工作原理及其优势,能够在实际项目中应用这一先进技术。 其他说明:文章提供了完整的代码片段供读者参考实践,同时也指出了在实现过程中可能会遇到的问题及相应的解决方案。此外,还提到了一些潜在的研究方向,如将QRLSTM与其他模型组合使用以进一步提升预测精度。

    【智能车竞赛】智能车竞赛技术综述与创新项目设想:关键技术及应用领域探索

    内容概要:本文全面介绍了智能车竞赛的背景、意义、发展历程、竞赛规则与组别设置。通过多个竞赛案例,展示了智能车竞赛的技术水平,深入探讨了智能车开发的关键技术,包括传感器技术、控制算法、路径规划、电机驱动等,并分析了这些技术在智能车竞赛中的应用。最后,提出了基于智能车开发技术的几个创新项目设想,旨在推动智能车技术的进一步发展与应用。; 适合人群:对智能车竞赛感兴趣的学生、教师、科研人员及智能车技术爱好者。; 使用场景及目标:①了解智能车竞赛的历史、规则和发展趋势;②掌握智能车开发的关键技术和应用实例;③探索智能车技术在未来物流配送、环境监测、农业作业等领域的创新应用。; 其他说明:本文不仅详细介绍了智能车竞赛的相关知识,还通过具体案例和技术探讨,为读者提供了深入了解智能车技术的机会。对于希望参与智能车竞赛或从事相关技术研发的人员来说,本文是一份宝贵的参考资料。阅读时应重点关注各个技术环节的具体实现方法及其在实际竞赛中的应用效果。

Global site tag (gtag.js) - Google Analytics