﻿<?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-ajoo</title><link>http://www.blogjava.net/ajoo/</link><description /><language>zh-cn</language><lastBuildDate>Fri, 17 Apr 2026 22:40:24 GMT</lastBuildDate><pubDate>Fri, 17 Apr 2026 22:40:24 GMT</pubDate><ttl>60</ttl><item><title>用Neptune来交互执行ant任务</title><link>http://www.blogjava.net/ajoo/archive/2006/02/10/30123.html</link><dc:creator>ajoo</dc:creator><author>ajoo</author><pubDate>Fri, 10 Feb 2006 05:06:00 GMT</pubDate><guid>http://www.blogjava.net/ajoo/archive/2006/02/10/30123.html</guid><wfw:comment>http://www.blogjava.net/ajoo/comments/30123.html</wfw:comment><comments>http://www.blogjava.net/ajoo/archive/2006/02/10/30123.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ajoo/comments/commentRss/30123.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ajoo/services/trackbacks/30123.html</trackback:ping><description><![CDATA[一般来说。ant的任务都是要写一个build.xml文件，然后删删改改，最后运行ant target。这自是正途。但是有时候，如果你需要的就是简单试验一下某个task，或者就想拿某个ant task当成shell命令的话，就不方便了。<br><br>在Neptune这个工具里面，附带了一个shell。这个shell允许交互执行Neptune的Command和Ant的Task。可以在这里下载：<br><a href="http://">http://docs.codehaus.org/display/JASKELL/Downloads</a><br><br>下面简要介绍一下怎么用：<br><br>启动Neptune shell很简单。按照要求安装完了之后（就是设置一个NEPTUNE_HOME和PATH环境变量），运行：<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);">np&nbsp;</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">i<br><br></span></div>shell启动后，你可以看见：<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);">Neptune&nbsp;Interactive<br></span><span style="color: rgb(0, 0, 0);">&gt;</span></div>这个"&gt;"是命令提示符。现在你可以输入命令了。<br><br>先看看最简单的ant echo任务。xml语法是这样的：<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);">&lt;</span><span style="color: rgb(0, 0, 0);">echo&nbsp;message</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello&nbsp;world</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/&gt;</span></div>对应的neptune语法是<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);">&gt;</span><span style="color: rgb(0, 0, 0);"> ant.echo{message</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello&nbsp;world</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">}-&gt;exec<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><pre class="code-java">starting command Echo ...<br>task Echo: hello world<br>command Echo executed.</pre></div><br>稍微解释一下：<br>1。所有ant命令都在ant这个namespace里面。<br>2。xml的尖括号换成大括号。大括号在jaskell语言里面表示一个tuple。<br>3。exec函数用来执行一个命令。如果没有exec，ant.echo只是生成一个命令对象，但不执行。这样做得好处是，你可以用变量临时存储这些命令对象，可以把他们存在任意的对象或者数组中，等到真正需要执行的时候再运行。<br>4。"-&gt;"这个函数用来以先参数后函数的循序调用函数，相当于exec(ant.echo{...})，语法上有的时候显得更漂亮些。<br><br><br><br>再来看个复杂点的。前两天我发现需要把某个目录下所有反编译出来的jad文件改名成java文件。dos的rename命令居然不支持。于是我就祭起法宝：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;rename&nbsp;{dir,from,to}&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> ant.move{todir</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">dir}.with&nbsp;[<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;ant.types.fileset{dir}.with&nbsp;[<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ant.types.include{name</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">**/$from</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">}<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;],<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;ant.types.mapper{type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">glob</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,from,to}<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;] -&gt;exec<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;rename()</span></div><br>这个东西定义了一个函数，接下来，我就可以拿rename当作一个简洁的命令了：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;rename{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);">decompiled</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,from</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">*.jad</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,to</span><span style="color: rgb(0, 0, 0);">=</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, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;<br>starting&nbsp;command&nbsp;Move<img src="http://www.blogjava.net/images/dot.gif"><br>command&nbsp;Move&nbsp;executed.<br></span><span style="color: rgb(0, 0, 0);">&gt;</span></div><br><br>后来，我把这个rename函数稍微完善了一下，增加了一个recursive参数来控制是否处理子目录，缺省值是false，给dir设置当前目录为缺省值。代码放在一个可以重用的脚本文件里面。现在可以这样做了。先把函数加载进来：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;helper&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;{resource</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">jfun/neptune/ant/anthelper.jsl</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">}<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><br></span></div><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);">&gt;</span><span style="color: rgb(0, 0, 0);"> helper.rename{</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);"></span><span style="color: rgb(0, 0, 0);">from</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">*.jad</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,to</span><span style="color: rgb(0, 0, 0);">=</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);">,recursive=true}-&gt;exec<br></span><span style="color: rgb(0, 0, 0);">&gt;</span></div><br>呵呵。<br><br>这个工具可以调用任意的ant任务。还有很多好用的函数。具体请见：<br><a href="http://">http://docs.codehaus.org/display/JASKELL/Neptune<br></a><img src ="http://www.blogjava.net/ajoo/aggbug/30123.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ajoo/" target="_blank">ajoo</a> 2006-02-10 13:06 <a href="http://www.blogjava.net/ajoo/archive/2006/02/10/30123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个方便的java shell</title><link>http://www.blogjava.net/ajoo/archive/2006/01/22/28913.html</link><dc:creator>ajoo</dc:creator><author>ajoo</author><pubDate>Sat, 21 Jan 2006 18:13:00 GMT</pubDate><guid>http://www.blogjava.net/ajoo/archive/2006/01/22/28913.html</guid><wfw:comment>http://www.blogjava.net/ajoo/comments/28913.html</wfw:comment><comments>http://www.blogjava.net/ajoo/archive/2006/01/22/28913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ajoo/comments/commentRss/28913.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ajoo/services/trackbacks/28913.html</trackback:ping><description><![CDATA[这两天完善了我的jaskell语言的一个shell。<br>
<br>
这个shell虽然是jaskell的，但是也可以作为一个交互式执行java代码的解释器。对于想快速地试试某个api比较有用。<br>
<br>
相比于eclipse scrapebook，它的好处是更方便，而且，jaskell的一些函数式的特性让你可以写出更加简洁的代码。<br>
<br>
下面举几个例子：<br>
<br>
<font size="5"><b>轻松玩Swing</b></font><br>
<br>
打开shell，它显示这样：<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);"><br>Jaskell&nbsp;Shell&nbsp;version&nbsp;</span><span style="color: rgb(0, 0, 0);">0.5</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">&gt;</span></div>然后假设你要运行一下javax.swing.JOptionPane.showInputDialog()函数的话，你可以这样写：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;javax.swing.JOptionPane.showInputDialog[</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">your age?</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span></div>回车两下（第一下，就是简单折行，因为你可以接着写下一行代码，只有连续两下折行，shell才认为你是要执行）<br>
结果就会出现一个简单的swing对话框。在对话框里面输入年龄“13"，回车，<br>
shell里面就会显示：13。<br>
<br>
<br>
这里面，一点需要注意的，java方法调用不用圆括号，而是方括号。你可以把这个理解为一个reflection调用，传递的永远都是一个数组。<br>
<br>
下面，假设你想重复地使用JOptionPane这个类，使用showInputDialog, showConfirmDialog这类的方法，总这么写javax.swing.JOptionPane也够麻烦的。我们可以简化它：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;dialog&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;javax.swing.JOptionPane<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">=&gt; class</span><span style="color: rgb(0, 0, 0);">&nbsp;javax.swing.JOptionPane<br></span></div>当你回车两次后，shell在"=&gt;"提示符后面自动显示这个表达式的值："class javax.swing.JOptionPane"。<br>
<br>
下面我们可以重复使用dialog变量了。在这之前，我们可能想看看JOptionPane到底都支持什么静态方法，我们可以用"?"来让shell告诉我们<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);">&nbsp;dialog</span></div>这个"?"不是jaskell语言的一部分，而是shell的命令，所以不需要回车两次。回车，shell就会把JOptionPane的所有方法都列出来。<br>
<br>
然后假设我们选择showMessageDialog，可以这样写：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;dialog.showMessageDialog[</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello&nbsp;world</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span></div>然后，一个"hello world"的对话框就弹了出来（看不见？找一找。它可能被藏在你的当前窗口后面了。）<br>
<br>
更简化一点，假设我要重复showMessageDialog若干遍，我可以这样写：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;say&nbsp;msg&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;dialog.showMessageDialog[</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">,&nbsp;msg]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>=&gt; say()</span></div>这个表达式的值是一个接受一个参数的，叫做say的函数。<br>
<br>
下面你可以say很多东西啦：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;say&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">how&nbsp;are&nbsp;you?</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;say&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">java&nbsp;sucks!</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span></div>等等等等。<br>
<br>
<br>
<br>
<font size="5"><b>傻瓜多线程</b></font><br>
<br>
好，看过了JOptionPane，我们来看看多线程。下面是用这个语言怎么启动一个线程：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;Thread.</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">[(\_</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">System.out.println[</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello&nbsp;world</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">])&nbsp;`</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;Runnable].start[]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>hello&nbsp;world</span></div>这里面Thread.new大概不需要解释。这里对构造函数的调用是Ruby风格的ClassName.new，而不是java的new ClassName。<br>
<br>
构造函数也需要用一个list来传递参数。我们这里传递的是一个Runnable对象。<br>
用来实现Runnable接口的是一个匿名函数，这个函数不管参数是什么，一旦调用，就println一下。<br>
<br>
implements
是一个函数，它负责用一个函数来动态生成一个实现某接口的proxy出来。它前面的那个反向单引号表示把一个函数以中缀语法调用，所以
(somefunction `implements Runnable)等价于implements(somefunction,
Runnable)。<br>
<br>
"\"符号是lamda函数表示法。"-&gt;"符号前面的是函数参数，后面的是函数体。这里因为我们不使用这个参数，所以用"_"这个通配符。<br>
<br>
最后，我们调用start[]方法来执行这个线程。<br>
<br>
<br>
我们还可以用标准的"const"函数来让代码更简短一点。"<i>const x</i>"语义上完全等价于"<i>\_-&gt;x</i>"。另外，我们也可以用java风格的new操作符函数来写，jaskell对两者都支持的：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Thread[</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">(System.out.println[</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello&nbsp;world</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">])&nbsp;`</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;Runnable].start[]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>hello&nbsp;world</span></div><br>
<br>
然后，考虑到重用，我们可以这样，先把System.out.println搞短一点，每次敲这么长太麻烦：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;println&nbsp;msg&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;System.out.println[msg]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>=&gt; println()</span></div><br>
（实际上，println函数是系统已经缺省就定义好的了。你完全没有必要自己定义println就可以直接用了。这里只是演示一下怎么自己定义函数）<br>
<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;run&nbsp;task&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Thread.</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">[const task </span><span style="color: rgb(0, 0, 0);">`</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;Runnable].start[]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>=&gt; run()<br></span></div><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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;run(println&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello&nbsp;world</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>hello&nbsp;world<br><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;run(println&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">pei!</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>pei</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);"><br><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;run&nbsp;(say&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">nice!</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span></div><br>
最后一个say "nice!"，如果不用单独线程的话，运行后这个对话框将阻塞当前线程。现在用run来运行它，就不会阻塞了。<br>
<br>
<br>
<font size="5"><b>今天你fp了吗？</b></font><br>
<br>
最后再随便看看jaskell作为函数式语言的本分所能做的一些事。<br>
<br>
<i><b>foreach函数：</b></i><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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;foreach&nbsp;[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"hello"</span><span style="color: rgb(0, 0, 0);">]&nbsp;println<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span></div>这个函数把1,2,"hello"三个都打印一遍。<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;foreach(list&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">,&nbsp;println)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span></div>这个函数把数字1到100按顺序打印一遍。<br>
<br>
<i><b>map函数：</b></i><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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;map&nbsp;(\x</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">Integer.parseInt[x])&nbsp;[</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);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">2</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);">3</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>=&gt; [</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">]</span></div>这个函数把一个字符串列表转换成一个整数列表。<br>
<br>
<br><i><b>
filter函数：</b></i><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);"><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;filter(\x</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">x</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">10</span><span style="color: rgb(0, 0, 0);">,&nbsp;list&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br>=&gt; [</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">6</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">7</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">8</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></div>这个代码把1到100中所有小于10的整数都取出来。<br>
<br>
filter函数的第一个参数是一个函数，这个函数对列表中的每一个元素都进行判断，返回true或者false。<br>
<br><i><b>
find函数：</b></i><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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;find(</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">,&nbsp;list&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">=&gt; 2</span></div>这个代码在列表中寻找整数2，如果找到，返回找到的位置（0为第一个）<br>
<br>
<br><i><b>
lookup函数：</b></i><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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;lookup(\x</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">x</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">x</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">x</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">50</span><span style="color: rgb(0, 0, 0);">,&nbsp;list&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">=&gt; 7</span></div>这个代码在列表中寻找第一个符合x*x&gt;x+50的元素，找到就返回位置。<br>
<br><i><b>
@函数：</b></i><br>
<br>
上面我们知道找到的数字是在位置7，可以用@来得到位置7的值：<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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;list&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">&nbsp;@&nbsp;</span><span style="color: rgb(0, 0, 0);">7</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">=&gt; 8</span></div>好，这个数是8。<br>
<br>
<br><i><b>
sum函数：</b></i><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);"><br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;sum(list&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">)<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">=&gt; 5050</span></div><br>
<br>
注意，最难的来了！<br>
<i><b>fold函数：</b></i><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);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;fold&nbsp;(</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">]<br></span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 0);">=&gt; 120</span></div>这个fold函数以1为初始值，然后对每个列表元素，把它和当前值做乘法，用结果更新当前值，最后把计算结果返回。所以这段代码实际上做的就是把从1到5乘起来。<br>
(*)是一个乘法函数。<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%;"><span style="color: rgb(0, 0, 0);">&gt;&nbsp; fold&nbsp;(\x&nbsp;y</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">x</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">y)&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">]</span></div>一样的。<br>
<br>
<br>
行了，差不多了。下载在：<br>
<br>
http://dist.codehaus.org/yan/distributions/jaskell.zip<br>
<br>
把jar文件都放到你的classpath里面，然后运行jfun.jaskell.shell.Shell类就行了。<br>
<br>
<img src ="http://www.blogjava.net/ajoo/aggbug/28913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ajoo/" target="_blank">ajoo</a> 2006-01-22 02:13 <a href="http://www.blogjava.net/ajoo/archive/2006/01/22/28913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个使用Spring transaction template的小工具</title><link>http://www.blogjava.net/ajoo/archive/2006/01/13/27847.html</link><dc:creator>ajoo</dc:creator><author>ajoo</author><pubDate>Thu, 12 Jan 2006 23:49:00 GMT</pubDate><guid>http://www.blogjava.net/ajoo/archive/2006/01/13/27847.html</guid><wfw:comment>http://www.blogjava.net/ajoo/comments/27847.html</wfw:comment><comments>http://www.blogjava.net/ajoo/archive/2006/01/13/27847.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ajoo/comments/commentRss/27847.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ajoo/services/trackbacks/27847.html</trackback:ping><description><![CDATA[昨天在千年妖精丽晶大宾馆，看见sparkle同学抱怨Spring的transaction template不好用。因为一些我没有问的原因，他们不能使用声明式事务，所以就只剩下两个选择：<br>
1。直接用hibernate事务。<br>
2。用spring的TransactionTemplate。<br>
<br>
直接用hibernate事务有以下问题：<br>
1。代码完全绑定在Hibernate上。<br>
2。自己控制事务难度比较大，不容易处理得好。<br>
<br>
对第二点，很多人可能都不以为然，不就是一个beginTransaction和一个commit(), rollback()么？太门缝里看人了吧？<br>
<br>
我就举个sparkle同学的小弟写的代码吧：<br>
<blockquote><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);">try</span><span style="color: rgb(0, 0, 0);">{<br>&nbsp;&nbsp;&nbsp;PetBean&nbsp;pet&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;<img src="http://www.blogjava.net/images/dot.gif">;<br>&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/images/dot.gif"><br>&nbsp;&nbsp;&nbsp;beginTransaction();<br>&nbsp;&nbsp;&nbsp;&nbsp;ssn.delete(<img src="http://www.blogjava.net/images/dot.gif">);<br>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/images/dot.gif"><br>&nbsp;&nbsp;&nbsp;&nbsp;commit();<br>&nbsp;&nbsp;&nbsp;&nbsp;petLog(<img src="http://www.blogjava.net/images/dot.gif">);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">(Exception&nbsp;e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rollback();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;e;<br>&nbsp;&nbsp;}</span></div> <br>
</blockquote>
一个大的try-catch块，在出现任何异常的时候都rollback。<br>
<br>
我想会这么写的人应该不在少数。同志们，革命不是请客吃饭那么简单地。<br>
<br>
问题在哪？<br>
<br>
1。最严重的。try里面一旦有Error抛出，rollback()就不会被执行。sparkle同学说，出了Error我们就不管了。可以，反正出Error的几率大概很小。所以你的软件可以说“大多数情况是可以工作地”。<br>
<br>

