<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>阅读 修心 学英语</title>
    <description></description>
    <link>http://lerye.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>[翻译] 九个应该问你老板的问题</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/200723" style="color:red;">http://lerye.javaeye.com/blog/200723</a>&nbsp;
          发表时间: 2008年06月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h1>九个应该问你老板的问题</h1>
<p>本文的翻译来自 <strong><a href="http://suntips.cn" title="SunTips.cn">SunTips.cn</a>
</strong>
</p>
<p>&nbsp;</p>
<p><span style="font-size: small;">&nbsp;如果有个合适的机会, 你也许会有一堆问题要问你的老板.
                  </span>
</p>
<p><span style="font-size: small;">&nbsp; &quot;这样的发型你还付给他钱了?&quot;</span>
</p>
<p><span style="font-size: small;">&nbsp; &quot;你是不是每顿饭都要吃大蒜?&quot;</span>
</p>
<p><span style="font-size: small;"> &nbsp; &quot;你这么好的人怎么最后会和那么讨厌的人结婚啊?&quot;</span>
</p>
<p><span style="font-size: small;"> &nbsp; 如果你还想保住工作, 这些问题最好永远放在肚子里.    &nbsp;不幸的是, 现在员工们都愿意把所有的问题都憋在肚子里,甚至包括一些说出来会对前程有益的问题.</span>
</p>
<p><span style="font-size: small;">
&quot;员工面对老板保持沉默是出于害怕失去信任, 害怕打击报复, 或者害怕自己的话被理解错误. 如果员工们选择沉默, 那就意味着忍受痛苦,&quot;
Kerry Patterson, &quot;Crucial Conversations&quot;的作者之一说.</span>
</p>
<p><span style="font-size: small;"> &nbsp;不管你保持沉默的原因是害怕惹麻烦,还是认为你的问题没有什么意义, 你都应该把它说出来.</span>
</p>
<p><span style="font-size: small;">
&quot;有个同事曾经对我说, '通过人们对我提的问题, 而不是他们对我诉说的内容, 我更能了解对方.'&quot; Edith
Onderick-Harvey, Change Dynamics Consulting,(一个优秀的行政顾问公司)
的懂事长说.&quot;对于管理者来说是同样的道理.
一些问题诸如公司的长远蓝景和当前的目标是什么,在实现这些目标的过程中你的角色所起的作用以及要求给予反馈,
这些会让你的老板认为你是专注于公司的事业, 而不只是为了一个工作.&quot;</span>
</p>
<p><span style="font-size: small;"> &nbsp;这里有九个应该向老板问的问题, 它们会对你的事业有帮助. (不要所有的问题一起问 -- 你的老板也许很忙.)</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;成功的标准是什么?&quot;</strong>
</span>
</p>
<p>
				  <span style="font-size: small;">
                  <!-- startclickprintexclude-->
<div class="cnnStoryElementBox"></div>
<!-- endclickprintexclude-->
				  </span>
</p>
<p><span style="font-size: small;">
&nbsp;员工们经常会忽略一个问题, 就是他们的工作表现是通过某种形式的审评认定的. &nbsp;为了能清楚你的工作成绩是如何被量化的,
你需要向你的老板提出这个问题. &nbsp;能清楚你的经理是只关心数字和结果, 还是同样也注重你的实现过程, Onderick-Harvey建议道.
&nbsp;这样, 你以后的工作活动就要基于他(她)眼中的重点.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;哪些方面我需要去努力从而能让事业有所提升?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">  &nbsp;这个问题是向你的老板表明你在主动把握自己的将来, 而不是等着别人能出什么事情来,Onderick-Harvey 说 &nbsp;如果你能够明确而有力的表达出事业目标,你的老板会告诉你在更上一层楼之前还有哪些经验需要掌握.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;我的哪些优点将会有助于事业上的发展?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">
&nbsp;不要总是专注于寻找自己的缺点却忘了发现自己的优点. &nbsp;你也许会认为自己知道自身的优缺点, 但是老板们却有他们自己的观点.
&nbsp;这并不是为了赚取称赞而找的一个借口, 它提供了一个机会让你向老板展示你想在事业上有所成就, Onderick-Harvey 说.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;员工工作表现评价是多久进行一次, 谁负责这些事情?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">
&nbsp;有些很基本的问题, 就像这个, 对你的工作表现特别重要, &nbsp;沃尔登大学的 Ivonne Chirino-Klevans 博士说. &nbsp;
了解你的所在公司的各种管理机制在任何时候都是个头等大事. &nbsp; 确定自己的季度或年度的目标, 让它们激励着做好每日的工作.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;公司里还有什么其它的发展方向可选择?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">
&nbsp;你也许会认为这个问题应该是在面试的时候说的, 但其实甚至当你被雇佣了很多年后, 还是值得问一问的, Chirino 说.
&nbsp;一个公司的结构一直都会在变化, 你应当能清楚对于事业上的进步,是否还有其他可以利用的机会. &nbsp;一旦你能清楚了你可以的选择,
你就能判断下一步的发展方向, 是瞄准一个新的职位?还是寻找一个更有前途的工作.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;我理解的对吗?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">
&nbsp;如果你有一个任务要处理, 而这个任务涉及到很多方面, 或者是涉及到一系列新的处理方式, 那么你要确定你真的能清了你的任务是什么.
&nbsp;承担一个任务, 但却没搞清楚干的方向是否正确, 如果到最后才发现,那就晚了. &nbsp;向你的老板验证一下,
确保你对所有任务的理解都符合他(她)的本意. &nbsp;该问题的问题如果不问, 很可能就会葬送了自己的前程, 尽管你也许完全胜任你的工作,
Chirino 告诫说.</span>
</p>
<p><span style="font-size: small;"> &nbsp;注意: 问这些问题选择好时机. &nbsp;没有老板愿意重复自己的话.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;我能帮你做点什么吗?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;"> &nbsp;这个简单的问题很重要但经常会被忽略, 行政指导Suzanne Bates这么说.  &nbsp;即使你帮不上什么忙, 你的老板也会注意到你的善意.&quot;高处不胜寒, 所以当老板看见你是希望他成功, 那你就在他心中脱颖而出了.&quot;</span>
</p>
<p> <span style="font-size: small;"><strong> &quot;我们最需要最关注的是那方面?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">
&nbsp;员工一般不会问这个问题, 因为他们担心自己不能胜任. &nbsp;的确,这涉及到一个人的责任心和整个团队的目标的问题.
&nbsp;当你有很多事情要处理,而老板继续给你派活时, 你要学会以重要性为顺序安排或处理这些事情. &nbsp;管理者都喜欢员工说一些有助于工作进展的问题,
Gayle Lantz(组织顾问,行政指导)说.</span>
</p>
<p> <span style="font-size: small;"><strong>&quot;这个任务可以让我去做吗?&quot;</strong>
</span>
</p>
<p><span style="font-size: small;">
                  
&nbsp;有太多的员工对自己的前程持放任的态度, 完全把它交给自己的老板, 就业问题专家 Rachelle J. Canter 博士说.
&nbsp;老板们都有他们自己的一大堆生活问题需要处理, 他们不会留下时间来为你的未来考虑. &nbsp;与其让自己的前程随波逐流,
不如主动寻</span>
找机会向他们证明你的积极态度和领导才能. &nbsp;创造锻炼的机会, 弥补自己的不足. </p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/200723#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 06 Jun 2008 00:08:43 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/200723</link>
        <guid>http://lerye.javaeye.com/blog/200723</guid>
      </item>
      <item>
        <title>我所知道的关于女人的 . . .(翻译)</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/199208" style="color:red;">http://lerye.javaeye.com/blog/199208</a>&nbsp;
          发表时间: 2008年06月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h1 class="heading">我所知道的关于女人的事 . . .</h1>
<p>本文的翻译来自 <a href="http://suntips.cn" title="suntips.cn">SunTips.cn</a>
</p>
<p>&nbsp;</p>
<p>我这样一个三十好几的男人, 已经花了20多年的时间去试图理解女人, 可还是没想明白. &nbsp;直到最近, 六个月前, 我终于看清楚了女人的思维是如何工作的. 
            </p>
<p>
这些全归功于Lou-Lou, 我两岁大的侄女. &nbsp;我想, 作为一个成年人, 我有义务教她一些有用的, 不是平时都能学到的东西, 因为这样,
我在教的过程中也长了学问.&nbsp; &nbsp;我教她如何眨一个眼睛, 如何噘嘴吐舌头, 如何打饱嗝, 以及从1数到10, 就像&quot;1,2,3,7,9,10&quot;,
对于我来说这几个数就够了, 我一直认为4,5,6,8 没多大用处.&nbsp;&nbsp; </p>
<p> &nbsp;作为回报,
在这两个月中我明白了很多关于女人的事, 比我自己花了20年研究出来的还要多. &nbsp;顺便澄清一下,
我并不是说女人们都像两岁大的小孩、要像小孩一样对待她们. &nbsp;我喜欢我的侄女。 &nbsp;我尊重我的侄女。
&nbsp;不仅仅只会逗她开心，我愿为她去扑向一个未爆炸的手榴弹。 &nbsp;当然只有当这个手榴弹会爆炸，要伤害到她时， 我才会这么做。
&nbsp;女人们都有自己的个性，我也把她们分过类，但是在两岁的 Lou-Lou 身上却保留着原味的， 未受影响的原型 &ndash; 成年女性的本质特征。
&nbsp;下面就是我学到的。 </p>
<p><strong>1 不理她们</strong>
</p>
<!--  #include file="m63-article-related-attachements.html"-->
<p> &nbsp;如果我一进门就冲着她，像个小丑似的蹦蹦跳跳的逗她，取悦她，她会完全漠然的看着。 &nbsp;就像什么都没看见似的。 &nbsp;但如果我是直接的走过她，这样，我保证她会大叫着我的名字让我跟她玩。 </p>
<p><strong>2 贿赂她们</strong>
</p>
<p> &nbsp;送礼物非常有效。 &nbsp;特别是那些会叫唤的会闪光的东西。 &nbsp;对于Lou-Lou，这些指的就是会唱歌的胖胖的小动物或者是漂亮的发卡。 &nbsp;对于成年女人们来说， 我想等效于，只是猜测，车和首饰。 </p>
<p><strong>3&nbsp;&nbsp;恭维她们</strong>
</p>
<p>
&nbsp;我曾经一直错误的认为：赞美就像钻石一样，因为稀少而珍贵。 &nbsp;当它们充斥于市场时就失去了所有的价值。 &nbsp;事实不是这样的。 &nbsp; Lou-Lou
大便正好拉在了尿布上，所有人都为她欢呼 &ndash; 就好像她给这个闹饥荒的世界带来了一种可行的解决方案似的 &ndash; Lou-Lou
会眉开眼笑的瞪着着她放光的大眼睛。 &nbsp;同样的道理对成年女人也一样，尽管，当然了，只适用于里面的基本原理，并不是指这里给出的特例。
(我从Lou-Lou身上学到这一点可受了不少苦.) </p>
<p><strong>4 倾听</strong>
</p>
<p>
&nbsp;我曾经花费我所有的时间研究女人究竟想要什么。 &nbsp;现在不用再为这个烦恼了。 &nbsp;我发现只要用心，Lou-Lou
会很清楚的告诉我她想要的：吃，跳舞，球，蹦蹦，跑，唱歌，玩，读书。 &nbsp;这样我就只需要照办就行了。
&nbsp;如果我认真听了，然后照办就行了，那我的生活可就简单容易多了。 </p>
<p><strong>5 道歉</strong>
</p>
<p>
&nbsp;你做了什么并不重要。 &nbsp;甚至你即使不知道曾做错过什么也不重要。 &nbsp;我曾经怠慢的在Lou-Lou 的幼儿车里放错了布娃娃。
&nbsp;对于你或我看来是多么轻微的错误呀，可对于她来说，跟干了种族灭绝的事有什么区别。 &nbsp;这时对你来说最好的做法是请求得到她的宽容和谅解。
&nbsp;你必须看起来是诚恳的。 &nbsp;你不必非要很<em>诚恳， </em>
但至少看起来要诚恳。 &nbsp;这个道理是如此的基本，可是有多少人这样做了？ </p>
<p><strong>6 随她们去</strong>
</p>
<p>
&nbsp;不管她们想干什么。 &nbsp;无论这事对你来说看起来是多么的荒诞，随她们做去。 &nbsp;当Lou-Lou在她脑子里有个想法时，我不会说任何阻止她的话。
&nbsp;事实上是却鼓励，支持她。 &nbsp;然后坐回来，希望她自己能发现那是一个多么愚蠢的想法。 &nbsp;就怕她最后还是认为那是一个极好的主意。
&nbsp;有一天，我发现自己整整两小时都在玩布娃娃的茶杯组件，而且假装着喝很多很多的茶，而且想像着整个一下午都在尿尿。 </p>
<p><strong>7 不要告诉她们该怎么做 </strong>
</p>
<p> &nbsp;如果想让她做你希望但她不一定会喜欢的事情，那就要说服她去做。 &nbsp;聪明的办法是让这看起来是她自己的主意&ndash; 还要让她觉得会很有意思。 &nbsp;我引以为豪的一件事情就是说服Luo-Luo去看橄榄球决赛，让她认为这比在沙滩上玩耍还有意思。 </p>
<p><strong>&nbsp;8 不要向她们诉苦</strong>
</p>
<p> 这是需要慎重的事情。 &nbsp;在这里，我的意思是不要把你的鸡毛蒜皮的麻烦变成她的负担。 &nbsp;当我就一个糟糕的会谈或腰痛向Lou-Lou诉苦时，她一点都不关心，但是如果真正的有不好的事情发生时，她会本能的发出同情，给我一个拥抱，给我意想不到的安慰。 </p>
<p><strong>9 不要争吵</strong>
</p>
<p> &nbsp;这个道理简单的不需要说明。 &nbsp;你永远不会赢，即使你争吵赢了，那也是个无意义的胜利，因为她的之后的心情会一直影响着你。 &nbsp;很简单，谁会希望没事找事呢？ &nbsp;这就产生了我最后的也是最重要的观点： </p>
<p><strong>10 别让她们哭啼</strong>
</p>
<p>
&nbsp;没有任何事情能比这个让我更痛苦 -
看着Lou-Lou大大的无辜的充满泪水的棕色眼睛，同时嘴巴张的大大的，流着口水，发出悲哀的空袭警报声，能刺穿我的整个心脏。
&nbsp;我完全被她的哭泣击溃。 &nbsp;而且没有任何的办法。 &nbsp;吃的？ &nbsp;模仿猴子？ &nbsp;骑马？ &nbsp;用筷子夹自己的眼睛？
&nbsp;不是为了她，是为了让她停止哭，我愿意做任何事情。 </p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/199208#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 01 Jun 2008 20:44:41 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/199208</link>
        <guid>http://lerye.javaeye.com/blog/199208</guid>
      </item>
      <item>
        <title>(翻译)兰迪教授在卡内基·梅隆大学的最后一课</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/182074" style="color:red;">http://lerye.javaeye.com/blog/182074</a>&nbsp;
          发表时间: 2008年04月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="story_byline">本文的翻译来自&nbsp;&nbsp; <a href="http://www.new6.net" title="译术人生网" target="_self">译术人生网</a>
