??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人av一区二区三区在线,欧美国产91,亚洲欧美不卡http://www.aygfsteel.com/rickhunter/category/3861.html关于JAVA的点Ҏ?/description>zh-cnTue, 27 Feb 2007 20:24:19 GMTTue, 27 Feb 2007 20:24:19 GMT60[转脓]使用Struts的Token机制解决表单的重复提? 选择?chinaewolf ?Blog http://www.aygfsteel.com/rickhunter/articles/15556.html千山鸟飞l?/dc:creator>千山鸟飞l?/author>Fri, 14 Oct 2005 16:24:00 GMThttp://www.aygfsteel.com/rickhunter/articles/15556.htmlhttp://www.aygfsteel.com/rickhunter/comments/15556.htmlhttp://www.aygfsteel.com/rickhunter/articles/15556.html#Feedback0http://www.aygfsteel.com/rickhunter/comments/commentRss/15556.htmlhttp://www.aygfsteel.com/rickhunter/services/trackbacks/15556.html

Struts的TokenQo牌)机制能够很好的解册单重复提交的问题Q基本原理是Q服务器端在处理到达的请求之前,会将h中包含的令牌?/i>? 保存在当前用户会话中的o牌D行比较,看是否匹配。在处理完该h后,且在{复发送给客户端之前,会产生一个新的o牌,该o牌除传给客户端以外,也会 用户会话中保存的旧的o牌进行替换。这样如果用户回退到刚才的提交面q再ơ提交的话,客户端传q来的o牌就和服务器端的令牌不一_从而有效地防止? 重复提交的发生?/p>

q时其实也就是两点,W一Q你需要在h中有q个令牌|h中的令牌值如何保存,其实和我们qx在页面中保存一些信息是一LQ通过隐藏字段? 保存Q保存的形式如: 〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,q个value是TokenProcessorcM? generateToken()获得的,是根据当前用Lsession id和当前时间的long值来计算的。第二:在客L提交后,我们要根据判断在h中包含的值是否和服务器的令牌一_因ؓ服务器每ơ提交都会生成新? TokenQ所以,如果是重复提交,客户端的Token值和服务器端的Token值就会不一致。下面就以在数据库中插入一条数据来说明如何防止重复提交?/p>

在Action中的addҎ中,我们需要将Token值明的要求保存在页面中Q只需增加一条语句:saveToken(request);Q如下所C:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
//前面的处理省?br>saveToken(request);
return mapping.findForward("add");
}
在Action的insertҎ中,我们Ҏ表单中的Tokeng服务器端的Token值比较,如下所C:
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
if (isTokenValid(request, true)) {
// 表单不是重复提交
//q里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代?br>}
}