2。这块代码最终抛出Exception！如果外面直接套一个函数的话，签名上就得写"throws Exception"。这种函数就一个字：“害群之马”。你让调用者根本不知道会出什么异常，笼统地告诉人家“什么情况都可能发生”可不是负责任的态度。<br>
<br>
3。这个代码依赖于rollback()的特定实现。因为一旦exception是在beginTransaction()之前或者beginTransaction()时候抛出的，那么本来不应该调用rollback()的。调用
rollback()会出什么结果呢？如果rollback()不检查当前是否在事务中，就坏菜了。而且，就算rollback()做这个检查，嵌套事务
也会把一切搞乱。因为很有可能整块代码是处在另外一个大的事务中的。调用我们的代码在我们抛出异常的时候，也许会选择redo，或者修复一些东西，不见得总是选择回
滚它那一层的事务的，不分青红皂白地就rollback上层事务，这个代码的健壮性真的很差。<br>
<br>
看，小小一段代码，bug和潜在问题如此之多。你还说自己写事务控制简单吗？<br>
<br>
真正健壮的，不对外界和调用者有多余的假设依赖的代码，可以这样写：<br>
<br>
<blockquote><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);">&nbsp;PetBean&nbsp;pet&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;<img src="http://www.blogjava.net/images/dot.gif">;<br>&nbsp;&nbsp;<img src="http://www.blogjava.net/images/dot.gif"><br>&nbsp;beginTransaction();<br>&nbsp;ok&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">{<br>&nbsp;&nbsp;&nbsp;&nbsp;ssn.delete(<img src="http://www.blogjava.net/images/dot.gif">);<br>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/images/dot.gif"><br>&nbsp;&nbsp;&nbsp;&nbsp;ok&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;&nbsp;&nbsp;&nbsp;commit();<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;petLog(<img src="http://www.blogjava.net/images/dot.gif">);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">ok)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rollback();<br>&nbsp;&nbsp;}</span></div> <br>
</blockquote>
放弃try-catch，改用try-finally。这样就不需要捕获异常再抛出那么麻烦。然后用一个bool变量来告诉finally块是否需要回滚。<br>