<br />
</div>
<div class="story_byline"><br />
</div>
<div class="story_byline">By Mark Roth, Pittsburgh Post-Gazette</div>
<div class="story_image_box_size_3">
<div class="story_image"><img class="image_size_3" src="http://www.lerye.net/archives/2008-03/CMU-professor-gives-his-last-lesson-on-life_files/20070919pprandypausch_500.jpg" alt="" />
</div>
<div class="story_image_byline">Pam Panchak/Post-Gazette</div>
<div class="story_image_caption">Randy Pausch talks to the standing room only crowd at CMU's McConomy auditorium yesterday.</div>
</div>
<!--    end story_image_box_size_3 -->
<p>  &nbsp;昨天在卡内基-梅隆大学, 兰迪教授在他的告别课上, 一开始就给自己的演讲定下了这样的基调.</p>
<p>&nbsp;&quot;如果我看起来不够忧郁郁闷，抱歉让你们失望了。&quot;,&nbsp;&nbsp; 46岁的已经得了绝症胰腺癌的计算机科学教授兰迪.波许这样说.</p>
<p>&nbsp; &quot;并不是没有意识到自己只有几个月的生命了', 面对拥挤在校园里McConom礼堂里的400听众以及通告网络收听他的演讲的成千上万的听众,他解释道. </p>
<p>&nbsp;其实是&quot;我的现在的状态是前所未有的好;这也许和你们的想像产生了巨大的冲突--事实上, 我比你们大部分人的体力都好,&quot; 他说</p>
<p>&nbsp;然后, 为了感谢听众的笑声和掌声, 兰迪教授趴在讲台地板上做了一些俯卧撑.</p>
<p>&quot;你们中谁想哭的或者是怜悯我的人可以过来趴在这儿做一阵俯卧撑, 然后你们再怜悯,&quot; 他说.</p>
<p>&quot;今天我要说的,&quot; 他继续道, &quot;不是癌症, 因为我已经花了太多的时间谈论这个话题 ... 而且 我们也不谈论那些更重要的事情, 例如我的妻子和我的(学龄前)孩子, 虽然我很乐观,但我还没有坚强到谈论他们时而不落泪.&quot;</p>
<p> &nbsp;他在那儿探讨的是如何实现童年时的梦想以及他的人生旅途中的种种经验教训。</p>
<p>&nbsp;当还是个孩子时, 兰迪教授说,他有一些很明确的梦想: 他想体验零重力的感觉; 他想参加全国橄榄球联盟; 他想给世界大百科全书写作(&rdquo;书呆子从小就可以看出来。&rdquo;,他开玩笑地说.);&nbsp; 他想成为&quot;星际迷航&quot;的库克船长; 还有他想为迪斯尼工作.</p>
<p>&nbsp;最终, 他还是基本上实现的所有的这些梦想, 他说--尽管他的足球水平没有达到NFL的高度.</p>
<p>&nbsp;在卡内基的十年里, 兰迪教师创建了&quot;娱乐技术中心&quot;,就在昨天,一个视频游戏的首席执行官称之为世上首选的使用视频以及其他交互工具教育学生的技术.</p>
<p>&nbsp;他还创建了一个一年一度的虚拟现实竞赛, 这个竞赛已经风靡各大校园. 他还帮着创建了Alice课程, 这是一个基于卡通动画的课程, 用来帮助高中和大学里的学生在学习计算机编程时如何发现乐趣.</p>
<p>&nbsp;正是这样些虚拟现实的工作,--参与者戴着眼罩耳目, 这可以让他们进入一个人造的数字虚拟环境--让他赢得登上美国空军飞机体验零重力的机会.这是航天局专门提供实现虚拟技术模型研究的学生准备的奖品.</p>
<p>&nbsp; 虽然他的橄榄球运动在大学里就终止了, 但他说从橄榄球运动里体验到的东西要比他实现的其它童年梦想过程收获的都要多.</p>
<p>&nbsp;在另外的一些事情里, 他懂得了教员责备犯错误的自己的价值, 因为在一次特别不愉快的事件后有个助教告诉他, &quot;当你把事情能糟但没有人责备你时, 这就意味着他们放弃了你.&quot;</p>
<p>&nbsp;虽然他没有成为那个库克船长, 扮演库克船长的William Shatner近几年却访问过他.</p>
<p>&nbsp;&quot;跟你童年时代的偶像见面是在是太棒了,&quot; 兰迪教师说. &quot;当他来我这里看我是如何在实验室里工作时,他还是那样酷.&quot;</p>
<p>&nbsp;他也是因为这个工作才有机会给世界百科全书写介绍虚拟现实的文章.</p>
<p>&nbsp;由于他的名气和和才华, 兰迪教授说服了迪斯尼的官员让他在年假时进入公司帮助设计阿拉丁的魔毯和加勒比海盗的虚拟现实装置.</p>
<p>&nbsp;就在最近, 他得到跟 Electronic Arts 这个视频游戏公司合作的机会, 这种关系得以让卡内基大学有权在Alice课程中使用这个公司的著名的Sims动画技术.</p>
<p>&nbsp;昨天演讲接近结束时, 兰迪教授给了她妻子, Jai, 一个惊喜, 为她周一的生日送上了一个蛋糕, 而且让所有的听众为她唱生日歌. &nbsp;他的妻子用了很久止住眼泪来吹熄蛋糕上唯一的蜡烛.</p>
<p>&nbsp;为了向他的妻子和他的事业致敬, Electronic Arts公司宣布设立一个奖学金来奖励那些卡内基大学里值得尊敬的女性计算机专业的学生.</p>
<p> &nbsp;学校也宣布将会把他的名字刻在连接新技术科学大厦和          Purnell艺术中心的桥上, 象征他把这两专业连接了起来.</p>
<p>&nbsp;兰迪教授的不幸是从一年前开始的, 当时他感觉到浮肿, 肠胃运动不正常, 他在一封e-mail里谈到这些. &nbsp;当医生给他做CT扫描看他是否有胆结石时, 发现了一个肿瘤.</p>
<p>&nbsp;&quot;我从医生那里得到了这个消息,&quot; 他写道, &quot;医生说:'你的胰脏上有问题, 老天对你不公平.'&quot;</p>
<p>&nbsp;&quot;后来我告诉他, 这是很不幸,也很不走运, 但不是不公平. &nbsp;我也经常对我5岁的孩子说, 当你没有得到你想要的东西时, 不要说'这不公平'. &nbsp;我们每个人都有被癌症飞镖丢中的风险.&quot;</p>
<p>&nbsp;在他的一个博客中跟踪记录着他的治疗情况,兰迪教授想一切办法努力的增大自己的生存几率. &nbsp;他知道这是很难的. &nbsp;尽管治疗技术在进步, 胰腺癌患者只有百分之五的人能活过5年. &nbsp;甚至1年存活率的也只有26%.</p>
<p>&nbsp;第一步是做手术, 恰好是一年前的今天在匹兹堡医疗中心进行的. &nbsp;大夫割掉了他的胆膀胱, 三分之一的胰脏, 部分的胃和几英尺的小肠.</p>
<p>&nbsp;当伤愈后, 兰迪教授发现休斯顿的<code>M.D. 安德森医院正进行一项实验, 利用高毒性的放射和化学治疗, 可以将胰腺癌的五年存活率提高到45%.</code>
</p>
<p>
&nbsp;这种治疗从11月开始,直到次年的五月份结束. &nbsp;&quot;情绪最低落的时候&quot;, 教授写道, &quot;是在去年的圣诞节:我的妻子和孩子在Norfolk,
我却在Houston 把毒药灌进我的动脉.&quot; &nbsp;我从来没有放弃过, 但是就在那一天我却是很难接受那样的残酷的现实.&quot;</p>
<p>&nbsp;但是随后, 完成放射疗和化学疗法不到一个星期, 兰迪教授就又和他的娱乐运动联盟的队员们玩起了旗橄榄球.</p>
<p>&nbsp;&quot;第一次玩这个运动, 我冲过了中场25码的距离,&quot; 他在日记写道. &quot;当然, 我是累的气喘吁吁, 但是回到运动场地的感觉真好.&quot;</p>
<p>&nbsp;在夏天7月份, 最初的检查显示他的癌症已经消失了, 他又在Baltimore的Johns Hopkins 医院使用一种试验性的癌症疫苗做了两轮治疗.</p>
<p>&nbsp;可是之后, 就在上个月,感到终于康复了的兰迪教授在他的日记里向他的读者送出了这样的消息: </p>
<p>&nbsp;&quot;最近的一次CT扫描显示我的肝脏里有10个肿瘤块, 而且我的脾脏里附满了小肿瘤. &nbsp;医生们说这是他们见过的最猛烈的病情反复.&quot;</p>
<p>&nbsp;他和他的妻子Jai搬到了Chesapeake,Va. 这样Jai和她的家人近些. &nbsp;他们已经开始考虑身后之事了, 兰迪教授使用一些缓和的化学疗法来争取多一点的时间.</p>
<p>&nbsp;&quot;我发现我确实很乐观,&quot; 他写道. &quot;唯一的我伤心的是想到孩子们--这并不奇怪, 我将不能看到他们如何学骑脚踏车这类的东西,这像是一个未能尽职的责任--我不能再把他们扶起来, 却把这些重担留给了妻子.&quot;</p>
<p>&nbsp;他现在正全部时间给他们的孩子制作视频. &nbsp;兰迪教授最近带着他最大的个孩子Dylan(5岁)去了一次迪斯尼, 他们和海豚一起游泳, 兰迪教授想只有这个孩子可能会对他留有一些直接的记忆.</p>
<p>&nbsp;妻子和孩子, 他说,&quot;对我意味着一切. &nbsp;他们给了我生活的意义和快乐的海洋, 这些快乐不是工作能带来的, 虽然我有很多杰出的工作.</p>
<p>&nbsp;&quot;我希望我的妻子以后能再婚. &nbsp;我希望她和孩子们能记得有个人曾爱着他们, 愿意为他们付出一切.&quot;</p>
<div class="story_first_published">First published on September 19, 2007 at 12:00 am</div>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/182074#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Apr 2008 13:32:29 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/182074</link>
        <guid>http://lerye.javaeye.com/blog/182074</guid>
      </item>
      <item>
        <title>一场关于GPL第三版的论战</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/99350" style="color:red;">http://lerye.javaeye.com/blog/99350</a>&nbsp;
          发表时间: 2007年07月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          前段时间看到有文章说GPL许可证里有什么灰色地带,我当时还不明白,不过最近看了一篇文章,才明白GPL里有很多故事,读起来就像下面这个图一样,这是很有意思<br />
