﻿<?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-Read Sean-随笔分类-On Java</title><link>http://www.blogjava.net/sean/category/35.html</link><description>Read me, read Sean.</description><language>zh-cn</language><lastBuildDate>Sun, 09 Mar 2014 10:25:17 GMT</lastBuildDate><pubDate>Sun, 09 Mar 2014 10:25:17 GMT</pubDate><ttl>60</ttl><item><title>IntelliJ IDEA 常用快捷键</title><link>http://www.blogjava.net/sean/archive/2014/03/09/410781.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 09 Mar 2014 05:38:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2014/03/09/410781.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/410781.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2014/03/09/410781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/410781.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/410781.html</trackback:ping><description><![CDATA[<br />
整理一下 IntelliJ IDEA 最常用的快捷键，按照便于记忆的方式排列：<br />
<br />
<pre>
Ctrl-N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class...&nbsp;(find&nbsp;by&nbsp;name)
Ctrl-Shift-N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File...&nbsp;(find&nbsp;by&nbsp;name)
Ctrl-Shift-Alt-N&nbsp;&nbsp;&nbsp;&nbsp;Symbol...&nbsp;(find&nbsp;by&nbsp;name)
Ctrl-G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Line...&nbsp;(goto&nbsp;line)
Ctrl-H&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;hierarchy&nbsp;(hierarchy)
Ctrl-Shift-H&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;hierarchy&nbsp;(hierarchy)
Ctrl-Alt-H&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call&nbsp;hierarchy&nbsp;(hierarchy)
Ctrl-Q&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quick&nbsp;documentation
Ctrl-Alt-I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Auto-indent&nbsp;lines&nbsp;(indent)
Ctrl-Alt-L&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reformat&nbsp;code&nbsp;(line&nbsp;up)
Ctrl-Alt-O&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Optimize&nbsp;imports&nbsp;(optimize)
Ctrl-/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Comment&nbsp;with&nbsp;line&nbsp;comment&nbsp;(//)
Ctrl-Shift-/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Comment&nbsp;with&nbsp;block&nbsp;comment&nbsp;(/*...*/)
Ctrl-W&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Select&nbsp;word&nbsp;or&nbsp;block&nbsp;(word)
Ctrl-D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Copy&nbsp;line&nbsp;(duplicate&nbsp;line,&nbsp;yyp)
Ctrl-X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cut&nbsp;line&nbsp;(dd)
Ctrl-U&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Uppercase/lowercase&nbsp;(upper)
Ctrl-J&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Insert&nbsp;live&nbsp;template
Ctrl-Alt-J&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Surround&nbsp;with&nbsp;live&nbsp;template
Ctrl-Alt-T&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Surround&nbsp;with&nbsp;(template)
Ctrl-Shift-J&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Join&nbsp;lines&nbsp;(join)
Ctrl-E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Recent&nbsp;files&nbsp;(editions)
Ctrl-Shift-E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Recently&nbsp;changed&nbsp;files&nbsp;(editions)
Alt-Shift-C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Recent&nbsp;changes&nbsp;(changes)
Ctrl-B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Delcaration
Ctrl-Shift-B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;declaration
Ctrl-Alt-B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Implementation(s)
Ctrl-P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parameter&nbsp;info&nbsp;(parameter)
Ctrl-Space&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Basic&nbsp;completion
Ctrl-Shift-Space&nbsp;&nbsp;&nbsp;&nbsp;Smart&nbsp;completion
Ctrl-Alt-Space&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Completion&nbsp;lookup
Alt-Enter&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Auto-complete
Alt-Insert&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Generate...
Ctrl-Shift-Up/Down&nbsp;&nbsp;Move&nbsp;statement&nbsp;up/down
Alt-Shift-Up/Down&nbsp;&nbsp;&nbsp;Move&nbsp;line&nbsp;up/down
Ctrl-Up/Down&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Scroll&nbsp;up/down
Alt-Up/Down&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Previous/next&nbsp;method
F2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next&nbsp;highlighted&nbsp;error
Shift-F2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Previous&nbsp;highlighted&nbsp;error
Ctrl-F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Find
Ctrl-R&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Replace
F3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next&nbsp;match
Shift-F3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Previous&nbsp;match
F4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Jump&nbsp;to&nbsp;source
Ctrl-Alt-Shift-T&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;this
F5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;copy
F6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;move
Ctrl-F6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;change&nbsp;signature
Shift-F6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;rename
Alt-Delete&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;safe&nbsp;delete
Ctrl-Alt-V&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;extract&nbsp;variable
Ctrl-Alt-F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;extract&nbsp;field
Ctrl-Alt-P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;extract&nbsp;parameter
Ctrl-Alt-M&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;extract&nbsp;method
Ctrl-Alt-N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Refactor&nbsp;inline
</pre>
<img src ="http://www.blogjava.net/sean/aggbug/410781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2014-03-09 13:38 <a href="http://www.blogjava.net/sean/archive/2014/03/09/410781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] Windows环境下Apache最基本的调优方法</title><link>http://www.blogjava.net/sean/archive/2011/08/02/355618.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Tue, 02 Aug 2011 13:04:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2011/08/02/355618.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/355618.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2011/08/02/355618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/355618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/355618.html</trackback:ping><description><![CDATA[<p>
今天远程支持同事在Windows环境调优Apache服务器性能，记录在此，供需要的朋友参考。</p>
<p>
Java EE应用，同时部署在两个Tomcat(5.5.27)实例上，前面放了个Apache(httpd-2.2.19-win32-x86-no_ssl)，通过mod_jk(1.2.32)做负载均衡，同一台物理服务器，操作系统为64位的Windows Server 2003 SP2。现象是60+客户端，平均每个客户端每秒请求数2次，单个请求正常响应时间在500ms以内，即每秒冲进来120个请求，并发量最多在60上下，Apache就已不堪"重"负，静态资源响应时间都超过10s，同时Tomcat和数据库服务器均正常。凭我的经验，同样的压力直接压到Tomcat也不至于这么难看。看来问题出在Apache。</p>
<p>
首先修改httpd.conf配置文件，打开status模块：</p>
<p>
<code>
LoadModule status_module modules/mod_status.so<br/>
&lt;Location /status&gt;<br/>
&nbsp;&nbsp;SetHandler server-status<br/>
&nbsp;&nbsp;Order deny,allow<br/>
&nbsp;&nbsp;Deny from all<br/>
&nbsp;&nbsp;Allow from 127.0.0.1 #需要的话也可放开为all<br/>
&lt;/Location&gt;
</code></p>
<p>
这样我们就能通过/status页面查看服务器当前的状态信息，结果观察到worker(即线程)数仅为64！坑爹啊！难怪撑不住。我记得以前Windows下面的Apache默认线程数没这么小的。找准问题，接下来就好办了：</p>
<p>
<code>
&lt;IfModule mpm_winnt.c&gt;<br/>
&nbsp&nbsp;ThreadsPerChild 300<br/>
&nbsp;&nbsp;MaxRequestsPerChild 0<br/>
&lt;/IfModule&gt;
</code></p>
<p>
稍微解释一下：mpm_winnt.c是Apache为Windows NT提供的MPM (Multi-Processing Module)，对应到Linux环境下，则有prefork.c(多进程/每进程1个线程)和worker.c(多进程+多线程)两种MPM可选。Windows下面只会有父与子两个进程，因此单个子进程能同时起多少线程(ThreadsPerChild)就成了调优的关键。另一个参数MaxRequestsPerChild的含义是单个子进程累计最多处理到少个请求，超过该值则退出重启，这是出于防止内存泄露慢慢拖垮整个服务器而做的防御性措施，0表示不做此限制。</p>
<p>
新配置上线后，客户端数量顺利冲上200+。Case closed.</p>
<img src ="http://www.blogjava.net/sean/aggbug/355618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2011-08-02 21:04 <a href="http://www.blogjava.net/sean/archive/2011/08/02/355618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>"上海"是如何变成"涓婃捣"的？</title><link>http://www.blogjava.net/sean/archive/2011/03/29/347243.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Tue, 29 Mar 2011 15:50:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2011/03/29/347243.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/347243.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2011/03/29/347243.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/347243.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/347243.html</trackback:ping><description><![CDATA[<br/ />
<p>今天帮同事解决一个邮件乱码的问题，简记于此。
</p>
<p>邮件正文就不贴了，有一段从上下文判断明显应该是"上海"，却显示成了"涓..."，于是自然而然的拿出"上"字和"涓"字来分析。

</p>
<p>通过简单的Groovy脚本对这两个汉字分别按gbk和utf-8编码，并将得到的byte[]转换成二进制表示输出如下：

</p>
<p><code>
== 上 ==<br/ />
11001001 11001111<br/ />   
11100100 10111000 10001010 <br/ />   
== 涓 ==<br/ />
11100100 10111000<br/ />   
11100110 10110110 10010011<br/ />    
</code>
</p>
<p>注意"上"字的第2排前两组和"涓"字第1排的两组byte正好相同，于是问题迎刃而解，乱码是由于邮件以utf-8编码后被错误的以gbk解码（随后又重新编码成utf-8）造成的。</p>
<p>关键代码：</p>
<p><code>
void showBytes(String input) {<br/ />
&nbsp;&nbsp;println("== " + input + " ==")<br/ />
&nbsp;&nbsp;b = input.getBytes("gbk")<br/ />
&nbsp;&nbsp;b.each { print Integer.toBinaryString(it).substring(24) + ' ' }<br/ />
&nbsp;&nbsp;println()<br/ />
&nbsp;&nbsp;b = input.getBytes("utf8")<br/ />
&nbsp;&nbsp;b.each { print Integer.toBinaryString(it).substring(24) + ' ' }<br/ />
&nbsp;&nbsp;println()<br/ />
}<br/ />
</code>
</p>




<img src ="http://www.blogjava.net/sean/aggbug/347243.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2011-03-29 23:50 <a href="http://www.blogjava.net/sean/archive/2011/03/29/347243.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何让统一版本的Eclipse RCP应用同时支持多个平台</title><link>http://www.blogjava.net/sean/archive/2011/01/30/343769.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 30 Jan 2011 04:17:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2011/01/30/343769.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/343769.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2011/01/30/343769.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/343769.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/343769.html</trackback:ping><description><![CDATA[<br/ /><p>和Swing应用的直接跨平台不同，SWT/RCP应用要想同时支持不同平台，需要做些特殊的配置，不过并不复杂，记录在此，希望能帮到有需要的朋友。目前win32、32位Linux、64位Linux和Mac OS X基本上就覆盖了所有主流的桌面操作系统，本文将以同时支持这四种OS为例来进行讲解。</p>
<p>首先是下载对应版本的RCP框架在不同操作系统的插件，将它们放在同一个plugins目录，比如你可以用win32为基础，然后添加针对其他平台的如下插件: </p>
<p>org.eclipse.core.filesystem<br/ />org.eclipse.core.filesystem.win32.x86<br/ />org.eclipse.core.filesystem.linux.x86<br/ />org.eclipse.core.filesystem.linux.x86_64<br/ />org.eclipse.core.filesystem.macosx</p>
<p>org.eclipse.core.net<br/ />org.eclipse.core.net.win32.x86<br/ />org.eclipse.core.net.linux.x86</p>
<p>org.eclipse.core.resources<br/ />org.eclipse.core.resources.win32.x86</p>
<p>org.eclipse.equinox.launcher<br/ />org.eclipse.equinox.launcher.win32.win32.x86<br/ />org.eclipse.equinox.launcher.gtk.linux.x86<br/ />org.eclipse.equinox.launcher.gtk.linux.x86_64<br/ />org.eclipse.equinox.launcher.carbon.macosx</p>
<p>org.eclipse.equinox.security<br/ />org.eclipse.equinox.security.win32.x86<br/ />org.eclipse.equinox.security.macosx</p>
<p>org.eclipse.swt<br/ />org.eclipse.swt.win32.win32.x86<br/ />org.eclipse.swt.gtk.linux.x86<br/ />org.eclipse.swt.gtk.linux.x86_64<br/ />org.eclipse.swt.carbon.macosx</p>
<p>接下来将不同平台下的eclipse可执行文件(Windows下面是eclipe.exe，Linux下是eclipse，Mac OS X下面是Eclipse.app)放到不同的子目录下，当然，如果你的RCP应用有别的名称，也可以重命名eclipse可执行文件，按照不同平台的规范更换图标，然后修改.ini文件让它的-startup和-startup.libraray参数指向相对路径中正确版本的插件即可。</p>
<p>最后分享一下我们软件部署的机制: 按照前面介绍的方式打包的应用程序，交到用户手里并不是很友好，因为需要他/她自己再做一次判断，当前的操作系统是什么，然后打开不同的目录去点击不同的可执行文件。我们的做法是单独提供一个Swing程序，在客户端自动判断OS，然后自动调用不同版本的可执行文件，同时，这个Swing程序被做成Java Web Start，把整个RCP客户端的下载和同步也处理掉，这样，对用户而言，整个过程就透明了，只需要一个JNLP，剩下的工作完全自动化。</p>

<img src ="http://www.blogjava.net/sean/aggbug/343769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2011-01-30 12:17 <a href="http://www.blogjava.net/sean/archive/2011/01/30/343769.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java命令行实用工具jps和jstat</title><link>http://www.blogjava.net/sean/archive/2011/01/27/343620.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Thu, 27 Jan 2011 04:04:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2011/01/27/343620.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/343620.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2011/01/27/343620.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/343620.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/343620.html</trackback:ping><description><![CDATA[<br/ /><p>在Linux或其他UNIX和类UNIX环境下，ps命令想必大家都不陌生，我相信也有不少同学写过 ps aux | grep java | grep -v grep | awk '{print $2}' 这样的管道命令来找出Java进程的pid。常言道，Java并非真的"跨平台"，它自己就是平台。作为平台，当然也有些基本的工具，让我们可以用更简单、更统一，同时又是非侵入的方式来查询进程相关信息。今天我们就来认识一下其中的两个。</p>
<p><strong>jps</strong></p>
<p>顾名思义，它对应到UNIX的ps命令。用法如下: </p>
<p>jps [ options ] [ hostid ]</p>
<p>其中，options可以用 -q (安静) -m (输出传递给main方法的参数) -l (显示完整路径) -v (显示传递给JVM的命令行参数) -V (显示通过flag文件传递给JVM的参数) -J (和其他Java工具类似用于传递参数给命令本身要调用的java进程)；hostid是主机id，默认localhost。</p>
<p><strong>jstat</strong></p>
<p>用于输出给定java进程的统计信息。用法如下: </p>
<p>jstat -options 可以列出当前JVM版本支持的选项，常见的有 -class (类加载器) -compiler (JIT) -gc (GC堆状态) -gccapacity (各区大小) -gccause (最近一次GC统计和原因) -gcnew (新区统计) -gcnewcapacity (新区大小) -gcold (老区统计) -gcoldcapacity (老区大小) -gcpermcapacity (永久区大小) -gcutil (GC统计汇总) -printcompilation (HotSpot编译统计)</p>
<p>假定你要监控的Java进程号是12345，那么<br />
jstat -gcutil -t 12345 200 300 即可每200毫秒连续打印300次带有时间戳的GC统计信息。</p>
<p>简单解释一下: -gcutil是传入的option；必选，-t是打印时间戳，是以目标JVM启动时间为起点计算的，可选；12345是vmid/pid，和我们从jps拿到的是一样的，必选；200是监控时间间隔，可选，不提供就意味着单次输出；300是最大输出次数，可选，不提供且监控时间间隔有值的话，就是无限期打印下去。</p>
<p>具体输出明细的解释请参考官方文档 <a href="http://download.oracle.com/javase/6/docs/technotes/tools/share/jstat.html" target="_blank">http://download.oracle.com/javase/6/docs/technotes/tools/share/jstat.html</a></p>

<img src ="http://www.blogjava.net/sean/aggbug/343620.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2011-01-27 12:04 <a href="http://www.blogjava.net/sean/archive/2011/01/27/343620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Scala解Hanoi塔</title><link>http://www.blogjava.net/sean/archive/2009/11/23/303374.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Mon, 23 Nov 2009 11:20:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/11/23/303374.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/303374.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/11/23/303374.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/303374.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/303374.html</trackback:ping><description><![CDATA[<p>到处吹嘘Scala很长时间了，却一直没有在自己的blog上增加过任何相关内容，今天就来补一补。当然，Scala的基本特性就不多废话了，网上已经有相当多的资料，如果懒得google，只想看完本文，那么你只需要知道它是一门以JVM为目标运行环境的静态编程语言(当然，Scala官方也有.NET版，但已不是其重点)，同时具备面向对象和函数式编程语言的特点。本文将通过一个简单的示例，展示Scala的FP能力，其中十分heavy的用到了implicit隐式转换和模式匹配。</p>
<p>代码是从guithub的gist上抄的，简单改了改，原始代码见: <a href="http://gist.github.com/66925" target="_blank">http://gist.github.com/66925</a></p>
<p>
</p>
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;scala.reflect.Manifest<br />
&nbsp;&nbsp;<br />
def&nbsp;simpleName(m:Manifest[_]):String&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;{<br />
&nbsp;&nbsp;val&nbsp;name&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;m.toString<br />
&nbsp;&nbsp;name.substring(name.lastIndexOf(</span><span style="color: #000000; ">'</span><span style="color: #000000; ">$</span><span style="color: #000000; ">'</span><span style="color: #000000; ">)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />
}<br />
&nbsp;&nbsp;<br />
trait&nbsp;Num<br />
</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Succ[Pre</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num]&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;Num<br />
</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;_1&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;Num<br />
type&nbsp;_2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Succ[_1]<br />
type&nbsp;_3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Succ[_2]<br />
type&nbsp;_4&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Succ[_3]<br />
&nbsp;<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Move[N</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num,A,B,C]()<br />
<br />
implicit&nbsp;def&nbsp;move1[A,B,C](implicit&nbsp;a:Manifest[A],&nbsp;b:Manifest[B])&nbsp;:&nbsp;Move[_1,A,B,C]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;{<br />
&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Move&nbsp;from&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;simpleName(a)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;to&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;simpleName(b))<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; "><br />
}<br />
&nbsp;<br />
implicit&nbsp;def&nbsp;moveN[P</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num,A,B,C](implicit&nbsp;m1:Move[P,A,C,B],&nbsp;m2:Move[_1,A,B,C],&nbsp;m3:Move[P,C,B,A])&nbsp;:&nbsp;Move[Succ[P],A,B,C]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; "><br />
&nbsp;&nbsp;<br />
def&nbsp;run[N</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num,A,B,C](implicit&nbsp;m:Move[N,A,B,C])&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; "><br />
&nbsp;&nbsp;<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Left()<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Center()<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Right()<br />
&nbsp;&nbsp;<br />
run[_3,Left,Right,Center]<br />
</span></div>
<p>&nbsp;</p>
<p>这段代码解决的是经典的汉诺塔问题，通过一根中柱，将左柱上64个大小依次叠加的圆盘全部移动到右柱，要求整个过程中每次只能移动一个圆盘，且每个圆盘只能独立占据一根柱子或是叠加在比自身更大的圆盘上。</p>
<p>简单分析一下就知道，这是一个递归问题(FP的英雄特长)：</p>
<ul>
    <li>当只有1个圆盘时，不用通过中柱，直接可以从左柱移动到右柱；</li>
    <li>当有2个圆盘时，将小盘移动到中柱，剩下的大盘移动到右柱，再从中柱把小盘移动到右柱；</li>
    <li>当有3个圆盘时，先移动2个圆盘到中柱，再移动大盘到右柱，再移动2个圆盘到右柱；</li>
    <li>...</li>
</ul>
<p>很容易发现一个pattern，那就是移动N(N&gt;1)个圆盘，可以通过以下三个步骤：</p>
<ol>
    <li>移动N-1个圆盘，从左柱到中柱；</li>
    <li>移动剩下的1个圆盘，从左柱到右柱；</li>
    <li>移动N-1个圆盘，从中柱到右柱。</li>
</ol>
<p>在解释代码之前，先说说Scala的implicit隐式转换，这是一个非常powerful的idea，当Scala编译器发现类型不匹配，它不会直接fail，而是尝试从代码中指定的，在scope内的implicit转换定义，来替换问题对象或表达式以满足类型要求，当然，为了避免歧义，同一时刻Scala需要找到唯一的一个满足条件的implicit定义。</p>
<p>我们的代码首先定义了一个取得友好类名的方法，不去深究它，然后定义了一个正整数的序列，也不去深究它了，你只需要当作他们是正整数就好，接触过FP的同学应该对此类定义不陌生，接下来定义了如下3个支持implicit传入参数的方法：</p>
<ol>
    <li>implicit def move1[A,B,C](implicit a:Manifest[A], b:Manifest[B]) : Move[_1,A,B,C]</li>
    <li>implicit def moveN[P&lt;:Num,A,B,C]( implicit <br />
    m1:Move[P,A,C,B], <br />
    m2:Move[_1,A,B,C], <br />
    m3:Move[P,C,B,A]<br />
    ) : Move[Succ[P],A,B,C]</li>
    <li>def run[N&lt;:Num,A,B,C](implicit m:Move[N,A,B,C])</li>
</ol>
<p>含义分别是：</p>
<ol>
    <li>当需要Move[_1,A,B,C]值时，可以找我帮忙(我有个side-effect，那就是输出移动指令)；</li>
    <li>当需要Move[Succ[P],A,B,C]时，可以找我帮忙；</li>
    <li>运行我，我接受Move[N,A,B,C]类型的参数。</li>
</ol>
<p>简单说明：Scala用[]表示类型参数，区别于Java的&lt;&gt;，另外，Scala的类型声明在变量/函数定义之后。Move[_,A,B,C]的含义是通过C，从A移动圆盘到B。</p>
<p>我们来模拟运行一下，为了演示效果，用一个中等复杂的数目，3个圆盘，从Left移动到Right。</p>
<p>run[_3,Left,Right,Center]，对应Move[Succ[_2],Left,Right,Center]，于是展开成三个Move：</p>
<p>Move[_2,Left,Center,Right]即Move[Succ[_1],Left,Center,Right]<br />
Move[_1,Left,Right,Center]<br />
Move[_2,Center,Right,Left]即Move[Succ[_1],Center,Right,Left]<br />
</p>
<p>然后继续展开Move[_2,Left,Center,Right]和Move[_2,Center,Right,Left]，得到：</p>
<p>Move[_1,Left,Right,Center]<br />
Move[_1,Left,Center,Right]<br />
Move[_1,Right,Center,Left]<br />
--------------------------<br />
Move[_1,Left,Right,Center]<br />
--------------------------<br />
Move[_1,Center,Left,Right]<br />
Move[_1,Center,Right,Left]<br />
Move[_1,Left,Right,Center]<br />
</p>
<p>这个时候已经全部都匹配Move[_1,A,B,C]，于是我们很容易得到以下输出：</p>
<p>Move from Left to Right<br />
Move from Left to Center<br />
Move from Right to Center<br />
Move from Left to Right<br />
Move from Center to Left<br />
Move from Center to Right<br />
Move from Left to Right<br />
</p>
<p>希望本文能带给Scala初学者一些感性认识和启发。</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/sean/aggbug/303374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2009-11-23 19:20 <a href="http://www.blogjava.net/sean/archive/2009/11/23/303374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] Spring+Hibernate之“暴力”update</title><link>http://www.blogjava.net/sean/archive/2009/01/29/252704.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Thu, 29 Jan 2009 08:54:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/01/29/252704.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/252704.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/01/29/252704.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/252704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/252704.html</trackback:ping><description><![CDATA[
		<br />先简单介绍一下问题的语境。<br /><br />手头有个开发了3年的Spring+iBATIS应用（经典三层架构），最近尝试用Hibernate实现原有SQLMap版的部分CRUD操作。除开混合事务和其他一些底层配置细节(如TransactionAwareDataSource、禁用lazy-load等)之外，最大的一个"pattern-mismatch"是：Model层和持久层采用了dirty flag机制，即每次INSERT和UPDATE操作，都会根据每个字段的dirty与否决定是否参加INSERT/UPDATE，而这些dirty flag可以被外部重置，所以业务层的代码，经常可以看到类似这样的pattern：<br /><br />1- new一个model类并setId() （或者在已有的model上重置dirty flag）<br />2- set需要update的字段（通常都只是部分字段）<br />3- 丢给DAO层去update<br /><br />最终的效果是某张表某个ID的某条记录的某些字段被更新了，而其他字段不受影响，这就是我在标题中提到的所谓"暴力"update，虽不elegant，但却也简单实用，至少很"直接"。<br /><br />为了让Hibernate版的DAO（默认除Trasient之外全体字段参加INSERT和UPDATE）继续支持这样的"use-pattern"，除了按照Hibernate的习惯去配置映射和SessionFactory等之外，我们需要做一些额外的工作：<br /><br />1- 在BO/Entity类上追加注解<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">@org.hibernate.annotations.Entity(dynamicInsert</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">, dynamicUpdate</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">)</span></div><br />2- 实现org.hibernate.Interceptor接口的findDirty()方法，Hibernate提供了一个EmptyInterceptor可以作为起点，方法签名如下：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">[] findDirty(<br />    Object entity, <br />    Serializable id, <br />    Object[] currentState, <br />    Object[] previousState, <br />    String[] propertyNames, <br />    Type[] types<br />);</span></div>返回的int[]包含所有应该被认为是dirty的字段索引，返回null表示默认处理，传入的entity是持久对象，字段列表会通过propertyNames参数传给你。<br /><br />3- 注入到Spring的Application Context中，类似这样：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="findDirtyInterceptor"</span><span style="color: rgb(255, 0, 0);"> class</span><span style="color: rgb(0, 0, 255);">="gao.sean.hybrid.interceptor.FindDirtyInterceptor"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">bean </span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="sessionFactory"</span><span style="color: rgb(255, 0, 0);"><br />    class</span><span style="color: rgb(0, 0, 255);">="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />    <br />    </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="entityInterceptor"</span><span style="color: rgb(0, 0, 255);">&gt;&lt;</span><span style="color: rgb(128, 0, 0);">ref </span><span style="color: rgb(255, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">="findDirtyInterceptor"</span><span style="color: rgb(0, 0, 255);">/&gt;&lt;/</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />    <br /></span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">&gt;</span></div><br />在这样的配置下，业务层的代码就可以继续"暴力"update了。<br /><br /><img src ="http://www.blogjava.net/sean/aggbug/252704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2009-01-29 16:54 <a href="http://www.blogjava.net/sean/archive/2009/01/29/252704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] Spring 2.5.6新特性之packagesToScan</title><link>http://www.blogjava.net/sean/archive/2009/01/29/252685.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Wed, 28 Jan 2009 18:59:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/01/29/252685.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/252685.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/01/29/252685.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/252685.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/252685.html</trackback:ping><description><![CDATA[
		<br />如果你使用早前版本的Spring，又恰好采用了Annotation注解方式(而非传统XML方式)配置Hibernate对象关系映射，那么在通过org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean配置sessionFactory时，你一定对annotatedClasses、annotatedPackages有一种说不出的胸闷的感觉，如此以高配置性见长的Spring，怎么在这一个小小的环节上就不能做得再灵活些呢，一定要一个个手写Class路径么？<br /><br />估计有不少人无奈选择了从AnnotationSessionFactoryBean继承一个自定义的子类，自己实现扫描逻辑，找出@Entity注解过的类清单配置进去。<br /><br />Spring 2.5.6里有个不怎么起眼的改进，那就是在AnnotationSessionFactoryBean上增加了一个新的方法：<br /><a target="_blank" title="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html#setPackagesToScan(java.lang.String[])" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html#setPackagesToScan%28java.lang.String%5B%5D%29">setPackagesToScan(String[] packagesToScan)</a><br /><br />有了这个方法，我们不再需要自己动手去实现实体类的扫描了，直接在Spring配置文件中AnnotationSessionFactoryBean这个section上增加类似如下的一个property即可(假定你需要加载的实体类所在的包名match这个字符串"com.**.bo")：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="packagesToScan"</span><span style="color: rgb(255, 0, 0);"> value</span><span style="color: rgb(0, 0, 255);">="com.**.bo"</span><span style="color: rgb(0, 0, 255);">/&gt;</span></div><br />你也可以以清单的方式指定多于1条的匹配字串，如：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="packagesToScan"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">list</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />        </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">com.abc.core.bo</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />        </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">com.abc.auditing.bo</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">list</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">&gt;</span></div><br /><img src ="http://www.blogjava.net/sean/aggbug/252685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2009-01-29 02:59 <a href="http://www.blogjava.net/sean/archive/2009/01/29/252685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>easyb - Getting Started</title><link>http://www.blogjava.net/sean/archive/2009/01/04/249798.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 04 Jan 2009 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/01/04/249798.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/249798.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/01/04/249798.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/249798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/249798.html</trackback:ping><description><![CDATA[
		<br />从某种意义上讲，easyb就是Groovy版的RSpec，是一个基于"BDD: Behavior-Driven Development"思维方式的测试框架。其作者Andrew Glover是《Groovy in Action》一书的合著者之一。项目的主页在：<br /><br /><a target="_blank" title="http://easyb.org/" href="http://easyb.org/">http://easyb.org/</a><br /><br />不多废话了，上代码，一个story大概长成这个样子（为了方便大家理解，举一个无比弱智的例子）：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">scenario </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">1+1应该等于2</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">, {<br />    given </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">a和b分别等于1</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">, {<br />      a </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />      b </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />    }<br />    when </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">c是a+b的和</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">, {<br />      c </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> a </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> b<br />    }<br />    then </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">c应该等于2</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">, {<br />      c.shouldBe </span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);"><br />    }<br />}<br /></span></div><br />如何在Eclipse环境下跑这段story脚本？请参考官方文档：<br /><a target="_blank" title="http://code.google.com/p/easyb/wiki/ConfiguringEclipseToRunEasyb" href="http://code.google.com/p/easyb/wiki/ConfiguringEclipseToRunEasyb">http://code.google.com/p/easyb/wiki/ConfiguringEclipseToRunEasyb</a><br /><br />最后你的输出应该类似：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Running first easyb story (FirstEasybStory.groovy)<br />Scenarios run: </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">, Failures: </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">, Pending: </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">, Time Elapsed: </span><span style="color: rgb(0, 0, 0);">0.629</span><span style="color: rgb(0, 0, 0);"> sec<br /><br /></span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"> behavior run with no failures<br /></span></div><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/249798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2009-01-04 22:28 <a href="http://www.blogjava.net/sean/archive/2009/01/04/249798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 3.0前瞻</title><link>http://www.blogjava.net/sean/archive/2008/12/27/248655.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sat, 27 Dec 2008 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/12/27/248655.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/248655.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/12/27/248655.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/248655.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/248655.html</trackback:ping><description><![CDATA[
		<br />周末花时间看了Rick Evans在London Spring User Group (LSUG)关于Spring 3.0介绍的视频，地址在这里：<br /><a target="_blank" title="http://java.dzone.com/videos/a-look-forward-spring-30" href="http://java.dzone.com/videos/a-look-forward-spring-30">http://java.dzone.com/videos/a-look-forward-spring-30</a><br /><br />根据Rick的介绍，Spring 3.0将于明年2月中旬正式发布，其中比较重要的两个亮点是：<br /><br />1- JDK 5将成为Spring 3.0的最低要求，因此很多遗留代码得以重构，更加清晰;<br />2- 引入了新的Spring Expression Language (SPEL)用于描述XML和Annotation中的配置信息。<br />（Rick还用了大量篇幅介绍Spring 3.0如何在API和配置层面支持REST，不过这不在我兴趣范围内）<br /><br />除了上述两大亮点，还有如下一些值得一提的变化：<br /><br />1- 去掉了Commons Attributes，减少了很多相关依赖;<br />2- 不再支持Struts 1.x;<br />3- 全面转向Listener-style的context加载方式;<br />4- 源码组织更加模块化，每个子模块都是独立项目;<br />5- 构建环境抛弃Maven，转为使用ANT+Ivy; (笔者非常赞成的一个变化)<br />6- 源码库由CVS全面转向Subversion。("逃离"CVS是大势所趋？)<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/248655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-12-27 17:55 <a href="http://www.blogjava.net/sean/archive/2008/12/27/248655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] 修改Java程序系统默认字体</title><link>http://www.blogjava.net/sean/archive/2008/10/24/236363.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Fri, 24 Oct 2008 03:36:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/10/24/236363.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/236363.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/10/24/236363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/236363.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/236363.html</trackback:ping><description><![CDATA[
		<br />实在受不了在中文Windows下Java(Swing)程序默认的字体，那叫一个难看。如果你和我一样，那么希望下面的小贴士可以帮到你（以JDK 1.5.0为例）：<br /><br />1- 找到JRE目录，如果你安装的是JDK，那么在JDK的目录下可以找到jre子目录，就是它了；如果你安装的JRE，那么默认应该在Program Files\Java\jre1.5.0_...。<br />2- 进入JRE目录下的lib文件夹，你应该可以看到很多fontconfig开头的文件，找到fontconfig.properties.src，拷贝一份，重命名为fontconfig.properties。<br />3- 打开fontconfig.properties，你会看到一大堆字体相关的配置，找到allfonts.chinese-ms936这一条（通常在最前面），可以看到默认设置为SimSun，修改这个配置，选填你需要的字体名称即可，如"Courier New"、"Consolas"等。<br /><br />更详细的配置，参考：<br /><a target="_blank" title="http://java.sun.com/j2se/1.5.0/docs/guide/intl/fontconfig.html" href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/fontconfig.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/fontconfig.html</a><br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/236363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-10-24 11:36 <a href="http://www.blogjava.net/sean/archive/2008/10/24/236363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iText vs FOP - Java动态生成PDF的两个选择</title><link>http://www.blogjava.net/sean/archive/2008/10/05/232577.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 05 Oct 2008 15:28:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/10/05/232577.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/232577.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/10/05/232577.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/232577.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/232577.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 由于工作需要，今天简单的看了一下Java生成PDF的相关资料。综合看下来，除了使用报表平台和OOo的附带工具，目前使用较为普遍的有两个途径：iText和Apache的FOP。从实际出发，我们分别看看两者处理带有中文的PDF的具体用法吧。&nbsp;&nbsp;<a href='http://www.blogjava.net/sean/archive/2008/10/05/232577.html'>阅读全文</a><img src ="http://www.blogjava.net/sean/aggbug/232577.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-10-05 23:28 <a href="http://www.blogjava.net/sean/archive/2008/10/05/232577.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] 使用Groovy处理邮件通知</title><link>http://www.blogjava.net/sean/archive/2008/08/27/225118.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Wed, 27 Aug 2008 10:55:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/08/27/225118.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/225118.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/08/27/225118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/225118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/225118.html</trackback:ping><description><![CDATA[
		<br />通过Groovy实现邮件通知（其实是转发到ANT）十分容易，先上代码：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 128);"> 1</span> <span style="color: rgb(0, 0, 0);">ant </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> AntBuilder()<br /></span><span style="color: rgb(0, 128, 128);"> 2</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 3</span> <span style="color: rgb(0, 0, 0);">def mail(subject, body, attachment </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> [dir:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,files:[]]) {<br /></span><span style="color: rgb(0, 128, 128);"> 4</span> <span style="color: rgb(0, 0, 0);">    ant.mail(mailhost:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">mail.com</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, mailport:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">1025</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, user:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">mailer</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, password:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">123</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, subject:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">${subject}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) {<br /></span><span style="color: rgb(0, 128, 128);"> 5</span> <span style="color: rgb(0, 0, 0);">        from(address:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">nobody@mail.com</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);"> 6</span> <span style="color: rgb(0, 0, 0);">        to(address:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">nobody@mail.com</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);"> 7</span> <span style="color: rgb(0, 0, 0);">        message(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">${body}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);"> 8</span> <span style="color: rgb(0, 0, 0);">        attachments() {<br /></span><span style="color: rgb(0, 128, 128);"> 9</span> <span style="color: rgb(0, 0, 0);">            </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (attachment.files) {<br /></span><span style="color: rgb(0, 128, 128);">10</span> <span style="color: rgb(0, 0, 0);">                fileset(dir:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">${attachment.dir}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) {<br /></span><span style="color: rgb(0, 128, 128);">11</span> <span style="color: rgb(0, 0, 0);">                    attachment.files.each {<br /></span><span style="color: rgb(0, 128, 128);">12</span> <span style="color: rgb(0, 0, 0);">                        include(name:it)<br /></span><span style="color: rgb(0, 128, 128);">13</span> <span style="color: rgb(0, 0, 0);">                    }<br /></span><span style="color: rgb(0, 128, 128);">14</span> <span style="color: rgb(0, 0, 0);">                }<br /></span><span style="color: rgb(0, 128, 128);">15</span> <span style="color: rgb(0, 0, 0);">            }<br /></span><span style="color: rgb(0, 128, 128);">16</span> <span style="color: rgb(0, 0, 0);">        }<br /></span><span style="color: rgb(0, 128, 128);">17</span> <span style="color: rgb(0, 0, 0);">    }<br /></span><span style="color: rgb(0, 128, 128);">18</span> <span style="color: rgb(0, 0, 0);">}<br /></span><span style="color: rgb(0, 128, 128);">19</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">20</span> <span style="color: rgb(0, 0, 0);">attachment </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> [dir:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/tmp</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, files:[</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">some.properties</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">some.sql</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">]]<br /></span><span style="color: rgb(0, 128, 128);">21</span> <span style="color: rgb(0, 0, 0);">mail(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Test mail message at ${new Date()}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">This is a test message.</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, attachment)<br /></span><span style="color: rgb(0, 128, 128);">22</span> <span style="color: rgb(0, 0, 0);"></span></div><br />这个简单的例子很好的展示了如下Groovy特性：<br />1- Groovy脚本可以不需要定义任何class，方法定义和实际调用也可以混在一起，十分顺手。<br />2- 定义变量不需要指定类型，只要赋值即可，不过运行期依然是强类型。<br />3- 方法参数可以有默认值。<br />4- List和Map的构建直接在语义层面提供支持，如[a:1,b:2]和[1,2]。<br />5- GString使得我们可以方便的在String中引用变量甚至是表达式，如"${a.b.c}"或"${new Date()}"。<br />6- 逻辑判断在true/false基础上有所扩展，[]（0个元素的List）和null均做false处理。<br />7- Closure支持，方便我们在外围代码处“当场”指定处理逻辑，省去了大多数在Java中需要匿名内部类来处理的麻烦，如attachment.files.each { .... }，只有一个传入参数时，可直接用it指代。<br />8- 与ANT的无缝集成，以及对Builder模式的良好支持，使得我们可以写出上述初看上去有些不可思议的代码。<br /><br />P.S. 虽然Groovy自己已经bundle了ANT，可以直接使用其中的绝大多数功能，不过为了调用ANT的mail task，还需要将ANT发行版中带有的ant-javamail.jar以及JavaMail API对应的jar包（可以从Sun网站下载）加到classpath。如果你的JDK版本低于6.0，还需要activation.jar。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/225118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-08-27 18:55 <a href="http://www.blogjava.net/sean/archive/2008/08/27/225118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] "When ANT is not enough"升级版 - Groovy to the rescue!</title><link>http://www.blogjava.net/sean/archive/2008/08/25/224246.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Mon, 25 Aug 2008 11:38:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/08/25/224246.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/224246.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/08/25/224246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/224246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/224246.html</trackback:ping><description><![CDATA[
		<br />
		<a target="_blank" title="http://www.blogjava.net/sean/archive/2008/08/20/223139.html" href="/sean/archive/2008/08/20/223139.html">前一篇随笔</a>提到目前计划系统学习Python和Groovy，有什么比实际使用更好的学习途径呢？1年多以前，我曾经在<a target="_blank" title="http://www.blogjava.net/sean/archive/2007/06/18/124859.html" href="/sean/archive/2007/06/18/124859.html">另一篇随笔</a>提到：当ANT不够用时，可以用JRuby+Antwrap，这是一个可行的方案，并且经过了长期实战的考验。不过Groovy可以做的更好（感兴趣的朋友可以和Antwrap版对照一下）：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 128);"> 1</span> <span style="color: rgb(0, 128, 0);">#</span><span style="color: rgb(0, 128, 0);">!/usr/bin/env groovy</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 2</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 3</span> <span style="color: rgb(0, 0, 0);">ant </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> new AntBuilder()<br /></span><span style="color: rgb(0, 128, 128);"> 4</span> <span style="color: rgb(0, 0, 0);">root </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">:pserver:cvsuser:password@10.10.10.1/cvsrepo/SampleProduct</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 5</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 6</span> <span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);"> checkout() {<br /></span><span style="color: rgb(0, 128, 128);"> 7</span> <span style="color: rgb(0, 0, 0);">    ant.cvs(cvsroot:root,command:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">checkout -A</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">package</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,dest:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,compressionlevel:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">9</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);"> 8</span> <span style="color: rgb(0, 0, 0);">}<br /></span><span style="color: rgb(0, 128, 128);"> 9</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">10</span> <span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);"> update() {<br /></span><span style="color: rgb(0, 128, 128);">11</span> <span style="color: rgb(0, 0, 0);">    ant.cvs(cvsroot:root,command:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">update -A -d</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">package</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,dest:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,compressionlevel:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">9</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">12</span> <span style="color: rgb(0, 0, 0);">}<br /></span><span style="color: rgb(0, 128, 128);">13</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">14</span> <span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);"> compile(project) {<br /></span><span style="color: rgb(0, 128, 128);">15</span> <span style="color: rgb(0, 0, 0);">    ant.javac(srcdir:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal/$project/src</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,destdir:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal/$project</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,target:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">1.5</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,encoding:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">GBK</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">16</span> <span style="color: rgb(0, 0, 0);">    ant.copy(todir:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal/$project</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) {<br /></span><span style="color: rgb(0, 128, 128);">17</span> <span style="color: rgb(0, 0, 0);">        fileset(dir:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal/$project/src</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) {<br /></span><span style="color: rgb(0, 128, 128);">18</span> <span style="color: rgb(0, 0, 0);">            exclude(name:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">**/*.java</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">19</span> <span style="color: rgb(0, 0, 0);">        }<br /></span><span style="color: rgb(0, 128, 128);">20</span> <span style="color: rgb(0, 0, 0);">    }<br /></span><span style="color: rgb(0, 128, 128);">21</span> <span style="color: rgb(0, 0, 0);">    ant.jar(destfile:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">build/$project.jar</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,basedir:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cvsoriginal/$project</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,manifest:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">MANIFEST.MF</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) {<br /></span><span style="color: rgb(0, 128, 128);">22</span> <span style="color: rgb(0, 0, 0);">        exclude(name:</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">src/**</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">23</span> <span style="color: rgb(0, 0, 0);">    }<br /></span><span style="color: rgb(0, 128, 128);">24</span> <span style="color: rgb(0, 0, 0);">}<br /></span><span style="color: rgb(0, 128, 128);">25</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">26</span> <span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">//</span><span style="color: rgb(0, 0, 0);"> to actually call your target<br /></span><span style="color: rgb(0, 128, 128);">27</span> <span style="color: rgb(0, 0, 0);">checkout root<br /></span><span style="color: rgb(0, 128, 128);">28</span> <span style="color: rgb(0, 0, 0);"></span></div><br />代码更紧凑，与Java的集成更无缝。只需要简单的培训，有Java基础的朋友就能上手，不必再额外学习和习惯Ruby的语法，不用gem install，也不用去monkey-patch个别文件来集成和打包Ant、Antwrap和JRuby，只需要一个groovy-all-x.x.x.jar加上自己的脚本即可轻松搞定。<br /><br />[2008-08-26 19:25:00 更新] 经过实际环境测试，原来JRuby(1.1)+Antwrap需要24分钟完成的构建，改用Groovy(1.5.6)后，仅需要16分钟，对于需要经常处理构建的项目和产品来说，这8分钟还是相当可观的。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/224246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-08-25 19:38 <a href="http://www.blogjava.net/sean/archive/2008/08/25/224246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>08年秋季学习计划</title><link>http://www.blogjava.net/sean/archive/2008/08/20/223139.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Tue, 19 Aug 2008 16:33:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/08/20/223139.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/223139.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/08/20/223139.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/223139.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/223139.html</trackback:ping><description><![CDATA[
		<br />从开始专心学习Java到现在，已经7年了，非常幸运的，在这7年中，除了1年的“半工半读”和1年的.NET项目，累积有5年都是从事的Java为主的应用开发，应该说，Java伴随我走过了从入行到站稳脚跟最关键的几年。从某种意义上讲，我应该感谢Java。<br /><br />然而，随着时间的推移，接触到的不同的东西越来越多，自己对不同问题的看法和解决问题的思路越来越成熟，Java虽然是全能型的语言，也变得越来越无法满足日常工作和娱乐的需要，在一些特定的场合，也越发别扭，有时我甚至会怀念学生时代的Pascal/Delphi和后来的C/C++。回过头去看自己，从刚入行时的Java fanboi，到现在这样一个pragmatist和purist的结合体，是多么有趣的转变。<br /><br />在过去的2年多，除了Java和.NET，陆陆续续接触到并有过简单使用经历的编程语言，有bash、PL/SQL、JavaScript、PHP、Perl、Ruby/JRuby、Scala、Python/Jython、Groovy等等，不过都没有系统的学习过，基本就是拿来主义，什么好用用什么，解决手里的问题为主。<br /><br />也许是工作性质的原因，日常要处理的非技术性任务越来越多，留给具体编程的时间现在一天比一天少，编程带来的乐趣和解决技术问题带来的快感，就显得十分珍贵。所以我下定决心一定要系统的学习1~2种和Java/.NET不同的编程语言。一开始这个选择并不容易，我曾经还<a target="_blank" title="http://twitter.com/laogao/statuses/853718837" href="http://twitter.com/laogao/statuses/853718837">半调侃式的和一个朋友讲：“Python, Ruby, Scala, Groovy, 一个都不能少”</a>，经过一段时间的权衡之后，还是比较自然的作出了最后的选择：Python和Groovy。<br /><br />Python这个选择其实并不难，留意Python这门语言，其实说起来也有差不多3年了，它完全符合“和Java/.NET不同的编程语言”这个条件，而且应用面很广，也十分成熟，功能也非常强大，加上大量现成的类库，能够胜任很多不同类型的编程任务。基本上这是一个不用任何思想斗争的选择。<br /><br />Groovy这个选择相对没有那么直接，至少在我真正用Groovy上手做一些东西之前，对它并没有特别的感觉，甚至质疑它存在的价值，因为有Jython和JRuby的选择，为什么一定要Groovy呢？到最近开始接触Groovy，才逐渐了解到它的出身（Groovy的作者受到Python的启发，不过后来Groovy发展的越来越接近Ruby），和它在“兼容”Java代码的前提下为Java语言带来的巨大的表达力提升。对于有Java基础的人而言，Groovy十分容易上手，而且可以帮助我们简化很多繁杂的任务，比如自动构建和自动化测试，而这正是我目前需要处理的。<br /><br />最后简单说说其他几个落选的原因（除了时间有限之外）：<br />bash - 目前掌握的基本够用，发现不够时，完全可以用Python代替。<br />PL/SQL - 基本很少使用了，偶尔需要维护，今后深入用的机会也不多。<br />JavaScript - 对“网页”版的编程语言可能有天生的偏见，尤其是作为Java fanboi，当然对它“盗用”Java这个名字是有意见的。<br />PHP - 用的机会很少，而且过于quick&amp;dirty，不是我喜欢的风格。<br />Perl - 虽然功能强大，但是感觉语法有些terse，不是很适应，能处理的任务，基本上Python也可以。<br />Ruby - 语法和设计理念还是有一些认同，但是对Unicode的支持和部署环境的支持都还不是很让人信服，另外，拿孟岩的话说，Ruby是一门魔幻语言，我不喜欢过于魔幻的东西，而更习惯具体直接的代码。<br />Scala - 也是一门和Java平台关系密切的语言，不过有些“学院派”，函数式编程固然是亮点，但短期内看不到太多的学习价值。<br /><br />所以，综上所述，最后再点一下题，08年秋季的学习计划是：系统学习Python和Groovy。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/223139.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-08-20 00:33 <a href="http://www.blogjava.net/sean/archive/2008/08/20/223139.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] JRuby 1.1.2 发布</title><link>http://www.blogjava.net/sean/archive/2008/05/28/203452.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Wed, 28 May 2008 04:08:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/05/28/203452.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/203452.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/05/28/203452.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/203452.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/203452.html</trackback:ping><description><![CDATA[
		<br />JVM下的Ruby语言实现JRuby发布1.1版的第二个升级版1.1.2，这个版本最主要关注的仍然是性能，值得一提的包括：<br />
1- 启动时间大大缩短。<br />
2- YAML标记解析速度提高100x以上。<br />
3- 方法调用在性能、线程和栈深度等方面的增强。<br />4- 其他bug。<br /><br />主页: <a target="_blank" title="http://jruby.codehaus.org/" href="http://jruby.codehaus.org/">http://jruby.codehaus.org/</a><br />下载: <a target="_blank" title="http://dist.codehaus.org/jruby/" href="http://dist.codehaus.org/jruby/">http://dist.codehaus.org/jruby/</a><br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/203452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-05-28 12:08 <a href="http://www.blogjava.net/sean/archive/2008/05/28/203452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] JRuby 1.1发布</title><link>http://www.blogjava.net/sean/archive/2008/04/05/190985.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sat, 05 Apr 2008 15:01:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/04/05/190985.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/190985.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/04/05/190985.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/190985.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/190985.html</trackback:ping><description><![CDATA[
		<br />JVM下的Ruby语言实现JRuby正式发布1.1版，这个版本最主要关注的是性能，除此之外，值得一提的包括：<br />1- 支持将Ruby代码编译成Java Bytecode。<br />2- 将Oniguruma这个Ruby 1.9标配的正则库移植到Java。<br />3- 重构过的IO实现。<br />4- 更低的内存消耗。<br />5- 修复大量其他兼容性问题。<br /><br />主页: <a target="_blank" title="http://jruby.codehaus.org/" href="http://jruby.codehaus.org/">http://jruby.codehaus.org/</a><br />下载: <a target="_blank" title="http://dist.codehaus.org/jruby/" href="http://dist.codehaus.org/jruby/">http://dist.codehaus.org/jruby/</a><br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/190985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-04-05 23:01 <a href="http://www.blogjava.net/sean/archive/2008/04/05/190985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] 移植Oracle数据库到PostgreSQL的要点</title><link>http://www.blogjava.net/sean/archive/2008/03/11/185510.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Tue, 11 Mar 2008 15:04:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/03/11/185510.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/185510.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/03/11/185510.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/185510.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/185510.html</trackback:ping><description><![CDATA[
		<br />最近尝试把一个Oracle数据库，连同构建在这个数据库上的Java应用移植到PostgreSQL环境。在移植过程中，总结了一些要点，一方面作为笔记备忘，一方面也给有类似任务需要处理而又无从下手的朋友作为参考。<br /><br />1- 首先是准备PostgreSQL环境。有条件的话，最好是找一台空闲的PC机作为测试服务器，安装Linux或BSD，然后从源码编译最新的PostgreSQL 8.3.0。编译时，通过configure指定--with-perl和--with-python以支持PL/Perl和PL/Python。因为绝大多数Linux发行版都已自带Perl和Python，不必额外安装。<br /><br />2- 如果是Windows环境，又需要Perl和Python，则必须额外安装，Python的话，可以方便的找到2.5 for Windows的安装包，Perl的话，推荐ActivePerl，相对麻烦一点，为了后面用到的一些便利的功能顺利加载，Perl版本尽量选5.8.8。<br /><br />3- 创建数据库和用户。通过initdb初始化数据目录，配置postgresql.conf指定主机IP、端口等等信息，配置pg_hba.conf指定访问权限，通过pg_ctl -D &lt;数据目录&gt; -l &lt;日志文件&gt; start启动postmaster，然后createdb、createuser创建数据库和用户。数据库建好之后，就可以createlang -d &lt;数据库名&gt; [plperl|plperlu|plpython|plpythonu]开启PL/Perl和PL/Python。具体命令行参数可通过各命令加--help查看。<br /><br />4- 安装PostgreSQL客户端pgAdminIII，最新版是1.8.2，有条件的话，也可以下载源码自己编译。<br /><br />5- 安装Oracle客户端，需要在PostgreSQL同一台机器，以便Perl用于连接数据库的DBI和Oracle驱动DBD::Oracle模块顺利安装。如果是Windows上的ActivePerl，则可以通过ppm install DBD-Oracle，如果是Linux/BSD，则可以通过CPAN来安装，如perl -MCPAN -e shell进入CPAN Shell，通过install &lt;模块名&gt;或force install &lt;模块名&gt;安装DBI和DBD::Oracle。<br /><br />6- 数据库的移植，可以选择ora2pg来帮忙，目前的版本是4.7。ora2pg是一个用于读取Oracle数据库schema、数据，并生成PostgreSQL脚本或直接导入PostgreSQL数据库的Perl工具。用法很简单，就是通过.conf文件指定数据库连接信息包括NLS_LANG、需要导出导入的schema、table、view、data等等，然后执行一个pl脚本。这是目前相对比较成熟的一个方案，但是遇到schema复杂、约束较强的数据库，需要手工处理的地方还是不少。建议不要直接写入PostgreSQL，而是生成SQL脚本，验证无误后再执行。ora2pg默认会把Oracle中名称的大写转换成小写，因为PostgreSQL在解析SQL时，除非""括起来，默认都是转成小写。schema、table、view、sequence、data等等，基本用ora2pg，加上一些手工调整即可搞定。至于function、stored procedure等，还是手工移吧，偷不得懒。除了ora2pg，其实也可以配置DBI-Link，将Oracle数据库挂到PostgreSQL数据库作为一组独立的"schema"，然后用create table xxx as select ... from ...这样的语法来倒表和数据。PostgreSQL的contrib包也附带有一个dblink，不过是连接其他PostgreSQL数据库的，如果需要连接非PostgreSQL，
还是考虑DBI-Link，任何可以通过Perl的DBI接口访问的数据库，都能link进PostgreSQL。<br /><br />7- 接下来就是Java应用本身了，我这次移的这个应用是Spring+iBatis架构的，很多SQL语句都是明文，好在DAO层的基础部分(CRUD)的SQLMap是工具自动生成，且都是符合ANSI SQL92标准的，不需要修改即可使用。其余的高级查询SQL，需要调整的地方不少，一些常见的修改列举如下：<br /><br />i. SELECT出来的column（包括子查询），如果有别名，必须加AS，比如 select null as some_column from some_table;<br />ii. PostgreSQL没有dual表，类似select 0 from dual的语句，写成select 0即可;<br />iii. DECODE函数需要重构成(case when some_column = 'some_value' then 'some_other_value' when ... then ... else 'some_default_value' end ) as some_column;<br />iv. NVL()函数，PostgreSQL中相对应的是coalesce()，其实几乎所有主流DBMS都支持coalesce，包括Oracle，这才是标准写法;<br />v. 比较日期，在PostgreSQL中，建议使用date_trunc('day', SOME_DATE) = date_trunc('day', #enteredDate#)这样的写法，其中'day'位置可选字段包括有year、month、week、hour、minute、second等等;<br />vi. SYSDATE，对应到PostgreSQL是current_timestamp，可以根据需要使用current_date;<br />vii. ROWNUM，通常我们用ROWNUM都是为了限制查询出来的记录数，PostgreSQL没有这个关键字，需要改成在SELECT语句最后添加 LIMIT语句，如LIMIT 100;<br />viii. (+)这样的外连接写法需要调整为SQL标准的 table1 [LEFT|RIGHT|FULL] OUTER JOIN table2 ON (...);<br />ix. CONNECT BY ... START WITH ... 递归查询可以参考 http: //www.postgresql.org/docs/8.3/static/tablefunc.html 的connectby()函数.<br /><br />最后再多提一点，PostgreSQL自带的过程语言是PL/pgSQL，在PostgreSQL上写function，除了用plpqsql，还支持sql、plperl(u)、plpython(u)等等。如果你对SQL天生过敏，看类似PL/pgSQL的代码都很吃力，别说是写了，你完全可以用你喜欢的语言来表达函数和存储过程的逻辑。有了PL/Python，你还怕什么呢？你几乎能做任何事。<br /><br />[更新 20080313] 把JDBC驱动的部分漏掉了，移植Java应用时，除了改SQL，还需要拿PostgreSQL的JDBC驱动放到classpath下面，如WEB-INF/lib，然后修改数据库连接URL，改成jdbc:postgresql://&lt;ip&gt;:&lt;port&gt;/&lt;dbname&gt;即可。<br /><br />[更新 20080323] 移植schema和数据时，比ora2pg更方便的一种方式是利用EnterpriseDB的Migration Tool，将Oracle的JDBC驱动ojdbc14.jar拷贝到EnterpriseDB安装路径下的jre/lib/ext下后，启动Developer Studio即可建立Oracle连接，选中schema后，可以通过右键Online Migration将schema、数据、函数包等等一次性通通导入EnterpriseDB。如果要继续往"纯"PostgreSQL移，从EDB做backup，然后到PostgreSQL下做restore，这样会丢掉函数包，因为毕竟EDB在PostgreSQL基础上做了相当改造以和Oracle兼容，不过函数包之类还是手工移比较稳妥。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/185510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-03-11 23:04 <a href="http://www.blogjava.net/sean/archive/2008/03/11/185510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] Sun Hires Python Experts</title><link>http://www.blogjava.net/sean/archive/2008/03/05/183819.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Tue, 04 Mar 2008 16:07:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/03/05/183819.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/183819.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/03/05/183819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/183819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/183819.html</trackback:ping><description><![CDATA[
		<br />在JRuby得到Sun的认可并成功发布1.0，已经向1.1迈进之时，比Ruby应用更广、更早出现JVM运行版本的Python也终于得到了Sun的重视：<br /><br /><a target="_blank" title="http://www.eweek.com/c/a/Application-Development/Sun-Hires-Python-Experts/" href="http://www.eweek.com/c/a/Application-Development/Sun-Hires-Python-Experts/">http://www.eweek.com/c/a/Application-Development/Sun-Hires-Python-Experts/</a><br /><br />尽管Sun官方的说法是他们会更多的应用和扶持native版的Python，相信一直饱受冷落的Jython，也多少会从中受益吧。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/183819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-03-05 00:07 <a href="http://www.blogjava.net/sean/archive/2008/03/05/183819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] Apache Harmony 5.0 reaches M5</title><link>http://www.blogjava.net/sean/archive/2008/02/29/183052.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Fri, 29 Feb 2008 15:28:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/02/29/183052.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/183052.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/02/29/183052.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/183052.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/183052.html</trackback:ping><description><![CDATA[
		<br />就在2月的最后一天，Apache Harmony发布了5.0的第5个milestone: <a target="_blank" title="http://harmony.apache.org/" href="http://harmony.apache.org/">http://harmony.apache.org/</a><br /><br />为默默耕耘的人鼓掌。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/183052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-02-29 23:28 <a href="http://www.blogjava.net/sean/archive/2008/02/29/183052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] Grails正式发布1.0版</title><link>http://www.blogjava.net/sean/archive/2008/02/07/179425.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Thu, 07 Feb 2008 02:47:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/02/07/179425.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/179425.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/02/07/179425.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/179425.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/179425.html</trackback:ping><description><![CDATA[
		<br />春节期间真是好事不断啊，继<a target="_blank" title="http://www.blogjava.net/sean/archive/2008/02/07/179424.html" href="/sean/archive/2008/02/07/179424.html">PostgreSQL 8.3正式release</a>后，Grails也如约发布1.0版。作为受到Ruby on Rails启发开动的"Groovy版Rails"项目，它在设计哲学上和Rails，包括JRuby版的Rails，有着很大的不同，Rails是从头开始用Ruby完整实现从表现层到ORM所有功能，而Grails则是利用Java社区现有的成熟开源框架，如Spring、Hibernate等，在此基础上整合出一套完整的Web应用框架，有点类似Pylons和Django的区别。<br /><br />我<a target="_blank" title="http://www.blogjava.net/sean/archive/2008/01/27/178036.html" href="/sean/archive/2008/01/27/178036.html">之前一篇随笔</a>也提到过，和其它在JVM中运行的动态语言如Jython、JRuby不同的是，Groovy对于有Java基础的人们来说，学习曲线几乎是平的，上手很快，如果你同时也熟悉Spring和Hibernate等，那么Grails更是不二之选。<br /><br />官网: <a target="_blank" title="http://grails.codehaus.org/" href="http://grails.codehaus.org/">http://grails.codehaus.org/</a><br />Release Notes: <a target="_blank" title="http://grails.org/1.0+Release+Notes" href="http://grails.org/1.0+Release+Notes">http://grails.org/1.0+Release+Notes</a><br />下载: <a target="_blank" title="http://grails.codehaus.org/Download" href="http://grails.codehaus.org/Download">http://grails.codehaus.org/Download</a><br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/179425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-02-07 10:47 <a href="http://www.blogjava.net/sean/archive/2008/02/07/179425.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[链接] 会Java？学Groovy？这里有篇很好的介绍/演示 </title><link>http://www.blogjava.net/sean/archive/2008/01/27/178036.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 27 Jan 2008 09:14:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2008/01/27/178036.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/178036.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2008/01/27/178036.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/178036.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/178036.html</trackback:ping><description><![CDATA[
		<br />如果你有一定的Java基础，想快速的尝尝动态语言的味道，Groovy是个自然的过渡选择。今天无意中看到一篇介绍Groovy的文章，很短，也很有趣，从一个典型的Java程序开始，一步一步"Groovy化"，最终改造成一个完整的Groovy程序：<br /><a target="_blank" href="http://java.dzone.com/news/java-groovy-few-easy-steps"><br />http://java.dzone.com/news/java-groovy-few-easy-steps</a><br /><br />如果你对当下动态语言的现状有所了解，那你多半已经知道能在JVM中运行的动态语言，远不止Groovy一种，那么什么理由会让你选择Groovy而非Jython、JRuby或者其他类似的语言呢？笔者认为主要还是编码习惯和风格，Groovy是这些语言中最接近Java的。Jython和JRuby都是从其他成功的动态语言"移植"过来，带有明显的Python、Ruby语法特征和习惯。选择Jython或者JRuby的朋友，我想大都是原本就有Python或者Ruby的基础，舍不得Python和Ruby的一些很方便的语法和编码风格/习惯/哲学，或者干脆就是为了将Python和Ruby世界的一些框架引入到Java中，或者说是让Python/Ruby应用能够更好的利用Java平台已有的资源。如果你在动态语言上没有这方面的需求，只是为了让你的Java应用更动态，选择Jython或者JRuby只能是凭空增加学习难度。要知道，Python和Ruby都是很有特点、很有个性的语言（其实Java又何尝不是），要从Java的思维和哲学，转向Python/Ruby的思维和哲学，并不是那么容易做到和做好的。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/178036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2008-01-27 17:14 <a href="http://www.blogjava.net/sean/archive/2008/01/27/178036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> [Tips] When ANT is not enough, JRuby to the rescue!</title><link>http://www.blogjava.net/sean/archive/2007/06/18/124859.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 17 Jun 2007 16:39:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/06/18/124859.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/124859.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/06/18/124859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/124859.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/124859.html</trackback:ping><description><![CDATA[
		<br />
随着项目越来越大，你的ANT脚本变得越来越臃肿，越来越依赖antcontrib来实现构建逻辑？不想放弃对构建过程和产出做精细的控制？恨不得自己写ANT Task？<br /><br />
等一等，在你考虑转向Maven或者真正卷起袖子开始研究ANT Task的API之前，先听我向你推荐Ruby/JRuby。相信我，也许这才是你真正需要的。<br /><br />
在我看来构建脚本最主要的要求是表达能力和控制能力，表达能力是我们应该能够很方便的告诉它我们要它做什么，而控制能力是我们告诉它如何去做，除了必要的
构建命令的参数、依赖关系之外，它应该能够理解我们其他一些特殊要求。在项目相对简单时，ANT的XML格式的"脚本语言"能够比较好的表达构建者的要
求，至少比纯Java的方式更加简单清晰，于是几乎从它诞生之日就成为Java领域当仁不让的头号构建工具。但是ANT也有它不够用的时候，尤其在控制能
力上，为了实现实际使用中越来越复杂越来越精细的对构建过程和产出的要求，ANT的使用者们开始对ANT进行扩展，最具影响力的"非官方"扩展可能就是
antcontrib了，很多实际Java项目的构建文件中我们都能够找到它的影子。但是一堆taskdef和<variable><substring><stringutil><length><math>之类的夹杂在ANT脚本里，怎么看怎么觉得别扭，也严重影响构建脚本的可读性。<br /><br />
我发现我需要的是一个具有完整功能脚本语言来写我的构建逻辑：一方面它要足够简单，我需要清晰的表达我的意图，另一方面当我需要的时候它要足够强大来帮我实现精细的控制。我自然而然想到Ruby。<br /><br />
由于Ruby是一个功能完整的工具，完全自己写Ruby脚本来调用Java自己的构建工具如javac、jar等等并非不可能，但是既然已经有人做了轮
子，我们拿来用就是了，大不了自己再改装一下，也少走些弯路。时下比较流行的解决方案有Buildr、Raven、Rant和Antwrap，它们各有特
点，大家可以根据需要进行选择。<br /><br />
我最终选了其中最"轻量"的Antwrap，原因嘛，我不想学新的API，我已经熟悉ANT常用的Task，而且我希望尽可能多的自己控制构建的过程和产
出。Antwrap最能够满足我的需要。而前不久JRuby刚刚发布了1.0版，这样一来Ruby和Java的跨界引用变得更加容易，Ruby的实现自然
就选择了JRuby。<br /><br />
安装JRuby和Antwrap相当容易，只要把下载的jruby-bin-1.0.tar.gz/.zip解压到本地，确保JAVA_HOME和
CLASSPATH的配置，然后gem install Antwrap (选择Java版)
即可。为了顺利加载Antwrap，需要在CLASSPATH中包含ANT的ant.jar和ant-launcher.jar。(当然，如果想更加方便
的share你的成果，可以把ant的文件拷贝到jruby目录下，在jruby的启动脚本加入必要的export/set命令，然后打包，这样别人只要
从你提供的zip包解压出来即可使用。)<br /><br />
为了给大家一个直观的感觉，举个简单的例子(貌似BlogJava没有提供对Ruby代码的默认支持，大家将就看吧)：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 128);"> 1</span> <span style="color: rgb(0, 0, 0);">require </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">rubygems</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 2</span> <span style="color: rgb(0, 0, 0);">gem </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">Antwrap</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 3</span> <span style="color: rgb(0, 0, 0);">require </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">antwrap</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 4</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 5</span> <span style="color: rgb(0, 0, 0);">@ant</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">AntProject.</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">(:name</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">SampleAntwrapBuild</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, :basedir</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);"> 6</span> <span style="color: rgb(0, 0, 0);">@cvsroot</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:pserver:cvsuser:password@10.10.10.1/cvsrepo/SampleProduct</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 7</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 8</span> <span style="color: rgb(0, 0, 0);">def cvscheckout<br /></span><span style="color: rgb(0, 128, 128);"> 9</span> <span style="color: rgb(0, 0, 0);">    @ant.cvs(<br /></span><span style="color: rgb(0, 128, 128);">10</span> <span style="color: rgb(0, 0, 0);">        :cvsroot</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{@cvsroot}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">11</span> <span style="color: rgb(0, 0, 0);">        :command</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">checkout -A</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">12</span> <span style="color: rgb(0, 0, 0);">        :</span><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">13</span> <span style="color: rgb(0, 0, 0);">        :dest</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">14</span> <span style="color: rgb(0, 0, 0);">        :compressionlevel</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">9</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">15</span> <span style="color: rgb(0, 0, 0);">end<br /></span><span style="color: rgb(0, 128, 128);">16</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">17</span> <span style="color: rgb(0, 0, 0);">def cvsupdate<br /></span><span style="color: rgb(0, 128, 128);">18</span> <span style="color: rgb(0, 0, 0);">    @ant.cvs(<br /></span><span style="color: rgb(0, 128, 128);">19</span> <span style="color: rgb(0, 0, 0);">        :cvsroot</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">#{@cvsroot}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">20</span> <span style="color: rgb(0, 0, 0);">        :command</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">update -A -d</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">21</span> <span style="color: rgb(0, 0, 0);">        :</span><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">22</span> <span style="color: rgb(0, 0, 0);">        :dest</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">23</span> <span style="color: rgb(0, 0, 0);">        :compressionlevel</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">9</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">24</span> <span style="color: rgb(0, 0, 0);">end<br /></span><span style="color: rgb(0, 128, 128);">25</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">26</span> <span style="color: rgb(0, 0, 0);">def compile(project_name)<br /></span><span style="color: rgb(0, 128, 128);">27</span> <span style="color: rgb(0, 0, 0);">    @ant.javac(<br /></span><span style="color: rgb(0, 128, 128);">28</span> <span style="color: rgb(0, 0, 0);">        :srcdir</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal/#{project_name}/src</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">29</span> <span style="color: rgb(0, 0, 0);">        :destdir</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal/#{project_name}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">30</span> <span style="color: rgb(0, 0, 0);">        :target</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">1.5</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">31</span> <span style="color: rgb(0, 0, 0);">        :encoding</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">GBK</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">32</span> <span style="color: rgb(0, 0, 0);">    @ant.copy(    :todir</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal/#{project_name}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">33</span> <span style="color: rgb(0, 0, 0);">        fileset(:dir</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal/#{project_name}/src</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">34</span> <span style="color: rgb(0, 0, 0);">            exclude(:name</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">**/*.java</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">35</span> <span style="color: rgb(0, 0, 0);">        end<br /></span><span style="color: rgb(0, 128, 128);">36</span> <span style="color: rgb(0, 0, 0);">    end<br /></span><span style="color: rgb(0, 128, 128);">37</span> <span style="color: rgb(0, 0, 0);">    @ant.jar(<br /></span><span style="color: rgb(0, 128, 128);">38</span> <span style="color: rgb(0, 0, 0);">        :destfile</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">build/#{project_name}.jar</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">39</span> <span style="color: rgb(0, 0, 0);">        :basedir</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">cvsoriginal/#{project_name}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, <br /></span><span style="color: rgb(0, 128, 128);">40</span> <span style="color: rgb(0, 0, 0);">        :manifest</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">MANIFEST.MF</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">41</span> <span style="color: rgb(0, 0, 0);">        exclude(:name</span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">src/**</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br /></span><span style="color: rgb(0, 128, 128);">42</span> <span style="color: rgb(0, 0, 0);">    end<br /></span><span style="color: rgb(0, 128, 128);">43</span> <span style="color: rgb(0, 0, 0);">end<br /></span><span style="color: rgb(0, 128, 128);">44</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">45</span> <span style="color: rgb(0, 0, 0);"># to actually call your target<br /></span><span style="color: rgb(0, 128, 128);">46</span> <span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> ARGV.empty</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">47</span> <span style="color: rgb(0, 0, 0);">    puts </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Usage: jruby #{$0} [target]</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">48</span> <span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">49</span> <span style="color: rgb(0, 0, 0);">    eval ARGV[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">]<br /></span><span style="color: rgb(0, 128, 128);">50</span> <span style="color: rgb(0, 0, 0);">end<br /></span><span style="color: rgb(0, 128, 128);">51</span> <span style="color: rgb(0, 0, 0);"></span></div><br /></math></length></stringutil></substring></variable>可以看到几乎都是我们熟悉的ANT Task，只是更加紧凑更加灵活，一旦掌握了最最基本的Ruby语法，用它写出功能强大的构建脚本可以说是分分钟搞定。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/124859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-06-18 00:39 <a href="http://www.blogjava.net/sean/archive/2007/06/18/124859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[八卦] Java "forks": first .NET, then SWT/Eclipse, now Harmony?</title><link>http://www.blogjava.net/sean/archive/2007/04/14/110644.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sat, 14 Apr 2007 07:20:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/04/14/110644.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/110644.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/04/14/110644.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/110644.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/110644.html</trackback:ping><description><![CDATA[
		<br />
读到一篇廷有意思的文章，来自Weiqi Gao：<br /><a href="http://www.weiqigao.com/blog/2007/04/12/java_the_third_fork_from_sun.html" target="_blank">http://www.weiqigao.com/blog/2007/04/12/java_the_third_fork_from_sun.html</a><br /><br />
近几年Sun的日子似乎并不好过：和微软先是不欢散后来虽然和解但貌合神离，微软不买Sun的账，干脆自己搞个.NET；对IBM更是气不打一处来，但是不管怎么说SWT/Eclipse这朵花确实开得太艳，甚至盖过了Sun的光芒；现在Sun又<a href="http://www.apache.org/jcp/sunopenletter.html" target="_blank">和Apache铆上了</a>。<br /><br />
这三次不和，背后的原因几乎都是Sun不愿意大胆革新Java，或者放弃对Java的控制权（Sun的JDK开源并不能改变Sun对Java的实际控制）。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/110644.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-04-14 15:20 <a href="http://www.blogjava.net/sean/archive/2007/04/14/110644.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] Java SE 1.6.0发布第一个update release</title><link>http://www.blogjava.net/sean/archive/2007/04/01/107840.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sun, 01 Apr 2007 14:49:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/04/01/107840.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/107840.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/04/01/107840.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/107840.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/107840.html</trackback:ping><description><![CDATA[
		<br />
版本号1.6.0_01。<br /><br />
详见:<br /><a href="http://java.sun.com/javase/6/webnotes/ReleaseNotes.html" target="_blank">http://java.sun.com/javase/6/webnotes/ReleaseNotes.html</a><br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/107840.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-04-01 22:49 <a href="http://www.blogjava.net/sean/archive/2007/04/01/107840.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[阅读] JRuby, Groovy, and Swing</title><link>http://www.blogjava.net/sean/archive/2007/02/21/100322.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Wed, 21 Feb 2007 12:03:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/02/21/100322.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/100322.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/02/21/100322.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/100322.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/100322.html</trackback:ping><description><![CDATA[<br />
以下是一组相互关联、按时间先后排列的3篇blog文章，主要探讨是Swing存在的问题以及动态语言如JRuby/Groovy能否帮我们解决Swing的问题：<br />
<br />
<a href="http://rawblock.blogspot.com/2007/02/jruby-can-save-swing.html" target="_blank">JRuby can save Swing</a><br />
<a href="http://pinderkent.blogsavy.com/archives/53" target="_blank">JRuby cannot save Swing</a><br />
<a href="http://shemnon.com/speling/2007/02/groovy-can-save-swing.html" target="_blank">Groovy can save Swing</a><br />
<br />
挺有趣的，推荐大家有空读一读。<br />
<br /><br />
<img src ="http://www.blogjava.net/sean/aggbug/100322.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-02-21 20:03 <a href="http://www.blogjava.net/sean/archive/2007/02/21/100322.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] Apache ActiveMQ graduates from incubator</title><link>http://www.blogjava.net/sean/archive/2007/02/07/98456.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Tue, 06 Feb 2007 16:28:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/02/07/98456.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/98456.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/02/07/98456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/98456.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/98456.html</trackback:ping><description><![CDATA[<br/>
Apache旗下的ActiveMQ日前正式"毕业"成为Apache的顶级项目之一。官方主页也从<a href="http://incubator.apache.org/activemq/">http://incubator.apache.org/activemq/</a>改为<a href="http://activemq.apache.org/" target="_blank">http://activemq.apache.org/</a>。<br/>
<br/>
<br/>
<img src ="http://www.blogjava.net/sean/aggbug/98456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-02-07 00:28 <a href="http://www.blogjava.net/sean/archive/2007/02/07/98456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[阅读] 谁射杀了桌面版Java</title><link>http://www.blogjava.net/sean/archive/2007/01/25/96047.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Thu, 25 Jan 2007 13:30:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/01/25/96047.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/96047.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/01/25/96047.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/96047.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/96047.html</trackback:ping><description><![CDATA[<br/>
<a href="http://mikeomatic.net/?p=138" target="_blank">http://mikeomatic.net/?p=138</a><br/>
<br/>
挺有趣的一篇文章。Java在桌面应用这个领域始终得不到广泛的认同，虽然Java 6和SWT/RCP都为改善桌面版Java应用做出了自己的努力，但Java在这个领域的坏名声已经难以挽回。造成这一现状的始作俑者是谁，是什么原因导致人们对桌面版Java心存偏见，使用Java开发桌面应用的朋友也会经常会觉得力不从心呢？该文作者提出了三点：<br/>
<br/>
<ol>
<li>Sun没有意识到这样一个事实：任何一款桌面框架的实现，假如不能无缝的运行在Windows上，都注定成为“也能运行”的一种GUI技术，始终无法和native的版本抗衡。</li>
<li>他们认定解决（实现）高级桌面控件的方法是通过Swing这种方式，为了“跨平台”，所有东西本质上都是通过JFrame自己在canvas上画，而不是利用现成已经实现的东西，带来额外的开销和重复劳动。</li>
<li>他们早应该把官方的开发工具做得更加完善，现在NetBeans发展很好，但是不是有点太晚意识到这个问题了，而不论OS X还是Windows，都在这方面积累了一大批忠实用户。</li>
</ol>
<br/>
我认为，不管桌面版Java过去的名声如何，能够跨平台运行，越来越好的虚拟机环境和性能，越来越好的API和工具支持，庞大的开发群体和开源框架/工具，Java仍然是开发企业级桌面应用的一个相当不错的选择。<br/>
<br/>
<br/>
<img src ="http://www.blogjava.net/sean/aggbug/96047.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-01-25 21:30 <a href="http://www.blogjava.net/sean/archive/2007/01/25/96047.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Learn to be defensive</title><link>http://www.blogjava.net/sean/archive/2007/01/25/95819.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Wed, 24 Jan 2007 16:03:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/01/25/95819.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/95819.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/01/25/95819.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/95819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/95819.html</trackback:ping><description><![CDATA[<br/>
作为开发者，我们必须要学会defensive programming，尤其是对要求高可靠性和无人职守的企业级应用中，需要特别留意我们的设计和编码，必须尽可能做到足够defensive。<br/>
<br/>
什么是defensive programming？举个大家都看过的例子：<br/>
<br/>
<code>
String str = ...<br/>
if ("".equals(str)) {} <br/>
</code>
<br/>
在这里我们不写str.equals("")而是反过来，就是为了防止出现不必要的NPE – NullPointerException。<br/>
<br/>
运行期异常是最最需要特别关照的一种非正常状况，除了像上面这类要求我们采用相对较好的编码习惯之外，为了减少运行期异常的发生，通常也需要使用try-catch代码块来把我们相对脆弱，或者需要格外保护的逻辑包起来，对于外部传进来的参数，一定要assert它们的合法性，即assert它们是否能够安全的被后面的逻辑所使用。<br/>
<br/>
通常意义上，defensive programming主要cover的是避免不必要的运行期异常发生。我们可以更进一步，更广义的运用defensive programming的核心思想：在企业应用中，除了运行期异常，对于有些看似严重的极端的错误，如网络超时，连接丢失，数据库提交失败等情况，需要我们具体问题具体分析，并非所有checked exception都一定需要我们去一一catch然后处理。更多的时候，尤其当开发无人职守的后台程序，我们可以采取重试、报告、修改外部数据等方式处理，能够自行解决的，就不要动不动就报错，或等待用户确认，不能自行解决的，则要及时报告并停止运行，避免更大的错误发生。<br/>
<br/>
举个相对具体的例子，两个异构的系统，通过一个中间层的消息平台相互发送消息，通信协议采用最基本的socket方式，这三个系统随时都可能出现宕机或链接中断的情况。为了保证数据的完整性，我们拿其中一个需要发送和接收消息的系统来细说：<br/>
<br/>
一个可能的实现方式是：该系统所有要发送的消息保存到数据库，给它一个初始状态；另一个独立进程从数据库按照时间先后拿出消息，更新拿出的这条消息的状态为处理中，并尝试发送消息；成功后根据需要，更新消息状态为成功发送或者直接删除，如果遇到失败或异常，消息恢复为初始状态，线程sleep一段时间，然后再次尝试，多次尝试或者尝试跨度超过一定时间范围，则停止处理，向管理员汇报（通过邮件、短信等途径）。对于接收到的消息，同样是先存入数据库，然后再由后续的进程用类似的方式取出并处理。如果程序崩溃，可以自动重新启动（应用或整个服务器）。这样不管哪一段通信线路出现故障或阻塞，或者宕机，系统都可以一步一个脚印，确保任务主动而自动的执行，并且忠实记录下有价值的状态信息，出现问题时管理员可以很直观的看到在哪个环节出现故障，从而快速找到问题关键并有效解决。<br/>
<br/>
Defensive programming可以让我们的应用更健壮，在保证数据正确性、完整性的前提下，面对困难也能更加独立自主。和defensive programming相关的话题我想大家如果感兴趣，可以展开更多更深入的探讨，这里只是给大家做个介绍性的铺垫，能抛砖引玉当然更好。<br/>
<br/>
<br/><img src ="http://www.blogjava.net/sean/aggbug/95819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-01-25 00:03 <a href="http://www.blogjava.net/sean/archive/2007/01/25/95819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[新闻] Eclipse Joins JCP</title><link>http://www.blogjava.net/sean/archive/2007/01/13/93582.html</link><dc:creator>laogao</dc:creator><author>laogao</author><pubDate>Sat, 13 Jan 2007 04:05:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2007/01/13/93582.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/93582.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2007/01/13/93582.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/93582.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/93582.html</trackback:ping><description><![CDATA[<br/>
原文:<br/>
<a href="http://www.linux-watch.com/news/NS6467114693.html" target="_blank">http://www.linux-watch.com/news/NS6467114693.html</a><br/>
<br/>
#更新:<br/>
根据Eclipse Foundation的Executive Director Mike Milinkovich的<a href="http://milinkovich.blogspot.com/2007/01/joining-communities.html" target="_blank">blog</a>文章，Eclipse Foundation除了将加入JCP之外，还将加入OMG和OSGi。<br/>
<br/>
<br/>
<img src ="http://www.blogjava.net/sean/aggbug/93582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">laogao</a> 2007-01-13 12:05 <a href="http://www.blogjava.net/sean/archive/2007/01/13/93582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>