SHH框架刷新,表单重复提交(跪求详解) 本帖最后由 QQ1122QQQQ 于 2011-11-19 13:57:37 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 在开发的时候,很多时候会需要防止用户重复提交表单。在Strut2中可以方便的实现这个功能。防止表单重复提交主要用到的标签是<s: token />,拦截器 <interceptor-ref name="token" />,还有一个默认的返回值<result name="invalid.token">/input.jsp</result> 在页面加载时,<s: token />产生一个GUID(Globally Unique Identifier,全局唯一标识符)值的隐藏输入框如:<input type="hidden" name="struts.token.name" value="struts.token"/><input type="hidden" name="struts.token" value="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR"/>同时,将GUID放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则将会话中的token删除并往下执行,否则向actionErrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个token就会不同。注意:产生的html代码中,struts.token.name是永远不变的,而struts.token是可以改变的(通过在jsp中引入标签<s:token name="你想取的名字"/>,这里的name属性就会取代掉struts.token),另外,两个struts.token是关联在一起的。举个例子:以下为action代码package com.polaris.token;import com.opensymphony.xwork2.ActionSupport;public class TokenAction extends ActionSupport{private static final long serialVersionUID = 1L;private String message;public String getMessage(){return message;}public void setMessage(String message){this.message = message;}@Overridepublic String execute() throws Exception{System.out.println("执行Action, 输出内容:" + getMessage());return SUCCESS;}}清单1:TokenAction代码再看看JSP的写法<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %><%@ taglib prefix="s" uri="/struts-tags" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>struts token</title> <s:head /></head><body> <s:actionerror /> <s:form action="token" > <s:textfield name="message" label="Message" /> <s:token /> <%-- 注意这里,记得放在form表单内,可以自己给token命名--%> <s:submit /> </s:form></body></html>清单2:message.jsp下面是struts2的配置文件<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><package name="struts2" extends="struts-default"><action name="token" class="com.polaris.token.TokenAction"> <result name="invalid.token">/message.jsp</result> <!--注意此处--> <result>/message.jsp</result> <interceptor-ref name="defaultStack" /> <interceptor-ref name="token" /> </action> </package></struts> 重复刷新用token你这句话说的是啥意思没看明白 楼主能将Servlet跳转到JSP的语句发出来看一下吗? 可能你用的是一次跳转,一次跳转在每次刷新的时候都会将刚刚的命令重复执行一边,即如果你是增加一条数据,刷新一次就增加一条重复数据。一般采用两次跳转就能避免这种问题了!! 3楼: // 画面初期化的时候调用,添加和删除成功的时候有调用了 public ActionForward manageLabel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { cus=(Customer) request.getSession().getAttribute("cus"); // 根据用户的ID取得用户的标签 List<FangKeLabel> cusLabelList = fangKeService.getcusLabel(cus.getId()); // 取得系统推荐的标签 int currentPage = request.getParameter("currentPage") == null ? 1 : Integer.parseInt(request.getParameter("currentPage")); int allRow = request.getParameter("allRow") == null ? fangKeService.getSysLabelCount() : Integer.parseInt(request.getParameter("allRow")); PageBean page = new PageBean(allRow, currentPage, 20); List<SystemLabel> sysLabelList = fangKeService.getSysLabel(page.getPageFirst(), 15); // request.setAttribute("cuslabelCount", cusLabelList.size()); request.setAttribute("page", page); request.setAttribute("cus", cus); request.setAttribute("cusLabelList", cusLabelList); request.setAttribute("sysLabelList", sysLabelList); saveToken(request); return mapping.findForward("ManageLabel"); } // 这是添加的方法 public ActionForward addLabel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { if (isTokenValid(request,true)) { // -------------------------------------request中没有取到值 resetToken(request); String labelName = null; if (request.getParameter("labelName") != null){ labelName = URLDecoder.decode(URLDecoder.decode(request.getParameter("labelName"),"UTF-8")); } cus=(Customer) request.getSession().getAttribute("cus"); if(cus==null){ return null; //跳转到登录页 } FangKeLabel fkLabel = new FangKeLabel(); fkLabel.setId( DateUtil.getStringTime("l")); fkLabel.setLabelName(labelName); fkLabel.setCusId(cus.getId()); fkLabel.setAddtime(new Date()); fangKeService.save(fkLabel); } return new ActionForward("/MangeLabel.do?method=manageLabel"); } 这是配置文件 <action path="/MangeLabel" parameter="method" name="FangKeLabelForm" type="org.springframework.web.struts.DelegatingActionProxy"> <forward name="ManageLabel" path="/fang/fk_add.jsp"></forward> </action> PS:添加删除功能都是在这个页面上【fk_add.jsp】,而且处理后的结果也要显示出来 前面的回答太繁琐估计你也没弄明白~~~我告诉你个好方法第一次的时候探测 session值,如果为null就执行程序在程序执行完毕后设置session值,当用户刷新的时候,session值就不会是null了,提示用户不要刷新~~ Spring2.0+Hibernate3.3.2事务配置问题 JSP基于web的电子账单查询与支付系统开发,急急急~~ 关于java 的return,返回一个函数是什么意思??(附源码) 有个JS中添加变量的问题 有人用过SVF吗?做帐票的!求救啊 日期类型转化问题?(在线等) 哪里有给Java编写的MD5加密的类??? 我是根据下面的步骤一步一步做的,怎么还是连不上服务器啊 WEB项目通过IE代理访问问题 ajax+CrossOrigin跨域导致session丢失,该如何解决 模态对话框问题 关于JSP中JSTL标记库的使用
防止表单重复提交主要用到的标签是<s: token />,拦截器 <interceptor-ref name="token" />,还有一个默认的返回值<result name="invalid.token">/input.jsp</result>
在页面加载时,<s: token />产生一个GUID(Globally Unique Identifier,全局唯一标识符)值的隐藏输入框如:
<input type="hidden" name="struts.token.name" value="struts.token"/><input type="hidden" name="struts.token" value="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR"/>
同时,将GUID放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则将会话中的token删除并往下执行,否则向actionErrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个token就会不同。注意:产生的html代码中,struts.token.name是永远不变的,而struts.token是可以改变的(通过在jsp中引入标签<s:token name="你想取的名字"/>,这里的name属性就会取代掉struts.token),另外,两个struts.token是关联在一起的。
举个例子:
以下为action代码
package com.polaris.token;
import com.opensymphony.xwork2.ActionSupport;
public class TokenAction extends ActionSupport{private static final long serialVersionUID = 1L;private String message;
public String getMessage(){return message;}
public void setMessage(String message){this.message = message;}
@Overridepublic String execute() throws Exception{System.out.println("执行Action, 输出内容:" + getMessage());return SUCCESS;}}清单1:TokenAction代码
再看看JSP的写法
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %><%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head> <title>struts token</title> <s:head /></head><body> <s:actionerror /> <s:form action="token" > <s:textfield name="message" label="Message" /> <s:token /> <%-- 注意这里,记得放在form表单内,可以自己给token命名--%> <s:submit /> </s:form></body></html>清单2:message.jsp
下面是struts2的配置文件<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd">
<struts><package name="struts2" extends="struts-default"><action name="token" class="com.polaris.token.TokenAction"> <result name="invalid.token">/message.jsp</result> <!--注意此处--> <result>/message.jsp</result> <interceptor-ref name="defaultStack" /> <interceptor-ref name="token" /> </action> </package></struts>
你这句话说的是啥意思没看明白
一般采用两次跳转就能避免这种问题了!!
// 画面初期化的时候调用,添加和删除成功的时候有调用了
public ActionForward manageLabel(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
cus=(Customer) request.getSession().getAttribute("cus"); // 根据用户的ID取得用户的标签
List<FangKeLabel> cusLabelList = fangKeService.getcusLabel(cus.getId());
// 取得系统推荐的标签
int currentPage = request.getParameter("currentPage") == null ? 1 : Integer.parseInt(request.getParameter("currentPage"));
int allRow = request.getParameter("allRow") == null ? fangKeService.getSysLabelCount() : Integer.parseInt(request.getParameter("allRow"));
PageBean page = new PageBean(allRow, currentPage, 20);
List<SystemLabel> sysLabelList = fangKeService.getSysLabel(page.getPageFirst(), 15); //
request.setAttribute("cuslabelCount", cusLabelList.size());
request.setAttribute("page", page);
request.setAttribute("cus", cus);
request.setAttribute("cusLabelList", cusLabelList);
request.setAttribute("sysLabelList", sysLabelList);
saveToken(request);
return mapping.findForward("ManageLabel");
}
// 这是添加的方法
public ActionForward addLabel(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
if (isTokenValid(request,true)) { // -------------------------------------request中没有取到值
resetToken(request);
String labelName = null; if (request.getParameter("labelName") != null){
labelName = URLDecoder.decode(URLDecoder.decode(request.getParameter("labelName"),"UTF-8"));
}
cus=(Customer) request.getSession().getAttribute("cus");
if(cus==null){
return null; //跳转到登录页
}
FangKeLabel fkLabel = new FangKeLabel();
fkLabel.setId( DateUtil.getStringTime("l"));
fkLabel.setLabelName(labelName);
fkLabel.setCusId(cus.getId());
fkLabel.setAddtime(new Date());
fangKeService.save(fkLabel);
}
return new ActionForward("/MangeLabel.do?method=manageLabel");
} 这是配置文件
<action path="/MangeLabel" parameter="method" name="FangKeLabelForm"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="ManageLabel" path="/fang/fk_add.jsp"></forward>
</action> PS:添加删除功能都是在这个页面上【fk_add.jsp】,而且处理后的结果也要显示出来