其实使用h很简单,举个最单、最需要用这个的例子Q?br>一般控刉复提交主要是用在Ҏ据库操作的控制上Q比如插入、更新、删除等Q由于更新、删除一般都是通过id来操作(例如QupdateXXXById, removeXXXByIdQ,所以这cL作控制的意义不是很大Q不排除个别现象Q,重复提交的控制也׃要是在插入时的控制了?br>
先说一下,我们目前所做项目的情况Q?br>? 前的目是用StrutsQSpringQIbatisQ页面用jstlQStruts复杂View层,Spring在Service层提供事务控Ӟ Ibatis是用来代替JDBCQ所有页面的讉K都不是直接访问jspQ而是讉KStructs的ActionQ再由Action来ForwardC? JspQ所有针Ҏ据库的操作,比如取数据或修改数据Q都是在Action里面完成Q所有的Action一般都l承 BaseDispatchActionQ这个是自己建立的类Q目的是为所有的Action做一些统一的控Ӟ在Struts层,对于一个功能,我们一般分 Z个ActionQ一个Action里的功能是不需要调用Struts的验证功能的Q常见的Ҏ名称有add,edit,remove,view, listQ,另一个是需要调用Struts的验证功能的Q常见的Ҏ名称有insert,updateQ?br>
拿论坛发脓来说吧,论坛发脓首先需要蟩转到一个页面,你可以填写帖子的主题和内容,填写完后Q单几Z提交”,贴子发表了Q所以这里经q两个步骤:
1、{C个新增的面Q在Action里我们一般称为addQ例如:
public ActionForward add(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        //q一句是输出调试信息Q表CZ码执行到q一D了
        log.debug(":: action - subject add");    
    
        //your code here

       //q里保存Token?br>        saveToken(request);
        
       //跌{到add面Q在Structs-config.xml里面定义Q例如,跌{到subjectAdd.jsp
        return mapping.findForward("add");
    }

2、在填写标题和内容后Q选择 提交 Q会提交到insertҎQ在insertҎ里判断,是否重复提交了?br>public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
if (isTokenValid(request, true)) {
// 表单不是重复提交
//q里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代?br>}
}

下面更详l一点(注意Q下面所有的代码使用全角括号Q:
1、你惛_贴时Q点几Z我要发贴”链接的代码可以里这LQ?br>〈html:link action="subject.do?method=add"〉我要发贴?html:link?br>subject.do ?method q些在struct-config.xml如何定义我就不说了,点击链接后,会执行subject.do的addҎQ代码如上面说的Q蟩转到subjectAdd.jsp面。页面的代码大概如下Q?br>〈html:form action="subjectForm.do?method=insert"?br>  〈html:text property="title" /?br>  〈html:textarea property="content" /?br>  〈html:submit property="发表" /?br>  〈html:reset property="重填" /?br>〈html:form?br>如果你在addҎ里加了“saveToken(request);”这一句,那在subjectAdd.jsp生成的页面上Q会多一个隐藏字D,cM于这栗input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,

2、点d表后Q表单提交到subjectForm.do里的insertҎ后,你在insertҎ里要表单的数据插入到数据库中,如果没有 q行重复提交的控Ӟ那么每点Mơ浏览器的刷新按钮,都会在数据库中插入一条相同的记录Q增加下面的代码Q你可以控制用L重复提交了?br>if (isTokenValid(request, true)) {
// 表单不是重复提交
//q里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代?br>}
注意Q你必须在addҎ里用了saveToken(request)Q你才能在insert里判断,否则Q你每次保存操作都是重复提交?br>? 住一点,Struts在你每次讉KAction的时候,都会产生一个o牌,保存在你的Session里面Q如果你在Action里的函数里面Q用了 saveToken(request);Q那么这个o牌也会保存在q个Action所Forward到的jsp所生成的静态页面里?br>如果你在你Action的方法里使用了isTokenValidQ那么Struts会将你从你的request里面去获取这个o牌|然后和Session里的令牌值做比较Q如果两者相{,׃是重复提交,如果不相{,是重复提交了?br>
? 于我们项目的所有Action都是l承自BaseDispatchActionq个c,所以我们基本上都是在这个类里面做了表单重复提交的控Ӟ默认是控 制addҎ和insertҎQ如果需要控制其它的ҎQ就自己手动写上面这些代码,否则是不需要手写的Q控制的代码如下Q?br>public abstract class BaseDispatchAction extends BaseAction {
protected ActionForward perform(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response)
    throws Exception {
        String parameter = mapping.getParameter();
        String name = request.getParameter(parameter);
if (null == name) { //如果没有指定 method Q则默认? list
            name = "list";
        }

        if ("add".equals(name)) {
            if ("add".equals(name)) {
                saveToken(request);
            }
        } else if ("insert".equals(name)) {
            if (!isTokenValid(request, true)) {
                resetToken(request);
                saveError(request, new ActionMessage("error.repeatSubmit"));
                log.error("重复提交Q?);
                return mapping.findForward("error");
            }
        }
        return dispatchMethod2(mapping, form, request, response, name);
    }
}



]]>
վ֩ģ壺 | ˫| | | ɽ| ɽ| | ˫| | ˫Ѽɽ| | | | | | | ǡ| ɽ| | | | ع| ϸ| ͺ| ͨ| | | | ʡ| ̳| | | | | | ɳ| ͷ| | | | |