<br>
这个代码不难理解，但是如果处处都用这个代码，也够丑陋的。<br>
<br>
既然已经用了spring，为什么不用spring的TransactionTemplate呢？用Spring TransactionTemplate（下面简称tt）的好处如下：<br>
1。事务代码不依赖hibernate，便于移植。<br>
2。自动得到异常安全，健壮的事务处理。写代码的时候几乎可以完全忘记事务的存在。<br>
<br>
当然，sparkle同学有他的道理。使用spring
tt需要实现TransactionCallback接口。而java的匿名类语法非常繁琐。更可恨的是，匿名类只能引用定义成final的局部变量，这
样在从tt里面往外传递返回值的时候就非常不方便。我们可能需要这么写：<br>
<blockquote><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, 0);">//</span><span style="color: rgb(0, 128, 0);">xxx</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;Object[]&nbsp;result&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(Object[])tt.execute(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionCallback()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;doInTransaction(TransactionStatus&nbsp;status)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Integer(resultOfUpdateOperation1());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;resultOfUpdateOperation2();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Objetct[]{obj1,obj2};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;});<br>&nbsp;&nbsp;System.out.println(((Integer)result[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">]).intValue()</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>&nbsp;&nbsp;System.out.println(result[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">]);</span></div><br>
</blockquote>
多么丑陋的result[0], result[1]呀。其它还有一些变体，比如每个结果用一个Object[]，或者定义一个通用的Ref类来支持"get()"和"set()"。<br>
<br>
可是，这么多的方案，sparkle同学都不满意。也是，这些方案都免不了类型不安全的down cast。而处理原始类型的结果还需要装箱！<br>
<br>
<br>
因为这些原因，我构思了一个简单的spring tt的wrapper。一个Tx类。这个Tx类可以这么用：<br>
<blockquote><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, 0);">//</span><span style="color: rgb(0, 128, 0);">xxx</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Tx(){<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;result0;<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;String&nbsp;result1;<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;run(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result0&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;resultOfUpdateOperation1();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;resultOfUpdateOperation2();<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;after(){<br>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(result0</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>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(result1);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;&nbsp;}<br>}.exec(tt);</span></div><br>
</blockquote>
通过把局部变量定义成Tx类的成员变量，我们绕过了downcast和原始类型装箱拆箱的麻烦。通过把事务之后要执行的动作封装在after()这个成员函数里面，我们可以方便地引用run()里面产生的结果。<br>
<br>
<br>
下面看看Tx, TxBlock, TransactionBlockException这三个类的设计：<br>
<br>
<blockquote><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);">&nbsp;</span><span style="color: rgb(0, 0, 255);">abstract</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;TxBlock&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionCallback{<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;before()<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;Throwable{}<br><br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">abstract</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;run(TransactionStatus&nbsp;status);<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;after()<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;Throwable{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;lastly(){}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;exec(TransactionTemplate&nbsp;tt){<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tt.execute(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;after();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">(RuntimeException&nbsp;e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;e;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">(Error&nbsp;e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;e;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">(Throwable&nbsp;e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionBlockException(e);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastly();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;doInTransaction(TransactionStatus&nbsp;status){<br>&nbsp;&nbsp;&nbsp;&nbsp;run(status);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;&nbsp;}<br>}</span></div><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, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">abstract</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;Tx&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;TxBlock{<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">abstract</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;run();<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;run(TransactionStatus&nbsp;status)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;run();<br>&nbsp;&nbsp;}<br>}</span></div><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);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionBlockException&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;NestedRuntimeException&nbsp;{<br><br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionBlockException(String&nbsp;arg0,&nbsp;Throwable&nbsp;arg1)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">(arg0,&nbsp;arg1);<br>&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionBlockException(String&nbsp;arg0)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">(arg0);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;TransactionBlockException(Throwable&nbsp;e){<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">error&nbsp;in&nbsp;transaction&nbsp;block</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;e);<br>&nbsp;&nbsp;}<br>}</span></div><br>
</blockquote>
所有的代码都在这了（除了import）。<br>
这个小工具除了after()，还支持before(), lastly()。before()在事务开始前运行。after()在事务结束后运行。lastly()保证不管是否出现异常都会被执行。<br>
<br>
如此，一个薄薄的封装，spring tt用起来庶几不会让sparkle再以头撞墙了。<br>
<br>

<img src ="http://www.blogjava.net/ajoo/aggbug/27847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ajoo/" target="_blank">ajoo</a> 2006-01-13 07:49 <a href="http://www.blogjava.net/ajoo/archive/2006/01/13/27847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>