﻿<?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-周游世界-随笔分类-B/S设计</title><link>http://www.blogjava.net/yanzhou/category/12959.html</link><description>喂马, 劈柴, 周游世界</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:29:19 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:29:19 GMT</pubDate><ttl>60</ttl><item><title>关于事务</title><link>http://www.blogjava.net/yanzhou/archive/2006/06/30/55910.html</link><dc:creator>周游世界</dc:creator><author>周游世界</author><pubDate>Fri, 30 Jun 2006 03:39:00 GMT</pubDate><guid>http://www.blogjava.net/yanzhou/archive/2006/06/30/55910.html</guid><wfw:comment>http://www.blogjava.net/yanzhou/comments/55910.html</wfw:comment><comments>http://www.blogjava.net/yanzhou/archive/2006/06/30/55910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yanzhou/comments/commentRss/55910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yanzhou/services/trackbacks/55910.html</trackback:ping><description><![CDATA[什么是事务？从表现上来看，事务是一个操作序列，这些操作要么都执行，要么都不执行，它是一个原子单元；从结果上看，事务是维护数据库或对象状态一致性的工作单位。事务的主要属性包括有：<br /><ol><li><font size="2">原子性(ATOMICITY): 一个事务要被完全的无二义性的做完或撤消。在任何操作出现一个错误的情况下，构成事务的所有操作的效果必须被撤消，数据应被回滚到以前的状态。</font></li><li><font size="2">一致性(CONSISTENCY): 一个事务应该保护所有定义在数据上的不变的属性(例如完整性约束)。在完成了一个成功的事务时，数据应处于一致的状态。换句话说，一个事务应该把系统从一个一致状态转换到另一个一致状态。举个例子，在关系数据库的情况下， 一个一致的事务将保护定义在数据上的所有完整性约束。</font></li><li><font size="2">隔离性(ISOLATION): 在同一个环境中可能有多个事务并发执行，而每个事务都应表现为独立执行。串行的执行一系列事务的效果应该同于并发的执行它们。这要求两件事:</font></li><ul><li><font size="2">在一个事务执行过程中，数据的中间的(可能不一致)状态不应该被暴露给所有的其他事务。</font></li></ul><ul><li><font size="2">两个并发的事务应该不能操作同一项数据。数据库管理系统通常使用锁来实现这个特征。 </font></li></ul><li><font size="2">持久性(DURABILITY): 一个被完成的事务的效果应该是持久的。</font></li></ol>在任何情况下都要求应维护一个工作单元的成功或失败，并且在失败的情况下将所有的资源返回到失败前的数据状态中。这在金融、贸易、电子商业等领域是要严格遵守的。<br /><img src ="http://www.blogjava.net/yanzhou/aggbug/55910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yanzhou/" target="_blank">周游世界</a> 2006-06-30 11:39 <a href="http://www.blogjava.net/yanzhou/archive/2006/06/30/55910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>防止重复提交解决方案</title><link>http://www.blogjava.net/yanzhou/archive/2006/06/28/55553.html</link><dc:creator>周游世界</dc:creator><author>周游世界</author><pubDate>Wed, 28 Jun 2006 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/yanzhou/archive/2006/06/28/55553.html</guid><wfw:comment>http://www.blogjava.net/yanzhou/comments/55553.html</wfw:comment><comments>http://www.blogjava.net/yanzhou/archive/2006/06/28/55553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yanzhou/comments/commentRss/55553.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yanzhou/services/trackbacks/55553.html</trackback:ping><description><![CDATA[B/S结构的软件开发中，特别是在越大型的分布式应用中体现的越明显，后端的处理往往会因为出现较多的时间消耗而引起延迟,这种延迟有可能过长而最终使用户认为是自己的操作错误，导致他们重新提交请求，由于任务的重复提交,服务器资源大部分被占用,情节严重可能出现类似死机现象。<br /><br />预期达到目标:<br />    1、当用户进行的是Refresh/Reload/Back/Forward操作、以及先Back再Submit操作时，仅仅是reloading先前的结果页。<br />    2、当用户重复提交同一个任务操作时,后台服务接收并处理第一次提交的任务，后面提交不起作用（不转向也不提示）。<br />    3、该功能具有公用性。<br /><br />基本形成思路：<br />    1、在basic filter中实现公用性<br />        if(true){//问题1：如何确定是否为重复提交<br />            ...<br />            chain.doFilter(request,response);<br />        }else{<br />            //问题2：如何实现不转向、不提示也不显示空白页<br />        }<br />    <br />    2、网上资料概括<br />        a、提交表单后按钮变灰/隐藏提交按钮<br />        b、在js里设置全局变量，提交后修改该变量的值，依据变量的值判断是否重复提交<br />        var flag=true;<br />        function checkForm(){<br />            if (flag==false){<br />                return;<br />            }<br />            flag=false;<br />            document.form1.submit();                      <br />        }<br />        c、struts （webwork没有找到这个资料）<br />        验证事务控制令牌,&lt;html:form &gt;会自动根据session中标识生成一个隐含input代表令牌，防止两次提交<br />        在action中：                       <br />        //&lt;input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"&gt;                       <br />        if (!isTokenValid(request))<br />            errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("error.transaction.token"));<br />        resetToken(request); //删除session中的令牌<br />        action有这样的一个方法生成令牌华<br />        protected String generateToken(HttpServletRequest request) {<br />            HttpSession session = request.getSession();<br />            try {<br />                byte id[] = session.getId().getBytes();<br />                byte now[] = new Long(System.currentTimeMillis()).toString().getBytes();<br />                MessageDigest md = MessageDigest.getInstance("MD5");<br />                md.update(id);<br />                md.update(now);<br />                return (toHex(md.digest()));<br />            } catch (IllegalStateException e) {<br />                return (null);<br />            } catch (NoSuchAlgorithmException e) {<br />                return (null);<br />            }<br />        }  <br />                    <br />        d、用户使用浏览器时，可以经常使用向后的按钮，因此就有可能重复提交一个他们已经提交过的form，这样就会带来一个重复事务处理的问题。同样，一个用户也可能在接收到一个确认的页面之前按下停止的按钮，接着再次提交同一个form。对于这些情况，我们都想跟踪并且禁止这些重复的提交，我们可以使用一个控制servlet来提供一个控制点，以解决这个问题。<br />        同步记号（Synchronizer (or Dvu) Token）<br />        这个策略是为了解决重复的form提交问题。一个同步的记号被设置在一个用户的Session中，并且包含在返回到客户的每一个form中。当form 被提交时，form中的同步标记就和Session中的同步标记作对比。在form首次提交的时候，这两个标记应该是一样的。如果标记不一样，那么该 form就会禁止提交，一个错误就会返回给用户。在用户提交一个form时，如果按下浏览器中的后退按钮并尝试重新提交同一个form时，标记就会出现不匹配的现象。<br />        另一方面，如果两个标记值匹配，那么我们就可以确信整个流程是正确的。在这种情况下，Session中的标记值就会被修改为一个新的值，同时允许提交该form。<br />        你也可以使用这个策略来控制对某些页面的直接访问，就好象上面资源保护中描述的一样。例如，假设一个用户将某个应用的页面A收藏到收藏夹中，而页面A只允许通过页面B和C访问。当用户直接通过收藏夹来访问页面A，这时页面的访问顺序就是不正确的，这样同步标记将处在一个不同步的状态，或者它根本就不存在。不论怎样，访问都被禁止了。<br />    <br />        e、做一个hidden框，名字自己定，提交后得到这个值放入session，提交前判断session是否为空。<br />        f、另Struts提供利用Token防止重复提交的方法：<br />        用户请求录入页面，这个与服务器建立的一次连接过程中，在服务器端①【生成一个session标识，同时返回到客户端一个与此匹配的hidden域】。用户提交了此页面，服务器端首先②【判断此hidden域与session标识是否匹配】，若不匹配，终止保存操作，提示同一表单不能提交两次，同时①【新建一个session标识和hidden域】，返回录入页面；若匹配，执行插入保存操作，同时③【清空（重置reset)session标识】。<br />        Struts正在基于这样的思路在org.apache.struts.action.Action类中提供了内置支持方法：<br />        java代码:<br />                <br />            protected void saveToken(HttpServletRequest request) 配合标签对应于①<br />            protected boolean isTokenValid(HttpServletRequest request) 对应于②<br />            protected void resetToken(HttpServletRequest request) 对应于③<br />                <br />        这样我们在写程序的时候，结合Struts的html标签，只要<br />            1.在forward到insert.jsp页面前加一个action执行saveToken(request)操作，或干脆在insert.jsp中写<br />            2.保存前加个判断操作isTokenValid(request)<br />            3.若isTokenValid(request)返回false,执行saveToken(request)操作，返回错误提示页面；true则执行resetToken(request)操作，然后进行实际的保存操作<br /><br />解决方案：<br />   1、后台公共类中实现前台的Form中自动生成两个hidden文本功能，一个是作page是否重复提交判断，并由系统自动附上关键值（如struts采用的方案）；另一个作为button是否重复提交判断（struts中好像没有）。由后台公共类实现界面两个hidden text自动生成的好处在于公用性。<br />   2、在basic filter中根据两个hidden text值判断是否为重复提交。<br />   3、javascript中作一个公共方法，实现功能：如果需要判断是否重复提交，就给第二个hidden text附上关键值，并使该功能不可用。<br /><br /><img src ="http://www.blogjava.net/yanzhou/aggbug/55553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yanzhou/" target="_blank">周游世界</a> 2006-06-28 15:51 <a href="http://www.blogjava.net/yanzhou/archive/2006/06/28/55553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>