zoukankan      html  css  js  c++  java
  • 防止表单重复提交的几种策略

    防止表单重复提交的几种策略

    表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如:

    • 点击提交按钮两次。
    • 点击刷新按钮。
    • 使用浏览器后退按钮重复之前的操作,导致重复提交表单。
    • 使用浏览器历史记录重复提交表单。
    • 浏览器重复的HTTP请求。
    • 几种防止表单重复提交的方法

        禁掉提交按钮。表单提交后使用Javascript使提交按钮disable。这种方法防止心急的用户多次点击按钮。但有个问题,如果客户端把Javascript给禁止掉,这种方法就无效了。

        我之前的文章曾说过用一些Jquery插件效果不错。

        Post/Redirect/Get模式。在提交后执行页面重定向,这就是所谓的Post-Redirect-Get (PRG)模式。简言之,当用户提交了表单后,你去执行一个客户端的重定向,转到提交成功信息页面。

        这能避免用户按F5导致的重复提交,而其也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进和后退按导致的同样问题。

        在session中存放一个特殊标志。当表单页面被请求时,生成一个特殊的字符标志串,存在session中,同时放在表单的隐藏域里。接受处理表单数据时,检查标识字串是否存在,并立即从session中删除它,然后正常处理数据。

        如果发现表单提交里没有有效的标志串,这说明表单已经被提交过了,忽略这次提交。

        这使你的web应用有了更高级的XSRF保护。

        在数据库里添加约束。在数据库里添加唯一约束或创建唯一索引,防止出现重复数据。这是最有效的防止重复提交数据的方法。

        你是如何克服数据重复提交问题的?你遇到过什么重复提交数据的现实例子吗?

        英文原文:Prevent Duplicate Form Submission

      二叉树遍历

       

      行文结构

      1. 递归方法
      2. 非递归方法
      3. 微软面试题

      二叉树遍历根据“根节点”遍历时相对的次序分为前序、中序、后序。图示为相对于根节点的次序,左右子树也是一样的规则。

                           前序遍历                                             中序遍历                                                后续遍历

      1. 递归方法

      前序遍历

      复制代码
      void PreorderTraversal(BiTree T)
      {
          if(T)
          {
              cout << T->data << endl;
              PreorderTraversal(T->left);
              PreorderTraversal(T->right);
          }
      }
      复制代码

      中序遍历

      复制代码
      void InorderTraversal(BiTree T)
      {
          if(T)
          {
              InorderTraversal(T->left);
              cout << T->data << endl;
              InorderTraversal(T->right);
          }
      }
      复制代码

      后续遍历

      复制代码
      void PostorderTraversal(BiTree T)
      {
          if(T)
          {
              PostorderTraversal(T->left);
              PostorderTraversal(T->right);
              cout << T->data << endl;
          }
      }
      复制代码

      整合参考程序

       View Code

      #include<iostream>
      #include<vector>
      using namespace std;

      typedef struct BiTNode
      {
      int data;
      BiTNode *left;
      BiTNode *right;
      }BiTNode, *BiTree;

      bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
      {
      if(!T)
      {
      p = f;
      return false;
      }
      else if(val == T->data)
      {
      p = T;
      return true;
      }
      else if(val < T->data)
      SearchBST(T->left, val, T, p);
      else
      SearchBST(T->right, val, T, p);
      }

      bool InsertBST(BiTree &T, int val)
      {
      BiTree p;
      if(!SearchBST(T, val, NULL, p))
      {
      BiTree node = new BiTNode;
      node->data = val;
      node->left = node->right = NULL;
      if(!p)
      T = node;
      else if(val < p->data)
      p->left = node;
      else
      p->right = node;
      return true;
      }
      return false;
      }

      void PreorderTraversal(BiTree T)
      {
      if(T)
      {
      cout << T->data << endl;
      PreorderTraversal(T->left);
      PreorderTraversal(T->right);
      }
      }

      void InorderTraversal(BiTree T)
      {
      if(T)
      {
      InorderTraversal(T->left);
      cout << T->data << endl;
      InorderTraversal(T->right);
      }
      }

      void PostorderTraversal(BiTree T)
      {
      if(T)
      {
      PostorderTraversal(T->left);
      PostorderTraversal(T->right);
      cout << T->data << endl;
      }
      }

      int main()
      {
      int array[] = {5, 1, 0, 45, 10, 3, 8, 5};
      int len_array = sizeof(array) / sizeof(*array);
      BiTree root = NULL;
      for(int i = 0; i< len_array; ++i)
      InsertBST(root, array[i]);
      cout << "PreorderTraversal" << endl;
      PreorderTraversal(root);
      cout << "----------------------" << endl;

      cout << "InorderTraversal" << endl;
      InorderTraversal(root);
      cout << "----------------------" << endl;

      cout << "PostorderTraversal" << endl;
      PostorderTraversal(root);
      cout << "----------------------" << endl;
      }

      结果

      2. 非递归方法

      非递归方法借助于栈,“记忆”走过的结点。

      前序遍历

      “根-左孩子-右孩子”,对每一个结点看成是根节点,先输出,后入栈(到时返回访问右孩子),然后访问左孩子。当不能在往左走时,查询栈中的记忆,根据栈顶进入右孩子,重复上边的故事。

      复制代码
      void PreorderTraversal(BiTree T)
      {
          stack<BiTree> s;
          while(T || !s.empty())
          {
              while(T)
              {
                  cout << T->data << endl;
                  s.push(T);
                  T = T->left;
              }
              T = s.top();
              T = T->right;
              s.pop();
          }
      }
      复制代码

      中序遍历

      “左孩子-根-右孩子”,对每一个结点看成是根节点,先入栈(到时返回访问自己和右孩子),然后访问左孩子。当不能在往左走时,查询栈中的记忆,根据栈顶访问自己并且进入右孩子,重复上边的故事。

      复制代码
      void InorderTraversal(BiTree T)
      {
          stack<BiTree> s;
          while(T || !s.empty())
          {
              while(T)
              {
                  s.push(T);
                  T = T->left;
              }
              T = s.top();
              cout << T->data << endl;
              T = T->right;
              s.pop();
          }
      }
      复制代码

      后续遍历

      “左孩子-右孩子-根”,为了达到这个效果,需要把把按“根-->右孩子-->左孩子”的顺序入栈,因为栈的特征是先进后出,所以访问时顺序相反。对于一个结点只有满足以下两个条件时,才访问,否则按“根-->右孩子-->左孩子”顺序入栈。

      • 左右孩子全为NULL
      • 前边访问的结点正好为当前结点的左孩子或右孩子(访问了左孩子必定已经访问了右孩子)
      复制代码
      void PostorderTraversal(BiTree T)
      {
          stack<BiTree> s;
          BiTree cur = NULL, pre = NULL;
          s.push(T);
          while(!s.empty())
          {
              cur = s.top();
              if((!cur->left && !cur->right) ||
                      (pre != NULL && (pre == cur->left || pre == cur->right)))
              {
                  cout << cur->data << endl;
                  pre = cur;
                  s.pop();
              }
              else
              {
                  if(cur->right)
                      s.push(cur->right);
                  if(cur->left)    
                      s.push(cur->left);
              }
          }
      }
      复制代码

      整合参考程序

       View Code

      #include<iostream>
      #include<stack>

      using namespace std;

      typedef struct BiTNode
      {
      int data;
      BiTNode *left;
      BiTNode *right;
      }BiTNode, *BiTree;

      bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
      {
      if(!T)
      {
      p = f;
      return false;
      }
      else if(val == T->data)
      {
      p = T;
      return true;
      }
      else if(val < T->data)
      SearchBST(T->left, val, T, p);
      else
      SearchBST(T->right, val, T, p);
      }

      bool InsertBST(BiTree &T, int val)
      {
      BiTree p;
      if(!SearchBST(T, val, NULL, p))
      {
      BiTree node = new BiTNode;
      node->data = val;
      node->left = node->right = NULL;
      if(!p)
      T = node;
      else if(val < p->data)
      p->left = node;
      else
      p->right = node;
      return true;
      }
      return false;
      }

      void PreorderTraversal(BiTree T)
      {
      stack<BiTree> s;
      while(T || !s.empty())
      {
      while(T)
      {
      cout << T->data << endl;
      s.push(T);
      T = T->left;
      }
      T = s.top();
      T = T->right;
      s.pop();
      }
      }

      void InorderTraversal(BiTree T)
      {
      stack<BiTree> s;
      while(T || !s.empty())
      {
      while(T)
      {
      s.push(T);
      T = T->left;
      }
      T = s.top();
      cout << T->data << endl;
      T = T->right;
      s.pop();
      }
      }

      void PostorderTraversal(BiTree T)
      {
      stack<BiTree> s;
      BiTree cur = NULL, pre = NULL;
      s.push(T);
      while(!s.empty())
      {
      cur = s.top();
      if((!cur->left && !cur->right) ||
      (pre != NULL && (pre == cur->left || pre == cur->right)))
      {
      cout << cur->data << endl;
      pre = cur;
      s.pop();
      }
      else
      {
      if(cur->right)
      s.push(cur->right);
      if(cur->left)
      s.push(cur->left);
      }
      }
      }

      int main()
      {
      int array[] = {5, 1, 0, 45, 10, 3, 8, 5};
      int len_array = sizeof(array) / sizeof(*array);
      BiTree root = NULL;
      for(int i = 0; i< len_array; ++i)
      InsertBST(root, array[i]);
      cout << "PreorderTraversal" << endl;
      PreorderTraversal(root);
      cout << "----------------------" << endl;

      cout << "InorderTraversal" << endl;
      InorderTraversal(root);
      cout << "----------------------" << endl;

      cout << "PostorderTraversal" << endl;
      PostorderTraversal(root);
      cout << "----------------------" << endl;
      }

      结果同递归遍历

      3. 微软面试题

      分析:由二叉遍历树变成有序的结构,不用说绝对是中序遍历。中序遍历分为两种方法——递归、非递归。递归不需要额外的空间,非递归需要额外空间(借助与栈)。现在用两种方法实现,其思路都是基本中序遍历的改进。

      方法一(递归方法)

      复制代码
      void BST2BLink(BiTree T, BiTree &pre)  //&地址操作,所有递归使用同一个
      {
          if(T)
          {
              BST2BLink(T->left, pre);
              if(pre)
              {
                  pre->right = T;
                  T ->left = pre;
              }
              pre = T;
              BST2BLink(T->right, pre);
          }
      }
      复制代码

      执行程序

       View Code

      #include<iostream>
      #include<stack>

      using namespace std;

      typedef struct BiTNode
      {
      int data;
      BiTNode *left;
      BiTNode *right;
      }BiTNode, *BiTree;

      bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
      {
      if(!T)
      {
      p = f;
      return false;
      }
      else if(val == T->data)
      {
      p = T;
      return true;
      }
      else if(val < T->data)
      SearchBST(T->left, val, T, p);
      else
      SearchBST(T->right, val, T, p);
      }

      bool InsertBST(BiTree &T, int val)
      {
      BiTree p;
      if(!SearchBST(T, val, NULL, p))
      {
      BiTree node = new BiTNode;
      node->data = val;
      node->left = node->right = NULL;
      if(!p)
      T = node;
      else if(val < p->data)
      p->left = node;
      else
      p->right = node;
      return true;
      }
      return false;
      }

      void BST2BLink(BiTree T, BiTree &pre)
      {
      if(T)
      {
      BST2BLink(T->left, pre);
      if(pre)
      {
      pre->right = T;
      T ->left = pre;
      }
      pre = T;
      BST2BLink(T->right, pre);
      }
      }

      int BST2BLink(BiTree &T)
      {
      stack<BiTree> s;
      BiTree cur = T, pre = NULL;
      while(cur || !s.empty())
      {
      while(cur)
      {
      s.push(cur);
      cur = cur->left;
      }

      cur = s.top();
      s.pop();
      cout << cur->data << endl;

      if(!pre)
      T = cur;
      else
      {
      pre->right = cur;
      cur ->left = pre;
      }
      pre = cur;
      cur = cur->right;
      }
      }

      void BLinkTraversal(BiTree root)
      {
      while(root)
      {
      cout << root->data << endl;
      root = root->right;
      }
      }

      int main()
      {
      int array[] = {5, 8, 0, 3, 100, 45};
      int len_array = sizeof(array) / sizeof(*array);
      BiTree root = NULL;
      for(int i = 0; i< len_array; ++i)
      InsertBST(root, array[i]);

      cout << "Recursion" << endl;
      BiTree pre = NULL;
      BST2BLink(root, pre);
      while(root->left)
      root = root->left;
      BLinkTraversal(root);
      /*
      cout << " Not Recursion" << endl;
      BST2BLink(root_copy);
      cout << "----------------------" << endl;
      BLinkTraversal(root);
      */
      }

      方法二(非递归方法)
      复制代码
      int BST2BLink(BiTree &T)
      {
          stack<BiTree> s;
          BiTree cur = T, pre = NULL;
          while(cur || !s.empty())
          {
              while(cur)
              {
                  s.push(cur);
                  cur = cur->left;
              }
      
              cur = s.top();
              s.pop();
              cout << cur->data << endl;
              if(!pre)
                  T = cur;
              else
              {
                  pre->right = cur;
                  cur ->left = pre;
              }
              pre = cur;
              cur = cur->right;
          }
      }
      复制代码

      执行程序

       View Code

      #include<iostream>
      #include<stack>

      using namespace std;

      typedef struct BiTNode
      {
      int data;
      BiTNode *left;
      BiTNode *right;
      }BiTNode, *BiTree;

      bool SearchBST(BiTree T, int val, BiTree f, BiTree &p)
      {
      if(!T)
      {
      p = f;
      return false;
      }
      else if(val == T->data)
      {
      p = T;
      return true;
      }
      else if(val < T->data)
      SearchBST(T->left, val, T, p);
      else
      SearchBST(T->right, val, T, p);
      }

      bool InsertBST(BiTree &T, int val)
      {
      BiTree p;
      if(!SearchBST(T, val, NULL, p))
      {
      BiTree node = new BiTNode;
      node->data = val;
      node->left = node->right = NULL;
      if(!p)
      T = node;
      else if(val < p->data)
      p->left = node;
      else
      p->right = node;
      return true;
      }
      return false;
      }

      void BST2BLink(BiTree T, BiTree &pre)
      {
      if(T)
      {
      BST2BLink(T->left, pre);
      if(pre)
      {
      pre->right = T;
      T ->left = pre;
      }
      pre = T;
      BST2BLink(T->right, pre);
      }
      }

      int BST2BLink(BiTree &T)
      {
      stack<BiTree> s;
      BiTree cur = T, pre = NULL;
      while(cur || !s.empty())
      {
      while(cur)
      {
      s.push(cur);
      cur = cur->left;
      }

      cur = s.top();
      s.pop();
      // cout << cur->data << endl;

      if(!pre)
      T = cur;
      else
      {
      pre->right = cur;
      cur ->left = pre;
      }
      pre = cur;
      cur = cur->right;
      }
      }

      void BLinkTraversal(BiTree root)
      {
      while(root)
      {
      cout << root->data << endl;
      root = root->right;
      }
      }

      int main()
      {
      int array[] = {5, 8, 0, 3, 100, 45};
      int len_array = sizeof(array) / sizeof(*array);
      BiTree root = NULL;
      for(int i = 0; i< len_array; ++i)
      InsertBST(root, array[i]);
      /*
      cout << "Recursion" << endl;
      BiTree pre = NULL;
      BST2BLink(root, pre);
      while(root->left)
      root = root->left;
      BLinkTraversal(root);
      */
      cout << " Not Recursion" << endl;
      BST2BLink(root);
      cout << "----------------------" << endl;
      BLinkTraversal(root);

      }

       
       
  • 相关阅读:
    【重要】攻击动作时间段判断~使用动画time比较动画length和使用一个变量数组做延迟
    角色头上冒数字
    ApplicationListener接口的生命周期
    Blender软件基本介绍(3D建模软件)
    unity中给图片换颜色
    Unity中建立文本保存数据
    UGUI脚本添加Btn回调的方法
    碰撞体速度过快穿透的问题
    Unity中的点击,长按,划动
    在对话系统中实现打字机效果
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3432434.html
Copyright © 2011-2022 走看看