<a href="http://i.cmpnet.com/informationweek/1130/130IDplateFinal_110.jpg"><img src="http://i.cmpnet.com/informationweek/1130/130IDplateFinal_110.jpg" alt="http://i.cmpnet.com/informationweek/1130/130IDplateFinal_110.jpg" /></a><br />
<br />
这篇文章叫做&quot;
<h1 class="storyHeadline" style="margin-left: -2px; padding-left: 1px; letter-spacing: 0px; text-align: left;">he Controversy Over GPL 3</h1>
有三部分,下面是我翻译的第一部分的内容,供大家参考,<br />
<br />
<br />
<h1 class="storyHeadline" style="margin-left: -2px; padding-left: 1px; letter-spacing: 0px; text-align: left;">   关于GPL3的争论(一)</h1>
<br />
<div class="storyDek" style="background-color: white; margin-left: 0px;"> 这个下一版的开源软件许可证正在使整个开源社区分裂,它到至今还没有正式发布.</div>
<div class="IntelliTXT">  自由软件运动里的各社团正在因为这个最流行的开源许可证(the General Public License, or GPL)的下一个版本而发生分裂. 这种意见冲突看起来要超出家庭内部矛盾的形式,因为这将会严重的影响那些公司在将来如何使用开源软件的问题.
<p> </p>
<p> 这个新版的GPL(总共三版,1991年第一版)预计将会在下个月发布. 但是由于对其中几个新条款的争论--以及制定者想知道微软和Novel关于Linux的合同的结果--把发布日期拖延到了今年晚些时候.  </p>
<p> </p>
<p>  除非从根本上重新制定GPL第三版(程序员术语GPLv3),会有很大一部分开源社区将拒绝接受它,他们的首领是Linus Torvalds,Linux之父.&quot;如果GPLv3限制了用户如何使用代码,我将不会对GPLv3签字,&quot;Torvalds在给 <em>InformationWeek</em>的一封长信中这样说. </p>
<p> </p>
<p>  如果流行的GPL项目随着时间的流逝分裂成了两不兼容的产品--那些在GPLv3下开发的和在GPLv3下开发的--这会增加对那些已经使用了这些开源软件的企业的许可认证和兼容工作的复杂性.  </p>
<p> </p>
<p> 正当开源软件的商业兴趣快速增加时,这个事情发生了.  Linux是作为一个服务器操作系统发展起来的--在 <em>InformationWeek</em>的 最近的优先选择调查中三分之一的回答者选择在他们的2007项目中使用Linux服务器--它在PC操作系统领域也正产生日益重要的影响,它被部分的当作 Windows Vista的替代品.&nbsp; 在欧洲,根据European Commission的一项研究,按照目前的使用率,到2010年,所有的IT软件服务将会有32%是由开源代码提供.</p>
<p> </p>
<p> Terry Barbounist,&nbsp;&nbsp; <em>Christian Science Monitor</em>的首席技术执行官 说他的企业&quot;在开源社区里的掠夺&quot; 主要是利用社区里的开发者. &nbsp;<em>Christian Science Monitor</em> 公司使用了开源的内容管理系统Alfresco, 而且和其他开源软件一起使用. 他是否关注关于GPLv3的讨论,因为&quot;对于一个需要自己管理的社区里的任何分裂都不会是一个好事情&quot;. </p>
<p> </p>
<p>
<table cellspacing="0" border="0" align="left" cellpadding="0" width="185">
    <tbody>
        <tr>
            <td width="175"><img src="http://i.cmpnet.com/informationweek/1130/130IDStallman.jpg" alt="Bare facts: What's the difference betweekn free and open? Ask Richard Stallman, who wrote the first GPL" /></td>
            <td rowspan="3" width="10"><img src="http://i.cmpnet.com/infoweek/spacer.gif" border="0" vspace="0" height="5" hspace="0" alt="" width="10" /><br />
            </td>
        </tr>
        <tr>
            <td align="center" width="175"><img src="http://i.cmpnet.com/infoweek/spacer.gif" border="0" vspace="0" height="4" hspace="0" alt="" width="175" /><br />
            <span class="artCaption"><strong>Bare facts: What's the difference betweekn free and open? Ask Richard Stallman, who wrote the first GPL.</strong></span></td>
        </tr>
        <tr>
            <td width="175"><img src="http://i.cmpnet.com/infoweek/spacer.gif" border="0" vspace="0" height="7" hspace="0" alt="" width="175" /></td>
        </tr>
    </tbody>
