<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>我的技术世界</title><link>http://www.webuc.net/mechiland/category/28.aspx</link><description>Java, JavaScript, and others.</description><managingEditor>Michael</managingEditor><dc:language>af</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>Michael</dc:creator><title>Spring BeanDoc</title><link>http://webuc.net/mechiland/archive/2005/01/28/2743.aspx</link><pubDate>Fri, 28 Jan 2005 10:09:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2005/01/28/2743.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2743.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2005/01/28/2743.aspx#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2743.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2743.aspx</trackback:ping><description>&lt;p&gt;从Howard的Blog上得到的消息，改善了XSLT的HiveDoc已经比较漂亮了：&lt;/p&gt; &lt;p&gt;&lt;a href="http://jakarta.apache.org/hivemind/hivedocs/index.html"&gt;http://jakarta.apache.org/hivemind/hivedocs/index.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;但是，遗憾的是，就是这种界面也不觉得有多漂亮。我在&lt;A href="http://webuc.net/mechiland/archive/2004/10/27/1890.aspx"&gt;HiveMind初探&lt;/a&gt;中提及，HiveDoc是Hivemind比Spring有优势的地方之一，这种优势已经不复存在，&lt;a href="http://springframework.sourceforge.net/beandoc/"&gt;BeanDoc&lt;/a&gt;生成了更漂亮的文档，相比HiveDoc而言，BeanDoc在组件之间的关系上进行了更清晰的描述。&lt;/p&gt; &lt;p&gt;BeanDoc描述的JPetStore: &lt;a href="http://springframework.sourceforge.net/beandoc/jpetstore/"&gt;http://springframework.sourceforge.net/beandoc/jpetstore/&lt;/a&gt;&lt;br /&gt;petClinic: &lt;a href="http://springframework.sourceforge.net/beandoc/petclinic/"&gt;http://springframework.sourceforge.net/beandoc/petclinic/&lt;/a&gt;&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2743.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>How many web frameworks now</title><link>http://webuc.net/mechiland/archive/2005/01/21/2671.aspx</link><pubDate>Fri, 21 Jan 2005 09:11:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2005/01/21/2671.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2671.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2005/01/21/2671.aspx#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2671.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2671.aspx</trackback:ping><description>&lt;table cellspacing="1" cellpadding="0" bgcolor="#e6e6e6"&gt; &lt;tbody&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Echo &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Cocoon &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Millstone &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;OXF &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Struts &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;SOFIA &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Tapestry &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;WebWork &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;RIFE &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Spring MVC &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Canyamo &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Maverick &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;JPublish &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;JATO &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Folium &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Jucas &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Verge &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Niggle &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Bishop &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Barracuda &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Action Framework &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Shocks &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;TeaServlet &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;wingS &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Expresso &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Bento &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;jStatemachine &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;jZonic &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;OpenEmcee &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Turbine &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Scope &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Warfare &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;JWAA &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Jaffa &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Jacquard &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Macaw &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Smile &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;MyFaces &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Chiba &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;JBanana &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Jeenius &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;JWarp &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Genie &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Melati &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Dovetail &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Cameleon &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;JFormular &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Xoplon &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Japple &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Helma &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Dinamica &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;WebOnSwing &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr bgcolor="#ffffff"&gt; &lt;td&gt; &lt;p&gt;Nacho &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Cassandra &lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p&gt;Baritus &lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2671.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>为什么Bindows不会成功</title><link>http://webuc.net/mechiland/archive/2005/01/19/2649.aspx</link><pubDate>Wed, 19 Jan 2005 11:48:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2005/01/19/2649.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2649.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2005/01/19/2649.aspx#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2649.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2649.aspx</trackback:ping><description>&lt;p&gt;Bindows(&lt;a href="http://www.bindows.net"&gt;http://www.bindows.net&lt;/a&gt;)新版本1.30beta出来了，增加了千呼万唤的Theme支持。Erik&amp;amp;Emil不愧为世界水平的JavaScript高手，原本仅用做浏览器脚本支持的这个小东西如今被发挥得淋漓尽致，几乎到了浏览器JavaScript所能表现的最高境界。看过的人几乎都会叹为观止。观止观止，观而止，这一点上，客户似乎与开发者保持同样的态度。&lt;/p&gt; &lt;p&gt;无论从Bindows的站点，还是其论坛，还是Google的搜索结果，对Bindows的感觉几乎停留在这样一个感觉层次：技术好，速度慢，至今没有商业案例。更有甚者，评价其为“C/S的回归”。回归意味着什么？对于开发者而言——呃，我一直将开发者置于比客户低的地位——，除了恢复原来的编程概念、方法、模式，照拿工资，几乎没有什么改变。技术的变革从来不是以开发者的利益作为第一位的。而对于客户，这种回归却是不可接受的。&lt;/p&gt; &lt;p&gt;ChinaUI(&lt;a href="http://www.chinaui.com"&gt;http://www.chinaui.com&lt;/a&gt;)上每天都有新的设计作品产生，有相当大的数量集中在B/S系统的产品上。B/S给软件开发带来巨大改变，但与此同时进行改变的是用户的审美品位的提高。你无法再将windows经典的窗体颜色应用到绝大多数Web应用中，美工开始变得重要。客户口味越来越奇怪，很多时候一个项目的交付被卡在美工上，客户喋喋不休的说这个颜色/那个颜色不喜欢。从国内外已经出现的软件界面设计公司，可以看到这样一个趋势：用户对软件的需求已经不仅仅满足于实现功能，对软件的体验开始变得同样重要。回忆一下，《冒牌天神》中发邮件的界面，一些电影中显示人员档案的界面，《黑衣人》中的海关电脑界面。随着软件的发展，这些界面相信也会出现在实际的软件中。&lt;/p&gt; &lt;p&gt;RIA应运而生。Macromedia公司的Flex(&lt;a href="http://www.macromedia.com/software/flex"&gt;http://www.macromedia.com/software/flex&lt;/a&gt;)，开源的Leszlo(&lt;a href="http://www.openlaszlo.org"&gt;http://www.openlaszlo.org&lt;/a&gt;)，都是这方面的代表。Flash经过多年的发展，已经从典型的动画格式开始向着一种用户友好的表现形式发展。从Macromedia官方公布的资料看来，已经有一些成功的商业应用采用了Flex，用户体验相当好。而从我给一些客户演示laszlo的实例来看，Laszlo“增加了对Web应用的期待”。这种期待显然是界面、操作感觉的期待。RIA, Rich Internet Application, 在我看来一个最为体贴的解释就是“丰富客户体验的Web应用”。Rich在这里，所指并不仅仅是提供开发者丰富的控件，更重要的是给客户丰富友好的体验。&lt;/p&gt; &lt;p&gt;Bindows所做的，从第一眼看上去，就象是所有windows控件的模拟。按钮，标签，列表，文本框，对话框，颜色，样式，等等，一个典型桌面应用应该有的控件、样式都具备了。客观的说，用JavaScript实现这些并不容易，作者花了整整两年时间，这个产品还在继续维护。为什么至今没有商业应用（据我所了解，没有）愿意采用Bindows呢？我分析：Bindows不能成功也不会成功的根本原因在于，它意味着用户体验的倒退。换句话说，这是一个开发人员一厢情愿的产品，丝毫没有考虑到用户操作感觉。如果这是一个彻底的桌面程序框架，融入到传统桌面程序的大潮中，那么也许还有成功的可能；但是这个产品定位于运行在浏览器中，是Web程序，没有用户愿意看着别人能够在浏览器里进行丰富多彩的操作，而自己只能对着灰蒙蒙的屏幕。当然，在我所未知特定行业里面或者用户操作计算机层次不高的情况下，用户体验也许不重要；但是随着时间的发展，这一点会逐渐消除。毕竟，没有人会拒绝美丽。&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2649.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>AMOWA: 不应该关注URL的形式</title><link>http://webuc.net/mechiland/archive/2005/01/18/2635.aspx</link><pubDate>Tue, 18 Jan 2005 11:34:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2005/01/18/2635.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2635.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2005/01/18/2635.aspx#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2635.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2635.aspx</trackback:ping><description>&lt;p&gt;除非是内容相关的系统，如CMS, Blog, 新闻，门户，论坛，网站系统等，这些系统需要一个明确的链接，来指引用户进行直接有效的访问。但是企业应用系统往往对这些并不关心。例如一个信息管理系统，几乎没有人关心浏览器地址栏里面的链接组织形式，除非一些别有用心的用户。&lt;/p&gt; &lt;p&gt;把握这一点很重要——我是指进行一个&lt;A href="http://webuc.net/mechiland/archive/2004/11/15/2195.aspx"&gt;Amowa&lt;/a&gt;的实现。在我去年提出观点中，我指出，amowa不适合内容相关的系统。虽然这么说，但是当我试图实现一个amowa思想的论坛时，URL相关的东西让我头痛不已。一方面，既然是改善客户体验，所有的操作采取无刷新的方式来进行，那么用户从浏览器中看到的就只有一个地址；而另一方面，用户也许需要对某一贴进行引用转贴时，需要知道类似与thread?id=123的东东。这个问题困扰了我很久，项目也迟迟未动工。&lt;/p&gt; &lt;p&gt;在参与现在的这个商业项目中，我注意到用户根本不关心链接的组织形式，特别是系统非常庞大，页面采用框架进行组织时，浏览器中地址从来都只有一个。操作的感觉就像原来的VB/Delphi时代的C/S软件一样。这么说来，对于操作/功能型的系统，URL并不重要，那么这个时候amowa的各种威力就发挥出来了。&lt;/p&gt; &lt;p&gt;下面附上这段时间思考的Amowa框架目标，希望对有志于amowa框架开发的同仁有些启发：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;采用纯粹HTML作为界面描述语言，减少学习梯度。只要学习HTML便可编写WEB界面。&lt;/li&gt; &lt;li&gt;利用XMLHTTP或者其他访问方式来进行远程访问/调用，减少带宽要求&lt;/li&gt; &lt;li&gt;一致性对待客户端与服务器端。对页面开发者而言，他看不到服务器端；对服务器端而言，他看不到客户端。两者完完全全的独立开来。&lt;/li&gt; &lt;li&gt;服务器端控制页面流转，非常简单的方式进行页面跳转，客户端被翻译为正确的JavaScript调用，从而让客户感觉更好。&lt;/li&gt; &lt;li&gt;客户端缓存。客户端访问得来的页面内容，被缓存到客户端，下次访问非常非常快。&lt;/li&gt; &lt;li&gt;丰富的客户端组件&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2635.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>Web框架选型思考</title><link>http://webuc.net/mechiland/archive/2004/12/07/2366.aspx</link><pubDate>Tue, 07 Dec 2004 21:46:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2004/12/07/2366.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2366.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2004/12/07/2366.aspx#Feedback</comments><slash:comments>29</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2366.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2366.aspx</trackback:ping><description>&lt;p&gt;经过漫长的商务折磨，终于确定了自己平台规划负责人的角色，任务非常明确：采用开源技术进行组装，开发一个具备业务含义、能够进行快速开发的软件平台。&lt;/p&gt; &lt;p&gt;现有项目的运行情况让我认识到了一点：在持久层与业务逻辑的相对成熟的情况下，WEB层的工作最为繁重，哪怕是引入了Tiles改善布局也如此。Struts天生的缺陷，让整个项目中WEB层显得笨拙不堪，成为整个系统中bad smell最重的的区域。从软件技术大会回来的同事说，很多同行都认为B/S系统中WEB端的工作量是整个系统的瓶颈。这一点看来已经得到了业界的普遍认可。&lt;/p&gt; &lt;p&gt;而现有的这个平台一定是持续使用的。如果不在WEB开发上进行改善，那么这个平台显得毫无意义：在依托面向对象技术的Java平台下，大部分其它的东西都有现成并且健壮的，对我而言都是熟悉的；而在WEB层，一定要有一个具备重用、珍惜每一个可重用WEB组件的框架在支撑。由于我们这个行业的特殊性，再带宽上也应当有所考虑。&lt;/p&gt; &lt;p&gt;基于这些特征，我首先想到的就是面向组件的WEB框架。这里的组件一定是网页上可见的组件，能够天生穿透Java/Javascript/Html，而不是笨拙的在JSP中import javascript；或者采用不堪的JSP tag. 这么看来，具备这一特征的、成熟的框架只有Tapestry了。&lt;/p&gt; &lt;p&gt;然而我对tapestry还有所保留，原因有两点：一个是对大型系统的支持不足。我们要面临的系统达到十几个子系统，3000多种交易。而Tapestry模块的支持区分不足，这一点上，WebWork来的要自然的多，Struts也提供了支持（我实在是难以出口这个词，虽然Struts将我引入了MVC的门，但是我对其丑陋的设计，臃肿的配置文件充满了憎恶）。&lt;/p&gt; &lt;p&gt;第二是Tapestry难以理解的URL，总让人觉得诡异（刚开始觉得挺有意思），不便于书签。好在有成功的项目证明进行修改是可行的，这个工作量也应该不大。&lt;/p&gt; &lt;p&gt;如果我的AMOWA概念有实现，那么我一定会选择Amowa的实现。因为Amowa中异步的概念刚好满足了系统带宽的要求。Web框架的选择过程让我了解到，组件式的web框架在知识积累上有多么重要。试问一下，我们以前做的WEB应用中，web端有多少能够自如的重用？&lt;/p&gt; &lt;p&gt;纵然Tapestry不尽人意，我还是决定选择Tapestry来作为平台的WEB框架（有人会说Tapestry不便于测试，试问又有多少合理的项目会将业务逻辑写在XXXPage中？），对其进行一些改造是必需的，比起持续使用与知识积累带来的好处，这么点工作量算不了什么。&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2366.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>java.lang.NoSuchMethodError: xjavadoc.XJavaDoc.setDocEncoding(Ljava/lang/String;)V</title><link>http://webuc.net/mechiland/archive/2004/11/20/2231.aspx</link><pubDate>Sat, 20 Nov 2004 10:38:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2004/11/20/2231.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2231.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2004/11/20/2231.aspx#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2231.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2231.aspx</trackback:ping><description>&lt;p&gt;昨晚开始了痛苦的历程。&lt;/p&gt; &lt;p&gt;一向工作得好好的xdoclet，自从我将核心包更新为1.2.2后，噩梦开始了。每次运行hibernatedoclet, 都会出现以下错误：&lt;/p&gt; &lt;p&gt;java.lang.NoSuchMethodError: xjavadoc.XJavaDoc.setDocEncoding(Ljava/lang/String;&lt;br /&gt;)V&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at xdoclet.XmlSubTask.startProcess(XmlSubTask.java:184)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at xdoclet.modules.hibernate.HibernateSubTask.execute(HibernateSubTask.j&lt;br /&gt;ava:123)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at xdoclet.XDocletMain.start(XDocletMain.java:48)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at xdoclet.DocletTask.start(DocletTask.java:468)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at xjavadoc.ant.XJavadocTask.execute(XJavadocTask.java:96)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Task.perform(Task.java:364)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Target.execute(Target.java:341)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Target.performTasks(Target.java:369)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Project.executeTarget(Project.java:1214)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Project.executeTargets(Project.java:1062)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Main.runBuild(Main.java:673)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.Main.startAnt(Main.java:188)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.launch.Launcher.run(Launcher.java:196)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at org.apache.tools.ant.launch.Launcher.main(Launcher.java:55)&lt;/p&gt; &lt;p&gt;无法生成hibernate配置文件&lt;/p&gt; &lt;p&gt;没有源码，反编译找到XmlSubTask，没发现什么问题；找到xjavadoc相关的类，setDocEncoding赫然存在。&lt;/p&gt; &lt;p&gt;Google了一下，只有两条纪录，也没有解决，只是说注意版本。我试着将所有xdoclet jar文件换成1.2b4, 再次ant...居然成功了！郁闷，然后依次将hibernate, web相关的jar更新为1.2.2,没问题；就在更新xdoclet.jar之后，出现了上面提到的那个错误。&lt;/p&gt; &lt;p&gt;问题很明显了，是最新版本的问题。具体原因不祥。还是老老实实用旧版本吧。&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2231.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>面向异步消息的Web应用(AMOWA)</title><link>http://webuc.net/mechiland/archive/2004/11/15/2195.aspx</link><pubDate>Mon, 15 Nov 2004 22:06:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2004/11/15/2195.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2195.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2004/11/15/2195.aspx#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2195.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2195.aspx</trackback:ping><description>&lt;p&gt;&lt;strong&gt;前言：&lt;br /&gt;&lt;/strong&gt;本文的源自于Martin Fowler的著作《Patterns of Enterprise Application Architecture》中关于Web表示模式的一些启发。作者做了多年Web开发，并不限于企业级Web应用。在娱乐方面的应用（如聊天室，即时消息，Web场景聊天等）得到的一些工作经验促使我在企业级应用上进行了深层次的探索和思考，并形成了这篇文章。目前国内外并没有明显在这方面的文章或著作，希望此文能够给做WEB开发的同仁一点借鉴之处。&lt;/p&gt; &lt;p&gt;本文的最先在2004年11月13日的javaparty聚会上以PPT提出，后经过整理完成。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1 观点提出&lt;/strong&gt;&lt;br /&gt;标准的遵循HTTP GET/POST的WEB开发方式往往遵循这样一个流程：客户端发送一个请求：GET或者POST给WEB服务器，WEB服务器处理完成后将结果以Response返回给客户端。在得到服务器的响应之前，客户端一直在等待，页面停滞，用户将看见浏览器长长的的等待条慢慢增长。&lt;/p&gt; &lt;p&gt;而Google Gmail给了我们完全不同的体验。你无法感受到页面的跳转，系统反应非常快。获取新邮件不需要手动或者自动的刷新浏览器。这一切给人的感觉是那么友好，以至于它一经推出便得到了众多用户的宠爱，并同时成为Sina，Yahoo等邮件提供商的追赶对象。&lt;/p&gt; &lt;p&gt;这便是我要提出的面向异步消息的WEB应用(Asynchronous-Messaging Oriented Web Application, 简称AMOWA)的一个小例子。一个具备AMOWA特征的WEB应用具备以下三条：&lt;/p&gt; &lt;p&gt;&lt;br /&gt;1.&amp;nbsp;系统必须是一个WEB应用。事实上，在非WEB环境中设计与实现异步调用非常简单，考虑也很自然。但在WEB环境下，设计与实现相对比较麻烦，思维方式也稍微会有些跳跃感。&lt;br /&gt;2.&amp;nbsp;系统中必须具备消息特征，无论是隐式或者显式。在网络游戏，即时消息工具等应用中，消息特征比较明显，这方面的论述也比较多；但有些企业应用，也能够发现一些隐含的消息模式。比如，一个商业智能WEB客户端，需要进行钻取、上溯、切片等操作，这些操作和返回值可以被包装为消息（事实上，目前已经有相关的规范，分别是MDX和XML/A）；在操作型WEB应用中，操作同样可以被抽象为消息，比如一个Bug管理系统，提交Bug, 查看Bug等，都可以包装为消息。&lt;br /&gt;3.&amp;nbsp;消息必须是异步的。这一点是与传统方式的根本不同之处。传统的方式在完成某个操作一定存在页面切换，而AMOWA不必。消息是异步传输，在操作完成之前客户可以看到一个友好的Loading或者其他友好的提示，等到操作完成数据可用之后，前台的UI采用javascript/Flash的方式进行刷新。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2 AMOWA的出生历程&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;AMOWA的提出来自于网页出现的这十多年。&lt;/p&gt; &lt;p&gt;最初始阶段传统的聊天室。前台网页往往需要经过几秒钟自动刷新一次来获取其他在线用户的发言。后来出现了无刷新聊天室，或多或少采用了隐藏帧来处理消息的定时收发。在这期间出现了Pushlet, 一种意图将HTTP消息"推"到客户端而不是客户端主动"拉"的方式。这种方式在客户端看来，就像是一个有一个永远也下载不完的页面；服务器端往往不允许buffer, 并通过response.write然后直接response.flush的方式向客户端写数据。&lt;/p&gt; &lt;p&gt;之后的一段时间WEB应用一直停留在标准的Request/Response的方式很久，直到XMLHTTP的出现，面向异步消息的应用才多了起来，同时由于思维方式的扩展，很多采用同样思维的应用也出现了，这些应用跨越了很多行业，包括商用和娱乐行业，直到现在，面向异步消息的WEB应用已经能够成功胜任大多数的WEB应用，并以改善用户体验为最终目标，越来越受到重视。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3 应用场景&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.jzchen.net/images/01.gif" /&gt; &lt;p&gt;商用领域，包括但不限于&lt;/p&gt; &lt;p&gt;l&amp;nbsp;邮件应用程序。这一点，在Gmail上已经得到验证。邮件应用是最典型的异步、消息的应用，在WEB环境下，异步消息模式完全有理由应用在邮件系统客户端中。如果有一种方式能够让你不刷新就能够获取新邮件，让你不需切换页面就能够阅读/编写邮件，你还会想回到老路上吗？&lt;/p&gt; &lt;p&gt;2&amp;nbsp;即时消息应用。典型的无外乎MSN Web Messenger. 即时消息并不要求实时性。在即时消息系统中，延迟2~3秒用户是完全符合用户期待。而这宝贵的2~3秒给了即时消息的WEB应用提供了生存空间，并给了即时消息服务提供商新的卖点。&lt;/p&gt; &lt;p&gt;3&amp;nbsp;商业智能客户端。商业智能产品越来越趋向于WEB--或许这是整个世界应用的发展趋势；WEB上对数据立方的钻取、旋转、切片如果需要切换页面，没有多少人会很愉快的接受这样的系统。这样需要频繁操作的系统，AMOWA是当仁不二的选择。&lt;/p&gt; &lt;p&gt;4&amp;nbsp;WEB地图系统。&lt;a href="http://www.go2map.com/"&gt;www.go2map.com&lt;/a&gt; 上的地图，大家可以看到异步操作模式下的地图是多么自然；相反，ICQ提供的地图服务让人难以接受：每次点击或者圈选地图之后，就要等待一段时间的白屏。&lt;/p&gt; &lt;p&gt;5&amp;nbsp;其它操作性强的系统。比如，财务信息管理系统，前面提到的Bug管理系统，具备明显或者能够抽象成命令特征的系统。注意，国内政府或者大型国企需要的OA等项目不太适合应用AMOWA，原因是大多数情况下，消息格式的定义比起需求的控制、界面的变更以及项目完成后的使用率，显得微不足道且毫无意义。&lt;/p&gt; &lt;p&gt;娱乐与游戏领域，包括但不限于：&lt;/p&gt; &lt;p&gt;l&amp;nbsp;聊天室。没有什么比一边聊天一边听着浏览器自动刷新时发出的"叭哒"声更讨厌了。更加细心的定义AMOWA的消息结构，你会发现聊天室的访问者更多了。&lt;/p&gt; &lt;p&gt;2&amp;nbsp;WEB在线游戏。不要以为不可能，请访问&lt;a href="http://www.51js.com/"&gt;www.51js.com&lt;/a&gt;, 那里有令很多传统WEB开发者意想不到的东西。目前已经实现的有：LiveChatV2, 一个纯JavaScript+HTML的场景聊天室；中国象棋，纯JavaScript+HTML的网络版中国象棋。目前台湾有一款真正的WEB网络即时战略游戏，正在线运营，月卡好几十台币。&lt;br /&gt;当然，由于异步消息的限制，WEB在线游戏不可能做到实时，因此目前WEB网游被限制在消息实时性要求不高的领域，如棋牌，社区，简单的网络游戏。3&amp;nbsp;其它。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;4 优点&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;4.1 从用户来看：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1.&amp;nbsp;更好的用户体验。&lt;br /&gt;&lt;/strong&gt;很多高级用户不愿意听到浏览器刷新发出的声音。这个用户群体在扩大。在现代的企业级WEB应用中，经常有及时消息传递的要求；让他们听到刷新的声音是不合适的。AMOWA的引入将彻底无刷新，用户感觉更好。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2.&amp;nbsp;更好的用户体验&lt;/strong&gt;&lt;br /&gt;对用户而言，单页面的操作更为友好。大部分用户对于切换页面时那段漫长的时光感到度日如年，并且感到不自然。在商业智能/报表这样的操作中，单页面操作显得格外重要。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3.&amp;nbsp;更好的用户体验&lt;br /&gt;&lt;/strong&gt;等待的页面更为友好。在操作得到数据返回之前，用户将看到的不是白屏和长长的浏览器状态条，取而代之更为友好的提示和状态条。对于高级用户，这样的改变将令他们惊喜。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;4….呃，更好的用户体验&lt;br /&gt;&lt;/strong&gt;由于系统中传递的是纯粹的数据，对用户而言，系统显得比普通的应用更快了，感觉当然更好。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;4.2 技术观点&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1.&amp;nbsp;在某些场景下，客户端可以是纯粹的HTML, 而不是讨厌的JSP Tag, 或者Tapestry难以理解的jwcid（实际上一点也不难理解^_^）, 或者Struts那恐怖的tag, 或者毫无IDE工具支持的JSF。业务逻辑、服务器端特定语言特征与客户端彻底分开。美工可以真正安心的做页面。&lt;/p&gt; &lt;p&gt;2.&amp;nbsp;服务器端可以进行一些有趣的设计，例如任务队列。由于客户端发送来的是消息，服务器端可以将发送来的消息按照队列来进行处理，而不用马上响应。&lt;br /&gt;3.&amp;nbsp;容易实现分布式部署。由于客户端与服务器端的完全分离，服务器端的分布、状态迁移、Cache共享将不成为问题。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;5 基于AMOWA的设计&lt;br /&gt;&lt;/strong&gt;基于AMOWA的设计将分为两个部分：面向企业级典型WEB应用和面向娱乐游戏的典型WEB应用。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;5.1 面向企业级典型WEB应用&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;基本原则：一个典型的企业级WEB应用一定是一个分层结构、设计良好的应用。分层设计意味着数据层，业务逻辑层与表示层能够清晰的分开。&lt;/p&gt; &lt;p&gt;AMOWA专著于WEB表示层，它连接了系统的业务逻辑与前端WEB页面。AMOWA Gateway负责解析前台发送来的消息包，将消息包解析为相应的业务操作，调用业务逻辑操作，将操作结果进行序列化，封包为消息，发送给客户端。&lt;/p&gt; &lt;p&gt;客户端有一个客户端引擎，能够接收、解析消息包，并根据消息内容，对UI进行刷新。这里的刷新可能对应一个javascript脚本，也可能对应一个Flash的action script脚本。&lt;/p&gt; &lt;p&gt;AMOWA定位在与Struts, WebWork, Tapestry等WEB框架的同一个层次上，并能够取代他们。&lt;br /&gt;下图表示了这种架构：&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.jzchen.net/images/02.gif" /&gt; &lt;br /&gt;这种WEB应用在AMOWA看来，具备最大的特征是：各个会话之间的交互较少。在下面的面向娱乐游戏的AMOWA设计中，会话之间的交互显得格外重要。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;5.2 面向娱乐游戏的AMOWA设计&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;面向娱乐的AMOWA与面向企业WEB应用的根本不同在于，前者会话交互需求较高，比如在一个网络游戏中，经常需要知道另一个在线玩家的当前状态，因此，在这种设计中存在一个中央context来保存这些信息，来保证在线操作者之间的交互。基本设计图如下：&lt;br /&gt;&lt;img src="http://www.jzchen.net/images/03.gif" /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;Context连接了基本的底层设施--比如，保存玩家经验值，扣点等。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;6 实现&lt;/strong&gt;&lt;br /&gt;以下是一个AMOWA接口的伪代码&lt;br /&gt;* 客户端将操作包装成消息并发送：&lt;br /&gt;&lt;font color="#a52a2a"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; clientOperation.sendMessageBundle(msgBundle, callback);&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callback定义了消息的处理策略。&lt;br /&gt;*&amp;nbsp;AMOWA Gateway负责获取前台发送的消息，并处理&lt;br /&gt;&lt;font color="#a52a2a"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; messageBundle = buildMessage(request); //将Request包装成MessageBundle&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; returnedMSGBundle = process(messageBundle); // 处理消息包&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sendReturnedBundle(returnedMSGBundle );&amp;nbsp; //发送处理结果&lt;/font&gt;&lt;br /&gt;*&amp;nbsp;在process方法内部，简单的调用业务逻辑层的处理方式：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#a52a2a"&gt;bizDTO = bizService.doSomething();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return bizDTO;&lt;br /&gt;&lt;/font&gt;AMOWA Engine将会将bizDTO序列化为系统能够辨认的消息格式，生成消息包。&lt;/p&gt; &lt;p&gt;以上的实现相对简略，实际上，设计这样的一个AMOWA Framework技术上不是太难的。如果想偷懒，XML-RPC的实现可以直接拿来使用。XML-RPC在几乎所有语言上都有实现。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;7 相关技术&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;客户端技术：&lt;/strong&gt;&lt;br /&gt;DHTML, JavaScript&lt;br /&gt;我在文中偏向于这两点，是因为我对这两种技术相对较熟悉，实际上Flash更适合用来做前台表现。当然，前台用何种技术并不影响AMOWA的架构方式。AMOWA定义了客户机于服务器之间的一种通信方式，而并非客户端实现方式。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;服务器端技术：&lt;/strong&gt;&lt;br /&gt;任意一种服务器端技术都是可以的。然而，具备面向对象特征的服务器端技术在实现上能够更自由、合理一些。那些老式的服务器端技术如ASP，想要实现一个AMOWA Framework显得较为困难，这一点在设计WEB网络游戏时显得格外突出。&lt;/p&gt; &lt;p&gt;XML-Binding的技术一定是需要的，无论是客户端或者是服务器端。这是由于我们的消息格时往往用XML的方式来定义。在服务器端返回对象时，能够直接序列化为XML将会给消息的包装带来便利之处；客户端若能够将HTML或者Flash某个控件直接与XML一个节点或者属性进行绑定，那么前台的工作量将会更少。鉴于服务器端的XML绑定已经有很多不同的实现，如JAXB, Castor, JiBX等，笔者最近在试图无浏览器差别的将XML对象绑定到HTML元素上。&lt;/p&gt; &lt;p&gt;选择一种消息传输协议是必要的。目前有两种选择：Web-Service和XML-RPC。在现有系统的消息特征明确并且不太可能会将每个方法暴露给外界的前提下，Web-Service是最不推荐的选择。Web-Service冗余的信息太多，传输或解析都会带来时间和带宽损耗。如果没有时间定义消息格式，那么XML-RPC将是一种比较好的选择。他对数据类型进行了较好的包装，对于WEB应用足够，并且有足够多的语言实现支持，客户端和服务器端都有。&lt;/p&gt; &lt;p&gt;如果时间足够，最好能够自行定义消息结构，和编码、解码方法。这并不是很复杂的事情。这样编码的消息能够以最小的带宽损耗进行传输。这一点，在带宽有限制的应用中显得格外重要，例如银行的业务系统。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;8 相关问答&lt;/strong&gt;&lt;br /&gt;问：AMOWA与RIA有什么关系？&lt;br /&gt;答：没有关系。AMOWA定义了WEB应用一种新型的交互方式--采用消息方式。RIA可以是AMOWA客户端的一种实现，AMOWA的客户端实现可以是Flash, XUL, 或者HTML. &lt;/p&gt; &lt;p&gt;问：AMOWA与XMLHTTP的关系？&lt;br /&gt;答：XMLHTTP是AMOWA实现无刷新、异步消息的一种手段。目前只有这样一种手段来获得异步连接。其他方式如动态加载远程javascript, 动态加载远程网页，多少是同步的方式，会导致客户端浏览器的瞬间不可用。&lt;/p&gt; &lt;p&gt;问：AMOWA有没有实现？&lt;br /&gt;答：暂时没有。我正在编写一个，主要面向在线游戏。但是由于工作繁忙，进展缓慢。基本思想如同上面的描述，有兴趣的同仁可以自行实现，造福人类。&lt;/p&gt; &lt;p&gt;问：发送和接收为什么是MessageBundle，而不是单个Message?&lt;br /&gt;答：这是为了保证执行效率。在LiveChatV2中，用户每次的鼠标点击将会发送一个消息，如果用户鼠标点击速度相当快--比如每秒几十次，这么密集的访问可能会造成服务器没必要的繁忙。因此，客户端采取没隔一段时间记录一次，将这段时间的鼠标动作捆绑成一个消息包，发送给服务器。&lt;/p&gt; &lt;p&gt;其他问题，欢迎交流：mechiland [###] gmail.com&lt;/p&gt; &lt;p&gt;&lt;strong&gt;9 总结&lt;/strong&gt;&lt;br /&gt;AMOWA引入一种新的WEB开发模式，可以换掉标准的MVC开发方式了！&lt;br /&gt;AMOWA的引入，从根本上讲，完全是为了给用户更好的体验，从而使产品更具人性化，更有竞争力。&lt;br /&gt;更快。&lt;br /&gt;&lt;/p&gt;&lt;/a&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2195.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>学习，研究，工作，灵感——学习过程其实是一张网</title><link>http://webuc.net/mechiland/archive/2004/11/04/2093.aspx</link><pubDate>Thu, 04 Nov 2004 11:12:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2004/11/04/2093.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/2093.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2004/11/04/2093.aspx#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/2093.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/2093.aspx</trackback:ping><description>&lt;p&gt;进行比较简单的学习时，专家或者教师往往给初学者这样一种建议：以学习Java为例，初学者最好学习C语言，掌握基本的语言概念；然后编写Java版的helloworld，然后学习基本的java.lang, java.util库，在学习的过程中不断体会OO的概念；然后根据需要，学习某一方面的如网络，UI, WEB等等……&lt;/p&gt; &lt;p&gt;很明显，这是一个箭头状的直线学习图。但是实际上没有人纯粹的依赖这些建议或指导来学习成功，最终往往是两种结果：一种是学习过程枯燥无味，最终放弃或者依靠毅力苦苦挣扎；一种是在学习过程中不断参照已有知识，反复印证参考，最终其乐融融小有所成。&lt;/p&gt; &lt;p&gt;大部分人都处于第二种状态，或者自己没有意识这一点，在积累越多的工作者身上体现越明显。大脑是一个圆，需要学习来刺激使他膨胀，线状的学习思路会违背几何规律，最终让自己疲惫不堪，充满挫折感。&lt;/p&gt; &lt;p&gt;所以，学习，不断的学习，不限于技术方面的学习。这一点在Java领域表现得尤为明显。Spring的核心作者Rod Johnson在音乐上的造诣与技术不相上下，大多数国内J2EE技术比较强的人都有哲学背景。所以，一定要不断的学习，不仅要对技术世界，开源领域自己业务范畴内的技术永远保持敏感，而且要不断花时间充实自己其他方面的积累。总有一天，比如你在文学上的一个灵感会让你的设计充满惊叹；或者你在打桌球领悟到业务架构可以更加优化一些。&lt;/p&gt; &lt;p&gt;学习与年龄无关，与惰性有关，所以，保持学习的劲头，活到老，学到老。网状的学习过程，不限于本行业的学习视野，不断的体会领悟的积累，会让学习真正成为快乐。&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/2093.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>连接DB2的问题--encoding not supported</title><link>http://webuc.net/mechiland/archive/2004/10/29/1903.aspx</link><pubDate>Fri, 29 Oct 2004 15:21:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2004/10/29/1903.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/1903.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2004/10/29/1903.aspx#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/1903.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/1903.aspx</trackback:ping><description>&lt;p&gt;Driver: com.ibm.db2.jcc.DB2Driver&lt;/p&gt; &lt;p&gt;用Squirrel SQL查看db2的数据结构，填好driver, url, username, password后，点“connect”，出现问题：&lt;/p&gt; &lt;p&gt;&lt;font color="#ff1493"&gt;com.ibm.db2.jcc.b.DisconnectException: encoding not supported!!&lt;/font&gt;&lt;/p&gt; &lt;p&gt;奇怪，怎么会出现这个错误？我以为是SquirrelSQL的问题，运行了一下自己以前写的一个代码生成器，输入相同的参数，发现还是出现这个问题……头痛，以为是通过Console输入的参数编码与通过Java文件输入的编码不一致，索性打开Eclipse, Class.forName，然后getConnection，问题同样。&lt;/p&gt; &lt;p&gt;同事把代码拿去，在WSAD下面重新编译运行，奇怪，没问题；我也在WSAD下面重新编译运行了一次，居然也没有问题。&lt;/p&gt; &lt;p&gt;问题很明显了，是那该死的IBM JDK. 把Squirrel SQL运行的Java_home设置为WSAD的jre_home，问题果然解决，db2数据库结构正常显示在面前。&lt;/p&gt; &lt;p&gt;虽然问题解决，我还是不知道为什么——我也不想知道。记得以前jdom在webshpere上不能正常运行就把我弄得死去活来，这次又耗掉了我1个小时。IBM的jvm真是诡异。&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/1903.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>Michael</dc:creator><title>HiveMind初探</title><link>http://webuc.net/mechiland/archive/2004/10/27/1890.aspx</link><pubDate>Wed, 27 Oct 2004 18:34:00 GMT</pubDate><guid>http://webuc.net/mechiland/archive/2004/10/27/1890.aspx</guid><wfw:comment>http://webuc.net/mechiland/comments/1890.aspx</wfw:comment><comments>http://webuc.net/mechiland/archive/2004/10/27/1890.aspx#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://webuc.net/mechiland/comments/commentRss/1890.aspx</wfw:commentRss><trackback:ping>http://webuc.net/mechiland/services/trackbacks/1890.aspx</trackback:ping><description>&lt;p&gt;今天HiveMind 1.0 的final版本出来了， 看了看他的examples代码。 有了IoC(DI)的感觉之后再看这些代码， 越看感觉越清晰。 实现一个IoC的容器本身没什么可说的， 现在就以他自带的example为例，来看看HiveMind在这方面的实现方法。&lt;/p&gt; &lt;p&gt;example程序是一个四则运算的类，基本思想是将加减乘除都做成接口，用不同的方式实现；计算器(Caculator)继承了加减乘除接口，在运行过程中，具体的加减乘除操作类通过HiveMind的配置注入到CaculatorImpl中，当然CaculatorImpl也是通过Caculator接口通过工厂产生出来的，以下是他的具体代码：&lt;/p&gt; &lt;p&gt;&amp;nbsp;double arg0 = Double.parseDouble(args[0]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; double arg1 = Double.parseDouble(args[1]);&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Registry registry = ExampleUtils.buildRegistry("examples.xml");&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Since we know there's exactly *one* service-point implementing Calculator,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // we can get it this way, and never have to know its service id.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Calculator calculator = (Calculator) registry.getService(Calculator.class);&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Inputs:&amp;nbsp;&amp;nbsp; " + arg0 + " and " + arg1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Add:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; " + calculator.add(arg0, arg1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Subtract: " + calculator.subtract(arg0, arg1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Multiply: " + calculator.multiply(arg0, arg1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println("Divide:&amp;nbsp;&amp;nbsp; " + calculator.divide(arg0, arg1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; registry.shutdown();&lt;/p&gt; &lt;p&gt;嗯，Registry registry = ExampleUtils.buildRegistry("examples.xml");&amp;nbsp; 这条语句看来是从examples.xml中进行相应的初始化并建立对应关系了，内部大概是根据配置文件定义拦截器，工厂，初始化方法之类，不用看。这里的Registry应该等于Spring中的ApplicationContext, Pico中的Configuration了。看了IoC容器这方面的也没什么别的东西，一定得有一个全局的东西hold这些被管理的类的。&lt;/p&gt; &lt;p&gt;下面的registry.getService(Calculator.class);看起来要比Spring的appContext.getBean(beanId)方便一点，在整个配置文件保证借口唯一的前提下，可以直接采用class作为参数取出对象。当然Spring完全可以这么做，只看Johnson先生高兴不高兴了。&lt;/p&gt; &lt;p&gt;Caculator接口继承了增删改查接口（就是4个各包含一个方法的接口）。&lt;/p&gt; &lt;p&gt;再看看examples.xml配置：&lt;/p&gt; &lt;p&gt;&amp;lt;module id="examples" version="1.0.0"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;service-point id="Adder" interface="org.apache.hivemind.examples.Adder"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;create-instance class="org.apache.hivemind.examples.impl.AdderImpl"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;interceptor service-id="hivemind.LoggingInterceptor"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/service-point&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...其他操作省略&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;service-point id="Calculator" interface="org.apache.hivemind.examples.Calculator"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;invoke-factory&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Most properties are autowired by the BuilderFactory --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;construct class="org.apache.hivemind.examples.impl.CalculatorImpl"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/invoke-factory&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;interceptor service-id="hivemind.LoggingInterceptor"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/service-point&amp;gt;&lt;br /&gt;&amp;lt;/module&amp;gt;&lt;/p&gt; &lt;p&gt;仔细看看这个配置文件就可以看出一些有趣的东西：&lt;br /&gt;service-point毫无疑问等于Spring中的bean。（Howard同志一向以长的配置名称闻名，这一点可以在Tapestry的配置文件中得到证实，不过比起Spring的超长package name和constant name，似乎又差了一点，呵呵），id, interface……等等，看来hlship完全不鼓励在这个Container中使用具体的类了，看看DTD文件的定义：&lt;/p&gt; &lt;p&gt;&amp;lt;service-point id=".." interface=".." &lt;br /&gt;&amp;nbsp;&amp;nbsp; [parameters-schema-id=".."]&lt;br /&gt;&amp;nbsp;&amp;nbsp; [parameters-occurs="unbounded |&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0..1 | 1 | 1..n | none"]&amp;gt;&lt;br /&gt;&amp;nbsp;[parameters-schema]&lt;br /&gt;&amp;nbsp;[create-instance]&lt;br /&gt;&amp;nbsp;[invoke-factory]&lt;br /&gt;&amp;nbsp;[interceptor]&lt;br /&gt;&amp;lt;/service-point&amp;gt;&lt;/p&gt; &lt;p&gt;确实没有class这个属性……这样做好还是不好？……不知道，完全面向接口的系统存在吗……这个问题暂时不想，以后再说。四个加减乘除的类的生成没什么好说的，看看&lt;br /&gt;&amp;lt;service-point id="Adder" interface="org.apache.hivemind.examples.Adder"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;create-instance class="org.apache.hivemind.examples.impl.AdderImpl"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;interceptor service-id="hivemind.LoggingInterceptor"/&amp;gt;&lt;br /&gt;&amp;lt;/service-point&amp;gt;&lt;br /&gt;的意思，应该是创建一个以org.apache.hivemind.examples.impl.AdderImpl的实例，从&amp;lt;create-instance&amp;gt;的DTD看来，他允许创建为primitive, singleton, threaded, pooled的形式。默认应该是每次调用创建一个实例吧，我猜。然后用一个拦截器（LogginInterceptor）来处理。&lt;/p&gt; &lt;p&gt;这里又发现了一个比Spring要方便的地方，interceptor可以直接定义在（我都不知道怎么说了，用Bean还是service-point?)Component的内部，用Spring的话还得另外建立一个新的Bean，然后指定Advice的作用域，如果系统中只有一两处需要的话，多一个Bean的配置显得有点不雅。记得xWork也是这样定义interceptor的。&lt;/p&gt; &lt;p&gt;下面的按照工厂形式创建实例有点意思。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;service-point id="Calculator" interface="org.apache.hivemind.examples.Calculator"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;invoke-factory&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Most properties are autowired by the BuilderFactory --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;construct class="org.apache.hivemind.examples.impl.CalculatorImpl"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/invoke-factory&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;interceptor service-id="hivemind.LoggingInterceptor"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/service-point&amp;gt;&lt;/p&gt; &lt;p&gt;先看看CaculatorImpl的实现：&lt;br /&gt;public class CalculatorImpl implements Calculator {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Adder _adder;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Subtracter _subtracter;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Multiplier _multiplier;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Divider _divider;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double add(double arg0, double arg1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _adder.add(arg0, arg1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...后面的减乘除就不写了，类似&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...一堆的setter/getter就不写了&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;&lt;br /&gt;刚开始诧异了一下，在我感觉里，这里怎么说应该有个输入参数的地方，就象下面：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;lt;invoke-factory&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;construct class="org.apache.hivemind.examples.impl.CalculatorImpl"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;set-property name="adder" ref="Adder" /&amp;gt;&lt;br /&gt;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;lt;/construct&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/invoke-factory&amp;gt;&lt;/p&gt; &lt;p&gt;看看他的注释：Most properties are autowired by the BuilderFactory，看样子他在BuilderFactory中默认将同id的service-point注入到construct中去了，这种便利是否必要？毕竟遍历一个类的set方法，判断方法所需的类型，寻找registry中的service-point然后注入，这都是需要代价的……没想清楚，暂时放下。&lt;/p&gt; &lt;p&gt;题外话：我没有一直跟随HiveMind的版本变化，但在我的记忆中，1.0的某个rc版本将配置文件换成了Howard同志自己发明的Simple Data Language，其实就是hlship根据JavaCC自己组织了一套语法，然后将所有的配置文件用这种语法改写……没多少日子这个东西就被pass掉了。直到现在我还怀疑他做这件事情的动机，目前最能让我觉得有趣的一种解释是：Howard看到JavaCC很强大，能够很轻易的定义一种新的语法并解析，具备Tapestry全新的创意的Howard，一时头脑发热就加入了这个东东……呵呵&lt;/p&gt; &lt;p&gt;HiveMind还有一些其他的特性，比如系统所有配置的文档生成（这个功能Spring加上就好了）以及其他的一些方便的特性。Howard一再强调HiveMind是一个Micro Kernel的框架，但在我看来，他是一个新的，可能更加方便的，完全面向接口的，基于IoC的容器。&lt;/p&gt;&lt;img src ="http://webuc.net/mechiland/aggbug/1890.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>
