﻿<?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-狂奔 lion</title><link>http://www.blogjava.net/yangyi/</link><description>用心 - 珍惜时间，勇于创造</description><language>zh-cn</language><lastBuildDate>Thu, 04 Dec 2008 06:12:55 GMT</lastBuildDate><pubDate>Thu, 04 Dec 2008 06:12:55 GMT</pubDate><ttl>60</ttl><item><title>JSON通用服务端处理</title><link>http://www.blogjava.net/yangyi/archive/2008/11/24/242323.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Mon, 24 Nov 2008 10:14:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/11/24/242323.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/242323.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/11/24/242323.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/242323.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/242323.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最近在学习JavaScript，发现不论是ext还是prototype都很推崇json这种通信协议的格式，但是这两个框架都是比较偏前端的，和dwr不同，dwr是一个一站式的ajax框架，不仅提供了客户端的工具方法，也包括服务端的配置和通信的处理。而ext和prototype等仅仅设置好了json的接口并对ajax通信做了封装，相对而言是一种比较&#8220;纯粹&#8221;的AJAX实现，当...&nbsp;&nbsp;<a href='http://www.blogjava.net/yangyi/archive/2008/11/24/242323.html'>阅读全文</a><img src ="http://www.blogjava.net/yangyi/aggbug/242323.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-11-24 18:14 <a href="http://www.blogjava.net/yangyi/archive/2008/11/24/242323.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件开发平台及框架的意义</title><link>http://www.blogjava.net/yangyi/archive/2008/10/26/236694.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Sun, 26 Oct 2008 05:24:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/10/26/236694.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/236694.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/10/26/236694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/236694.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/236694.html</trackback:ping><description><![CDATA[<div class="blog_content">
<p>学过软件工程的都知道，软件产品的生产周期是一个经历若干阶段的漫长过程，包括需求获取 - 设计 - 开发 - 维护等等。</p>
<p>需求阶段 - 总想考虑到所有的问题，或是一切按合同办事。但在现实中根本不得能，因此很多公司开始提倡&#8220;随需而变&#8221;的能力，希望快速的响应用户的需求变化<br />
维护阶段 - 总希望自己开发出来的东西一劳永逸，永远不要再产生任何麻烦，产生了麻烦也不要找到我。甚至有些项目组的人员开发出来一大堆不成熟的产品、项目后撒手不管，走人了事，毫无职业操守，亦是对自身行业声誉（至少是国内IT服务提供商声誉）的一个打击。真正的项目开发不应该这样，一定是非常易于维护的，能够快速地找出问题的所在，或是新需求切入点的所在，然后解决</p>
<p>&nbsp;</p>
<p>很明显，前面提到的两个问题都要也只能通过设计和开发来解决。问题来了，怎样开发出的软件才能快速地响应需求，易于维护？可以有很多不相冲突的说法，比如解耦，比如通过POJO封装数据等等。这些东西流行开来以后，很多人有疑问，为什么我的项目中一定要用这些框架？我不用这些框架也可以快速的开发出我要的功能，而且更加简单，等等。如果孤立地从设计和开发的角度看这些问题，这种说法并没有错误，但是如果从整个软件开发的生命周期来看，则不是这样。当然，这里还有一个是否&#8220;过度设计&#8221;的trade-off在里面，不过那又是另一个话题了。<br />
<br />
</p>
<p>再说说各种各样的平台吧，它们和框架不同，软件体系结构中有一种架构模型即层次模型，我们现在的TCP/IP协议栈即属于这种模型，我们的软件对于平台产品的依赖是一种朝向稳定的依赖，就好像我们在调试代码时往往不会去调试操作系统API的bug一样，因此在开发这种平台层次级别的产品时就没有必要再去采用那些为了保障&#8220;企业应用&#8221;Web软件生命周期中所采用的方法了，完全可以用最基础，最底层的手段。只要能够做到高效、稳定即可。因此，平台中间件产品的开发必须和应用软件产品分开来看，虽然它们可能都在用Java这种编程语言。</p>
</div>
<img src ="http://www.blogjava.net/yangyi/aggbug/236694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-10-26 13:24 <a href="http://www.blogjava.net/yangyi/archive/2008/10/26/236694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>形式化与自动化</title><link>http://www.blogjava.net/yangyi/archive/2008/09/12/228560.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 12 Sep 2008 04:49:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/09/12/228560.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/228560.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/09/12/228560.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/228560.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/228560.html</trackback:ping><description><![CDATA[<p>本科读书时，曾听过离散数学老师一句很精彩的论断：&#8220;只要能够形式化的东西，就可以自动化&#8221;。可是今天我不谈离散数学，倒想说说其他不相关的东西。<br />
<br />
你一定听到过&#8220;一流的企业卖标准，二流的企业卖品牌，三流的企业卖产品&#8221;。<br />
<br />
什么是形式化？为什么形式化的东西就可以自动化呢？撇开数学符号不谈，对企业来说，形式化的东西可以是一些规章及做事的方法，生产产品的方法等等。为什么人民币稍一升值，中国的中小制造型企业就要痛苦不堪？因为我们每既没有品牌，更没有标准，拿生产DVD机为例，最初的90年代生产DVD机卖到欧美很赚，可是现在据说不赔钱就不错了，因为要缴纳一大笔的专利费。中国的大多数企业处在整个产业链的最下端，所得的利润的大多数被其他企业剥夺了，因为我们用的是别人的品牌，别人的标准。我们的公司在全球经济中处于&#8220;民工&#8221;的境地。<br />
<br />
回到我们的问题中来，一流企业所做的标准，是生产一种产品的方式和规约，这一层面是抽象世界的最高层次，无法对这层抽象的产生进行形式化，所以是一种创造性的劳动；二流企业所卖的品牌是对一种产品具体生产方法的规约，通过&#8220;模板方法模式&#8221;的应用，这一层次的抽象的模板可以从上一个层次的形式化中自动化，然后只需形式化具体的操作细节，对于生产细节的形式化，也需要一定的创造性的劳动；三流的企业是一部机器，因为到此为止一切的东西都已经形式化了，只需要有时间和精力的机器去自动完成而已。<br />
<br />
让我们好好想想在一个知识经济的社会里，什么事物是创造性的，是只能被形式化而不能被自动化的。因为只有人类的创造性思想不能被机器所取代，这也是为什么机器人无法取代人类的原因。<br />
<br />
80年代出生的人应该记得历史教科书中的论述，工业革命时，一些工人去砸毁机器，觉得这些机器剥夺了他们的工作。如果有一天，老板突然来告诉您：你可以离开了，请不要沮丧和懊悔，因为您早该意识到您其实就是一部机器。当然为了防止上面悲剧的发生，早点去从事有创造性的工作吧，停止对于各种软件自动化辅助工具的抱怨和担忧，勇敢地迎接明天。</p>
<p>还记得小时候常看的电影《神鞭》吧！<br />
</p>
<img src ="http://www.blogjava.net/yangyi/aggbug/228560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-09-12 12:49 <a href="http://www.blogjava.net/yangyi/archive/2008/09/12/228560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>也谈普元</title><link>http://www.blogjava.net/yangyi/archive/2008/09/04/226983.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Thu, 04 Sep 2008 07:41:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/09/04/226983.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/226983.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/09/04/226983.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/226983.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/226983.html</trackback:ping><description><![CDATA[偶然间看到下面有一个网友慨叹普元的强大，而开发人员的渺小。<br />
小弟刚刚参加工作，也在项目中接触到了普元的EOS。普元的这个东西怎么说呢，就是乱用XML然后Spring没做好就变成那个样子的，同时失去了类型的表述，一部机器要进行装配需要组件和零件，软件应该自上而下，分而治之，这是上个世纪70年代，学者们就达成的共识，所以关于&#8220;银弹&#8221;神话的唯一结论就是——&#8220;没有银弹&#8221;。<br />
为什么说EOS是没有做好的Spring？<br />
Spring简化了对象的装配，强调重用，是建立在面向对象基础上的，是建立在敏捷测试基础上的，是建立在强类型基础上的；<br />
而EOS则是建立在面向过程的基础上的，建立在不可测试的基础上的，建立在毫无类型基础上的（全是String）<br />
然而EOS也有很多的优点（据小弟不完全发现）：<br />
1）EOS固化的开发流程强制一个team从一种易于维护的结构组织Web，包括页面，表示层，逻辑层等等。否则的话就需要一个架构师来做出规约，但仍不易于管理；<br />
2）EOS的画图功能让人耳目一新，从&#8220;代码即文档&#8221;的哲学出发，这些画图很好地诠释了代码表述的内容和结构，给程序的维护带来便利。<br />
3）相对于OO和J2EE传统开发，EOS易于上手，学习曲线较短。但是这一点有争议，EOS的知识不具备通用性。<br />
综上，根据2-8的关系法则，在某些领域EOS的确有其优点，但是认为EOS完全&#8220;解放&#8221;了程序员，则是不负责任的说法。<br />
这只是我的个人看法，欢迎大家就此话题讨论。
<img src ="http://www.blogjava.net/yangyi/aggbug/226983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-09-04 15:41 <a href="http://www.blogjava.net/yangyi/archive/2008/09/04/226983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>标准化与非标准化</title><link>http://www.blogjava.net/yangyi/archive/2008/09/03/226747.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Wed, 03 Sep 2008 10:54:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/09/03/226747.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/226747.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/09/03/226747.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/226747.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/226747.html</trackback:ping><description><![CDATA[<div class="blog_content">
<p>联合国是国家间的标准化组织，可惜一超多强们只把它当作是一个道具，需要时拿来用一下，不需要时完全可以踢到一边。<br />
历史上，每个朝代都认识到失败的教训，却最终都迎来了相似的结局。<br />
<br />
有人说，软件行业是一个天生的垄断行业，其特质是，产品研发的过程异常的复杂，但产品一旦出炉，就可以疯狂而不计成本地生产。只有NRE Cost，眼下的软件行业也出现了群雄逐鹿的场面，上游产业被几家大公司所瓜分，这些大公司如果能互相牵制，则会坐在一起，成立一个组织。如果一家独大，则我行我素，称王称霸。</p>
<p>&nbsp;</p>
<p>看看他们的一路成长：</p>
<p>初始：</p>
<p>他们想占有你，最初都会很乖。就像女孩在成为家庭主妇之前总能收到男孩的礼物。</p>
<p>成长：</p>
<p>大公司们也渐渐从规范的参与者，变成规范+的树立者，比如IE，Office，再比如Oracle的特性等等。</p>
<p>称霸：</p>
<p>市场占有的差不多了，可以不顾客户的意志做自己喜欢的事情，反正你已经离不开我。</p>
<p>消亡：</p>
<p>客户们怨声载道，新的&#8220;符合规范&#8221;或简洁明了的产品出现市场。</p>
<p><br />
希望这些大软件厂商们能够吸取教训，也希望小软件厂商们将来不要走入历史的怪圈。 </p>
</div>
<img src ="http://www.blogjava.net/yangyi/aggbug/226747.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-09-03 18:54 <a href="http://www.blogjava.net/yangyi/archive/2008/09/03/226747.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OA的杀手级应用</title><link>http://www.blogjava.net/yangyi/archive/2008/03/05/183948.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Wed, 05 Mar 2008 05:31:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/03/05/183948.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/183948.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/03/05/183948.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/183948.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/183948.html</trackback:ping><description><![CDATA[在远古时期人们靠结绳纪事，据说美洲的玛雅文明在覆灭之前都一直没有自己的文字，而采用这种古老的方法。<br />
后来我们的祖先发明了文字，在竹简上，布帛上书写文字，竹简和布帛就是信息的载体，这样的载体造价不菲，所以我们的文言和白话就有这么大的差距，留下的论语也要微言大义。再后来我们的祖先发明了纸张，严重地降低了承载信息的开销，于是人类的文明得以更好地记录和更快地发展。今天，我们的信息载体又有了新的变化，一张光盘，一个硬盘都可以承载无数的学问。<br />
信息有了载体，随之产生了信息管理的问题：<br />
如何对信息进行增删改查的操作？如何处理附加在信息上的工作流？如何管理权限？<br />
在IT系统出现之前，人们通过图书馆管理图书，通过搬运工进行信息流动，通过钥匙和锁头管理权限。<br />
在IT系统出现之后，人类可以通过计算机来完成这些操作。这其中数据库系统，工作流系统帮了我们大忙。<br />
IT系统处理信息的过程是：<br />
多样式的文档（抽象为XML）-&gt; 内存数据 -&gt; 持久化（文件数据库）-&gt;内存数据 -&gt; 多样式的文档(抽象为XML)<br />
我们让用户在我们设定的UI窗口进行输入，然后通过报表的形式产生各种各样的输出。中间一个步骤一个步骤，一个环节一个环节的走下去。<br />
这其中，我们把很大一部分精力消耗在，如何让用户舒服的输入，和产生用户所需要的输出上。<br />
于是人们就要思考，难道不可以直接编辑一种全世界认可的文档形式（大家现在正在和MS争吵的东西）通过网络流转，然后获得结果吗？为什么要从程序员的角度加给用户数据库，工作流，录入界面这些繁杂的东西？<br />
从这点意义上说，我推崇Sharepoint或者Google sites。<br />
就拿google docs来说吧，在线编辑word，每个环节通过分享的形式进行编辑，授权这部分可以通过历史记录来找到，随时恢复到历史版本，因此也不怕误操作和无权限操作，真正的所见即所得，支持50人同时在线编辑。这难道不是OA的杀手级应用吗？
<img src ="http://www.blogjava.net/yangyi/aggbug/183948.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-03-05 13:31 <a href="http://www.blogjava.net/yangyi/archive/2008/03/05/183948.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何学习spring</title><link>http://www.blogjava.net/yangyi/archive/2008/01/16/175607.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Wed, 16 Jan 2008 02:19:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/01/16/175607.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/175607.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/01/16/175607.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/175607.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/175607.html</trackback:ping><description><![CDATA[学习这些框架技术，我觉得归根结底就是做什么的，为什么做，如何做<br />
前人说读书有三个层次，我看这大概可以总结为是新的三个层次：）<br />
因为没有搞清楚为什么要用，就会误用，用了还不如没用。其实我觉得学spring读读rod那个原著挺好的，比单纯学spring有帮助，最好自己有体会。比如你开发网站很熟练了，自然就知道为什么要用spring了。等完全领会了他那两本书后，再读读他们的reference book应该差不多了。<br />
这个过程其实就是做什么-&gt;为什么-&gt;怎么做的过程<br />
<br />
<img src ="http://www.blogjava.net/yangyi/aggbug/175607.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-01-16 10:19 <a href="http://www.blogjava.net/yangyi/archive/2008/01/16/175607.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>系统模型及系统故障日志的思考</title><link>http://www.blogjava.net/yangyi/archive/2008/01/07/173344.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Mon, 07 Jan 2008 06:44:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/01/07/173344.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/173344.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/01/07/173344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/173344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/173344.html</trackback:ping><description><![CDATA[最近在研究关于系统的基于日志的故障恢复，无意间在网上发现一篇论文中对于系统日志模型的精彩论述，翻译过来并附上我的思路：<br />
『<br />
<font color="#0000ff">一个系统是一个具有明显的边界的实体，它根据一定的输入，自身运行逻辑及系统的内部时钟变化来产生相应的输出。<br />
所谓&#8220;明显的边界&#8221;是指系统所产生的输出是明确而无二义性的。我们称这个边界为系统的设计规范（specification）。一个系统通过与其所处环境进行交互，从而获取输入并产生输出。一个系统可以被拆解为不同的子系统。这些子系统通常被称为系统模块（system components），每个模块又独立地成为一个系统，作为一个系统，这个模块又会和它的相关环境进行交互（比如，一个更大的系统中的其他的模块组件）来获取输入并产生输出，这些模块还可以继续被分解为更小的子系统。<br />
一个系统可以被建模为一个状态机（state machine），其中的状态包含了系统所持有并处理的数据。这些状态的迁移被分为两大类：由系统内部逻辑所触发且对外部环境透明的迁移和直接与外部环境相接触的迁移。前者的例子如内存数据和寄存器数据的转换，内存中数据结构的重组。第二种迁移的例子包含了各种各样的系统和环境之间的交互，一般来说，如果这个过程能被建模成系统的I/O操作，则应属于这一类别。因此，一个消息内容的形成是一个或多个第一类别状态迁移的结果，但将消息输出到系统的环境则是属于第二类迁移。<br />
第二类别的状态迁移可以捕获交互事件（interaction events），或者简单的事件（events）。这些事件可以由系统外部的观察者（observer）来获取。显然，这里的事件是消息、信号、数据及其内容以及一切系统和其环境交互（如机器人运动手脚，报警器报警，打印机打印等等）的发送和接受的模型。此外事件还可以用来描述系统缺乏交互的时间，比如一个计时器在日志中输出系统的空闲时间等。<br />
当一个大的系统被拆分成多个模块时，每个模块都被赋予了整个系统所处理数据的一部分，正因为模块和模块间的接口衔接和数据感知，一些原来属于第一类别的状态转换，因为系统的拆分在更低的层次上变成了第二类别，成为系统和环境之间的交互。<br />
对于一个特定的系统，他对于输入的形式和获取时间是不可预知的，但是这个系统却应该能够做到根据一个特定的输入以及系统当前的特定状态获取一个特定的输出。因此系统的执行可以被建模为状态转换序列，每个状态的输入是一个不确定性事件。为了记录日志并做到故障恢复，我们还应做到能够在环境中捕获这个不确定性事件输入。<br />
此外，在系统与系统间进行交互式，事件的传递时间也应该是不确定性的。</font><br />
』<br />
<br />
怎样用日志来预防系统崩溃，在崩溃后如何还原系统，我想关键问题就是怎么做好内存的快照，这样，在断电重启后可以通过日志来还原内存的信息这样第一步就是确认内存中的数据结构，哪些是必不可少的。确定系统恢复的粒度，按照子系统的分割和事件的记录来进行replay，根据子系统的划分，可以找出每个子系统中第二类别的事件进行记录。<br />
以向数据库系统提交作业为例，实际上在整个作业提交的过程中，每个层次都要做到可以在失败的情况下重现，这个功能在完善的数据库系统和集群批处理系统中当然已经很完善。但如果是针对web系统的作业提交，则需要针对Web的作业持久方案，做一个日志恢复处理。需要特别指出的是，对于数据的查询是不需要做备份的。<br />
在具体实现上，我想应该包括：日志记录，故障检测，日志持久三个部分。一份日志就是一个对于系统检查点（checkpoint）的连续记录。日志记录者负责记录日志到日志持久者，故障检测器随时监控系统，发现故障后，从日志持久者中读取日志，进行replay. 
<img src ="http://www.blogjava.net/yangyi/aggbug/173344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-01-07 14:44 <a href="http://www.blogjava.net/yangyi/archive/2008/01/07/173344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用osworkflow实现业务流程</title><link>http://www.blogjava.net/yangyi/articles/172666.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 04 Jan 2008 02:53:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/articles/172666.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/172666.html</wfw:comment><comments>http://www.blogjava.net/yangyi/articles/172666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/172666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/172666.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 自己以前翻译的文章，转贴过来集中管理。&nbsp;&nbsp;<a href='http://www.blogjava.net/yangyi/articles/172666.html'>阅读全文</a><img src ="http://www.blogjava.net/yangyi/aggbug/172666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-01-04 10:53 <a href="http://www.blogjava.net/yangyi/articles/172666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何实现包含插件功能的Applet Web界面</title><link>http://www.blogjava.net/yangyi/archive/2008/01/02/172204.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Wed, 02 Jan 2008 07:07:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2008/01/02/172204.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/172204.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2008/01/02/172204.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/172204.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/172204.html</trackback:ping><description><![CDATA[<p>不知诸位有没有想过用Applet来组织Web的程序界面？小弟最近整理了一些杂碎的思路，思想完全开放，欢迎批评。<br />
先说一下可能遇到的问题：<br />
1 安全性：Applet对本地资源的操作需要相应的安全许可；<br />
2 库资源的下载：如何下载及管理支持本地Applet的库资源；<br />
3 通信：Applet如何与后台的Servlet进行通信；<br />
4 图形的加载：如何利用Applet动态的实例化并展现界面。</p>
<p>下面一一展开讨论</p>
<p>（一）保障安全性</p>
<p>安全性的主要解决方案是利用Java提供的keytool生成一个keystore，并利用这个keystore对jar包进行signjar的操作。<br />
整个对Java文件的编译，打包和signjar过程可以利用Ant来完成，比如下面的Ant脚本片段就是用来处理signjar的，大家也可以通过相应的Java命令直接处理：</p>
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />
<span style="color: rgb(0, 0, 255);">&lt;</span>
<span style="color: rgb(128, 0, 0);">target&nbsp;</span>
<span style="color: rgb(255, 0, 0);">name</span>
<span style="color: rgb(0, 0, 255);">="signjar"</span>
<span style="color: rgb(255, 0, 0);">&nbsp;depends</span>
<span style="color: rgb(0, 0, 255);">="jar"</span>
<span style="color: rgb(0, 0, 255);">&gt;</span>
<span style="color: rgb(0, 0, 0);">
<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;</span>
<span style="color: rgb(0, 0, 255);">&lt;</span>
<span style="color: rgb(128, 0, 0);">signjar&nbsp;</span>
<span style="color: rgb(255, 0, 0);">jar</span>
<span style="color: rgb(0, 0, 255);">="example.jar"</span>
<span style="color: rgb(255, 0, 0);">
<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;keystore</span>
<span style="color: rgb(0, 0, 255);">="${basedir}/yangyi.keystore"</span>
<span style="color: rgb(255, 0, 0);">&nbsp;storepass</span>
<span style="color: rgb(0, 0, 255);">="mypassword"</span>
<span style="color: rgb(255, 0, 0);">&nbsp;alias</span>
<span style="color: rgb(0, 0, 255);">="mykey"</span>
<span style="color: rgb(0, 0, 255);">&gt;&lt;/</span>
<span style="color: rgb(128, 0, 0);">signjar</span>
<span style="color: rgb(0, 0, 255);">&gt;</span>
<span style="color: rgb(0, 0, 0);">
<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />
</span>
<span style="color: rgb(0, 0, 255);">&lt;/</span>
<span style="color: rgb(128, 0, 0);">target</span>
<span style="color: rgb(0, 0, 255);">&gt;</span>
</div>
<p>如果直接用命令，则其形式为：<br />
jarsigner [ options ] jar-file alias<br />
具体的操作方法可以参考下面的链接：<br />
<a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/jarsigner.html">http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/jarsigner.html</a><br />
通过这个signjar的操作，我们就给这个包中的类进行了一次数字签名，这样，当Applet进行默认许可之外的操作时，窗口将弹出这个数字签名要求本地用户进行确认，只有在确认后，用户才可以继续进行操作。</p>
<p>这样我们可以在第一次用户运行Applet程序时，在用户的许可下动态地在用户的$user.home/.java.policy下生成一个授权文件，以后就可以执行需要的操作了，为保证客户端的安全性，仅赋予用户执行特定文件夹权限的权利，如（仅作为例子,可以根据需要自己配置文件和Socket访问权限）：<br />
grant codeBase "file:/home/yiyang/test/&#215;" {<br />
&nbsp;java.security.AllPermission;<br />
};</p>
<p>（二）下载并管理库支持</p>
<p>这个过程可以通过Java的URL类提供的openConnection方法来获取一个InputStream从而获取到远程的资源（包括支持库和配置文件两部分）<br />
1）对于配置文件，因为其内容都比较少，而且比较简单，可以直接通过输入流来获取，这是没有异议的；<br />
2）对于库文件，在下载之前先到我们管理的库的目录下找到版本索引文件（我们设定一个版本索引文件来管理升级），这个版本索引文件如下所示：</p>
<p>time={资源获取的时间戳}<br />
lib1.jar=1.0<br />
lib2.jar=1.1</p>
<p>其中，服务器端也保留有一份这样的版本文件，当下载库文件时，首先对客户端和服务端的库的总时间戳进行比较，如果客户端大于或等于服务端，则不需下载，否则，如果客户端对应项目为空或者其总的时间戳小于服务端，则进一步比较内部库文件的版本，发现版本低的库或在客户端不存在的库后，自动到服务器上进行下载，在下载成功后，更新客户端的索引文件。</p>
<p>（三）通信</p>
<p>这个问题小弟曾在以往的blog中有过详细的讨论，可以到<a href="http://yangyi.blogjava.net">http://yangyi.blogjava.net</a>中的相应随笔中找到答案。总的来说，在类型协议并不复杂，且客户端，服务端均为Java开发的情况下，应用Hessian是一个好的解决方案，需要指出的是Hessian中的代码对客户端来说并不是全部必须的，大家可以根据客户端的使用情况对这个库进行瘦身。只保留作为客户端必要的类即可。</p>
<p>（四）动态的实例化及插件结构</p>
<p>我们要实现用户界面的集成，从根本上说要解决下面的几个问题：<br />
1）菜单集成<br />
2）支持库集成<br />
3）集成点<br />
4）输出变量<br />
对于客户端为Applet开发的插件，我们把上面的四项配置统一在XML文件中进行描述定义。<br />
这里需要注意的是菜单要提供名称，支持库要提供下载路径或者本地路径，集成点我们希望是一个JPanel。<br />
在定义好XML后，可以到网址：<a href="http://www.flame-ware.com/xml2xsd/">http://www.flame-ware.com/xml2xsd/</a>去获得一个对应的schema，利用这个schema和JAXB提供的xjc工具，我们就可以生成对应的XML操作类，来对配置进行处理。<br />
对于菜单的集成可以动态地在JMenu中添加MenuItem（表示插件的功能）<br />
根据配置的支持库的位置，我们可以通过Java的URLClassLoader对库进行动态的加载，然后根据相应的集成点，获取实例，这个过程的示例代码如下所示：<br />
</p>
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />
<span style="color: rgb(0, 0, 0);">File&nbsp;f&nbsp;</span>
<span style="color: rgb(0, 0, 0);">=</span>
<span style="color: rgb(0, 0, 0);">&nbsp;</span>
<span style="color: rgb(0, 0, 255);">new</span>
<span style="color: rgb(0, 0, 0);">&nbsp;File(</span>
<span style="color: rgb(0, 0, 0);">"</span>
<span style="color: rgb(0, 0, 0);">a.jar</span>
<span style="color: rgb(0, 0, 0);">"</span>
<span style="color: rgb(0, 0, 0);">);&nbsp;</span>
<span style="color: rgb(0, 128, 0);">//</span>
<span style="color: rgb(0, 128, 0);">a.jar是我们从配置文件中读取的支持库</span>
<span style="color: rgb(0, 128, 0);">
<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />
</span>
<span style="color: rgb(0, 0, 0);">URL&nbsp;url&nbsp;</span>
<span style="color: rgb(0, 0, 0);">=</span>
<span style="color: rgb(0, 0, 0);">&nbsp;</span>
<span style="color: rgb(0, 0, 255);">null</span>
<span style="color: rgb(0, 0, 0);">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />Class&nbsp;lib&nbsp;</span>
<span style="color: rgb(0, 0, 0);">=</span>
<span style="color: rgb(0, 0, 0);">&nbsp;</span>
<span style="color: rgb(0, 0, 255);">null</span>
<span style="color: rgb(0, 0, 0);">;<br />
<img id="Codehighlighter1_89_288_Open_Image" onclick="this.style.display='none'; Codehighlighter1_89_288_Open_Text.style.display='none'; Codehighlighter1_89_288_Closed_Image.style.display='inline'; Codehighlighter1_89_288_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_89_288_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_89_288_Closed_Text.style.display='none'; Codehighlighter1_89_288_Open_Image.style.display='inline'; Codehighlighter1_89_288_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span>
<span style="color: rgb(0, 0, 255);">try</span>
<span style="color: rgb(0, 0, 0);">&nbsp;</span>
<span id="Codehighlighter1_89_288_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
<img src="http://www.blogjava.net/images/dot.gif"  alt="" />
</span>
<span id="Codehighlighter1_89_288_Open_Text">
<span style="color: rgb(0, 0, 0);">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;url&nbsp;</span>
<span style="color: rgb(0, 0, 0);">=</span>
<span style="color: rgb(0, 0, 0);">&nbsp;f.toURI().toURL();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;lib&nbsp;</span>
<span style="color: rgb(0, 0, 0);">=</span>
<span style="color: rgb(0, 0, 0);">&nbsp;Class.forName(</span>
<span style="color: rgb(0, 0, 0);">"</span>
<span style="color: rgb(0, 0, 0);">Lib</span>
<span style="color: rgb(0, 0, 0);">"</span>
<span style="color: rgb(0, 0, 0);">,&nbsp;</span>
<span style="color: rgb(0, 0, 255);">true</span>
<span style="color: rgb(0, 0, 0);">,&nbsp;</span>
<span style="color: rgb(0, 0, 255);">new</span>
<span style="color: rgb(0, 0, 0);">&nbsp;URLClassLoader(<br />
<img id="Codehighlighter1_184_190_Open_Image" onclick="this.style.display='none'; Codehighlighter1_184_190_Open_Text.style.display='none'; Codehighlighter1_184_190_Closed_Image.style.display='inline'; Codehighlighter1_184_190_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_184_190_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_184_190_Closed_Text.style.display='none'; Codehighlighter1_184_190_Open_Image.style.display='inline'; Codehighlighter1_184_190_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;</span>
<span style="color: rgb(0, 0, 255);">new</span>
<span style="color: rgb(0, 0, 0);">&nbsp;URL[]&nbsp;</span>
<span id="Codehighlighter1_184_190_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
<img src="http://www.blogjava.net/images/dot.gif"  alt="" />
</span>
<span id="Codehighlighter1_184_190_Open_Text">
<span style="color: rgb(0, 0, 0);">{&nbsp;url&nbsp;}</span>
</span>
<span style="color: rgb(0, 0, 0);">));&nbsp;</span>
<span style="color: rgb(0, 128, 0);">//</span>
<span style="color: rgb(0, 128, 0);">Lib是我们从配置文件中读取的集成点</span>
<span style="color: rgb(0, 128, 0);">
<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />
</span>
<span style="color: rgb(0, 0, 0);">&nbsp;JPanel&nbsp;plugin_panel&nbsp;</span>
<span style="color: rgb(0, 0, 0);">=</span>
<span style="color: rgb(0, 0, 0);">&nbsp;(JPanel)lib.newInstance();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;</span>
<span style="color: rgb(0, 0, 255);">return</span>
<span style="color: rgb(0, 0, 0);">&nbsp;plugin_panel;<br />
<img id="Codehighlighter1_310_334_Open_Image" onclick="this.style.display='none'; Codehighlighter1_310_334_Open_Text.style.display='none'; Codehighlighter1_310_334_Closed_Image.style.display='inline'; Codehighlighter1_310_334_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_310_334_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_310_334_Closed_Text.style.display='none'; Codehighlighter1_310_334_Open_Image.style.display='inline'; Codehighlighter1_310_334_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />}</span>
</span>
<span style="color: rgb(0, 0, 0);">&nbsp;</span>
<span style="color: rgb(0, 0, 255);">catch</span>
<span style="color: rgb(0, 0, 0);">&nbsp;(Exception&nbsp;e)&nbsp;</span>
<span id="Codehighlighter1_310_334_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
<img src="http://www.blogjava.net/images/dot.gif"  alt="" />
</span>
<span id="Codehighlighter1_310_334_Open_Text">
<span style="color: rgb(0, 0, 0);">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;e.printStackTrace();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span>
</span>
</div>
<p>对于输出变量，其主要作用是用户各个插件之间的信息交互，我们可以通过一个总的HashMap来实现，为避免变量值出现冲突，在变量名前自动加上插件名的前缀。<br />
如plug_in1的变量var1，其系统名称为：plug_in1__var1.</p>
<p>解决了上面的四个障碍，我们就可以把精力投入到具体的功能实现上了。</p>
<img src ="http://www.blogjava.net/yangyi/aggbug/172204.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2008-01-02 15:07 <a href="http://www.blogjava.net/yangyi/archive/2008/01/02/172204.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>