</table>
<strong>关于代码的规定</strong><br />
这 里有许多种开源许可证,但是只有少部分被用来约束这些代码的商业使用. 最流行的是GPL,1989年产生了第一版. 这个GNU GPL,如官方所说(GNU代表Gnu's Not Unix,文字游戏),跟政治声明一样,是一个契约,提倡软件源代码的自由发布和修改,反对个人私有和商业利用. 它是由Richard Stallman写的,这个人在1985年建立了自由软件基金会.</p>
<p> </p>
<p> 谈论起Stallman的有趣的性格就像谈论作为一个有趣的篮球运动员的罗德曼一样. 在上世纪八十年代,Stallman几乎是程序员嬉皮士精神的化身:反资本主义,反独裁,麻省理工学院人工智能实验室里疯狂的程序员,而且会在桌子下面睡 着,他始终找不到一个真正的工作. 然而,有时他会被认为是预言家. Stallman激进的software-wants-to-be-free理论(被他称做&quot;copyleft&quot;)导致了GNU工具集的产生,在这些无价 的IT工具中就有GNU C 编译器,然后就有了GPL,它最终对开源软件产业的发展产生了指导作用. </p>
<p> </p>
<p> 想要理解目前所争论的本质,最主要的是理解自由软件和开源软件之间的区别. 自由软件的倡导者希望软件不受专利权,限制性的,专利性的许可制度的影响. 开源软件倡导者更实际化,接受基于开源软件代码的商业产品.</p>
<p> </p>
<p> Stallman拒绝关于这个事件的采访,并说<em>InformationWeek</em>'经常不把Linux说成GNU Linux. 这个要求反映了两个阵营间的紧张关系来源已久. Torvalds被大家信任并掌管着Linux的内核. Stallman说这个内核是基于基金会改编的未完成的操作系统之上. Torvalds相信基金会和GNU tools对Linux的成功所做的贡献.但他经常会反对基金会制定的基本章程.</p>
<p> GPL最受争议的特征--到目前--是它的一个条款,要求任何人修改了一个自由软件的源代码,都必须发布这个修改,让社团得到这个修改的版本. 现在这个&quot;giveback&quot;的要求被很多人认为是开源软件与众不同的,有益的特征.</p>
</div>
GPLv2已经被证明非常的有生命力和实效,开源宿主网站SourceForge下的处于开发状态的143,562个项目中有72%的是采用 GPLv2.&nbsp; 它让开源软件里的最成功的三个有了掌管自己数据的方法:Linux操作系统,MySQL数据库,和Window-Linux文件共享系统,也就是 Samba.
<p> </p>
其它的许可证用不同的方式控制开源软件. <br />
<br />
(第一部分完)
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/99350#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 09 Jul 2007 11:13:27 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/99350</link>
        <guid>http://lerye.javaeye.com/blog/99350</guid>
      </item>
      <item>
        <title>SOA? CORBA? 缩写首字母变了, 窘境依然</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/89509" style="color:red;">http://lerye.javaeye.com/blog/89509</a>&nbsp;
          发表时间: 2007年06月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SOA (面向服务的架构)好像已经成了很时髦的话!!! SOA可以解决所有的问题,每个人都希望用SOA--我听说的差不多就是这样. 然而,当CORBA诞生时,我记得也是这样相似的声明. 人们期望它能改变IT业的工作方式. 对我来说,SOA就是基于CORBA的拥有更完善标准的XML/SOAP. 我可能错了.<br />
<br />
然 而时间到了现在,却没有什么变化. Well,也许不是没有改变,至少有一点可以确定 -- IT复杂度正在以一种恐怖的速度增加,我真的不知道 -- 在失控之前,我们最大能承受的复杂情况是什么样子? 网上购物网站最担心这种事情,他们花了大成本去处理这种复杂度. 我有一个问题 --- SOA的引入真的能帮助IT人员更好的管理复杂度和降低成本吗? 还是在CORBA后面重蹈覆辙? 目前为止我看到了它在这个领域起的积极作用,但也有不少的怀疑的声音.<br />
<br />
我能确信的是那些组织机构正在寻找一些新的方式来利用这种技术,将它变成一种竞争优势. 掌控这种新的日益复杂的平台会只是一种挑战.<br />
<br />
我的观点认为SOA的引入只会把IT复杂度推向一个新的高度,超过了那些目前能够有效的实施管理的管理架构. 为什么我要这样说? 有几个理由:<br />
<br />
<br />
-- 以SOA为基础应用需要一些能够更快的适应需求改变情况的管理工具,而目前的管理工具却不要求这样.<br />
<br />
--以SOA为基础的应用会把大量的各种非集成的业务组合到一起,创建一个集成的业务层,而这种集成的东西却不能被那些以事件触发为基础的健康监控程序监控到.<br />
<br />
那些需要用来管理SOA环境的大量的工具和技术本身就需要去维护了,过于复杂了. <br />
<br />
如果管理不好,或者不能系统的降低和简化,复杂性会呈指数级上升.<br />
<br />
所以SOA架构有一个潜在的特征就是把事情复杂化,复杂化到不能控制,它比那些典型的3层结构, client/server或者是monolithic应用的管理复杂的多. <br />
<br />
这样一来,我们如何去处理它一方面有优势而另一方面会增加复杂性的关系呢? 我觉得只有一个办法可以解决这个 -- 在SOA管理工具上和管理经验是多下投资. 不仅需要技术,而且需要技能,过程方法,和实践经验. 这里有几种方法看起来很有吸引力:<br />
<br />
*虚拟化 -- 处理复杂性的一种方法是简化工作环境&nbsp; -- do more with less -- 较少的硬件,较少的网络工作,较少的软件系统. Less is more very often(少经常会变成多).<br />
<br />
*建立和维护能力储备 -- 而不是工具储备或你需要去掌握的工具清单. 很显然,你需要掌握至少一种技术或工具所能发挥的所有重要的能力. 也许不需要第二种. 着重是技术的功效,而不是工具和技术本身. 使用这些技术储备可以简化你的工作环境.<br />
<br />
*使用KISS方法 -- 自从大学时代我喜欢这种方法. 保持傻瓜式和简单明了. 应用到每个可能的方面. 复杂的设备,构造很难去维护和管理.<br />
<br />
如果不加斟酌, SOA的优势就会被不断增加的维护工作所吞噬,服务质量会下降,收入会降低,顾客的忠诚对也会下降.  SOA环境实现的成功与否决定于均衡增长的策略 -- 不要仅考虑增加功能能力,也要考虑如何降低复杂度.<br />
<br />
<font size="3">about author:<br />
</font>&nbsp;&nbsp; </font><font size="3"><a href="http://thought-space-albertm.blogspot.com/">Albert Amashev</a> is a seasoned technology professional, and has worked in many large enterprise integration exercises. His professional interest lies in IT integration, performance tuning, and service-oriented architecture (SOA).</font><br />
<font size="4"> <br />
</font>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/89509#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 12 Jun 2007 17:17:17 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/89509</link>
        <guid>http://lerye.javaeye.com/blog/89509</guid>
      </item>
      <item>
        <title>Google在修补,改进MySQL</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/80853" style="color:red;">http://lerye.javaeye.com/blog/80853</a>&nbsp;
          发表时间: 2007年05月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="-1" color="#000000" face="tahoma,arial,sans-serif"><blockquote> 根据Google工程师Mark Callaghan的最近一篇blog所说,Google是使用MySQL的大用户,并且是MySQL的爱好者. Callaghan介绍了Google对MySQL代码基础做的一些修改和强化来使DBMS的更具可扩展展性和可管理性. 这些修改已经以GPL license方式捐献给了MySQL社团.</blockquote> <!--htdig_noindex-->  <!--/htdig_noindex-->     </font>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"> 当MySQL宣布支持这个流行的开源DBMS的公司的收益已经达到$50M,并且准备进行一次IPO的这一天,我们就可以感觉到大企业在关键使命的项目上 对MySQL的依赖正在增加. Google就是这样的大公司其中之一,Google工程师Mark Callaghan最近发表的这篇blog描述了Google对MySQL基础代码做的一些贡献.</font></p>
<blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"> 我们认为MySQL是个很棒的数据存储方案,当我们的项目需求需要这个数据在某些领域有所提高时,我们对MySQL做了些改善,主要是针对高效性和可管理性领域.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">  高可用性的特征包括支持半同步复制,监视从一个master到一个slave的binlog,应急恢复时及时把一个slave提升到master,在应急修复中保持InnoDB和复制的状态.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">可管理性特征包括用来监视table和account使用的资源的新的SQL语句. 这个包括了计算每个account和每个table取到的或者是被改变的行数的能力.  这同样也包括测量一个account执行SQL命令使用数据库的时间.</font></p>
</blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">Google Code页面中子项目的Wiki对这些改进有较详细的描述:</font></p>
<font size="-1" color="#000000" face="tahoma,arial,sans-serif">  </font><blockquote> <font size="-1" color="#000000" face="tahoma,arial,sans-serif">
<li><strong>Semi-synchronous replication</strong><br />
<p>MySQL的复制协议是异步的. master并不知道何时或者是否一个slave得到了复制事件. 这样很高效. 一个slave会请求一个file的某个偏移处的所有复制事件. 当它们准备好时master会把事件推给它们...</p>
<p>每个发送给半同步的slave的复制事件都需要额外的两个字节放在头部来指明这个事件是否需要答复. 这些字节会被slave IO线程剥去,剩下的事件信息会被正常处理. 当需要答复时,slave IO线程会用现有的连接去回应master.指示一个事务结束的事件,例如commit或者允许自动提交的insert,一般需要回复.</p>
</li>
<li><strong>Mirrored Binlogs</strong><br />
<p>我们已经修改了slave IO线程让它在master写入relay log时维护master的binlog的副本. 通过拷贝,保证这个文件拥有相同的名称和内容. 当这个完成后,slave就会在复制代理slave中透明的启用应急备份,直到所有的代理都镜像了binlog.</p>
</li>
<li><strong>Transactional Replication</strong><br />
<p>slave复制状态被存在两个文件里:relay-log.info and master.info. slave SQL线程向存储引擎提交事务,然后更新这些文件,指示relay log里的下一个事件将会被执行. 事务提交过程中如果slave mysqld被终止了,这个file update状态和复制状态不一致,slave SQL线程就会在slave mysqld重启时重复最后一个事务.</p>
<p>这个功能通过将复制状态存储在InnoDB事务log里来保护InnoDB 储存引擎. On restart, this state is used to make the replication state files consistent with InnoDB.</p>
</li>
<li><strong>Activity monitoring per table, account and index</strong><br />
<p>我们增加了一些代码来测量数据库的活动,统计每个account,table,和index的数据. 我们同时新增了一些SQL声明来显示这些数据.</p>
</li>
<li><strong>Asynchronous IO in InnoDB</strong><br />
<p>InnoDB在Windows上支持异步IO. Linux上,它在后台使用4线程去执行IO任务而且每个线程都是要同步IO... 当InnoDB在random IO中发现locality,当它检测到一个序列扫描时,它会发出预取请求. 然而,它只会使用一个线程去执行这些请求. 越多的IO请求被并行的执行时,多磁盘的server就被利用的越充分.</p>
<p>因为现在的服务器都使用大GB的内存,所有应该尽可能的使用直接的IO操作. 我们修改了InnoDB,让它能够配置用来在后台执行读写请求的IO线程的数目. </p>
</li>
<li><strong>Fast Master Promotion</strong><br />
<p>这些指令可以让一个slave迅速的提升为master. 因为我们可以让它不需要重启就能实现,所有很快.  有脏页面的数据库引擎,例如InnoDB,通常需要花很长时间去shutdown(超过一分钟)</p>
</li>
</font></blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">What features do you believe MySQL would really need in order for developers to use the open-source DMBS in demanding enterprise projects?</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/80853#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 18 May 2007 11:50:32 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/80853</link>
        <guid>http://lerye.javaeye.com/blog/80853</guid>
      </item>
      <item>
        <title>总结Java企业级应用十大性能问题</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/79762" style="color:red;">http://lerye.javaeye.com/blog/79762</a>&nbsp;
          发表时间: 2007年05月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span class="ts">Vincent Partington, (曾在参与过&nbsp;</span> <a href="http://java.apache.org/">Apache JServ</a>, the <a href="http://www.postgresql.org/">PostgreSQL</a> JDBC driver,&nbsp; MySQL <a href="http://www.worldserver.com/mm.mysql/">mm.mysql&nbsp; </a>jdbc driver.的开发) <font size="-1" color="#000000" face="tahoma,arial,sans-serif"><font size="-1" color="#000000" face="tahoma,arial,sans-serif">, 最近写了一系列的Blog,每篇都探讨了一个可能影响</font><font size="-1" color="#000000" face="tahoma,arial,sans-serif"> Java EE application性能的问题.</font> .他注意到,大多数性能问题的起因都是因为错误的使用技术,起因于开发人员没有完全的掌握如何去使用一种技术, Partington这样写道:</font>  <blockquote>
<p> <font size="-1" color="#000000" face="tahoma,arial,sans-serif">Java开发人员应该把性能当作他们的应用软件中的一个重要的质量需求来对待,在项目的从始至终都应该对这个问题保持注意.  Java开发人员应该和相关人员一起工作,例如服务器和数据库的管理员,这样能对提高他们的应用的性能很有好处...</font></p>
</blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><font size="-1" color="#000000" face="tahoma,arial,sans-serif">Partington在他的性能相关的系列主题文章中</font></font><font size="-1" color="#000000" face="tahoma,arial,sans-serif">不乏至理名言,下面是他写的将近10篇Blog的每篇的中心思想,由 <a href="http://docman.cn">docman.cn 翻译家</a> 提供.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><br />
</font></font></p>
<blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>10. 过多的事件记录</strong><br />
当你做事件记录时有两件事情发生. 首先是大量的字符串操作被执行...然后是把结果写入一个文件...</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>9. 错误的application server配置</strong><br />
J2EE specification麻痹了开发人员,让他们有了虚假的安全感,想一想??只要我的代码和J2EE兼容,它能正确的运行??... 开发人员不应该只是把它们的EAR文件丢给运行系统;开发人员应该和application server管理员一起工作来处理这.....</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>8. 错误的Java EE用法</strong><br />
这个问题在一些老的应用中特别流行,因为几年前POJO/轻量级的解决方案还没有出现.... 像Spring这样的轻量级框架允许开发人员挑选一些必须的基础服务(transactions, security, distributed objects). Java EE... offers all of them all of the time. </font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>7. 不必要的使用XML</strong><br />
XML有很多有意思的属性,这导致一般的企业Java应用的功能领域几乎都用到了它....  不幸的是XML操作是一个很耗CPU和内存的过程.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>6. 不适当的缓存使用</strong><br />
正确的缓存可以极大的提高你的Enterprise Java application的性能,它甚至是达到可接受的性能水平所必须的.但有时缓存过程本身却导致的你的性能问题.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>5. 过度的内存使用</strong><br />
过度的内存使用表现的两个方面:大量的地址分配(给短生命周期的对象使用)和每秒钟都有大量的对象.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>4. 糟糕的执行库</strong><br />
一些开发组很愿意往他们的WEB-INF/lib目录下或者是POM文件里堆砌JAR文件,不管它们是否真的需要这些(也不考虑所需要的功能是否已经被现 有的类库提供了),也不检查这些类库是否能提供很好的性能,也不考虑是否有一种更高效的替代类库,不去研究文档来学会如何正确的使用它们,不明了自己的应 用是如果使用这些类库的.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>3. 不正确的并发实现</strong><br />
一个主要的原因是竞争锁定,如果有多个线程调用发生这只能会成为一个问题..... 应用程序在执行轻量级的任务时运行的很好,而重负荷是却慢的近乎停止.....</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>2. 不必要的远程操作</strong><br />
一些案例中系统架构被设计成为内置了能够适用某些预期的将来可能出现的功能的功能,可这些预期的功能从来就没有实现...... 因为需要调用其他的系统和程序,Enterprise Java applications往往会使用远程操作,不必要的远程操作是伤害Enterprise Java applications效率的重要原因.</font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><strong>1. 错误的数据库用法</strong><br />
许多的企业Java项目里,数据库只是被当作一个简单的装字节的容器,DBA被当作一个只是在产品机器前执行SQL语句的人. 这种对数据库以及数据库专家的轻视导致了恶劣的应用程序执行效率.....</font></p>
</blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">What's the source of <em>your</em> #1 enterprise Java performance problem?</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/79762#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 14 May 2007 11:42:39 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/79762</link>
        <guid>http://lerye.javaeye.com/blog/79762</guid>
      </item>
      <item>
        <title>Spring is the new Java EE</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/78430" style="color:red;">http://lerye.javaeye.com/blog/78430</a>&nbsp;
          发表时间: 2007年05月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前些天曾经在Javaeye和一些网友讨论过&quot;Java EE 是什么?&quot;的话题,很多人对Java EE的范畴不是很了解.最近看到了Salil Deshpande--The Middleware Company 的执行总裁些的一篇文章,题目是:&nbsp; <a href="http://www.theserverside.com/tt/articles/article.tss?l=SpringNewJavaEE">Spring is the new Java EE version.,</a>讲了一些Spring的发展前景,我觉得这篇文章对我们了解什么是Java EE有所帮助, 下面的这小段是他写的这篇文章的最后的一段,算是个引用吧,由于翻译水平有限,里面一些不懂的地方用问号标记了,请大家迁就,如果能给出正确的翻译是最好了.这篇文章既有趣味又有技术性,值得一看.       <blockquote>关 于Spring详细的话题太大了,我不得不在这篇文章了里再详细介绍它一遍. Rod Johnson的一次关于Spring 2.0的谈话中提到,在2007年剩下的时间里Spring将会和OSGI集成. OSGI一个Java的动态模块系统,这个东西在起初就本该是Java的一部分. 奇怪的是,它却因为Eclipse(插件)而普遍的使用在client端,而不知大家所知的server端. Spring-OSGi集成可能将会成为OSGi标准. 并且作为Spring是一个松耦合的,组件架构的证明,Spring已经成为了OSGi的有效的捆绑包<br />
<br />
更长远的,Spring框架将会成为the Spring Portfolio(??). 它将会和JCA, CICS, and IMS集成. 会有Spring Web Services, 和 Spring LDAP. Spring的Message-driven POJOs将会成为可能. Acegi,这个领先的企业级Java安全框架,会成为Spring的Security框架. 跟Spring Message-driven POJO一样,会有Spring Web Flow. Spring在SOA中的角色会由于the Service Component Architecture (SCA)而标准化. 一个对Spring开发提供支持的IDE(由Eclipse插件实现)正在完善中,这个IDE提供了对AOP,Spring Web Flow的支持<br />
<br />
也 许最重要的是,Interface21计划把这一大堆组成Spring平台或者是Spring portfolio的小部件打包,把它们做成一个可下载的文件&hellip;or distro(??). 这并只是把它们评凑的一起的事情,而是要经过测试,集成,给它们正确的版本,让它们相互配合工作. 我相信这将会稳固它. Enterprise Java将会意味这Spring.<br />
<br />
最后,但并不是最不重要的,BEA,也许是IBM的下一代application server将会建立在Spring平台上.  不会是只有我发现了这些令人兴奋的事吧?</blockquote>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/78430#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 10 May 2007 10:06:32 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/78430</link>
        <guid>http://lerye.javaeye.com/blog/78430</guid>
      </item>
      <item>
        <title>J2EE成功背后的问题</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/75852" style="color:red;">http://lerye.javaeye.com/blog/75852</a>&nbsp;
          发表时间: 2007年04月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Dan Creswell(这个人在2004获得了Jini Contributors Award,而且是Apache River项目的重要成员)发表了一篇Blog"Victims Of J2EE Success,",其中谈到:现在J2EE已经在Java中间件中成为统治地位的技术标准,但一些特定的应用程序的需求却不能够使用J2EE所设计的标准去解决,例如eBay,MySpace或者Google,这时问题就产生了.<br /><br />对于J2EE编程者,他说:(下的的引用是从Blog中翻译的)<br /><br />   <div class="quote_title">引用</div><div class="quote_div"> ...程序员已经将他们的思维封锁在了J2EE里了,通常会这样想:<br /><br />       1. 除了数据库,还是数据库<br />       2. POJO只是针对业务逻辑<br />       3. 这是分布式程序设计<br />       4. Ops是其他人的事<br />       5. 通过部署更强大或更多的服务器来提供可伸缩性<br /><br />    大多数的企业可以很高兴的接受以这种方式建立的系统,但是如果你不是这个大多数中的一员呢? 如果你是eBay或者MySpace该怎么办?例如eBay已经抛弃大多数J2EE上的东西,他们开发了自己的librarie来解决他们所面对的问题.<br /><br />       1. Monitoring<br />       2. Hot Upgrades<br />       3. Scaling<br /><br />    基本上一旦你遇到的问题挑战超过了某个水平,J2EE方式的思考模式和设计模式就不能使用了. 到哪儿去找可以应对这一挑战的Java程序员呢？<br /></div><br />作者的文章里谈到一些其它技术,但核心的问题就是这个.<br />不知道各位有没有遇到他所说的情况?<br /><br />.<br />.
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/75852#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 28 Apr 2007 13:25:37 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/75852</link>
        <guid>http://lerye.javaeye.com/blog/75852</guid>
      </item>
      <item>
        <title>单元测试还是功能测试?</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/74575" style="color:red;">http://lerye.javaeye.com/blog/74575</a>&nbsp;
          发表时间: 2007年04月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">Cedric Beust,&nbsp; <a href="http://www.artima.com/lejava/articles/testng.html">TestNG</a> 测试框架的作者, 在他最近的一篇blog&quot; <a href="http://beust.com/weblog/archives/000444.html">Unit or functional?</a> &quot;说,   </font></p>
<blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">尽管在过去的几年里单元测试得到了大量的注意,但功能性测试却是让你的应用程序按照客户的期望运转的最终保证.</font></p>
</blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">Beust 通过一个例子解释了这个观点,这个例子中程序在单元测试中获得通过,但在功能测试中却显示有个错误. 因为最终用户只关心程序功能,Beust说, </font></p>
<blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">理想状况下,你希望你的程序既能被单元测试覆盖,也能被功能测试检测,但如果工期紧张,你只能选择其中之一,我...还是推荐后一种(因为它是为用户服务的),然后顺着走下去,在你认为合适的地方实现一些单元测试.</font></p>
</blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"> Beust同时指出,在一个测试套件里需要由功能测试和单元测试两部分共同组成,单元测试经常服务于功能性能测试失败的精确定位:也就是说,单元测试主要是对开发人员有用,但功能性测试却是测试用户们所关心的. </font></p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">根据Beust所说,一个由功能测试和单元测试共同组成的测试套件本质上会具有超过100%的测试覆盖率:</font></p>
<blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">超过100%? 可能吗? 我知道这个听起来有点怪,它却很简单的表明在这个类中运行所有的这些测试也许会让你的主程序里的某部分多跑好几次,但却不是一件没有价值的事情. 从另外一种方式考虑,只进行[功能性测试]也会得到100%的覆盖率,等价于只运行[单元测试].</font></p>
</blockquote>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif">当你的项目进度压力大时,什么样的测试你认为可以先放弃? 什么样的测试在你发布程序前必要要进行?</font></p>
<p>本文由 <a href="http://docman.cn">docman.cn 翻译家</a>&nbsp; 奉献</p>
<p>----</p>
<p><font size="-1" color="#000000" face="tahoma,arial,sans-serif"><br />
</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/74575#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 25 Apr 2007 10:32:19 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/74575</link>
        <guid>http://lerye.javaeye.com/blog/74575</guid>
      </item>
      <item>
        <title> JDBC 4.0 里的新东西</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/71556" style="color:red;">http://lerye.javaeye.com/blog/71556</a>&nbsp;
          发表时间: 2007年04月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <br />
<a href="http://jcp.org/en/jsr/detail?id=221">JSR 221:JDBC 4.0 API  specification</a>已经出现好几个月了,<br />
这个API规范对JDBC 4.0 的一些新特征进行了详细的说明,里面的内容很多,<br />
下面的译文只是对这些新特征里的一些主要的东西进行了简要的概述,<br />
个人觉得JDBC 4.0距离我们还有点远.<br />
<br />
下面的译文有 <a href="http://docman.cn">docman.cn翻译家</a> 提供<br />
<br />
<br />
<p>在JDBC 4.0的说明书里列出了大约有20个新的特征和改进,其中一些是主要的,另一些是次要的.  在这篇文章里我不可能把所有的这些都讨论到,我试图以它们提供的功能或者改进的内容将它们分类:</p>
<ol>
    <li>驱动器和连接管理  </li>
    <li>异常处理  </li>
    <li>数据类型的支持  </li>
    <li>API修改 </li>
</ol>
<p>下面的部分将按这些分类进行更详细的讲解.</p>
<h4 id="driver-and-connection-management">驱动器和连接管理</h4>
<p>从驱动程序的使用到连接和结果集管理--JDBC的各方面都有着许多新的特征和提高.下面的三个方面是最重要的.</p>
<h4 id="getting-connected-becomes-easier">获取连接变的更简易</h4>
<p>如果你已经使用JDBC编程有一段时间,我相信你仍然留着为了同目标数据库建立连接而遵循的典型步骤的清单. 这个清单里的第一条应该是加载一个合适的驱动.  你是否想过这个步骤可以改进一下,还是认为就该一直这样? 在JDBC的这个版本了他们确实做了改进. 你再也不需要调用  <code>Class.forName</code> 去显式的加载驱动了. 当你的应用程序第一次试图去连接数据库时,,  <code>DriverManager</code>&nbsp;会自动的把在应用程序的 <code>CLASSPATH</code>.里发现的驱动加载上.  这是这个版本的JDBC里主要新增的特征之一.</p>
<p>虽然现在&nbsp;<code>DriverManager</code> 可以自动加载了,但是,建立一个正确数据源对象仍然是推荐的获得连接的方式.  这样具有透明性和可移植性,因为数据源实例的属性可根据需要取得连接的不同数据库而修改.  你不需要为了连上一个不同的数据库实例甚至是一个需要加载不同的驱动的完全不同类型的数据库而改变你的应用程序代码,</p>
<h4 id="using-resultset-becomes-more-flexible">更加灵活的 <code>ResultSet</code>  用法</h4>
<p>现在&nbsp;<code>ResultSet</code>&nbsp;的接口层上提供了几个能促进编程灵活性的重要的特性. &nbsp;<code>RowSet</code>  子接口提供了一个可滚动的, 可更新的,&nbsp;以及可离线编辑的 <code>ResultSet</code>.  而&nbsp;<code>WebRowSet</code>&nbsp;子接口提供了能够从数据表中读取数据,将之序列化成XML文档,以及读取一个XML文档将之返序列化成结果集的能力  . 这些特征在&nbsp;OnJava&nbsp;文章 &quot;<a href="http://onjava.com/pub/a/onjava/2006/06/21/making-most-of-jdbc-with-webrowset.html">  Making the Most of JDBC with <code>WebRowSet</code></a>.&quot;进行了详细的讨论.虽然  <code>RowSet</code>&nbsp;接口在以前的 JDBC版本中出现过,但当前的版本中&nbsp;对 SQLXML&nbsp;数据类型 (以后讨论)  进行了支持,这些特征会使JDBC编程更加简化和灵活.</p>
<h4 id="more-apis-become-available">有更多的API可用了</h4>
<p>为了能够访问 <a href="http://en.wikipedia.org/wiki/SQL:2003">SQL:2003</a>里实现的特征,当前版本的JDBC里增加了一下新的API.  除此之外,有些添加到通用使用接口的方法是用来支持更简化和更好的处理数据的.</p>
<p>现在,让我们来看一下可以运行的代码,讨论一下下面这个 <code>Example1</code>&nbsp;类的执行结果. 它将会去连接一个嵌入式的Apache  Derby 数据库,将查询结果输出到控制台.尽管JDBC 4.0 已经发布了好几个月了,我发现,目前为之只有Apache Derby  这个一个数据库提供了对其支持的驱动,而且是部分实现了JDBC 4.0规范. 这篇文章的所有例子都是基于JDK 1.6 和Apache Derby  10.2.2.0 开发的. 因为是代码样例,我将只会向你显示这个相关讨论所涉及到的真正的Java源文件的一些片段.</p>
<pre><code><br />public class Example1 {<br />  public static void main(String[] args) {<br />    ...<br />    String dbName = &quot;example1&quot;;<br />    String tableName = &quot;stu1&quot;;<br />    ds = new EmbeddedDataSource40();<br />    ds.setDatabaseName(dbName);<br />    String connectionURL = &quot;jdbc:derby:&quot;+dbName+&quot;;create=true&quot;;<br />    try {<br />      con = ds.getConnection();<br />      stmt = con.createStatement();<br />      rs = stmt.executeQuery(&quot;select * from &quot;+tableName);<br />      int colCount= rs.getMetaData().getColumnCount();<br />      for (int j=0; j&lt; colCount; j++){<br />        System.out.print(rs.getMetaData().getColumnName(j+1) <br />          + &quot;\t&quot;);<br />      }<br />      while (rs.next()) {<br />        System.out.print(&quot;\n&quot;);<br />        for (int i = 0; i &lt; colCount; i++) {<br />         System.out.print(rs.getString(i + 1) + &quot;\t&quot;);<br />        }<br />      }<br />     } catch (SQLException e) { <br />           e.printStackTrace();<br />         }<br />     finally{<br />      //close connections<br />     }<br />   }<br />}<br /></code> </pre>
<p>如果在你的 <code>example1</code> 数据库的&nbsp; <code>stu1</code>&nbsp;表中有一些数据,那么编译运行  <em>Example1.java</em> 将会在控制台打印出如下内容. Here is what I got. </p>
<pre><code><br />ID    NAME            COURSE <br />1001  John Doe        Statistics     <br />1002  Jack McDonalds  Linear Algebra <br /></code> </pre>
<p>如果你想让&nbsp;<code>DriverManager</code>&nbsp;自动加载 JDBC 驱动,你可以把在Example1里调用的  <code>con=ds.getConnection()</code> 换成  <code>con=DriverManager.getConnection(connectionURL)</code>.这个类的输出结果会完全一致.  在这个例子里可以看到你不再需要显示的使用 <code>Class.forName()</code> 来加载驱动了.</p>
<h4 id="exception-handling">异常处理</h4>
<p>你是如何区分一个Java 程序是否健壮的? 我认为,异常处理的运用是一个重要的因素.  一个健壮的Java程序很好的处理异常情况,能够让程序在某些条件下从事故中恢复.  另一方面,糟糕的异常处理会导致一个程序生产错误的输出结果,最终会终止你的应用程序.</p>
<p>JDBC 4.0  为异常处理增加了一下简单但强大的特征,包括支持异常链,使用增强的for-each循环获取异常链里的异常.下面的Example2显示了用这种先途径处理异常链的Java  类的部分代码.</p>
<pre><code><br />public class Example2 {<br />  public static void main(String[] args) {<br />    String dbName = &quot;example&quot;;<br />    String tableName = &quot;student4&quot;;<br />    try {<br />      con = ds.getConnection();<br />          stmt = con.createStatement();<br />      rs = stmt.executeQuery(&quot;select * from &quot; + tableName);<br />    } catch (SQLException sx) {<br />      for(Throwable e : sx ) {<br />        System.err.println(&quot;Error encountered: &quot; + e);<br />      }<br />    }<br />    finally{<br />      //close connections <br />    }<br />  }<br />}<br /></code> </pre>
<p>我运行Example2.java 类,并指明student4作为表名,可是这个表是不存在的. 在下面的调用中会触发一个异常链.</p>
<pre><code><br />rs = stmt.executeQuery(&quot;select * from &quot; + tableName);<br /></code> </pre>
<p>在一个真实的应用程序中,你需要去捕捉这样的异常链,检查它们,作出相应的处理.  在这个例子中,我只是来说明如何将它们输出到错误控制台.下面的就是如何做到这些.</p>
<pre><code><br />for(Throwable e : sx ) {<br />  System.err.println(&quot;Error encountered: &quot; + e);<br />}<br /></code> </pre>
<p>下面的是运行Example2的输出:</p>
<pre><code><br />Error encountered: java.sql.SQLSyntaxErrorException: <br />   Table/View 'STUDENT4' does not exist.<br />Error encountered: java.sql.SQLException: <br />   Table/View 'STUDENT4' does not exist.<br />Exception in thread &quot;main&quot; java.lang.NullPointerException <br />   at ex.Examlpe2.main(Examlpe2.java:51)<br /></code> </pre>
<p>通过JDBC4.0,你现在可以使用少许的代码获取并迭代处理异常链了. 在以前的版本中,你必须去单独的获取异常链,并且通过调用  <code>getNextException</code> 来迭代处理异常.</p>
<h4 id="data-type-support">数据类型支持</h4>
<p>这个版本的JDBC增加了一些新的数据类型,对其它的类型的支持也有了增强. 我很高兴对XML的支持已经明确了,SQLXML,已经被加入了.  用我的观点,这个接口值得用一个单独的小节来讨论.</p>
<h4 id="sqlxml-and-xml-support">SQLXML and XML Support</h4>
<p>SQLXML是对应于SQL里的XML数据类型的一种Java语言的数据类型.XML类型是个内置的类型,用于将一个XML值存储成一个表里的一行的一个column值.  缺省的驱动实现了一个SQLXML对象,它是指向XML类型数据的逻辑指针,而不是直接指向数据的. 一个SQLXML对象在它被创建的事务处理过程中有效.</p>
<p>在下面的Examle3类中,我将向你展示如何从当前的连接中创建一个SQLXML对象以及用它更新数据表里的值.</p>
<pre><code><br />  public class Example3 {<br />    public static void main(String[] args) {<br />      ...<br />      con = ds.getConnection();<br />      SQLXML sx= con.createSQLXML();<br />      sx.setString(&quot;Math is Fun&quot;);<br />      String psx =&quot;insert into &quot;+tableName+ <br />        &quot; ( id, textbook) values(?,?) &quot;;<br />      PreparedStatement pstmt = con.prepareStatement(psx);<br />      pstmt.setString(1,&quot;1000&quot;);<br />      pstmt.setSQLXML(2,sx);<br />      pstmt.executeUpdate();<br />          ...<br />      }<br />    }<br /></code> </pre>
<p>这个例子只是向你展示了一个简单用法. 如果你继续研究,你会发现它会很有趣.  但是在我们继续深入之前,让我向你解释一下在运行Example3.java时发生了什么.  不幸的是,我没有能够取到SQLXML对象,这个程序终止了,输出了下面令人失望的信息:</p>
<pre><code><br />java.sql.SQLFeatureNotSupportedException: Feature not <br />   implemented: no details.<br />at org.apache.derby.impl.jdbc.SQLExceptionFactory40.<br />   getSQLException(Unknown Source)<br />... ... ... ...<br />at ex.Example3.main(Example3.java:62)<br /></code> </pre>
<p>这证明Apache Derby 并不支持从一个 Connection 里创建一个SQLXML对象.  但是你仍然将要看到我在Example3里想做的事:我要将 一个 id 字段值是1000,textbook字段(SQLXML类型)值是Math is Fun  的一行数据插入表中.</p>
<p>我下面将向你展示一个代码片段,它从一个表里读出XML值然后解析成一个Document对象.就将它当作这个小节的结束吧.</p>
<pre><code><br />SQLXML sqlxml = rs.getSQLXML(column);<br />InputStream binaryStream = sqlxml.getBinaryStream();<br />DocumentBuilder parser =<br />  DocumentBuilderFactory.newInstance().newDocumentBuilder();<br />Document doc = parser.parse(binaryStream);<br /></code> </pre>
<p>从数据表中读出字段的值并直接生成XML文档,是不是很棒? 我觉得这是个非常棒的特性.</p>
<h4 id="rowid-data-type">&nbsp;<code>ROWID</code> 数据类型</h4>
<p>SQL <code>ROWID</code> 表示数据表里的一行数据,它是最快的一种访问一行数据的方式.  这个版本中增加了一个新的RowId接口,用来提供从Java 类里访问ROWID SQL类型的方法.</p>
<h4 id="enhanced-support-for-large-object-types">Enhanced Support for Large Object  Types</h4>
<p>在JDBC 2.0 版本中增加了<font face="Courier New">Clob</font>, <code>Blob</code>,  <code>Array</code>, and <code>Struct接口来支持 CLOB, <code>BLOB</code>,  <code>ARRAY</code>, and <code>STRUCT</code> 等大SQL对象</code>  在当前的版本中增加了更多的对这这种数据类型的支持. 我将会在&nbsp;<a href="http://docman.cn/docs/?lang=encn&amp;id=13#apichanges">API Changes</a>  部分讨论几个这样的方法.</p>
<h4 id="support-for-national-character-set-ncs-conversion">对国际字符集转换的支持</h4>
<p>SQL:2003 提供了对<code>NCHAR</code>, <code>NVARCHAR</code>,  <code>LONGNVARCHAR</code>, and <code>NCLOB</code>.等数据类型的支持.  它们除了类似于&nbsp;<code>CHAR</code>, <code>VARCHAR</code>, <code>LONGVARCHAR</code>, and  <code>CLOB</code> 之外还能够用不同的字符集对值进行编码.,这被称做国际字符集 (NCS).  如果你的数据需要扩展的字符处理操作,你就不能使用常规的数据类型,而是要用NCS数据类型.  这个版本的JDBC增加了一些对NCS的新的支持,还对有些支持进行了强化.</p>
<ul>
    <li>向<font face="Courier New">PreparedStatement</font>,  <code>CallableStatement</code>, and <code>ResultSet</code>  接口里增加了一些setter和update方法来支持NCS转换.例如&nbsp;<code>setNString</code>,  <code>setNCharacterStream</code>, and <code>setNClob</code> 等方法就是这些新增的里的几个.  </li>
    <li>在 <code>SQLInput</code> and <code>SQLOutput</code>&nbsp;接口里增加了读和写的方法来支持  <code>NClob</code> and <code>NString</code> 对象. </li>
</ul>
<h4 id=""><a name="apichanges" id="apichanges">API Changes</a></h4>
<p>JDBC 4.0 里的强化的特征大多存在于API层,下面这小节会对此进行简短的讨论. 更多的细节请参考 <a href="http://jcp.org/en/jsr/detail?id=221">JSR 221:JDBC 4.0 API  specification</a>.</p>
<h4 id="array"><code>Array</code></h4>
<p>在Array接口里增加了一个'释放'方法用于释放array对象,并释放它占有的资源.</p>
<h4 id="connection-and-pooledconnection"><code>Connection</code> and  <code>PooledConnection</code></h4>
<p><code>Connection</code> 接口现在提供了一批用来创建大对象比如 <code>createClob</code>,  <code>createBlob之类的方法</code>.  其他的增加是对针对客户端信息的getter和setter方法的版本信息的覆盖,以及当前连接的有效性的检查.</p>
<p>现在&nbsp;<code>PooledConnection</code>&nbsp;接口提供了 <code>addStatementEventListener</code>  and <code>removeStatementEventListener 方法</code>&nbsp;,当你需要去注册和反注册一个  <code>StatementEventListener</code> 接口时,有了它事情会变得很容易, <font face="Courier New">StatementEventListener</font> 接口是在当前版本里引进的. 当  <code>Statement</code> pool.里的 <code>PreparedStatement</code>s  有事件发生时,这个接口的注册者的实例会被通知. 例如,当一个声明里的<font face="Courier New">PreparedStatement</font> 被关闭时,如果有过注册,驱动器就会调用所有<font face="Courier New">StatementEventListener里的statementClosed方法.</font></p>
<h4 id="databasemetadata"><code>DatabaseMetaData</code></h4>
<p>不同的关系数据库通常是支持不同的特征,用不同的方式实现特征,以及使用不同的数据类型.  这个会引起可移植性的问题,因为在一种数据库上工作的代码由于数据库底层实现的不同而不能在其他数据库上运行.  这些问题可以通过调用这个接口里方法获得一些扩展的使用信息来解决. 例如,假设你写一些代码通过传入一个SQL语句来创建一个表. 你可以通过调用这个接口里的  <code>getTypeInfo 方法来确定那些数据类型可以在CREATE TABLE 语句里使用.</code></p>
<p>这个版本的JDBC里增加了不少用来支持查询数据库原信息的方法. 在 Example4中,我用一个代码片段来演示用这个新功能来获得符合典型搜索条件的数据库  schemas 清单.</p>
<pre><code><br />con = ds.getConnection();<br />DatabaseMetaData dmd = con.getMetaData();<br />rs=dmd.getSchemas(&quot;TABLE_CAT&quot;, &quot;SYS%&quot;);<br />//iterate over the rs and print to console<br /></code> </pre>
<p>首先我调用 <code>dmd.getCatalogs</code>&nbsp;,遍历它的结果集只得到一个<code>TABLE_CAT分类</code>.  然后我使用这个值通过调用 <code>rs=dmd.getSchemas(&quot;TABLE_CAT&quot;,  &quot;SYS%&quot;)</code>.来搜索数据库中以SYS开头的schemas. 下面是我得到的table schema清单: </p>
<pre><code><br />SYS<br />SYSCAT<br />SYSCS_DIAG<br />SYSCS_UTIL<br />SYSFUN<br />SYSIBM<br />SYSPROC<br />SYSSTAT<br /></code> </pre>
<h4 id="scalar-function-support">标量函数支持</h4>
<p>一个标量函数处理一个输入的预定义的集合,返回处理结果. 例如调用标量函数 <code>ABS(number)会返回number的绝对值.</code>  这些函数可以作为Java代码里的SQL句子的一部分. 如果底层的数据库支持下面的新标量函数: <code>CHAR_LENGTH</code>,  <code>CHARACTER_LENGTH</code>, <code>CURRENT_DATE</code>,  <code>CURRENT_TIME</code>, <code>CURRENT_TIMESTAMP</code>, <code>EXTRACT</code>,  <code>OCTET_LENGTH</code>, and  <code>POSITION,这个版本的JDBC就需要它的驱动实现对这些的支持.</code></p>
<h4 id="statement-preparedstatement-and-callablestatement"><code>Statement</code>,  <code>PreparedStatement</code>, and <code>CallableStatement</code></h4>
<p>Statement接口现在提供了一个isClosed方法来查询statement是否被关闭了,一个setPoolable方法,当你想让这个statement被poolable或者non-poolable是用它来设置,一个isPoolable方法来检查当前的statement是否是poolable的.</p>
<p>&nbsp;<code>PreparedStatement</code> and  <code>CallableStatement</code>&nbsp;接口提供了更多的方法来通过<font face="Courier New">InputStream</font> and <code>Reader</code>&nbsp;插入大数据对象.</p>
<h4 id="wrapper">Wrapper</h4>
<p>这个版本的API中增加了一个Wrapper接口,这接口提供了一个用于访问一些由于架构的原因而被封装的资源的实例的机制. 这个封装范式,也叫做 <a href="http://en.wikipedia.org/wiki/Adapter_pattern">Adapter  pattern</a>,被许多的JDBC实现所使用,用来提供基于传统的提供给数据源的JDBC API的扩展功能.  这个接口的主要意图是避免用非标准的方式来访问厂商特有的资源. 在这个接口的实例上调用unwrap方法,你会得到一个实现了这个接口的对象.  因为这个unwrap方法是个十分耗资源的操作,你在unwarping之前应该使用这个接口里的isWrapperFor方法来检查这个实现了接口的class是间接的还是直接的封装了某部对象.</p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/71556#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Apr 2007 18:35:10 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/71556</link>
        <guid>http://lerye.javaeye.com/blog/71556</guid>
      </item>
      <item>
        <title>社论: Java EE 走上了可怕的歧途</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/69256" style="color:red;">http://lerye.javaeye.com/blog/69256</a>&nbsp;
          发表时间: 2007年04月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="itemsummary"><font size="4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这篇社论是TSS的编辑最近发表的,作者对Java EE的发展方向表示了疑问,并且是自己的亲身体会中总结出来的,有很多跟贴对作者的观点进行了补充或反对,有兴趣的朋友可以看看原文里的跟贴,这样可以深入的了解这些外国人对这个论题的观点.</font></div>
<div class="itemsummary"><font size="4"></font></div>
<div class="itemsummary"><font size="4"></font></div>
<div class="itemsummary"><font size="4">本文是由 <a href="http://docman.cn">docman.cn 翻译家</a>&nbsp;组织翻译</font></div>
<div class="itemsummary"><font size="4"></font></div>
<div class="itemsummary"><font size="4"></font></div>
<div class="itemsummary"><font size="5">
<h1>&nbsp;</h1>
<p><font face="Arial">Editorial: Where Java EE goes horribly wrong</font></p>
</font></div>
<div class="itemsummary"></div>
<div class="itemsummary"><font size="4"></font></div>
<div class="itemsummary"><font size="4">确实,Java EE囊括了一切,除了这些小角落.........但是为什么,为什么有这么多的小角落?!<br />
<br />
Java EE在动摇,确实是这样的. 我使用它通常是很愉快的. 但是它却在一直打击着我---当它处理了几乎所有的东西,可偏偏忘了一些角落,这些角落它本该覆盖到的,而且能使他更强大,可它却没有. 这成了Java的&nbsp;</font><a href="http://en.wikipedia.org/wiki/Achilles_heel"><font size="4">Achilles' heel</font></a><font size="4"> .<br />
<br />
例如,&nbsp;看看我 </font><a href="http://epesh.blog-city.com/help_me_test_jndi_and_jms_in_glassfish.htm"><font size="4">最近的一次辛苦</font></a><font size="4"> ──为了给我的 </font><a href="http://java.sun.com/j2ee/connector/overview.html"><font size="4">EIS component</font></a><font size="4">配置一个JMS消息目的地。考虑到我已经有了一个内在的EIS组件──它将与一个JNDI资源交互──这本应该不是一个大问题. <br />
<br />
当时的事情是这样的:我写了一个收取mail的EIS组件. 它需要去伪造email地址(例如:所有的地址都是动态生成的),我的意图是当email发过来时,要把每个email送到JMS队列里. 一个message-driven bean监听这个JMS队列来判断是否该忽略这个email还是不能忽略.<br />
<br />
我之所以在EIS组件里做这些,是因为这种方式不需要我记住应该把所有的应用组件都启动起来，否者我必需要启动我的数据库和应用程序服务器,把它们全都做好。<br />
<br />
这样一来,我的EIS组件启动时需要一个已经准备好的JMS,不然的话它将会绑定一个端口,也就无法运行了. 这样我的&quot;问题&quot;就来了.<br />
<br />
证明显示在 </font><a href="https://glassfish.dev.java.net/"><font size="4">Glassfish</font></a><font size="4">&nbsp;里, JNDI </font><a href="https://glassfish.dev.java.net/javaee5/docs/DG/beanr.html#beanw"><font size="4">只有在sever完全启动后才会被组装</font></a><font size="4">. 这样,我的EIS组件初始化后,却不可能得到有效的JNDI资源来运行. 这在设计上的,明显的,如果我没搞错,是一种缺陷,我已经将它提交给Glassfish了. (</font><a href="https://glassfish.dev.java.net/issues/show_bug.cgi?id=1950"><font size="4">Bug #1950</font></a><font size="4">, 正巧那一年我还没出生.)<br />
<br />
我现在需要一个&nbsp;</font><a href="https://glassfish.dev.java.net/javaee5/docs/DG/beamc.html"><font size="4">Glassfish Lifecycle module</font></a><font size="4">,用它来检查server是否已经准备好了,&nbsp;这样我就可以从 lifecycle process中得倒 JNDI context了. 我可以启动一些线程(直到我把它们关掉),让它们去做我想要的. 在某方面这算是一个较为清洁的方案,比起将 </font><a href="http://subethasmtp.tigris.org/"><font size="4">SubEthaSMTP</font></a><font size="4">&nbsp;拆解,我可以在生命周期模块里只启动 SubEthaSMTP,这样就可以了.<br />
<br />
但是...如果我想把它转移到,比如,JBoss,将会发生什么事情? Or OC4J? Or WebLogic? Or WebSphere? Geronimo? JONAS? RESIN? 我现在使用的是Glassfish,用它来开发---主要是因为它是JEE5规格说明书的一种参考实现.并不是因为任何它作为一个应用服务器有着绝对的性能保证的特征. 如果我一直停留在Glassfish上,写一个生命循环事件是不错的事,但是我不想和任何一个特定的server绑的太紧. 这个生命周期只是针对Glassfish的,──其他的server好像并不会跟随着它的带领.<br />
<br />
JavaEE ,在这个案例中,让我失败了. 这并不是个大的问题,除非你会在Java EE里的这个角落里一遍一遍又一遍运行这种类型的程序.<br />
<br />
你也许想知道为什么人们在有了Messiah又要去关注 </font><a href="http://www.springframework.org/"><font size="4">Spring</font></a><font size="4"> ? 你也许想知道为什么&nbsp;</font><a href="http://www.theserverside.com/"><font size="4">TheServerSide.com</font></a><font size="4"> 总是对 OSGi and grids and Ruby and AJAX and 之类的喋喋不休?这就是为什么. 它们提供了覆盖那些小角落的方案. 不是一直要这样--我在期待着一个处理application server 的 OSGi or Spring 模板(例如,&quot;向这个bean里注入一个app server,启动它&quot;)但是这样我们需要把这些小角落的问题当成它们的本身---角落,而不是一直要斗争下去的障碍.<br />
<br />
Java EE doesn't suck - not really - but let's be real, it DOES suck in ways it shouldn't.(这句话中的suck不知道是什么意思!) JEE规格说明书应该提供一种指示去说明这些小角落,提供一些东西让开发者们可以去依赖. 我知道我对此有保留,我只是对那些它们中的一些没有价值的东西不满意.<br />
<br />
有些争论认为,为这种问题提供反射注入点会增加复杂度-- witness people </font><a href="http://weblogs.java.net/blog/edburns/archive/2007/03/prejcpfiled_dra_1.html"><font size="4">complaining about all the phaselistener things in JSF 2.0</font></a><font size="4">.Hey, I get that. 但是让我们现实点:如果你不需要它们,你就不必使用这种能力. 就是这样,如果你需要它,现在,那就不要漂泊了,你被规格说明书的作者规范在这里了,这个作者会认为通用性能的重要性大于通用需求.<br />
<br />
这里必须要改变,否则就像 Bruce Tate 说的 Java is &quot;</font><a href="http://www.theserverside.com/news/thread.tss?thread_id=39066"><font size="4">dead like COBOL</font></a><font size="4">&quot;──是说确实还活着,但不是十分的活跃──最终将会变成真的. <br />
</font></div>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/69256#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 09 Apr 2007 15:06:26 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/69256</link>
        <guid>http://lerye.javaeye.com/blog/69256</guid>
      </item>
      <item>
        <title>调用Java编译器API编译Java</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/69002" style="color:red;">http://lerye.javaeye.com/blog/69002</a>&nbsp;
          发表时间: 2007年04月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">本文由 <a href="http://docman.cn">docman.cn 翻译家</a> 组织翻译<br />
<br />
<br />
</font>
<div class="pagetitle2">Core Java Technologies Tech Tips</div>
<div class="smallpagetitle" id="sharepage">
<h1>Compiling with the Java Compiler API</h1>
<h1>调用Java编译器API编译Java</h1>
</div>
<p>从第一天开始,标准Java平台就缺少能够被调用,去产生Java字节码的编译器接口. 使用Sun实现的平台,一个用户可以通过非标准的  <code>com.sun.tools.javac</code>&nbsp; 包中的<code>Main</code> class&nbsp;去编译你的代码  (你可以在lib子目录下的 <code>tools.jar</code> 文件里找到它). 然而这个包并没有提供一个标准的公开的编程接口.  使用其它实现的用户必然不能访问这个类. 使用Java SE  6和在JSR-199中定义的它的新的Java编译器接口,你可以从你自己的应用程序里访问javac编译工具了.</p>
<p>有两种方式使用这种工具. 一种是简单的,一种是稍微复杂点但拥有更多选项的. 你首先将会用较简单的一种去编译 <code>&quot;Hello,  World&quot;程序,就是下面的这个:</code></p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>public&nbsp;class&nbsp;Hello&nbsp;{</code><br />
            <code>&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;{</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(&quot;Hello,&nbsp;World&quot;);</code><br />
            <code>&nbsp;&nbsp;}</code><br />
            <code>}</code>  <code></code></td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>要想从Java程序里调用Java编译器,你需要访问<code>JavaCompiler</code> 接口.  除此外,通过访问这个接口,你可以设置源代码的路径,classpath,和目标目录. 通过指定可编译的文件为  <code>JavaFileObject</code>instance ,你可以将它们全部编译. 然而,你并不需要对  <code>JavaFileObject</code> 了解多少.</p>
<p>可以使用 <code>ToolProvider</code> 类去请求 the<code>JavaCompiler</code> 接口的缺省实现. 这个  <code>ToolProvider</code> 类提供了一个 <code>getSystemJavaCompiler()</code> 方法, 它返回一个  <code>JavaCompiler</code> 接口的实例.</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>使用 <code>JavaCompiler</code> 运行编译最简单的方法是调用在这个接口工具里定义的 <code>run()</code>  方法,它的实现是:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>int&nbsp;run(InputStream&nbsp;in,&nbsp;</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out,&nbsp;</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;err,&nbsp;</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;String...&nbsp;arguments)</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>分别为前三个缺省参数 <code>System.in</code>, <code>System.out</code>, and  <code>System.err</code> 传入 <code>null</code> 值. 参数集 <code>String</code>  对象表示着传入编译器的文件的名称.</p>
<p>这样,你应该像下面这样去编译前面显示的 <code>Hello</code> 源程序:<code></code> </p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>int results = tool.run(null, null, null, &quot;Hello.java&quot;);</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>假设没有编译错误,这样会在目标目录里产生一个 <code>Hello.class文件.</code> 如果这里有错误,  <code>run()</code> 方法会把它输出到标准错误输出流里,也就是 <code>run()&nbsp;  </code><code>方法的的第三个参数.</code> 当错误发生时这个方法返回一个非0的结果.</p>
<p>你可以使用下面的代码去编译 <code>Hello.java</code> 源文件:<br />
</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>import&nbsp;java.io.*;</code><br />
            <code>import&nbsp;javax.tools.*;</code><br />
            <br />
            <code>public&nbsp;class&nbsp;CompileIt&nbsp;{</code><br />
            <code>&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;throws&nbsp;IOException&nbsp;{</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;JavaCompiler&nbsp;compiler&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ToolProvider.getSystemJavaCompiler();</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;results&nbsp;=&nbsp;compiler.run(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null,&nbsp;null,&nbsp;null,&nbsp;&quot;Hello.java&quot;);</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(&quot;Result&nbsp;code:&nbsp;&quot;&nbsp;+&nbsp;results);</code><br />
            <code>&nbsp;&nbsp;}</code><br />
            <code>}</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>一旦你编译了 <code>CompileIt</code> 一次 <code></code>,你就可以多次运行它,当你修改了  <code>Hello.java</code>源程序时或者要重新编译它,你不需要重新编译 <code>CompileIt</code> . 如果没有错误,运行  <code>CompileIt</code> 会产生下面的输出:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>&gt; java CompileIt</code><br />
            <code>Result code:  0</code><br />
            </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>运行 <code>CompileIt</code> 同样也会在相同的目录下产生一个 <code>Hello.class</code>  文件:<br />
</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>&gt;&nbsp;ls</code><br />
            <code>CompileIt.class</code><br />
            <code>CompileIt.java</code><br />
            <code>Hello.class</code><br />
            <code>Hello.java</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>你可以完事了,因为这样使用标准编译器已经足够了,可是这还有更有用的. 当你需要更好的处理这些结果时,你可以使用第二种方法来访问编译器.  更特别的是,这第二种方式允许开发者将编译输出结果用一种更有意义的方式表现出来,而不是简单的那种送往stdeer的错误文本. 利用  <code>StandardJavaFileManager</code> 类我们有这种更好的途径使用编译器.  这个文件管理器提供了一种方式,用来处理普通文件的输入输出操作. 它同时利用 <code>DiagnosticListener</code> 实例来报告调试信息.  你需要使用的 <code>DiagnosticCollector</code> 类其实是监听器的一种实现.</p>
<p>在搞清楚你需要编译什么之前,你需要一个文件管理器. 生成一个管理器基本上需要两步: 创建一个  <code>DiagnosticCollector</code> 和 使用 <code>JavaCompiler</code> 的  <code>getStandardFileManager()</code> 方法获得一个文件管理器. 把  <code>DiagnosticListener</code> 对象传入 <code>getStandardFileManager()</code> 方法中.  这个监听器可以报告一些非致命的问题,到后来你可以选择性的通过把它传入 <code>getTask()</code> 方法来和编译器共享.</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>DiagnosticCollector&lt;JavaFileObject&gt;&nbsp;diagnostics&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;DiagnosticCollector&lt;JavaFileObject&gt;();</code><br />
            <code>StandardJavaFileManager&nbsp;fileManager&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;compiler.getStandardFileManager(diagnostics,&nbsp;aLocale,&nbsp;aCharset);</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>你也可以往这个调用里传入一个 null 值的诊断器,但这样也就等于用以前的编译器方法了.</p>
<p>在详细查看 <code>StandardJavaFileManager</code> 之前 ,编译过程涉及到  <code>JavaCompiler</code> 的一个方法叫做 <code>getTask()</code>. 它有六个参数,返回一个叫做  <code>CompilationTask </code>内部类的实例:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>JavaCompiler.CompilationTask&nbsp;getTask(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Writer&nbsp;out,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;JavaFileManager&nbsp;fileManager,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;DiagnosticListener&lt;?&nbsp;super&nbsp;JavaFileObject&gt;&nbsp;diagnosticListener,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Iterable&lt;String&gt;&nbsp;options,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Iterable&lt;String&gt;&nbsp;classes,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Iterable&lt;?&nbsp;extends&nbsp;JavaFileObject&gt;&nbsp;compilationUnits)</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>缺省情况下,大部分它的参数可以是 null.<br />
<code>* out: System.err</code><br />
<code>*  fileManager:</code> compiler's standard file manager<br />
<code>*  diagnosticListener:</code> compiler's default behavior<br />
<code>* options: no  command-line</code> options to compiler<br />
<code>* classes: no class</code>  names for annotation processing</p>
<p>最后一个参数 <code>compilationUnits</code> 却是不能够为null ,因为它是你要去编译的东西. 它把我们又带回了  <code>StandardJavaFileManager</code>类.注意这个参数类型: <code>Iterable&lt;?</code>  extends <code>JavaFileObject&gt;</code>. &nbsp; <code>StandardJavaFileManager</code>  有两个方法返回这样的结果. 你可以使用一个文件对象的List或者<code></code> <code>String</code>  对象的List,用它们来表示文件名:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>Iterable&lt;?&nbsp;extends&nbsp;JavaFileObject&gt;&nbsp;getJavaFileObjectsFromFiles(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Iterable&lt;?&nbsp;extends&nbsp;File&gt;&nbsp;files)</code><br />
            <code>Iterable&lt;?&nbsp;extends&nbsp;JavaFileObject&gt;&nbsp;getJavaFileObjectsFromStrings(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Iterable&lt;String&gt;&nbsp;names)</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>并不仅仅 <code>List</code>,实际上,任何一个能够标识需要编译的内容的集合的 <code>Iterable</code> 都可以.  &nbsp;<code>List</code> 出现在这里只是因为它容易生成:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>String[]&nbsp;filenames&nbsp;=&nbsp;...;</code><br />
            <code>Iterable&lt;?&nbsp;extends&nbsp;JavaFileObject&gt;&nbsp;compilationUnits&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;fileManager.getJavaFileObjectsFromFiles(Arrays.asList(filenames));</code><br />
            <br />
            </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>现在你有了编译源文件的所有的必要的信息. 从&nbsp;<code>getTask(</code>) 返回的  <code>JavaCompiler.CompilationTask</code>&nbsp;实现了 <code>Callable</code>.接口  这样,想让任务开始就去调用call()方法.</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>JavaCompiler.CompilationTask&nbsp;task&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;compiler.getTask(null,&nbsp;fileManager,&nbsp;null,&nbsp;null,&nbsp;null,&nbsp;compilationUnits);</code><br />
            <code>Boolean&nbsp;success&nbsp;=&nbsp;task.call();</code><br />
            <br />
            </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<br />
<p>如果没有编译警告和错误,这个call() 方法会编译所有的 <code>compilationUnits</code>  变量指定的文件,以及有依赖关系的可编译的文件. 想要知道是否所有的都成功了,去查看一下返回的 <code>Boolean</code> 值.  只有当所有的编译单元都执行成功了,这个 <code>call()</code> 方法才返回 <code>Boolean.TRUE</code>&nbsp;.  一旦有任何错误,这个方法就会返回 <code>Boolean.FALSE</code>.</p>
<p>在展示运行这个例子之前,让我们添加最后一个东西,<code>DiagnosticListener</code>,&nbsp;或者更确切的说,&nbsp;  <code>DiagnosticCollector</code>.的实现类.把这个监听器当作getTask()的第三个参数传递进去,你就可以在编译之后进行一些调式信息的查询了.</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>for&nbsp;(Diagnostic&nbsp;diagnostic&nbsp;:&nbsp;diagnostics.getDiagnostics())&nbsp;{</code><br />
            <code>&nbsp;&nbsp;System.console().printf(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Code:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Kind:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Position:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Start&nbsp;Position:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;End&nbsp;Position:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Source:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Message:&nbsp;&nbsp;%s%n&quot;,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getCode(),&nbsp;diagnostic.getKind(),</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getPosition(),&nbsp;diagnostic.getStartPosition(),</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getEndPosition(),&nbsp;diagnostic.getSource(),</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getMessage(null));</code><br />
            <code>}</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>在最后,你应该调用管理器的<code>close()</code> 方法.</p>
<p>把所有的放在一起,就得到的了下面的程序,让我们重新编译Hello类.</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>import&nbsp;java.io.*;</code><br />
            <code>import&nbsp;java.util.*;</code><br />
            <code>import&nbsp;javax.tools.*;</code><br />
            <br />
            <code>public&nbsp;class&nbsp;BigCompile&nbsp;{</code><br />
            <code>&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;throws&nbsp;IOException&nbsp;{</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;JavaCompiler&nbsp;compiler&nbsp;=&nbsp;ToolProvider.getSystemJavaCompiler();</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;DiagnosticCollector&lt;JavaFileObject&gt;&nbsp;diagnostics&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;DiagnosticCollector&lt;JavaFileObject&gt;();</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;StandardJavaFileManager&nbsp;fileManager&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;compiler.getStandardFileManager(diagnostics,&nbsp;null,&nbsp;null);</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Iterable&lt;?&nbsp;extends&nbsp;JavaFileObject&gt;&nbsp;compilationUnits&nbsp;=</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileManager.getJavaFileObjectsFromStrings(Arrays.asList(&quot;Hello.java&quot;));</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;JavaCompiler.CompilationTask&nbsp;task&nbsp;=&nbsp;compiler.getTask(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null,&nbsp;fileManager,&nbsp;diagnostics,&nbsp;null,&nbsp;null,&nbsp;compilationUnits);</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;success&nbsp;=&nbsp;task.call();</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Diagnostic&nbsp;diagnostic&nbsp;:&nbsp;diagnostics.getDiagnostics())&nbsp;{</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.console().printf(</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Code:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Kind:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Position:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Start&nbsp;Position:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;End&nbsp;Position:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Source:&nbsp;%s%n&quot;&nbsp;+</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Message:&nbsp;&nbsp;%s%n&quot;,</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getCode(),&nbsp;diagnostic.getKind(),</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getPosition(),&nbsp;diagnostic.getStartPosition(),</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getEndPosition(),&nbsp;diagnostic.getSource(),</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diagnostic.getMessage(null));</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;}</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;fileManager.close();</code><br />
            <code>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(&quot;Success:&nbsp;&quot;&nbsp;+&nbsp;success);</code><br />
            <code>&nbsp;&nbsp;}</code><br />
            <code>}</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<br />
<p>编译和运行这个程序会输出成功的信息:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>&gt; javac BigCompile.java</code><br />
            <code>&gt; java  BigCompile</code><br />
            <code>Success:  true</code><br />
            </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>然而,如果你把 <code>println</code>&nbsp;方法改成书写错误的 <code>pritnln</code>  方法,当你运行时你会得到下面的信息:</p>
<div style="overflow: auto; width: 600px;">
<table class="grey4" cellspacing="0" border="0" cellpadding="10" width="100%">
    <tbody>
        <tr>
            <td><code>&gt;&nbsp;java&nbsp;BigCompile</code><br />
            <code>Code:&nbsp;compiler.err.cant.resolve.location</code><br />
            <code>Kind:&nbsp;ERROR</code><br />
            <code>Position:&nbsp;80</code><br />
            <code>Start&nbsp;Position:&nbsp;70</code><br />
            <code>End&nbsp;Position:&nbsp;88</code><br />
            <code>Source:&nbsp;Hello.java</code><br />
            <code>Message:&nbsp;&nbsp;Hello.java:3:&nbsp;cannot&nbsp;find&nbsp;symbol</code><br />
            <code>symbol&nbsp;&nbsp;:&nbsp;method&nbsp;pritnln(java.lang.String)</code><br />
            <code>location:&nbsp;class&nbsp;java.io.PrintStream</code><br />
            <code>Success:&nbsp;false</code>  </td>
        </tr>
    </tbody>
</table>
<span class="sp10">&nbsp;</span></div>
<p>使用Compiler API,你可以实现比在这篇简要的提示介绍的更多的事情. 例如,你可以控制输入输出的目录或者在集成编译器里高亮一些编译错误. 现在,向  Java Compiler API表示感谢,你可以使用标准API了. For more information on the Java Compiler API  and JSR 199, <a href="http://jcp.org/en/jsr/detail?id=199">see the JSR 199  specification.</a></p>
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/69002#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 08 Apr 2007 14:35:14 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/69002</link>
        <guid>http://lerye.javaeye.com/blog/69002</guid>
      </item>
      <item>
        <title>没有事务处理的日子(草译)</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/68630" style="color:red;">http://lerye.javaeye.com/blog/68630</a>&nbsp;
          发表时间: 2007年04月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          本文由&nbsp; <a href="http://docman.cn">docman.cn 翻译家 </a>&nbsp;&nbsp; 组织翻译<br />
<br />
<br />
没有事务处理的日子<br />
<div class="tc"><span class="ts">Living Without Transactions<br />
<br />
</span></div>
<p> </p>
<div class="summary">
<div class="summarytitle">摘要</div>
<!--/htdig_noindex-->Martin Fowler  (敏捷大师)发表了一篇blog,是关于放弃数据库事务管理,以依靠程序代码来管理事务的方法替代对数据事务管理的依赖.也许有时候这也是个正确的解决方案.<!--htdig_noindex-->  <!--/htdig_noindex--></div>
<p><font color="#000000" face="tahoma,arial,sans-serif">在&nbsp;<a href="http://martinfowler.com/bliki/Transactionless.html">Transactionless</a>&nbsp;这篇blog中,Martin  Fowler 对eBay的架构师DanPritchett最近的一次关于为什么eBay的架构师并不十分依赖数据库事务处理的演讲发表了评论.  ebay的数据的完整性是由应用层代码完成的. Fowler 指出.</font></p>
<blockquote>
<p><font color="#000000" face="tahoma,arial,sans-serif">不用事务管理的根本原因是它在某种程度上损耗了eBay的处理效率.  这种影响因为eBay非常大量的将它们的数据分割在很多很多的物理数据库里的事实而变得更加恶化.  结果就是使用事务管理就意味着要使用分布式事务管理,这向来就是需要谨慎的事情.</font></p>
<p><font color="#000000" face="tahoma,arial,sans-serif">这种大量的分割,以及在性能问题上,让数据库扮演主要角色的做法意味着eBay不能够使用许多的其他的数据库工具.相关的完整性和数据的排序全是用应用层代码完成的.  它们几乎不能用到trigger和存储过程.</font></p>
</blockquote>
<p><font color="#000000" face="tahoma,arial,sans-serif">Fowler不加思索的指出事务处理是一个非常有用的数据管理工具,而且指出:</font></p>
<blockquote>
<p><font color="#000000" face="tahoma,arial,sans-serif">没有人想要把事务处理从工具里排除掉.  我没有足够的关于eBay的详细信息让我来判断放弃事务的对于eBay来说是正确的做法.  但是eBay的例子让我们明白,没有事务管理的日子并不是像人们想象的那样不可能.</font></p>
<p><font color="#000000" face="tahoma,arial,sans-serif">除了成为一个我们值得考虑的一种替换方案的事实外,它也是一个例子表明非事务处理的方式的使用要比人们平时所认为的更加常见.  业务需要分多步走,而且和多个资源相关,而且时长时间的分布事务,或是资源不支持事务,这样的事情是常见的.</font></p>
</blockquote>
<p><font color="#000000" face="tahoma,arial,sans-serif">根据Fowler's  blog写的,在应用层里控制数据的完整性需要非常的小心,还需要许多额外的代码:</font></p>
<blockquote>
<p><font color="#000000" face="tahoma,arial,sans-serif">你需要加倍小心你提交的顺序,让最重要的放在最前面.  每一步提交你都要检查是否提交成功了,如果失败了如何处理.</font></p>
</blockquote>
<p><font color="#000000" face="tahoma,arial,sans-serif">当开发人员观察放大企业应用程序时,经常会发现数据层是最终的瓶颈. 目前好像是出现了两种途径去提高数据库层: In-memory,  distributed caches,such as Tangosol's Coherence and JBoss Cache,  和把大数据库分割成许多小的数据库,在这些数据库中横向的反数据集群.</font></p>
<p><font color="#000000" face="tahoma,arial,sans-serif">在第一种方法中,缓存成了应用程序的主要持久数据目标了.  许多的缓存解决方案提供了他们自己的API,通过这些API,他们绕过了传统的企业数据管理接口,例如JDBC和J2EE事务管理.</font></p>
<p><font color="#000000" face="tahoma,arial,sans-serif">非集群的数据库,在另一方面,需要应用程序管理多个数据库连接,很可能要依赖分布式事务管理来确保这些跨越数据库的操作的成功.分布式事务处理--特别是分布式事务处理的协调者,就成了又一个瓶颈和失败点,而且可测量性也有限.  就像Fowler的文章指出的,分布式数据库中利用应用程序协调跨越数据库的工作可以增加可测量性.</font></p>
<p><font color="#000000" face="tahoma,arial,sans-serif">在你的应用中,你是如何避免让数据库成为一个(single  point of failure??)个别的失败和可测量到的瓶颈的? 对Fowler的博客里描述的非事务处理类型的应用的你是如何考虑的?</font></p>
<!--htdig_noindex-->
          <br/>
          <span style="color:red;">
            <a href="http://lerye.javaeye.com/blog/68630#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 06 Apr 2007 15:16:07 +0800</pubDate>
        <link>http://lerye.javaeye.com/blog/68630</link>
        <guid>http://lerye.javaeye.com/blog/68630</guid>
      </item>
      <item>
        <title>节选 : Groovy in Action 第二章(草译)</title>
        <author>opensdp</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lerye.javaeye.com">opensdp</a>&nbsp;
          链接：<a href="http://lerye.javaeye.com/blog/67806" style="color:red;">http://lerye.javaeye.com/blog/67806</a>&nbsp;
          发表时间: 2007年04月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="tc"><span class="sts">本文转自&nbsp;&nbsp; <a href="http://docman.cn">docman.cn 翻译家</a><br />
<br />
<br />
GROOVY IN ACTION</span><br />
<span class="ts">第二章<br />
序<br />
Groovy 基础</span> </div>
<blockquote><strong>概述</strong><br />
这是Manning Publications 出版的Groovy in Action  第二章中的一个由三部分组成的系列中的第一部分. 这个章节将用很高视角的方式介绍这种语言. 读了这一系列后,你将会由对Groovy的基本原理有个完整的基本理解.  这个章节讲将你揭示Groovy编码的基本面貌,以及它和Java的相似处和不同点.  同时也介绍了一个Groovy的内置特性:assertionts(断言),整部书将会用这个特性去做书中用例程序的自我校验.</blockquote> <hr align="left" width="90%" />
<p>一首经典乐曲的序曲通常是向听众介绍整部乐章的主题,这个章节也将采用这种模式. 经典作曲家编写出优美的乐章在以后的演奏中会被再次研究,扩展,改变和组合.  在一定程度上,序曲是整部乐章的缩影. 在这个章节中,我将向你介绍许多Groovy语言的基本概念.  但是首先,我们的学习将从了解Groovy的两个特征开始:编码格式和断言.  这个章节中,我们提供了一些程序例子来让你开始认识这种语言.然而,每个例子只有一小部分会被详细的解释,只是能够让你有个开始而已.  如果你想透彻分析每个例子,那么先读完这章,回头再来研究. 序曲可以让你调整适应这乐器,这声音,这音量和座椅.  所以,背靠下,放松,享受这Groovy交响乐.</p>
<h1>2.1 基本编码风格</h1>
<p>计算机语言在他们的代码感观上往往有一个明显的传统.  例如,一个C程序员在看Java代码时也许不认识许多的关键词,但他们却熟悉大括号的这种布局,操作符,圆括号,注释,声明结束符和样子.  你开始使用Groovy时你也许会无法将它和Java区分开来,当你对这种语言的了解增加时,你会发现从Java转变成这样更加轻量级的,有启发性的,习惯风格的语言很平滑.  我们先来看一些基础的:如何去注释掉代码,比较Java和Groovy的不同,看看他们的相似处,以及为什么Groovy抛弃一些定义语法代码会更加简洁.  首先,Groovy对代码缩进不敏感,但是对代码块遵循这通常的缩进结构时一个好的技术习惯.  Groovy通常对多余的空格没有察觉,但对当前声明的换行和独行注释例外. 让我们来看看Groovy编码中的一些风格样子. </p>
<h2>2.1.1 注释Grovvy代码</h2>
<p>除了第一行的可选的脚本代码外,单行注释和多行注释跟java完全一样.</p>
<pre class="indent">			<br />		  #!/usr/bin/groovy<br />		  <br />		  // some line comment<br />		 <br />		  /*<br />		     some multiline<br />		     comment<br />		  */<br /> </pre>
<p>对于写Groovy注释这有一些提示: </p>
<ul>
    <li>这个#! 注释符只能出现在第一行. 它是让Unix shell去定位Groovy启动程序,来运行这些代码.  </li>
    <li>// 是注释掉这一单行一直到结束.  </li>
    <li>多行注释要被包围在/* 和*/ 标记里面.  </li>
    <li>包围在 /** 和 */ 里面的Javadoc风格的注释将会受到多行注释一样的对待,但是对Groovydoc的支持会在写作的时候实现.  它会成为对于Groovy来说跟Javadoc对等的东西,有这相同的语法. </li>
</ul>
然而,Groovy中跟Java相近的语法并非只是注释.
<h2>2.1.2 语法的比较</h2>
有一些(但不是全部)Groovy代码的样子跟他们在Java里的完全一样. 这经常会导致一些说  Groovy语法是Java语法超集的错误结论. 尽管相似,但其中没有一种语言是另一种的超集.  例如,Groovy目前不支持传统Java的for(init;test;inc)循环. 就像你会在表2.1看到,相当的语法定义会有轻微的不同,(例如,==操作符)  除了这些细微差别外,整个的主要的java语法是Groovy语法的一部分. 这些适应于
<ul>
    <li>通常的packaging机制  </li>
    <li>声明(包括package和import声明)  </li>
    <li>类和方法的定义(嵌套类定义除外)  </li>
    <li>控制结构(除了传统的 for(init;test;inc) 循环)  </li>
    <li>操作符,表达式和赋值  </li>
    <li>异常处理  </li>
    <li>常数的声明(有些变化)  </li>
    <li>对象实例,引用和解除对象引用,以及方法调用. 下面是在Groovy中增加的语法:  </li>
    <li>简化了的对Java类访问的新表达式和操作符  </li>
    <li>允许更多