﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-网络中漫步-文章分类-struts</title><link>http://www.blogjava.net/Yadira/category/43712.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 12 Mar 2010 08:26:01 GMT</lastBuildDate><pubDate>Fri, 12 Mar 2010 08:26:01 GMT</pubDate><ttl>60</ttl><item><title>利用Struts的Token解决表单重复提交</title><link>http://www.blogjava.net/Yadira/articles/313884.html</link><dc:creator>网络中漫步</dc:creator><author>网络中漫步</author><pubDate>Thu, 25 Feb 2010 06:27:00 GMT</pubDate><guid>http://www.blogjava.net/Yadira/articles/313884.html</guid><wfw:comment>http://www.blogjava.net/Yadira/comments/313884.html</wfw:comment><comments>http://www.blogjava.net/Yadira/articles/313884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Yadira/comments/commentRss/313884.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Yadira/services/trackbacks/313884.html</trackback:ping><description><![CDATA[<div><font face="Geneva, Arial, Sans-serif"><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">用户在</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">web</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">页面上会可能会重复提交表单</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">比如提交完后利用</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">IE</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">的</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Back</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">按钮回退再提交</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span> <span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">即使后台程序费了九牛二虎之力气很好地捕捉了这种异常</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">也存在服务器不得不去响应这些</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">"</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">骚扰</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">"</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">而造成不必要的负担</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span> <span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Struts</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">的</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Token</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">利用令牌机制开发出很好实现的方法供开发人员使用</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">假设有一个页面是用来给用户填写数据</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">并提交给</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Database</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">的页面</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"> insert.jsp,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">按照普通的</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">sturts</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">结构</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">, </span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">我们会有</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">InsertAction. <br />
</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">程序转向关系如下</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Insert.jsp-&gt;InserAction</span> <br />
<br />
利</font><font face="Geneva, Arial, Sans-serif"><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">用令牌机制</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">程序转向关系如下</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif">&nbsp;&nbsp; <span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">取得令牌</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">-&gt;Insert.jsp-&gt;</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">验证令牌</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&amp;</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">清空令牌</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">-&gt;</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">普通</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">InsertAction</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">逻辑</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&#8230;</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">当取得令牌</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">转向</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Insert.jsp</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">后</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,Insert.jsp</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">中会有原始的令牌值</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">而这个值也被记在</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">session</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">中</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">然后提交</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">, </span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">提交前验证通过并清空了</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">session</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">中的令牌值</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">, </span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">所以一旦用户回退到之前的页面</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">, </span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">再次提交</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span> </font><font face="Geneva, Arial, Sans-serif"><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">由于</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">insert.jsp</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">页面中的令牌值和</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">session</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">中的不匹配</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">所以可以很轻松地捕捉重复提交的行为</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span> <span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">用单独的一个</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">PrepareInsertAction</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">来取得令牌</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">验证</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&amp;</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">清空令牌放在</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">InsertAction</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">完成</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">整个变化如下</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">:</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Struts-Configure.xml</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">调用</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">insert.jsp</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">修改前</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&nbsp;&nbsp; &lt;forward name=&#8221;insert&#8221; path=&#8221;InsertAction&#8221;/&gt;</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Struts-Configure.xml</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">调用</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">insert.jsp</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">修改后</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&nbsp;&nbsp; &lt;forward name=&#8221;insert&#8221; path=&#8221;PrepareInsertAction&#8221;/&gt;</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">当然相应</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">jsp</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">上也要进行修改</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">.</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">Struts-Configure.xml</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">要配置<font face="Geneva, Arial, Sans-serif">PrepareInsertAction<br />
</font></span></font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&lt;action path=&#8221;/PrepareInsertAction&#8221;</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: 9.5pt; color: #333333; font-family: Verdana">type=&#8221;{packagename}.PrepareInsertAction&#8221;&gt;</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&lt;forward name=&#8221;passvalide&#8221; path=&#8221;/insert.jsp&#8221;/&gt;</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&lt;/action&gt;</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">PrepareInsertAction.java execute()</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">方法核心是</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">saveToken(request);</span> <br />
</strong></font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">return mapping.findForward(&#8230;.);</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&nbsp;</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">InsertAction.java execute()</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">方法首先需要进行令牌验证</span><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">,</span><span lang="ZH-CN" style="font-size: 9.5pt; color: #333333; font-family: 宋体">加入的程序行如下</span> <br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&#8230;&#8230;&#8230;&#8230;&#8230;.</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&nbsp;&nbsp; <strong>ActionMessages errorsM=new ActionMessages();</strong></span><strong>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana">&nbsp;&nbsp; ActionErrors errors = new ActionErrors();</span>&nbsp;<br />
</strong></font><font face="Arial"><strong>&nbsp;&nbsp;&nbsp;<span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;</span>if (!isTokenValid(request)){</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>errorsM.add(ActionMessages.GLOBAL_MESSAGE,</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;&nbsp; </span>new ActionMessage("error.invalid.token"));</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>errors.add(errorsM);</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>saveErrors(request,errors);</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><strong><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>saveToken(request);&nbsp; </strong>/*验证不通过,还是要生成新的令牌号*/</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>// System.out.println("prepare to return");</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><strong><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return mapping.findForward("pagecallinsert.jsp"); </strong>/*通常是回到调用insert.jsp的page*/</span>&nbsp;<br />
</font><font face="Geneva, Arial, Sans-serif"><strong><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;&nbsp;&nbsp; </span>}else{</span>&nbsp;<br />
</strong></font><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;<strong>&nbsp;&nbsp;&nbsp;&nbsp; </strong></span><strong>resetToken(request);</strong></span><strong>&nbsp;<br />
</strong></font><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><font face="Geneva, Arial, Sans-serif"><strong><span>&nbsp;&nbsp;&nbsp; </span>}&nbsp;<br />
</strong></font></span><font face="Geneva, Arial, Sans-serif"><span style="font-size: 9.5pt; color: #333333; font-family: Verdana"><span>&nbsp;</span>&#8230;&#8230;&#8230;..</span> <br />
</font><font face="Arial">完成这些配置和修改,就可以解决表单重复提交的问题了.<br />
</font><font face="Arial">延伸点思考,组织得好的应用系统里,一旦准备转到往数据库中插入记录的jsp页面,可以在<br />
</font><font face="Arial">&lt;global-forward&gt;中设定<br />
</font><font face="Arial">&nbsp;&lt;foward name="beforeinsert" path=/PrepareInsert"/&gt;<br />
</font><font face="Arial">......<br />
</font><font face="Arial">这样做的好处,很显然的. </font></div>
 <img src ="http://www.blogjava.net/Yadira/aggbug/313884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Yadira/" target="_blank">网络中漫步</a> 2010-02-25 14:27 <a href="http://www.blogjava.net/Yadira/articles/313884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>