<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>JavaEye论坛精彩帖子</title>
    <description>JavaEye论坛精彩帖子 - Java编程，Ruby编程，微软.net，AJAX，敏捷软件开发，综合软件技术</description>
    <link>http://www.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>发现JBoss Seam很棒呀！有用Seam做过项目的吗？</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://robbin.javaeye.com">robbin</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/212105" style="color:red;">http://www.javaeye.com/topic/212105</a>&nbsp;
          发表时间: 2008年07月06日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          上周去见了一个朋友Mark，他应邀在Red Hat的研讨会上面介绍他曾经用JBoss Seam做过的一个大的项目。因为听了他的演讲，对JBoss Seam多了一点认识，有点出乎意料的方便。所以周末在家下载了JBoss Seam摆弄了一下，把Seam自带的examples都浏览了一遍，也大致看了一下Seam的Reference，感觉挺惊艳的。于是又在JavaEye上面搜索了一下Seam，这才发现自从去年下半年开始，JavaEye已经有大量关于Seam的讨论了，这都一年多过去了，看来自己对Java社区已经有点孤陋寡闻了。<br /><br />写这个文章的目的是和大家一起交流一下JBoss Seam，虽然我通过文档和代码，已经对Seam有了不少了解，但是毕竟没有用Seam写过项目，希望有这方面经验的朋友多谈谈自己的体会。那么作为抛砖引玉，结合与Spring的对比，我先谈谈自己的感觉吧：<br /><br /><br /><span style="font-size: large">一、Seam适应快速开发、简化框架的趋势</span><br /><br />在RoR流行之前，Java社区的主流还是非常讲究分层、架构、复用和模式，而比较忽视快速开发和简化架构的，其结果就是代码量大、开发周期长、架构相当烦琐。以比较常见的Struts/Spring/Hibernate为例，从大的分层来说就有Web层、业务层和持久层，从细的分层就从前到后有：View(JSP) -> Struts Action -> Spring Business Object Bean -> Spring DAO Bean -> Hibernate Persistent Object。如果有Remoting调用，那么还需要相应的Service Facade层。每层都是用不同的技术框架或者模式、各层之间整合的方式也是五花八门。把整个项目的架构搭建起来，已经是非常麻烦的事情了。<br /><br />Seam给我的感觉像是一个异常简单的MVC框架，他实际上只有两层：JSF View和 Seam Component。而Seam Component有两类：一类是Entity Bean，另一类就是Session Bean。Entity Bean映射数据库表，Session Bean完成所有的业务逻辑，包括可能的持久化，事务，响应页面请求、商业逻辑，页面流控制等等。配置文件也不多，除了一堆基础的配置文件，唯一一个需要不断修改的就是pages.xml了，即配置JSF的view映射。<br /><br />所以Seam开发项目看起来很简单、很直接，无分层之苦恼。相应的也会让程序员把精力主要放在业务逻辑组件的实现上，而不是把精力浪费在架构、分层、模式和基础设施搭建的工作上面。<br /><br /><br /><span style="font-size: large">二、Seam的数据绑定做的很出色</span><br /><br />由于是一个简单的两层结构，View和Component之间的数据绑定做的很出色，看起来比我欣赏的Webwork的数据绑定方式更胜一筹。官方的说法叫做双向依赖注入，在component里面可以直接取到页面提交的数据，在页面也可以直接访问component数据。<br /><br />另外持久化数据的校验也直接集成好了，在EntityBean里面声明数据的约束，在页面就可以直接校验了，和RoR的数据校验方式是一样的，当然这也得益于Gavin King是Seam和Hibernate两个项目的作者的缘故。<br /><br /><br /><span style="font-size: large">三、Seam的组件机制看起来相当好用</span><br /><br />既然Seam简化了分层，实际上把主要的工作都推到组件层去完成了。但是Seam的组件层看起来很简单，这得益于Seam的组件机制设计了很多的组件状态，根据不同的组件状态，天然的划分了不同组件的功能和逻辑。<br /><br />Seam的组件有点类似于把传统MVC的Action和Spring的Bean合二为一了，但还是不同于传统的MVC框架下面的Action：传统的MVC Action是基于页面请求的，无法复用，而Seam的组件是事件驱动方式，它只需要捕获和实现事件代码就可以了，至于怎么触发它并不需要知道，他和Web层可以不绑定，因此理论上面来说是可以实现组件复用的。我个人认为Seam的这个组件机制非常巧妙，既可以用来实现响应页面事件，绑定页面数据的所谓Web Bean，也可以用来实现和Web没有任何关系的纯业务逻辑组件，一个很漂亮的实现。<br /><br />另外Seam的组件注入机制看起来也很简单，不像Spring那样麻烦，而且内置了很多现成的组件进来，直接用Annotation声明一下就可以用了，感觉写组件真的很方便、很灵活、很强大。<br /><br /><br /><span style="font-size: large">四、Seam把数据库资源的管理和事务的封装完全隐藏起来了</span><br /><br />Spring的数据库资源管理和事务封装是通过提供了一系列的代理类以及配置文件来实现的，程序员还是要通过配置文件的方式来手工管理事务，访问数据库也必须通过Template编写匿名内部类来实现，而且在Spring/Hibernate框架下面，OpenSessionInView是一个很讨厌的问题。<br /><br />但是Seam已经把数据库资源的管理和事务的封装全部都隐藏起来了，程序员完全不需要知道，也不需要操心这些事情，这真是个大大的解放。当然Seam可以做到这一点，也无非是因为Seam提供了一套上至View层，下至持久层完整的框架，因此可以把实现细节隐藏在框架内部，不暴露给程序员。Spring之所以做不到这一点，也因为他只充当了一个黏合剂，不能够直接修改View层和持久层带来的限制。<br /><br /><br /><span style="font-size: large">五、Seam对第三方框架的整合看起来比Spring更深入</span><br /><br />原来印象当中只有Spring才提供了一站式的解决方案，这次一看Seam文档，呵！发现Seam也都齐全了，什么邮件啦、工作流啦、页面流啦、规则引擎啦、异步任务调度啦、消息系统啦、Web服务啦、远程调用啦、甚至全文检索啦全部都集成了。而且集成的比Spring更深入一些，例如Java EE本身的JMS，MDB自然是Seam的强项，而JBoss自家的JBPM，JPDL，Rules集成的更加没得说。<br /><br />从整合角度来说，感觉Spring和Seam的出发点不同：Spring更像一个平台，我提供整合的可能性，然后程序员你自家去整合，我提供一些写好的整合bean，对于这些你通过XML配置一下就整合进来了，如果我没有提供bean的，那么你也可以自己写bean来整合。而Seam更像一个完整的框架而不是平台，我这个框架想提供的功能，框架自身就已经整合好了，你直接用就是了，你也可以自己写扩展来整合，但是这个不是Seam希望程序员做的事情。<br /><br />因此对于程序员的感觉来说，Spring给你提供了一切的零件和半成品，但你要自己动手来组装，而Seam已经给你装好了一个成品，你就别自己改装了，直接拿去用吧。<br /><br /><br /><span style="font-size: large">六、Seam提供了方便的代码生成器</span><br /><br />和appfuse类似，可以直接用ant task来生成一个完整项目的骨架，以及相应的组件代码生成器，利用seam-gen可以快速生成一个完整的、带有AJAX功能的CRUD项目，而且还是一个eclipse或者netbeans工程，你可以直接用IDE打开编辑了。这功能虽然不太难做，但是对于程序员来说，帮助是很大的。Seam做的相当不错。<br /><br /><br />以上是我对Seam的一点小小的赞许，当然我也有一点疑问：<br /><br /><span style="font-size: large">一、Seam的View实现是JSF，看页面代码还是密密麻麻的Tag</span><br /><br />我是非常反感JSP Tag的，看看页面密密麻麻的Tag就头皮发麻，能不能弄一个Template呀，例如freemarker啥的？这些Tag既不直观，也不方便扩展。需要扩展页面组件，总不能让我自定义Tag去干活吧？不清楚这个问题怎么办？像freeamarker还可以方便的自定义页面宏呢。<br /><br /><span style="font-size: large">二、每次修改都要重新打包发布，太麻烦了吧</span><br /><br />就算修改一个页面，也要整个打包deploy成为一个ear去拷贝到jboss的应用目录下面，这个要是改页面，不是得烦死？ 我以前都是在项目里面直接内嵌Jetty，作为一个application启动，修改页面根本无需重起呀，更不要说deploy了。<br /><br /><br />总体来说，我觉得Seam框架非常出色，尤其是他的组件机制设计的很有匠心，真不愧是Gavin King精心打造的框架了，虽然看起来还是有些缺陷，但是做企业应用项目的话，Seam是一个很棒的选择，作为程序员来说，要比用Spring/Hibernate/Struts省心的多，更能够把精力放在业务逻辑的编写上面，开发效率也很不错，可能是Java开源框架里面最优秀的快速开发框架之一了。
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/212105#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, 06 Jul 2008 20:56:35 +0800</pubDate>
        <link>http://www.javaeye.com/topic/212105</link>
        <guid>http://www.javaeye.com/topic/212105</guid>
      </item>
      <item>
        <title>Java程序员应该学习Ruby</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/208478" style="color:red;">http://www.javaeye.com/topic/208478</a>&nbsp;
          发表时间: 2008年06月27日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Java v.s Ruby，prototype js v.s jquery， Hibernate v.s iBatis v.s EJB ...<br />这种语言之争，框架之争，每隔<a href="http://www.javaeye.com/topic/180517" target="_blank">一段时间</a>总会在论坛<a href="http://www.javaeye.com/topic/206906" target="_blank">出现</a><br /><br />最近我读到一篇博客：<a href="http://jbossdna.blogspot.com/2008/06/java-developers-should-learn-ruby.html" target="_blank">Java程序员应该学习Ruby</a>，非常赞同作者的观点，粗略翻译其中的小部分，希望大家可以减少这种无意义的争论<br /><br />--------翻译开始分割线--------<br />Java程序员应该学习Ruby<br /><br />当然，它不一定是Ruby，你可以挑选其他语言，比如ErLang，甚至JavaScript，只要它和Java有足够的差异就可以了。<br />因为它能够让你成为一个更好的Java程序员：<br /><br /><span style="font-size: medium">1. 学习另外一种语言，它能够让你深入不同的开发者社区</span><br /><br />针对相同的问题，你可以找到不同的思想和不同的做法，或许它们不一定是更好，只是不同而已。其他社区往往有新鲜的视角来看待相同的问题，有时候甚至会让你更感激Java社区（比如Java有大量优秀的library）<br /><br /><span style="font-size: medium">2. 学习另一种语言，可以教你新的idioms</span>（idioms - 我想用行话来翻译idiom更准确一些）<br /><br />你可以在Java使用其中的一些行话，或者由于语言限制，你还不能使用它。<br />以Ruby的blocks为例子，它是Ruby闭包的一种表现，比方说你可以很方便地遍历数组，然后做一些操作(打印)：<br /><pre name="code" class="ruby">
animals = ['lion','tiger', 'bear']
animals.each {|animal| puts animal }
</pre><br /><br />很遗憾，目前Java还没有闭包，在Java 6里面如果要做类似的事情就是通过匿名内部类来解决，需要2个接口：<br /><pre name="code" class="java">
public interface OnEach&lt;T> {
  void run(T obj);
}
public interface List&lt;T> ... {
  void each( OnEach&lt;T> action );
}
</pre><br /><br />然后上面ruby例子就可以这样用：<br /><pre name="code" class="java">
List&lt;String> animals = Arrays.asList( new String[]{"lion", "tiger", "bear"} );
animals.each( new OnEach&lt;String>() {
 public void run( String animal ) {
  System.out.println(animal);
 }
});
</pre><br /><br />不过还是有点麻烦，Java 7将会引进闭包，目前已经有<a href="http://www.javaworld.com/javaworld/jw-06-2008/jw-06-closures.html" target="_blank">多个设计</a><br /><br /><span style="font-size: medium">3. 学习另一种语言，也迫使您使用不同的工具和过程</span><br /><br />以Ruby的<a href="http://rspec.info/" target="_blank">RSpec</a>为例，它是一个<a href="http://behaviour-driven.org/" target="_blank">Behavior Driven Development</a>框架，通过使用它你会发现和Java社区的Test Driven Development区别，并且可以从中学到很多。<br /><br /><br />Java是伟大的，并且还会继续，但是它需要进化。它已经有13年的历史了，我们一些人几乎把所有的时间都花在Java领域。去探索一下其他语言，我打赌你会成为一个更好的Java程序员。<br />--------翻译结束分割线--------<br /><br /><br />我之前一直是一个Java程序员，去年开始接触Ruby，在不到一年的时间里（更准确的说是在学习了Ruby 2个星期后），我觉得已经变成了一个更好的Java程序员，你还在等什么，开始学习Ruby吧。
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/208478#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, 27 Jun 2008 09:35:07 +0800</pubDate>
        <link>http://www.javaeye.com/topic/208478</link>
        <guid>http://www.javaeye.com/topic/208478</guid>
      </item>
      <item>
        <title>推荐一款使用Extjs做GUI的数据库浏览工具--DBExplorer</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://cnetwei.javaeye.com">cnetwei</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/207901" style="color:red;">http://www.javaeye.com/topic/207901</a>&nbsp;
          发表时间: 2008年06月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-size: small;">学习Ext的过程中 完成一个数据库浏览工具&mdash;&mdash;DBExplorer。基于JDBC连接各种数据库：支持sql语句执行，支持数据浏览和修改，支持LOB数据的查看、下载和修改，支持数据导出等功能。</span></p>
<p><span style="font-size: small;">更多细节内容可以在 </span><a href="http://jdbexplorer.googlecode.com"><span style="font-size: small;">http://jdbexplorer.googlecode.com</span></a><span style="font-size: small;">&nbsp;进一步了解。</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;">其它的就不多说啦，贴几张图看看：</span></p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/207901#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>Wed, 25 Jun 2008 15:59:43 +0800</pubDate>
        <link>http://www.javaeye.com/topic/207901</link>
        <guid>http://www.javaeye.com/topic/207901</guid>
      </item>
      <item>
        <title>XP的反省-Pair Programming</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://emarket.javaeye.com">emarket</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/207558" style="color:red;">http://www.javaeye.com/topic/207558</a>&nbsp;
          发表时间: 2008年06月24日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>常常看到论坛上有人讨论PP（Pair Programming）,但是大多是纸上谈兵，书上云的过多。真正谈感受的少。 我在一家做XP的公司做了4年了，从做service到做product, 总的来说pair programming给我带来的的忧大于喜，缺点大于有点。 </p>
<p>&nbsp;</p>
<p>总的来说PP有它的优点，很多researcher也发表了论文，记得比较清楚的一片就是一个大学里面对一个班的学生分组实验，结果用PP的那组效率比较高。 但这毕竟是research, 给我们的启示是PP在某种特定的情况下的结果:</p>
<p>&nbsp;</p>
<p style="padding-left: 30px;"><strong>1. Pair的人必须对等 （同班同学）</strong>
</p>
<p style="padding-left: 30px;"><strong>2. Pair的人必须全力以赴 (同学们，老师在做实验哦，不要走神！)</strong>
</p>
<p style="padding-left: 30px;"><strong>3. Pair的人必须对要解决的问题有相同（或相近）的认知 </strong>
</p>
<p>&nbsp;</p>
<p>而上面的3点在现实公司里却大部分情况下不能成立。1就不用说了，2，举个例子，如果有一个人生病，或是惦记的其他的事则会screw up整天的进度。3，和1相关，人的水平不同，不可能像大学那样对一个东西的认知近似。 </p>
<p>&nbsp;</p>
<p>我个人的经验是<span style="font-size: medium;"><strong>10%的pair时间是高效的pair，其余的则是浪费时间</strong>
</span>
。</p>
<p>&nbsp;</p>
<p>另外从人性的角度来讲，<strong>pair on everything则是对人性的强奸</strong>
，强调沟通没有错误，但是工作毕竟是工作，如果天到晚说比写花的时间更多，则有点本末倒置了。我们公司是100% pair, 任何的task，不管有没有必要，都要pair （条件允许的话）, 老板的原则是绝不让任何一个知识点停留在一个人的脑瓜里：）,一个人躺下了，另一个就能补上。 但是从现实的角度来讲，我们的产品的确出现过超过一个developer走了，结果他们经常working的那个module就会没有人能够维护了，结果需要重写。 所以从knowlege spread的角度来说，公司的benifit和情感留人+document, 比pair来的更实惠。</p>
<p>&nbsp;</p>
<p>另外<strong>pair的确剥夺了developer的个人空间</strong>
。 以前的公司， 上网灌水，给朋友 MSN, 的小动作全都不行了：（， 也许有人会说这些的东西在公司应该禁止！ 但是现实一点，我来java eye灌水 ， 跟几个圈内的朋友msn讨论心得，是对工作有正面影响的。 而且msn的圈内朋友对于疑难问题的帮助会很大的。 </p>
<p>&nbsp;</p>
<p>而且还有一点最大的就是<strong>pair剥夺了自学的时间</strong>
， 没有pair的时候当有东西不会的时候， 对一个问题的研究会刨根结底，但是pair的时候，如果你的partner会，他大概只会给你概括一下，如果你的partner不会，那就会是一个非常有趣的pairing session, 什么google, yahoo, 大部分情况，结果是 this is a fking task that we should never touch as we dont have corrosponding knowlege... 但是如果一个人能够静下心来把问题的来龙去脉搞清楚，把相应的prerequiste的knowlege搞清楚， 问题在得到解决的同时，自己也会得到提高。说白了当两个新手在pair的时候的确很低效，而且不利于&ldquo;成长&rdquo;</p>
<p>&nbsp;</p>
<p>说了这么多， 一句话<span style="font-size: medium;"> <strong></strong>
</span>
</p>
<p style="text-align: center;"><span style="font-size: medium;"><strong>少Pair可以怡神，多pair的确伤身， 不pair也能过日子</strong>
</span>
。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/207558#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, 24 Jun 2008 16:10:04 +0800</pubDate>
        <link>http://www.javaeye.com/topic/207558</link>
        <guid>http://www.javaeye.com/topic/207558</guid>
      </item>
      <item>
        <title>开源Visual Swing Designer for Eclipse，邀请有志者帮忙改进</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rehte.javaeye.com">rehte</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/208787" style="color:red;">http://www.javaeye.com/topic/208787</a>&nbsp;
          发表时间: 2008年06月27日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一直以来非常喜欢Swing，对Swing的研究也有很长一段时间了，一直希望Swing在Java桌面开发中扮演重要的角色。但是很久以来Java桌面开发始终是个弱项，其中很大一部分原因是缺乏比较好用的界面设计工具。<br /><br />NetBeans的界面设计工具(以前叫Matisse Project)的出现给Java的Gui开发尤其是Swing开发带来了希望，但遗憾的是当前Java集成开发环境仍然是Eclipse的天下，据统计，目前市场上至少2/3的份额是被eclipse占有。虽然netbeans已经获得长足的进步，并进一步吸引了更多的developer，但是由于历史习惯和遗留系统等等问题，这个市场份额在最近几年肯定还是eclipse的天下。<br /><br />当然eclipse也有很多很优秀的界面工具插件，可惜的是免费的插件其质量难以与netbeans的匹敌，好用的插件又都是收费的。因此<strong>一直想为eclipse开发一款免费的、开源的、功能上与Mattise Project相近的界面设计工具，</strong>算是为Swing的发展做一点贡献。<br /><br />从今年1月份开始，我来到一家新公司，主要做基于eclipse插件平台的开发，得以学习了eclipse的插件开发知识。以前曾经使用swing做过一个swing的界面设计工具，但由于是一款独立的工具，没有集成到任何IDE中，因此几乎没有实用价值。因此决定在闲暇时间将这个工具重新用eclipse插件技术进行开发。<br /><br /><strong>经过了五个月左右周末的努力，这款界面设计工具终于快要完成了，目前定的版本是0.9.0。但由于还有许多细节需要细化，需要大量的精力投入其中，因此想提前把代码开源出来，希望有志者能帮我一起完成。</strong><br /><br /><strong>开发这款工具的目标是希望达到以下特点：</strong><br /><br /><strong>1. 界面布局模仿Netbeans界面设计工具，操作和netbeans设计工具基本一模一样，容易直观的实现布局。</strong>这是第一目标。目前已经实现。<br /><br /><strong>2. 代码的生成和解析不需要辅助form文件，直接从源代码文件进行解析生成。生成代码可读性要强，要可以编辑并且同步。</strong>目前已经基本实现，有些折中处理，采用约定代替配置的办法提高代码解析速度。<br /><br /><strong>3. 直接支持树和表的界面设计，不需要写代码，直观的采用界面操作，便可以直接生成表和树的数据模型代码。</strong>此功能已经实现。而且目前的框架可以很容易扩展，实现类似其他复杂组件的界面设计。<br /><br /><strong>4. 工具的性能良好，界面设计功能流畅，代码解析/生成速度快。</strong>目前来看，速度和性能还不错，初步的打算是将速度放在最后处理优化。<br /><br /><strong>5.支持在设计时切换LookAndFeel,并能生成所设定LookAndFeel的代码。</strong>这样就能做到设计时和运行时完全一致。而NetBeans的设计工具只能以NetBeans自身相同的LookAndFeel设计，然后使用另外的LookAndFeel预览。<br /><br />说了这些，忘了说明一下代码位置：<br />http://code.google.com/p/visualswing4eclipse/<br />使用的是LGPL授权方式。照顾商业利用和开源改进而采用此授权。<br />目前支持的Eclipse平台是3.4，JDK请使用1.6<br /><br />忘了一条，我的msn是rehte @ hotmail . com<br /><br /><strong><br />看到还有人关心我很欣慰，毕竟在提到做Java开发就是指Web应用开发的时代，还有人关注Java桌面开发。我这个帖子的目的是邀请熟悉最好是精通Swing/SWT和Eclipse RCP技术的朋友参加这个项目，帮助我完成这个工具。这个工具离实用阶段还有一定的距离，但是目前在实现来说只是细节打磨、bug修改阶段了，但这需要大量的精力，我一个人吃不消，希望有人能帮助我。当然你在功能和实用性上提的意见也是欢迎的，我会把它们作为参考意见加入到今后的开发中。由于这个工具目前一直是我一个人来做，能力和精力都有限，所以最好不要上来直接和netbeans和其他商用的工具比较。我的目标是他们，但需要大家的帮助。</strong>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/208787#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, 27 Jun 2008 18:59:16 +0800</pubDate>
        <link>http://www.javaeye.com/topic/208787</link>
        <guid>http://www.javaeye.com/topic/208787</guid>
      </item>
      <item>
        <title>分布式缓存系统Memcached学习心得</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://liubin65030-gmail-com.javaeye.com">悠游键客</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/208981" style="color:red;">http://www.javaeye.com/topic/208981</a>&nbsp;
          发表时间: 2008年06月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          缘起: 在数据驱动的web开发中，经常要重复从数据库中取出相同的数据，这种重复极大的增加了数据库负载。缓存是解决这个问题的好办法。<br />Memcached是什么?<br />Memcached是由Danga Interactive开发的，高性能的，分布式的内存对象缓存系统，用于在动态应用中减少数据库负载，提升访问速度。<br /><br /><strong>Memcached能缓存什么？</strong><br />       通过在内存里维护一个统一的巨大的hash表，Memcached能够用来存储各种格式的数据，包括图像、视频、文件以及数据库检索的结果等。<br /><br /><strong>Memcached快么？</strong><br />       非常快。Memcached使用了libevent（如果可以的话，在linux下使用epoll）来均衡任何数量的打开链接，使用非阻塞的网络I/O，对内部对象实现引用计数(因此，针对多样的客户端，对象可以处在多样的状态)， 使用自己的页块分配器和哈希表， 因此虚拟内存不会产生碎片并且虚拟内存分配的时间复杂度可以保证为O(1).。<br />       Danga Interactive为提升Danga Interactive的速度研发了Memcached。目前，LiveJournal.com每天已经在向一百万用户提供多达两千万次的页面访问。而这些，是由一个由web服务器和数据库服务器组成的集群完成的。Memcached几乎完全放弃了任何数据都从数据库读取的方式，同时，它还缩短了用户查看页面的速度、更好的资源分配方式，以及Memcache失效时对数据库的访问速度。<br /><br /><strong>Memcached的特点</strong><br />       Memcached的缓存是一种分布式的，可以让不同主机上的多个用户同时访问， 因此解决了共享内存只能单机应用的局限，更不会出现使用数据库做类似事情的时候，磁盘开销和阻塞的发生。<br /><br /><strong>Memcached的使用 </strong><br />一 、Memcached服务器端的安装 （此处将其作为系统服务安装）<br />     下载文件：memcached 1.2.1 for Win32 binaries (Dec 23, 2006)<br />   1 解压缩文件到c:\memcached<br />   2 命令行输入 'c:\memcached\memcached.exe -d install' <br />   3 命令行输入 'c:\memcached\memcached.exe -d start' ，该命令启动 Memcached ，默认监听端口为 11211<br />  通过 memcached.exe -h 可以查看其帮助<br /><br />二、客户端使用<br />      下载memcached java client：http://www.whalin.com/memcached/#download<br />   1 解压后将java_memcached-release_2.0.1.jar jar包添加到工程的classpath中<br />       2 利用memcached java client 一个简单的应用<br /><pre name="code" class="java">
package com.danga.MemCached.test;    
   
import java.util.Date;    
   
import com.danga.MemCached.MemCachedClient;    
import com.danga.MemCached.SockIOPool;    
   
   
public class Test {        
    protected static MemCachedClient mcc = new MemCachedClient();       
       
    static {       
        String[] servers ={"192.168.40.4:12000"};       
       
        Integer[] weights = { 3 };       
       
        //创建一个实例对象SockIOPool     
        SockIOPool pool = SockIOPool.getInstance();       
       
        // set the servers and the weights    
        //设置Memcached Server    
        pool.setServers( servers );       
        pool.setWeights( weights );       
       
        // set some basic pool settings       
        // 5 initial, 5 min, and 250 max conns       
        // and set the max idle time for a conn       
        // to 6 hours       
        pool.setInitConn( 5 );       
        pool.setMinConn( 5 );       
        pool.setMaxConn( 250 );       
        pool.setMaxIdle( 1000 * 60 * 60 * 6 );       
       
        // set the sleep for the maint thread       
        // it will wake up every x seconds and       
        // maintain the pool size       
        pool.setMaintSleep( 30 );       
       
        // Tcp的规则就是在发送一个包之前，本地机器会等待远程主机    
                  // 对上一次发送的包的确认信息到来；这个方法就可以关闭套接字的缓存，    
                  // 以至这个包准备好了就发；    
                  pool.setNagle( false );       
        //连接建立后对超时的控制    
                  pool.setSocketTO( 3000 );    
        //连接建立时对超时的控制    
                  pool.setSocketConnectTO( 0 );       
       
        // initialize the connection pool       
        //初始化一些值并与MemcachedServer段建立连接    
                  pool.initialize();    
               
       
        // lets set some compression on for the client       
        // compress anything larger than 64k       
        mcc.setCompressEnable( true );       
        mcc.setCompressThreshold( 64 * 1024 );       
    }       
           
    public static void bulidCache(){       
        //set(key,value,Date) ,Date是一个过期时间，如果想让这个过期时间生效的话，这里传递的new Date(long date) 中参数date，需要是个大于或等于1000的值。    
        //因为java client的实现源码里是这样实现的 expiry.getTime() / 1000 ，也就是说，如果 小于1000的值，除以1000以后都是0，即永不过期    
        mcc.set( "test", "This is a test String" ,new Date(11211));   
    //十秒后过期    
              
    }       
      
    public static void output() {       
        //从cache里取值    
        String value = (String) mcc.get( "test" );       
        System.out.println(value);        
    }       
           
    public static void main(String[] args){       
        bulidCache();      
        output();           
    }     
       
}       

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/208981#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 Jun 2008 17:58:52 +0800</pubDate>
        <link>http://www.javaeye.com/topic/208981</link>
        <guid>http://www.javaeye.com/topic/208981</guid>
      </item>
      <item>
        <title>解决海量数据的新思路——分布式数据库</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://chester60.javaeye.com">chester60</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/212046" style="color:red;">http://www.javaeye.com/topic/212046</a>&nbsp;
          发表时间: 2008年07月06日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          目前，分布式的概念越来越流行，但是在数据库领域里，分布式的应用相对较少。在参阅了Google的Map/Reduce概念后，我构思了一种分布式数据库的架构，并实现了其雏形，现在将其基本思路写出来，希望能起到抛砖引玉的作用。我工作时间不长，其中错误，不完善之处还请大家多多指出，谢谢。<br /><br />    设计这个分布式数据库的目的在于快速的处理海量数据。基本思路其实很简单，将数据分布到多个数据节点中，在执行SQL语句时，分析SQL语句的语义，对一个或多个数据库进行操作。这样就可以使查询的压力分散到每一个节点上面，面对海量数据时的处理时间大大缩短。<br /><br />    先拿几个简单的SQL语句做分析，看看在分布式的环境下和平常有何不同。假设我们现在有两个数据节点A和B，表名为Table，其中ID为1~100的数据保存在节点A，ID为101~200的数据保存在节点B。以下的SQL语句都是同时对2个数据库执行。<br /><br />    Select * from Table where ID=1<br />    这样A数据库将返回ID为1的数据，数据库B返回为空。这时简单的合并A和B的数据，就可以得到正确的结果。<br /><br />    Select top 10 * from Table<br />    这时A数据库将返回10条数据，B数据库返回10条数据，这时如果合并A和B，将返回20条结果。这时必须移除多余的10条数据才是正确的结果。<br /><br />    Select * from Table order by ID<br />    这时A，B数据库将返回所有的数据，但是要使得数据符合order by的条件，很显然应该进行一次排序操作。<br /><br />    Select top 10 * from Table order by ID<br />    这时A，B数据库都返回10条数据，经过合并后，还要经过排序，移除的操作，才能确保结果正确。<br /><br />    SQL语句中需要处理的关键字还有max，min，count，sum，avg等，这里就不写出来了。经过这几个例子我们可以看到，其实只要经过一些处理，分别对不同数据节点上的查询，可以转化成对单一数据库查询等效的结果。而这些处理归纳起来，只有合并，排序，移除这三种情况，其实这和Map/Reduce思想非常的类似，无论什么复杂的动作，最终归结都可以通过几个简单操作来完成。这些处理当然需要一定的时间，但是在面对海量数据时，很多情况下，处理所需要的时间可以小到忽略不计。<br /><br />    上面只是一些简单的SQL语句，面对一些复杂的SQL语句，要在SQL语句处理的过程中，进行数据节点之间的数据交换才能完成的（例子在文末会给出）。因此要实现一个完全能够处理SQL语句的分布式数据库，需要在数据库的内核部分进行改动。在实现这个组件时，时间是有限的，进行内核部分的改造不现实，所以我采取了中间件的方式，来实现了这个分布式数据库的雏形，采用的数据库是MSSQL2000，下图是我设计的分布式数据库的概念图（参见附件1）：<br /><br /><br />    如图所示，数据根据一定规则分布（一般可以直接Hash主键）到每一个数据节点中，由分布式数据库服务器对每个数据节点进行访问，进行归并/排序/移除操作，然后通过数据接口，返回给程序。<br /><br />    其中几个数据接口所适用的场景为：<br /><br />    Reader：提供对数据库的查询结果，逐条进行读取的接口。在海量数据下，有时候需要读取大量数据进行处理，如果一次读取到内存中显然不现实。此时可以使用Reader模式逐条读取，进行分批处理。<br /><br />    DataFiller：提供对数据的XML包装，适用于小数据量的读取，主要是给Web应用提供一个方便的接口。<br /><br />    Command：执行delete，update，insert等不返回数据的SQL语句。<br /><br />    BulkCopy：批量插入接口。主要是为大数据量的导入提供高速接口。<br /><br />    实现这个中间件，难点应该是在SQL语句的语义分析上。这块应该使用编译原理来实现，但是在我的实现中，并没有用到，原因一个是时间问题，另外一个是因为基于中间件的方式，对一些复杂的SQL语句无法得到正确的结果。所以使用了正则表达式和一些方法来对SQL语句进行分析，分析出应该如何对执行结果进行处理，以及SQL语句应该发送到单个节点还是多个节点。以下是处理的流程示意图（参见附件2）：<br /><br />    在实现时需要注意的地方是，一定要让SQL语句从发送到执行，到返回结果之间没有任何延迟，否则每秒能够执行的SQL语句最多只有几十条。一开始我使用的模型是很常见的查询线程模型（参见附件3）：<br /><br />    每个语句执行完毕之后，在HashMap中将执行状态设置为执行完毕。使用一个查询线程，不断的遍历HashMap，发现有执行完毕的语句，便将其发往结果处理模块。为了避免CPU占用率100%，查询线程必须要有Sleep语句，但是windows下线程轮切的最小时间段为15ms，并且在Sleep的过程中，CPU将优先处理其他线程，这样Sleep一次至少需要20ms。这样，无论SQL查询再快，分布式数据库的处理速度也会被限制在1000/20=50条/秒以下。在我做的第一个模型中，每秒最多只能处理20多条SQL语句，在面对Web应用时，显然是不够的。<br /><br />    后来我采用的是信号量机制，即在生成Query线程时，给其分配一个信号量，执行每个SQL语句都会将一个监视线程加入线程池，监视线程堵塞住，等待所有信号量置为发信状态，然后立刻将结果送入结果处理模块。Windows处理信号量是非常快的，可以以CPU指令周期来计量。经过这个改进，分布式数据库处理一个查询的语句，基本等同于执行查询所需的时间。当然，这样的设计造成了使用的线程比较多，调试起来非常困难，需要非常小心的设计，而且在数据节点多的时候，必须维护一个成百上千线程的线程池，个人觉得是非常不好的。我注意到无论处理多少数据，MSSQL中的线程只有20多个，可以判断出他们的设计是非常精巧的，肯定和我的这种设计不同。如果有更好的方法解决这个问题，请不吝赐教，谢谢。<br /><br />    以上便是一个分布式数据库中间件的基本概念和一个基本实现。当然，实现一个商用的中间件，还有很多工作需要做，例如权限，数据安全，节点故障处理，日志等模块，都有很多改进的地方。目前我实现的这个中间件非常简陋，由于MSSQL本身的限制，有很多模块实现得不够优雅，不过唯一值得欣慰的是，性能上来说是非常不错的，达到了分布式系统的初衷。目前有3台机器作为数据节点运行，进行随机数据访问时，负载基本平均分到了每一个节点上。大数据量读取，大数据量写入一般都有单数据库2倍以上的速度。当然，分布式不是万能的，目前有些问题是无法解决的。例如：<br /><br />    1、多表问题：简单的举个例子，例如有一张用户表，一张产品ID表，还有一张交易记录表，以用户表，产品ID表为外键，如果执行诸如<br /><br />    Select * from 交易记录表 where 交易记录表.产品ID=产品ID表.ID and 交易记录表.用户ID=用户表.用户ID<br /><br />    这样的语句时，如果只对执行完的结果进行处理，无论如何架构这几张表，都会出错。为什么？原因有点难说清楚，有兴趣的话仔细思考一下就知道了。<br />    对于这样的语句，中间件根本无法处理，只有修改内核，在执行语句的过程中，对每个数据节点进行数据交换，才可以解决。目前的解决方法是把其中一张表放到单个数据库上。不过这样程序看起来就很怪异，一个查询动作要用到两个不同的数据库访问类，没有弄明白整个框架的程序员都不知道为什么要这样做。<br /><br />    2、语意分析：在分布式的环境下，SQL语意转换为操作原语的难度更加高了，确保其逻辑完全正确很困难，我离散数学学得很差，目前还不能达到100%的正确率，所以不得不在数据接口中保留了手动模式，即手工决定该如何处理数据，非常的丑陋。以目前的识别率，一些复杂的SQL语句要么分开几次写，要么使用手动模式自定义其处理流程才能确保其正确，目前也没时间去完善分析模块，只能随它去了。<br /><br />    提出这些问题希望能得到大家的指点，毕竟独自一人开发思路会有很多局限性，个人感觉其中还有很多地方可以挖掘，完全可能成为另外一种处理海量数据的方式。最后，谢谢你的观赏。
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/212046#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>Sun, 06 Jul 2008 15:17:48 +0800</pubDate>
        <link>http://www.javaeye.com/topic/212046</link>
        <guid>http://www.javaeye.com/topic/212046</guid>
      </item>
      <item>
        <title>一次Java垃圾收集调优实战</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calvin.javaeye.com">江南白衣</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/212967" style="color:red;">http://www.javaeye.com/topic/212967</a>&nbsp;
          发表时间: 2008年07月09日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h3>1 资料</h3>
<ul>
<li><span class="nobr"><a href="http://calvin.javaeye.com/blog/91905" title="Visit page outside Confluence" rel="nofollow">JDK5.0垃圾收集优化之--Don't Pause(花钱的年华)<sup><img class="rendericon" src="../../../../images/icons/linkext7.gif" border="0" height="7" align="absmiddle" alt="" width="7" />
</sup>
</a>
</span>
&thinsp;</li>
<li><span class="nobr"><a href="http://calvin.javaeye.com/blog/91903" title="Visit page outside Confluence" rel="nofollow">编写对GC友好，又不泄漏的代码(花钱的年华)<sup><img class="rendericon" src="../../../../images/icons/linkext7.gif" border="0" height="7" align="absmiddle" alt="" width="7" />
</sup>
</a>
</span>
&thinsp;</li>
<li><span class="nobr"><a href="http://pengjiaheng.spaces.live.com/blog/cns!2DAA368B386E6AEA!770.entry" title="Visit page outside Confluence" rel="nofollow">JVM调优总结<sup><img class="rendericon" src="../../../../images/icons/linkext7.gif" border="0" height="7" align="absmiddle" alt="" width="7" />
</sup>
</a>
</span>
&thinsp;</li>
<li><span class="nobr"><a href="http://www.md.pp.ru/~eu/jdk6options.html" title="Visit page outside Confluence" rel="nofollow">JDK 6所有选项及默认值<sup><img class="rendericon" src="../../../../images/icons/linkext7.gif" border="0" height="7" align="absmiddle" alt="" width="7" />
</sup>
</a>
</span>
&thinsp;</li>
</ul>
<h3>2 GC日志打印</h3>
<p>&nbsp; GC调优是个很实验很伽利略的活儿，GC日志是先决的数据参考和最终验证：</p>
<div class="macro">
<div class="code">
<div class="codeContent">
<pre class="code-java">-XX:+PrintGCDetails -XX:+PrintGCTimeStamps(GC发生的时间) -XX:+PrintGCApplicationStoppedTime(GC消耗了多少时间) -XX:+PrintGCApplicationConcurrentTime(GC之间运行了多少时间)</pre>
</div>
</div>
</div>
<p>&nbsp;</p>
<h3>3 收集器选择</h3>
<h4><a name="JavaPerformance-CMS收集器：暂停时间优先" style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(../../../CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;amp;file=anchor.gif);"></a>
CMS收集器：暂停时间优先</h4>
<p>&nbsp;&nbsp; 配置参数：-XX:+UseConcMarkSweepGC<br />
&nbsp;&nbsp; 已默认无需配置的参数：-XX:+UseParNewGC(Parallel收集新生代)
-XX:+CMSPermGenSweepingEnabled(CMS收集持久代)
-XX:UseCMSCompactAtFullCollection(full gc时压缩年老代)</p>
<p>&nbsp;&nbsp; 初始效果：1g堆内存的新生代约60m，minor gc约5-20毫秒，full gc约130毫秒。</p>
<h4><a name="JavaPerformance-Parallel收集器：吞吐量优先" style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(../../../CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;amp;file=anchor.gif);"></a>
Parallel收集器：吞吐量优先</h4>
<p>&nbsp;&nbsp;&nbsp; 配置参数： -XX:+UseParallelGC -XX:+UseParallelOldGC(Parallel收集年老代，从JDK6.0开始支持)</p>
<p>&nbsp;&nbsp;&nbsp; 已默认无需配置的参数： -XX:+UseAdaptiveSizePolicy(动态调整新生代大小)</p>
<p>&nbsp;&nbsp;&nbsp; 初始效果：1g堆内存的新生代约90-110m(动态调整)，minor gc约5-20毫秒，full gc有无UseParallelOldGC 参数分别为1.3/1.1秒，差别不大。</p>
<p>&nbsp;&nbsp;&nbsp; 另外-XX:MaxGCPauseMillis=100 设置minor gc的期望最大时间，JVM会以此来调整新生代的大小，但在此测试环境中对象死的太快，此参数作用不大。</p>
<h3><a name="JavaPerformance-1.4调优实战" style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(../../../CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;amp;file=anchor.gif);"></a>
4 调优实战</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Parallel收集高达1秒的暂停时间基本不可忍受，所以选择CMS收集器。
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在被压测的Mule 2.0应用里，每秒都有大约400M的海量短命对象产生：</p>
<ol>
<li>因为默认60M的新生代太小了，频繁发生minor gc，大约0.2秒就进行一次。</li>
<li>因为CMS收集器中MaxTenuringThreshold(生代对象撑过过多少次minor gc才进入年老代的设置)默认0，存活的临时对象不经过Survivor区直接进入年老代，不久就占满年老代发生full gc。</li>
</ol>
<p>&nbsp; &nbsp;&nbsp; 对这两个参数的调优，既要改善上面两种情况，又要避免新生代过大，复制次数过多造成minor gc的暂停时间过长。</p>
<ol>
<li>使用-Xmn调到1/3 总内存。观察后设置-Xmn500M，新生代实际约460m。(用-XX:NewRatio设置无效，只能用 -Xmn)。</li>
<li>添加-XX:+PrintTenuringDistribution 参数观察各个Age的对象总大小，观察后设置-XX:MaxTenuringThreshold=5。</li>
</ol>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 优化后，大约1.1秒才发生一次minor gc，且速度依然保持在15-20ms之间。同时年老代的增长速度大大减缓，很久才发生一次full gc，</p>
<p>&nbsp; &nbsp; &nbsp; 参数定稿：</p>
<div class="macro">
<div class="code">
<div class="codeContent">
<pre class="code-java"> -server -Xms1024m -Xmx1024m -Xmn500m -XX:+UseConcMarkSweepGC   -XX:MaxTenuringThreshold=5  -XX:+ExplicitGCInvokesConcurrent</pre>
</div>
</div>
</div>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后服务处理速度从1180 tps 上升到1380 tps，调整两个参数提升17%的性能还是笔很划算的买卖。</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp;&nbsp; 另外，JDK6 Update 7自带了一个VisualVM工具，内里就是之前也有用过的Netbean Profiler，类似JConsole一样使用，可以看到线程状态，内存中对象以及方法的CPU时间等调优重要参考依据。免费捆绑啊，Sun 这样搞法，其他做Profiler的公司要关门了。</p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/212967#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>Wed, 09 Jul 2008 10:39:01 +0800</pubDate>
        <link>http://www.javaeye.com/topic/212967</link>
        <guid>http://www.javaeye.com/topic/212967</guid>
      </item>
      <item>
        <title>分享一款word风格的rails在线编辑器</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://liuqiang.javaeye.com">liuqiang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/213151" style="color:red;">http://www.javaeye.com/topic/213151</a>&nbsp;
          发表时间: 2008年07月09日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="Section0" style="LAYOUT-GRID:  15.6pt none">
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp;&nbsp;在线编辑器是web应用中最常见的东西了，关于它的作用和意义我不想多说什么了。对于编辑器的使用，之前就是随便找个简单的HTML编辑器甚至是textarea来应付，也没花多少时间来整这个东西，但事情开始逐渐变得麻烦起来，因为我们的客户（可能就是你的老板）的要求越来越高：能不能加上点丰富的表情？能不能使编辑器再多支持几种格式排版？或许有一天客户看到了搜狐的编辑器，回来说能不能让我们的编辑器也增加本地图片上传？最好再要加个附件功能，并且也要从本地上传&nbsp;&hellip;&hellip;&hellip;&hellip;，这一切让我以前做的小编辑器显得无地自容，也忒简陋了吧。于是我很自然地想到了rails里面最常用的FCK编辑器，的确，它基本可以满足我的所有需要，可是仍有3点让我感到不大舒服的地方：</span></span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp; 1&nbsp;<span style="font-family: 宋体;">尽管FCk的配置使用已经很方便了，但仍然有不少需要汉化和定制的地方。</span></span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp; 2&nbsp;<span style="font-family: 宋体;">这个东西显的有稍稍有点大，为了性能，我还期望让它再小一点。</span></span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;3&nbsp;<span style="font-family: 宋体;">这是个不是理由的理由：用户感到单调了，为什么我们的系统里面的编辑器都是一个模样，我们需要点新口味。</span></span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span>&nbsp;</p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp; 我首先的想法就是改改FCk，旧米做新饭，可是我发现修改FCK不是件容易的事，并且把FCK修改成另外一种风格和结构更难，后来转念一想，反正里外都是改，我何不找另外一款编辑器做做文章，之前在51js混的时候听说新浪的编辑器做的不错，于是load下来看看，豁豁豁&hellip;&hellip;，这不就是word吗？太酷了，我有了马上就使用它的冲动，但是打开源码一看是个asp版本的，并且转为utf8后，注释也成了乱码，好在它的js代码可读性还算比较好，于是我开始着手做两件事，1是裁掉一些功能&nbsp;2是把它转为rails版本的。经过一段时间的修改和维护这个东东算是稳定下来了，使用和效果如下：</span></span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp; 将editor文件夹放在public下，在需要用编辑器的的form中写：</span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span>&nbsp;</p>
<pre name="code" class="ruby"><span style="color: #ff0000;"> 注意这里的id不要写成content，貌似是由于命名冲突的原因</span> 
&lt;input type="hidden" id="content1" name="content" value=""&gt;&lt;/input&gt; 
<span style="color: #ff0000;">注意这里要把上面的隐藏域的id穿给编辑器的iframe</span>
 &lt;iframe id="myEditor" src="/editor/editor.htm?id=content1" frameborder="0" scrolling="no" width="550" height="220"&gt;&lt;/iframe&gt;

再附上一段js校验编辑器内容不为空的代码
var content = myEditor.getHTML().replace(/&lt;.*?&gt;/g,"").split(" ").join("").split(" ").join("");
if(content.length==0){
        alert('公告内容不能为空！');
        return false;
    }</pre>
<p class="0">&nbsp;<span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">
<p class="0">&nbsp;</p>
</span></p>
<p class="0"><img src="../../upload/picture/pic/17662/0cff6c23-c499-31a1-9f16-be27f2dbb9e2.jpg " height="464" alt="" width="631" /></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp; 效果还不错吧，下面还有2件重要的事情要做：上传图片和上传附件，之所以说这个是rails版的，也就是这两个功能和rails有点干系。先简分析下上传本地图片吧，原理是这样的，点击上传图片后弹出一个新窗口，叫你输入你的本地图片，这个窗口对应的页面是editor\editor目录下的img.htm文件，打开看看可以看到有个向服务器提交图片的form，并且action指向服务器保存编辑器图片的那个action，用户提交本地图片后，服务器将图片保存，并把该图片的保存地址返还回去，编辑器接收到该图片地址后，插进编辑器的主窗口，这样图片基本就在编辑中显现了，当然你可以在img.htm写上校验逻辑，我已经加上了图片类型判别的js校验。整个流程就是这样，上传本地附件和图片的流程基本一样，上传附件窗口对应的文件是attach.htm文件，只不过服务器保存用户提交的附件后，返还的是下载该附件的地址，我也已经在attach.htm加上zip和rar的校验。注意我已经将上述的东西做好了，无需修改任何东西！当然你可以再去修改成你自己喜好的风格。</span></p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp; 接下来就开始写服务器处理上传图片的附件的逻辑了，注意由于我在上传图片和上传附件的form中把action的地址分别指向的是:/front/editors/upload_editor_image和/front/editors/upload_editor_attach，所以如果你不想修改任何东西的话，那么请保证后台的控制器一定要是front/editors,action分别是upload_editor_image和upload_editor_attach。代码附上：</span></p>
<span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">
<pre name="code" class="ruby">class Front::EditorsController &lt; ApplicationController
  skip_before_filter :verify_authenticity_token
  # 上传图片
  def upload_editor_image
    file = params[:imgfile]
    filename = params[:imgfile].original_filename.split('.').reverse  
    filename = Time.now.strftime("%Y%m%d%H%M%S")  + rand(10000).to_s + "." + filename[0]  
    File.open("#{File.expand_path(RAILS_ROOT)}/public/upload/editor_image/#{filename}", "wb") do |f|   
      f.write(file.read)        
    end      
    render :text =&gt; "&lt;script&gt;window.parent.LoadIMG('/upload/editor_image/#{filename}')&lt;/script&gt;"
  rescue
    render :text =&gt; "&lt;script&gt;window.parent.alert('您上传的图片无效或者损坏！');window.parent.divProcessing.style.display='none'; &lt;/script&gt;"
  end
  
  # 上传附件
  def upload_editor_attach
    file = params[:attach]
    filename = params[:attach].original_filename.split('.').reverse  
    filename = Time.now.strftime("%Y%m%d%H%M%S") + rand(10000).to_s + "." + filename[0]  
    File.open("#{File.expand_path(RAILS_ROOT)}/public/upload/editor_attach/#{filename}", "wb") do |f|   
      f.write(file.read)        
    end      
    render :text =&gt; "&lt;script&gt;window.parent.LoadAttach('/upload/editor_attach/#{filename}')&lt;/script&gt;"
  rescue
    render :text =&gt; "&lt;script&gt;window.parent.alert('您上传的附件无效或者损坏！');window.parent.divProcessing.style.display='none'; &lt;/script&gt;"
  end
  
  def download_attach
    send_file params[:path]
  rescue
    render :text =&gt; "对不起，改附件已经损坏，无法下载！"
  end
end
</pre>
<p class="0">&nbsp;</p>
</span>
<p class="0">&nbsp;</p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span>&nbsp;效果如下：</p>
<p class="0"><img src="../../upload/picture/pic/17664/73cd0cd5-1038-3a79-a77e-ff62417b1a70.jpg " height="208" alt="" width="412" /></p>
<p class="0">&nbsp;</p>
<p class="0"><img src="../../upload/picture/pic/17660/ae845d1e-c7ce-3dcd-b737-7448aadc4e43.jpg " height="337" alt="" width="649" /></p>
<p class="0">下面是改编辑器的压缩包，直接解压即可。</p>
<p class="0"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span>&nbsp;</p>
</div>
<!--EndFragment-->
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/213151#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>Wed, 09 Jul 2008 16:51:10 +0800</pubDate>
        <link>http://www.javaeye.com/topic/213151</link>
        <guid>http://www.javaeye.com/topic/213151</guid>
      </item>
      <item>
        <title>小公司如何做项目管理(上)</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://liuqiang.javaeye.com">liuqiang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/216779" style="color:red;">http://www.javaeye.com/topic/216779</a>&nbsp;
          发表时间: 2008年07月21日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="Section0" style="layout-grid: 15.6pt none;">
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我所在的公司和大多数国内IT公司一样，十几到几十人的规模，每次在做完项目过程中我们都会感觉</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">很</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">累，老板其实也很累，在小公司老板更像是一个项目经理的角色，很多东西都没有流程化的东西可走，所以很多事情都要等老板拍板后才可以继续下去，员工在很多时候就会感到迷茫，随着公司规模的扩大，公司也意识到没有一套规范的项目管理方案是万万不行的</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，自己在这方面也摸索的一段时间。</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我首先接触的是敏捷开发的方法，但很快我就感觉这个方法行不通，至少对于我们是这样，因为我们无法保证和客户以及业务人员及时沟通，一个月见几次面就很不错了，而且我们的开发人员也并不具有敏捷能力。后来接触了下CMMI，CMMI对于小公司就更不靠谱了，它庞大的身躯足以把一个小公司压垮，如果仅为一个证书的话，我建议完全可以向o6z订购，但不可否认的是CMMI也有很多优秀的地方可以借鉴。那么我对小公司项目管理的看法是一定要精简，做到不是傻瓜都能够理解并且能够执行，况且很多项目经理（老板）也并不是领域专家。在此我想简单谈谈我对适合小公司的项目管理方案的一些想法</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">所谓基本适合就是80%适合，我要是说100%适合那我是在扯淡，另外20%怎么办？那就像06z所说的那样，靠经验这个王道。</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">首先</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">要谈的是</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">需求这个东西，那么什么是需求？需求就是掏钱买你产品的人一些需要，只要是客户的需要，不管是合理不合理那都是需求。其实很多开发人员都意识需求的重要性，那么真正去做需求的人有多少呢？需求应该是包括需求开发和需求管理这两个过程，这里有个特别的情况是对于自主研发的项目，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我接触的项目也是这种情况居多，于是</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我们认为自己就是客户，所以需求开发做</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">很简单甚至跳过去，结果后期的需求管理非常混乱，我</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">觉得</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">既然自己是客户，那就要当好客户这个角色，在做客户时应完全忘却自己是个开发人员</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，同样要把需求做全面</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">。很多教科书上都说应该做需求，但关于怎么做的问题上却和实际情况差别比较大，以下是我关于需求该做什么以及怎么做到一些看法。</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';">1&nbsp;<span style="font-family: 宋体;">需求调研</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我觉得需求调研非常的重要，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';">1</span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">年前我还打算做一个在线教育服务平台，理念就是淘宝在网上卖商品，我在网上卖教育资源，我提供网上交易场所，签约的老师、学校以及培训机构提供</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">可交易的</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">服务，这种服务可以通过视频、音频、在线PPT、文本的形式展现。忙活了好一阵，发现这个市场早就有很多人做了，而且这个市场并不是很好做，首先在网上学习的人有几个？并且先不说前期推广需要海量资金就是所需要的那么些高性能服务器丫也买不起！这件事就此搁浅，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">结果</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">信了马云</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的邪</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，2年后你</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">还</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">想创业你在创业！我觉得这就是典型的需求调研没做好，没有对用户需求做调查，没有考虑同行竞争，没有考虑可行性！另外还要考虑括行业标准和法律规定，比如前些时候国家就出台了关于办视频网站的政策，我觉得你丫没有足够的背景就不要往火坑里跳楼。总之根据所做行业情况尽可能的把需求调研做全面，这样才可以保证项目首先是可以赚钱的。那么文档要写吗？我觉得可以不要正式的文档，小公司的人手本来就不够用，要把主要文档</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">化工作</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">集中在重要的环节上，对于需求调研，本来就很杂乱，完全可以记在工作笔记上，放到需求分析的时候整理。</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';">2&nbsp;<span style="font-family: 宋体;">需求分析</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">为了得到用户的金钱，我们总是在说，用户是上帝，用户永远是对的，尽管背地里在说客户端坏话：&ldquo;你丫钱给的倒不多，要求还真少，这需求根本不合理，是正常人的逻辑吗？&rdquo;，如果你想活下去，最终我们还是要想方设法满足用户的要求。</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">用户</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">是个外界因素，我们</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">是</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">无法控制</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，那么我们只有尽可能改进需求分析的方法来尽量减少不必要的麻烦。那么我觉得日本人做法倒是可以借鉴，在有条件的情况下派专人去现场，随时记录关键性的需求，即使不能去现场也尽可能的获取尽可能多大信息，不要指望开发后去获取什么有价值的东西。那么是否应该做个原型给客户看看？我是觉得这不大合适，因为如果项目周期短的话，等你做好原型，黄花菜都凉了。但我觉得等到需求做到差不多的时候可以做用户界面，所谓用户界面就是用户接口，是和用户打交道的地方，所谓一图解千言，有了界面用户会清楚自己所买的东西在未来会是个什么样的东西，再者开发几个有说明性都界面倒是不会暂用很多时间。等到需求确定下来后</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">就</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">要整理成文档了，这个是很重要的一步，是做设计时候的重要凭证和依据，这个文档就是用户规格说明书，所谓规格就是有规范的格式和内容。</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';">3 <span style="font-family: 宋体;">需求评审</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我们已经有了较正规的文档了，那么下一步就是召集所有开发人员开会，最好有客户代表参加，尽管我是很厌烦开会，但该开的会还是要开到，因为之前我遇到这种情况，开发人员根据设计文档写代码，可是他并不知道自己在开发什么，站在自己的角度想一下，如果自己都不确定自己做的东西，即使有再完备的设计，也会对开发毫无兴趣，只会让自己觉得自己是个代码机器。所以所有人员参加需求评审是让大家知道自己在做一件有意义的事情，自己正在满足社会的需要，自己在为和谐社会做贡献，即使你从没那么想过，那你敢保证的你的潜意识没那么想过吗？人是要有社会满足感的吧。另外开会前一定要准备关键有价值的议题，据我观察需求评审会最容易扯到不着边的话题，所以主持人要控制话题，会议控制在2-3个钟头，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">最好做成幸运52的形式，所有人员一定要互动起来，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">否则</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">就</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">变成了</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">个人演讲</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">。需求也做了，会也开了，那么要求客户签字吧。</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';">4&nbsp;<span style="font-family: 宋体;">需求管理</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">需求管理是在开发开始之后进行的，这也是另所有人头疼的一件事，之前做完一个项目后，客户经常打电话找我们，改过来改过去，后</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">来</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我听到电话，血压都要</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">升</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">高50个百分点，后来索性就不接电话，客户就在网上找我，搞的我连QQ都不敢登，但躲是躲不掉滴，客户直接打我手机，丫的真烦人，见过难缠的，没见过这么难缠的。后来转念一想，难道这种情况真的不能避免吗？至少是可以大幅度的缓解</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">吧。这就是我们需求管理中的变更管理没做好，</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">改了哪些地方自己都忘记了，最后是跟着感觉走，拆东墙补西墙。</span></span><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">在这里我建议要建立需求跟踪矩阵表，有了这个表我们至少可以对要修改的地方有了依据，迫使我们去调查到底是改什么地方，怎么改，最后改成了什么样。可能你会说客户需要大幅度修改原有计划，很难跟踪到具体某一项需求，那么我觉得这是由于前期的需求开发没有做好，在后期客户进行实质性的修改的几率是很小的，比如客户要求我们做个OA系统，最后总不会要我们改成个门户网站吧，在举个例子，在比如你开发一个ERP系统，客户自己的业务流程不会轻易的改变吧，总不至于把盘点这个业务改成一个报表系统吧。如果真是这样，我们完全有理由告诉客户，你丫乖乖掏银子，我们再给你们开发2期工程，要改，没门！</span></span></p>
<p class="0" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">大家开始拍砖吧，有时间继续&hellip;&hellip;</span></span></p>
</div>
<!--EndFragment-->
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/216779#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>Mon, 21 Jul 2008 08:09:12 +0800</pubDate>
        <link>http://www.javaeye.com/topic/216779</link>
        <guid>http://www.javaeye.com/topic/216779</guid>
      </item>
      <item>
        <title>利用rails轻松建立个性化主页门户</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://liuqiang.javaeye.com">liuqiang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/211468" style="color:red;">http://www.javaeye.com/topic/211468</a>&nbsp;
          发表时间: 2008年07月04日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 简单来说，个性化主页就是结合了各种小模块和网络信息的个人主页。与传统网站的区别是：用户可以非常自由地控制其内容（通过RSS，email等等），内容会更适合用户口味并且使用查看也非常方便，由于有了ajax技术，所以更像是一个桌面软件。例如<a href="http://www.netvibes.com/">http://www.netvibes.com/</a>就提供了比较酷的个性化主页服务。<br />总的来说主要有以下几个特点：</p>
<p>1 页面中的内容是一个个小模块，其内容来自于其他站点或者服务&nbsp;</p>
<p>2 用户可以根据自己的喜好通过拖拽随意摆放这些小模块 </p>
<p>3 用户可以添加自己感兴趣的小模块 </p>
<p>4&nbsp; 用户可以删除任意已添加的小模块 </p>
<p>5 用户可以改变自己的页面风格以及布局。</p>
<p>用rails解决这些问题显得极为简洁，为了简化说明，这里不考虑用户权限，如下：</p>
<p>&nbsp;</p>
<p>1 在主应用（也就是提供主页服务的系统）建立模块加载机制和代理转发功能（依据dlee翻译的《ajax模式与最佳实践》最后一章的MVC模式），在这里简化下就是一个user有N个page,一个page有N列，一列有N个模块。建立模型如下：</p>
<pre name="code" class="ruby">class User &lt; ActiveRecord::Base
   has_many :pages
 end

class Page &lt; ActiveRecord::Base
   has_many :columns
   belongs_to :user
 end

class Column &lt; ActiveRecord::Base
   has_many :cells
   belongs_to :page
end

class Cell &lt; ActiveRecord::Base
      belongs_to :column
end</pre>
<pre name="code" class="ruby">#在后台发起向其他系统调用服务，当然可以带有一些查询参数比如username已取得和该用户相关的模块内容。
def show
    @cell = Cell.find params[:id]
     Net::HTTP.start(@cell.url,@cell.port) do |http|
        response = http.get(<a href="mailto:'#{@cell.path}'">'#{@cell.path}'</a>, 'Accept' =&gt; 'text/xml')
     end
     render :text =&gt; @response.body
 end

#其他系统处理请求并返回，返回结果可以是html/xml/rss/flash/js等等，这里暂用字符串文本代替。
def show
     render :text =&gt; "ok"
 end
</pre>
<p>其中需要说明的是：cells表中应存有name、来源URl、port、path，name表示改模块的名字，URl的作用是记录该cell的内容来自于哪个外部站点的rest服务，port指定外部站点的端口，path指定服务的路径。</p>
<p>&nbsp;</p>
<p>2 利用rails内置的ajax功能处理拖拽，代码如下：</p>
<pre name="code" class="ruby">#为简明起见，取id为1的 page,当然也可以根据user来取page
def index 
    @page = Page.find 1
    @columns = @page.columns
end</pre>
<p>&nbsp;</p>
<pre name="code" class="ruby">  &lt;%= javascript_include_tag :defaults %&gt;</pre>
<pre name="code" class="ruby">&lt;table id="table_&lt;%= @page.id %&gt;" align="center"&gt;
      &lt;tr id="tr_&lt;%= @page.id %&gt;"&gt;
        &lt;% for column in @page.columns %&gt;           
          &lt;td id="td_&lt;%= column.id %&gt;" style="height:auto;word-break:break-all;vertical-align:top;"&gt;       
            &lt;% for cell in column.cells %&gt;            
                &lt;div id="cell_&lt;%= cell.id %&gt;" class="cell"&gt;
                    正在载入……
            &lt;/div&gt;       
            &lt;% end %&gt;
          &lt;/td&gt;
        &lt;% end %&gt;
      &lt;/tr&gt;
    &lt;/table&gt;

     &lt;% for column in @page.columns %&gt;
        &lt;%= sortable_element "td_#{column.id}",  
          :url =&gt; { :action =&gt; "sort" , :column_id =&gt; column.id } , 
          :dropOnEmpty =&gt; true ,   
          :tag =&gt; "div" ,
          :containment =&gt; [
           #一个页面最多可以支持4列，总之把page的所有column设置为拖拽容器即可。
       "td_#{@page.columns[0].id}" ,
          "td_#{@page.columns[1].id}" , 
          "td_#{@page.columns[2].id}" ,
          "td_#{@page.columns[3].id}"
        ] , :constraint =&gt; false %&gt;    
      &lt;% end %&gt;
    &lt;% end %&gt;</pre>
<p>&nbsp;异步地为每个小模块加载内容</p>
<p>&nbsp;</p>
<pre name="code" class="ruby">&lt;script&gt;
window.onload = function(){
&lt;% for column in @page.columns %&gt;                 
      &lt;% for cell in column.cells %&gt;   
                new Ajax.Updater('cell_&lt;%= cell.id %&gt;',
                '/Cell/show/&lt;%= cell.id %&gt;',
                {asynchronous:true,evalScripts:true,method:'get'});
      &lt;% end %&gt;
&lt;% end %&gt;
}
&lt;script&gt;</pre>
<p>&nbsp;</p>
<p>后台处理排序</p>
<pre name="code" class="java">def sort
    @column = Column.find params[:column_id]
    td_index = "td_" + @column.id.to_s 
    list = params[td_index] 
    list.each_with_index { |id,idx| 
      cell = Cell.find id
      cell.column = @column
      cell.row_index = idx.to_i
      cell.save
    } 
end</pre>
<p>&nbsp;</p>
<p>3 向页面添加模块，这里默认向页面的第一列添加，添加模块的div可以做成弹出的浮动div形式。</p>
<pre name="code" class="ruby">   &lt;div&gt;
        &lt;% for cell in @cells %&gt;
              &lt;%= link_to_remote cell.name , :update =&gt; "td_#{@page.columns[0].id}" , :mothod =&gt; :get ,
:url =&gt; {:action =&gt; "add_cell" , :page_id =&gt; @page.id , :id =&gt; cell.id} ,:position =&gt; "top"  %&gt;
         &lt;% end %&gt; 
  &lt;/div&gt;
</pre>
<p>&nbsp;后台代码如下：</p>
<pre name="code" class="ruby">def add_Cell
    @page = Page.find params[:page_id]
     #获取该页面的第一列，column_index表示改列的列标
    @column = Column.find :first , :conditions =&gt; ["page_id=? and column_index=?" , @page.id , 1]
      @cell = Cell.find params[:id]
      @cell.column = @column
      @cell.row_index =  0#row_index 表示该模块在一列中的位置
    @cell.save
end</pre>
<p>&nbsp;</p>
<p>&nbsp;4 删除模块</p>
<pre name="code" class="java">#在这里简单的删除该cell记录，前台直接隐藏该cell的div再向后台发送ajax请求。
def delete_cell
    Cell.delete params[:id]
end</pre>
<p>&nbsp;</p>
<p>5 关于设置主题和列数，这个用ajax实现比较容易也比较常见，在此不做解释了。</p>
<p>&nbsp;</p>
<p>6 这里仅提供了一个思路，很多地方可以完善和扩展，比如在现实中column和cell应为多对多的关系，这里简化为一对多，这个方案已经过简单的扩展和测试，效果还不错。</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/211468#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, 04 Jul 2008 12:10:02 +0800</pubDate>
        <link>http://www.javaeye.com/topic/211468</link>
        <guid>http://www.javaeye.com/topic/211468</guid>
      </item>
      <item>
        <title>看看mina和memcached的联姻（适合不同语言客户端，高并发？）</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ahuaxuan.javaeye.com">ahuaxuan</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/217165" style="color:red;">http://www.javaeye.com/topic/217165</a>&nbsp;
          发表时间: 2008年07月21日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: medium">/** <br />* 作者：张荣华 <br />* 日期：2008-07-21 <br />**/<br /><br />看看mina和memcached的联姻<br /><br />先来解释一下这两个东东的身世<br /><br />Mina，是什么？<br />	Minan是一个network 应用框架，她能很方便的帮助用户开发出高性能和高可扩展性的网络应用程序。官方地址请看：<a href="http://mina.apache.org/" target="_blank">http://mina.apache.org/</a><br /><br /><br />Memcached是什么？<br />memcached一个remote cache，它只提供数据存储服务，不过它得java客户端比较不错，还有很多其他语言的客户端，也就是说其周边比较丰富。Memcached的文章太多了，随便一搜一大堆。<br /><br />现在相信大家对这两个东西有点了解了，接着转入正题吧，我估计猛一看标题，很多童鞋估计都有那么一点云中子的感觉（因为云中子一般在云里或者雾里，所以云中子＝＝云里雾里），从上面的解释来看mina和memcached好像是八竿子打不到一起去的东西。这两个东西怎么能走到一起呢。先看他们能解决什么样的需求。<br /><br />	需求：我们知道，所有的互联网服务几乎都离不开connection这个东东，比如我们打开一个网页，从浏览器发起请求到tomcat接受请求并返回数据，这个过程就开启了一个短连接，数据返回之后这个连接就关闭了，也就是说每个请求其实都是一个新连接的开启和关闭。然后，tomcat中的application向数据库发送一个查询语句，它需要从连接池中拿到一个connection，这个connection一直在pool中，显然这个connection是一个长连接，由此可见一次请求，从浏览器到db再到浏览器既经过了短连接有经过了长连接，我们的生活是离不开连接的。<br /><br />	上面说的这个例子是一个请求的最简单模型，因为我们的application可不只是依赖数据库，尤其在互联网应用中，通常我们的application还依赖于其他的server，比如说我们的互联网应用可能还连接着memcached server，通常，这里也有一个连接池，维护着一堆长连接，那么结束了吗，不，再通常我们的application还依赖于其他的application。好及了，一个相对有点复杂的应用网络，接着往下说，快到重点了<br /><br />	重点：<br />一般情况下，我们的application依赖于其他application的的时候我们会直接使用http协议，或者再次封装过的http协议(诸如webservice之流)，而且这种情况是大多数情况，但是不是全部情况，因为在互联网上我们会遇到各种各样的需求。因为http连接是短连接，每次发起连接的3次握手不可避免，这是造成其并发量不高的重要原因之一（有的人也许会说，即使http并发高有什么用，你的application还是撑不住，但是我想说的是不是所有的应用都是这样的，只是你没有遇到过而已）。那么假设我有一个数据中心，这个数据中心可以提供common数据的服务，这些common的数据会被网站的各个地方获取，这些common的数据之间可能还有一些计算，我可以通过请求的参数来执行对应的操作，比如查询，统计等等(哇，看来能有效的降低数据库的压力啊)，那么看来memcached是不行了(不能定制计算)，只能自己写这样的应用了，不过以什么样的形势发布接口呢，短连接不行，并发量有限，只能长连接，还要考虑到一点，我的服务的客户端是不定的，有可能是php，也有可能是java，也有可能是python，也有可能是ruby，如何是好啊。<br /><br />	首先长连接是不二选择，高并发，高连接数是我们最中意的，有了这两个特性，我们这个application就可以被其他很多app使用了，就象共享memcached server一样。<br /><br />其次支持多客户端语言最好是能够有效利用现有资源，比如说不需要自己去开发客户端。<br /><br />	这时候memcached就可以抱着mina出场了。理由：<br />1 Memcached有众多的客户端，可谓周边齐全，看来非它莫数。<br />2 mina可以非常方便的开发出server端程序，好姑娘啊。<br /><br />来吧，看看最简单的示例：<br />Server端主类：<br /><pre name="code" class="java">import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

/**
 * @author ahuaxuan(aaron zhang)
 * @since 2008-7-21
 * @version $Id$
 */
public class MinaServer {

	private static final int PORT = 11211;
	
	public static void main(String[] args) throws IOException {
		// code will go here next
		ByteBuffer.setUseDirectBuffers(false);
		ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

		IoAcceptor acceptor = new SocketAcceptor();

		SocketAcceptorConfig cfg = new SocketAcceptorConfig();
//		cfg.getFilterChain().addLast("logger", new LoggingFilter());
		cfg.getFilterChain().addLast(
				"codec",
				new ProtocolCodecFilter(new TextLineCodecFactory(Charset
						.forName("UTF-8"))));

		 acceptor.bind(new InetSocketAddress(PORT), new ServerHandler(), cfg);

		 System.out.println("------------ Mina Server start up -----------");
	}

}</pre><br />这样，启动这个main方法，就可以建立一个socket server的实例了，欢迎大家来连！！！<br />相当简单啊，再看看一个重要的ServerHandler类<br />其中有一个重要的方法：<br /><pre name="code" class="java">public void messageReceived(IoSession session, Object msg) throws Exception {
		String str = msg.toString();
		String[] parts = str.split(" ");
		if (parts != null && "get".equals(parts[0])) {
			
			StringBuilder sb = new StringBuilder();
			sb.append("VALUE").append(" key ");
			sb.append("1").append(" ");
			sb.append(str.length()).append(" \r\n ");
			sb.append(str + "\r\n").append("");

			//看看这里吧
			session.write(sb.toString());
			session.write("END\r\n");

			System.out.println("Message written..." + sb.toString());
		} else {
			throw new IOException("unsupportoperation");
		}

	}</pre><br />哟，这么多\r\n，还有”END\r\n”这种东西？不好意思，这个是memcached协议定的我也没有办法（说到这里大家终于知道了本文其实只不过是用mina来实现memcached协议而已，前面被我那么多废话解释弄晕了吧，嘿嘿）。<br /><br /><br />	看到这里，我想要提醒一下，msg通常是这样的get aaabbbccc,其中aaabbbccc是key，但是用在我们自己的server上，它就可以不是key了，比如说它可以是/getDistrict.do?name=xx&cc=yy`````````，server拿到这样的字符串之后，一解析就知道客户端要什么了，那么就可以返回数据了，是我的话我会用json序列化我的对象，然后返回。只是一定要告诉客户端我的数据包括哪些内容，又快并发又高（再次提醒，我的application可以高并行计算，比如说大多数数据都在内存中哦），hoho，而且任何一个客户端语言都可以享受这种服务哦。<br /><br /><br />     好了，数据成功返回之后，为了让memcached的客户端能够成功解析，我们必须使用memcacached协议，看一段get协议的解释吧（目前主要是使用这个）：<br /><br />一行取回命令如下：<br /><span style="color: green">get &lt;key>*\r\n<br />&lt;key>* 表示一个或多个键值，由空格隔开的字串<br />这行命令以后，客户端的等待0个或多个项目，每项都会收到一行文本，然后跟着数据区块。所有项目传送完毕后，服务器发送以下字串：<br />"END\r\n"来指示回应完毕。<br /><br />服务器用以下形式发送每项内容：VALUE &lt;key> &lt;flags> &lt;bytes>\r\n<br />&lt;data block>\r\n<br />&lt;key> 是所发送的键名<br />- &lt;flags> 是存储命令所设置的记号<br />&lt;bytes> 是随后数据块的长度，*不包括* 它的界定符“\r\n”<br />- &lt;data block> 是发送的数据如果在取回请求中发送了一些键名，而服务器没有送回项目列表，这意味着服务器没这些键名（可能因为它们从未被存储，或者为给其他内容腾出空间而被删除，或者到期，或者被已客户端删除）。</span><br /><br /><br /><br />这样就可以了，注意，这里只不过是很简单的测试代码（正式代码不便给出），也只不过是提供一个思路而已，大家如果也需要用到这样的场景可以沿着这个思路走下去。<br /><br /><br />声明：由于ahuaxuan水平有限，文中难免有不妥之处，希望大家不吝赐教。<br /><br />ps:如果你没有memcached的客户端，最快的见效的是通过telnet，在windows console里输入telnet localhost 11211，就可以了<br /></span>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/217165#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, 21 Jul 2008 17:06:45 +0800</pubDate>
        <link>http://www.javaeye.com/topic/217165</link>
        <guid>http://www.javaeye.com/topic/217165</guid>
      </item>
      <item>
        <title>RubyCAS-----来自ruby世界的一款灵巧的CAS服务器</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://liuqiang.javaeye.com">liuqiang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/212170" style="color:red;">http://www.javaeye.com/topic/212170</a>&nbsp;
          发表时间: 2008年07月07日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-family: 仿宋;"><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">
<p class="0">&nbsp;</p>
<p><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;"><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体"><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体">
<p class="0">&nbsp;&nbsp;&nbsp;&nbsp;说到cas服务器，首先想到的是耶鲁大学的那款基于java的开源cas服务器，研究一段时间后发现，不是很让人满意，首先是配置过程有点麻烦，新版本的java&nbsp;cas&nbsp;server&nbsp;基于spring&nbsp;framework，用maven部署打包，如果没有一定java功底的话，很难驾驭它。再有就是定制过程麻烦，要对源码做一些修改，这就要求对源码结构有一定的了解。另外还有一些数字证书导入导出的繁琐过程。</p>
</font></font></font></font></span><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体"><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';">
<p class="0">&nbsp;</p>
</font></font></font></span><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体">
<p class="0">&nbsp;</p>
</font></font></span><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';">
<p class="0">&nbsp;</p>
</font></span>
<p class="0">&nbsp;</p>
</p>
<p>&nbsp;</p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp; 那么现在就让Ruby将生活变得简单点，让</span></span><span style="font-weight: normal; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Rub</span><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">yCAS<span style="font-family: 宋体;">将sso问题变得的容易些吧。之所以说</span></span><span style="font-weight: normal; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Rub</span><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">yCAS<span style="font-family: 宋体;">灵巧主要有以下几个原因：</span></span></p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp; 1&nbsp;<span style="font-family: 宋体;">安装部署简单，你甚至可以不了解ruby编程。</span></span></p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp; 2&nbsp;<span style="font-family: 宋体;">可以不用SSL，因为很多应用，比如论坛博客社区等系统没有那么高的安全性要求，我们也不想在页面跳转时出现警告框。</span></span></p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp; 3 可以用SSL,但它的过程是非常简单的，只需安装个gem即可。</span></p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;<span style="font-family: 宋体;">定制简单，基本所有的定制在一个yml文件就搞定了。</span></span></p>
<p class="0">&nbsp;&nbsp;&nbsp; &hellip;&hellip;&hellip;&hellip;</p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://code.google.com/p/rubycas-server/wiki/QuickStart">http://code.google.com/p/rubycas-server/wiki/QuickStart</a>，这里有linux下配置安装的说明，那下面我就展示下windows/WEBrick平台下的安装部署测试过程。</span></span></p>
<p>&nbsp;</p>
<p class="0">&nbsp;</p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">1&nbsp;<span style="font-family: 宋体;">安装</span></span><span style="font-weight: normal; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Rub</span><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">yCAS，安装之前请保证你的你的机器已经装有ruby 1.8.4或更新的版本。在shell中输入：gem install rubycas-server </span></p>
<p class="0">&nbsp;</p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">2 <span style="font-family: 宋体;">必要的配置，主要是指定cas server的端口、用户数据库以及验证策略，打开C:\ruby\lib\ruby\gems\1.8\gems\rubycas-server-0.6.0目录，新建config.yml文件，并将config.example.yml文件的内容全部拷贝进去，由于yml文件的可读性非常好，所以基本都可以理解其中的配置项，把以下3个地方的注释去掉并做如下修改：</span></span></p>
<pre name="code" class="ruby">server: webrick 
port: 443 
#ssl_cert: /path/to/your/ssl.pem 

database: adapter: mysql 
database: cas 
username: root 
password: 123456 
host: localhost 

authenticator: class: CASServer::Authenticators::SQL      
    database:cas    
    adapter: mysql 
    database: cas 
    username: root 
    password: 123456 
    server: localhost 
  user_table: users 
  username_column: username password_column: password </pre>
<p class="0">&nbsp;&nbsp;</p>
<p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">3 <span style="font-family: 宋体;">为了能在windows下运转正常，修改一行代码，linux平台下就省去这一步。打开C:\ruby\lib\ruby\gems\1.8\gems\rubycas-server-0.6.0\lib目录中的casserver.rb文件，</span></span></p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">找到这行：
<p><span style="color: #ff0000;">$CONFIG_FILE ||= '/etc/rubycas-server/config.yml'</span></p>
<p class="0">&nbsp;改为：</p>
<span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;"><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体"><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体">
<p class="0"><span style="color: #ff0000;">$CONFIG_FILE ||= 'C:\ruby\lib\ruby\gems\1.8\gems\rubycas-server-0.6.0\config.yml'</span></p>
</font></font></font></font></span><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体"><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';">
<p class="0">&nbsp;</p>
</font></font></font></span><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';"><font face="宋体">
<p class="0">&nbsp;</p>
</font></font></span><font face="'宋体'" style="font-weight: normal; font-size: 10.5pt; mso-spacerun: 'yes';">
<p class="0">&nbsp;</p>
</font></span>
<p class="0">&nbsp;</p>
</p>
<p class="0">&nbsp;</p>
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">4&nbsp;<span style="font-family: 宋体;">以上3步基本搞定cas&nbsp;server所有该做的事情了，事情就那么简单，在cmd中输入rubycas-server启动cas server,访问<a href="http://localhost:443">http://localhost:443</a>即可看到登录界面。</span></span><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">那么下面我们编写客户端测试吧，这里我采用的是ruby做客户端，<a href="../../../topic/210994">http://www.javaeye.com/topic/210994</a>这篇文章已经介绍了ruby客户端的配置使用，在这里只要在<span style="font-family: Courier New;">config/environment.rb</span> 文件中最后那段修改为：</span></span></p>
<p class="0">&nbsp;</p>
</p>
<pre>CASClient::Frameworks::Rails::Filter.configure( :cas_base_url =&gt; http://localhost:443 ) </pre>
<font face="仿宋"><font face="'宋体'" style="font-weight: bold; font-size: 10.5pt; mso-spacerun: 'yes';">
<p>
<p class="0">&nbsp;</p>
<p class="0">&nbsp;</p>
<span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">
<p class="0"><span style="font-weight: normal; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">5&nbsp;按照上一步建立2个rails应用A和B,分别装上rubycas客户端，我的测试结果如下，访问A时跳到了cas服务器登录界面，只有输入正确密码才跳回A,这时访问B时无需验证直接进入，并通过session[:cas_user]得到了在访问A时登入的用户名，关闭浏览器，A B反过来再来一遍，一样是可以的。</span></p>
</span></p>
</font>
<p class="0">&nbsp;</p>
</font></span><font face="仿宋">
<p>
<p class="0">&nbsp;</p>
</p>
</font></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><!--EndFragment--><a href="http://code.google.com/p/rubycas-server/">http://code.google.com/p/rubycas-server/</a></p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/212170#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>Mon, 07 Jul 2008 08:52:07 +0800</pubDate>
        <link>http://www.javaeye.com/topic/212170</link>
        <guid>http://www.javaeye.com/topic/212170</guid>
      </item>
      <item>
        <title>Spring Framework 2.5 Reference中文版正式发布</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://digitalsonic.javaeye.com">DigitalSonic</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/209974" style="color:red;">http://www.javaeye.com/topic/209974</a>&nbsp;
          发表时间: 2008年07月01日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong><span style="font-size: small;">声明</span> </strong><br />Spring中文参考手册得到Spring Framework开发团队的直接授权和大力的支持，其目的是在中文世界推广优秀的开源技术。本次翻译活动由满江红开放技术研究组织(<a href="http://www.redsaga.com" target="_blank">http://www.redsaga.com</a> )和Spring中文论坛(<a href="http://spring.jactiongroup.net" target="_blank">http://spring.jactiongroup.net</a> ) 共同发起、组织。我们在此郑重宣布，本次翻译遵循原Spring Framework的授权协议，即Apache 2.0协议。在完整保留全部文本(包括本版权页)，并且不违反Apache 2.0协议的前提下，允许和鼓励任何人进行全文转载及推广，所有参与人员放弃除署名权外的一切权利。<br /><br /><strong><span style="font-size: small;">致谢</span> </strong><br />如此庞大的项目不是一两个组织可以独立完成的，就像Spring本身一样，涵盖了Java技术的方方面面。因为有了大家的关心和支持才使此次项目能够顺利完成。有理由相信，中文开源世界必将在不久的将来展现出更广阔的发展空间，希望大家都能为推动中国软件发展奉献出自己的一份力量。<br /><br />项目主页：<br /><a href="http://wiki.redsaga.com/confluence/display/Spring2/Spring2.5" target="_blank">http://wiki.redsaga.com/confluence/display/Spring2/Spring2.5</a> <br /><br />在线版本：<br /><a href="http://www.redsaga.com/spring_ref/2.5/html/" target="_blank">HTML</a> / <a href="http://www.redsaga.com/spring_ref/2.5/html_single/" target="_blank">HTML Single</a> <br /><br />下载地址：<br /><a href="http://www.redsaga.com/spring_ref/2.5/spring-reference.pdf" target="_blank">PDF(593页，4.41MB)</a> / <a href="http://www.redsaga.com/spring_ref/2.5/Spring-Reference_zh_CN.chm" target="_blank">CHM(2.08MB)</a> <br /><br />勘误表：<br /><a href="http://wiki.redsaga.com/confluence/pages/viewpage.action?pageId=3171" target="_blank">http://wiki.redsaga.com/confluence/pages/viewpage.action?pageId=3171</a> </p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/209974#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, 01 Jul 2008 00:01:54 +0800</pubDate>
        <link>http://www.javaeye.com/topic/209974</link>
        <guid>http://www.javaeye.com/topic/209974</guid>
      </item>
      <item>
        <title>MySQL Storage Engine 小记</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://mozart.javaeye.com">Mozart</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/211951" style="color:red;">http://www.javaeye.com/topic/211951</a>&nbsp;
          发表时间: 2008年07月05日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>这段时间在看《High Performance MySQL》，看到存储引擎这个地方感到很多细节比较陌生，所以总结小记一些<br />
<br />
为了适应各种不同的运行环境，MYSQL提供了多种不同的存储引擎（Storage Engine ）,在应用程序开发这个层面上，开发者可以根据不同的需求选择适合的Storage Engine 方案，更为灵活的是，你可以根据每张表将要存储数据的特点，选择不同的Storage Engine,也就是说，在一个MYSQL数据库中，可以混合使用多种不同的Storage Engine<br />
<br />
首先小瞥一下MySQL的体系结构，在最高抽象层度下，可以用Garlan &amp; Shaw的分层结构体系来表示（左）<br />
<img src="../../upload/picture/pic/17429/e9ca34d9-432d-3ad2-b8d9-d13b45b74fc9.jpg" alt="" />
<br />
其中应用层为所有RDBMS用户提供用户接口，逻辑层包括了所有核心功能的实现，物理层则负责将数据存储在硬件设备上。<br />
<br />
图中右侧更为具体的描述了逻辑层的组成，查询处理子系统、事务管理子系统、恢复管理子系统和存储管理子系统共同组成了MySQL的逻辑层。相信Storage Engine的位置是在Storage Management处，既Storage Engine属于Storage Management子系统的一部分<br />
<br />
为了让思路更清晰一些，下面给出一幅比较全面的体系结构图（或更确切的说是流程图，只是忽略了反馈）<br />
<img src="../../upload/picture/pic/17425/e3795bbd-c9d8-3c04-bc0e-83db0bfb8322.jpg" height="770" alt="" width="616" />
<br />
上面三幅图来自于一篇非官方（不保证百分百的正确）的MySQL体系结构的报告，与《High Performance MySQL》一书中给出的MySQL大体结构（下图,基本对应于Logic Layer，从第一幅图右侧可以看出MySQL logic layer同样遵从分层体系结构）还是比较吻合的。<br />
<img src="../../upload/picture/pic/17423/a8a8105e-5ba7-3c4d-9bc3-6716c7bb9c3c.jpg" height="226" alt="" width="373" />
<br />
连接上图中第二层和第三层之间的接口是并不针对任何存储引擎的单一API,.大概由20个基本的类似&ldquo;启动事务，返回结果集&rdquo;等函数组成。存储引擎并不处理SQL，相互之间也不通信，它们的任务只是简单的响应高层传来的请求。<br />
<br />
<strong><span style="font-size: small;">存储引擎各自的一些特点</span>
</strong>
<br />
<br />
上面提到的四种存储引擎都有各自适用的环境，这取决于它们独有的一些特征。主要体现在性能、事务、并发控制、参照完整性、缓存、 故障恢复，备份及回存等几个方面<br />
<br />
<br />
目前比较普及的存储引擎是MyISAM和InnoDB.而MyISAM又是绝大部分Web应用的首选。MyISAM与InnoDB的主要的不同点在于性能和事务控制上。<br />
<br />
MyISAM是早期ISAM(Indexed Sequential Access Method,我现在用的MySQL5.0已经不支持ISAM了）的扩展实现，ISAM被设计为适合处理读频率远大于写频率这样一种情况，因此ISAM以及后来的MyISAM都没有考虑对事物的支持，排除了TPM，不需要事务记录，ISAM的查询效率相当可观，而且内存占用很少。MyISAM在继承了这类优点的同时，与时俱进的提供了大量实用的新特性和相关工具。例如考虑到并发控制，提供了表级锁，虽然MyISAM本身不支持容错，但可以通过myisamchk进行故障恢复。而且由于MyISAM是每张表使用各自独立的存储文件（MYD数据文件和MYI索引文件），使得备份及恢复十分方便（拷贝覆盖即可），而且还支持在线恢复。<br />
<br />
所以如果你的应用是不需要事务，处理的只是基本的CRUD操作，那么MyISAM是不二选择<br />
<br />
InnoDB被设计成适用于高并发读写的情况.使用MVCC(Multi-Version Concurrency Control)以及行级锁来提供遵从ACID的事务支持。InnoDB支持外键参照完整性，具备故障恢复能力。另外 InnoDB的性能其实还是不错的，特别是在处理大数据量的情况下,用官方的话说就是： InnoDB的CPU效率是其他基于磁盘的关系数据库存储引擎所不能比的。不过InnoDB的备份恢复要麻烦一点，除非你使用了4.1以后版本提供的Mulit-tablespace支持，因为InnoDB和MyISAM不同，他的数据文件并不是独立对应于每张表的。而是使用的共享表空间，简单的拷贝覆盖方法对他不适用，必须在停掉MYSQL后对进行数据恢复。使用Per-Table Tablespacesd，使其每张表对应一个独立的表空间文件，则情况要简单很多。<br />
<br />
一般来说，如果需要事务支持，并且有较高的并发读写频率，InnoDB是不错的选择。要是并发读写频率不高的话，其实可以考虑BDB,但由于在MySQL5.1及其以后版本中，将不再提供BDB支持。这个选项也就没有了<br />
<br />
至于Heap和BDB（Berkeley DB），相对来说，普及率不如前两种，但在有些情况下，还是挺适用的<br />
<br />
Heap存储引擎就是将数据存储在内存中，由于没有磁盘I./O的等待，速度极快。但由于是内存存储引擎，所做的任何修改在服务器重启后都将消失。<br />
&nbsp;<br />
Heap挺适合做测试的时候使用<br />
<br />
<br />
BDB是MySQL第一款事务安全的存储引擎。在Berkeley DB database library的基础上建立，同样是事务安全的，但BDB的普及率显然不及InnoDB，因为大多数在MySQL中寻找支持事务的存储引擎的同时也在找支持MVCC或是行级锁定存储引擎，而BDB只支持Page-level Lock。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>附上一张《High Performance MySQL》 中的各存储引擎的特性表</p>
<table rules="all" cellspacing="0" border="1" width="100%" cellpadding="4">
<thead>
<tr>
<th class="docTableHeader">
<p class="docText">Attribute</p>
</th>
<th class="docTableHeader">
<p class="docText">MyISAM</p>
</th>
<th class="docTableHeader">
<p class="docText">Heap</p>
</th>
<th class="docTableHeader">
<p class="docText">BDB</p>
</th>
<th class="docTableHeader">
<p class="docText">InnoDB</p>
</th>
</tr>
</thead>

<tbody>
<tr>
<td class="docTableCell">
<p class="docText">Transactions</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Lock granularity</p>
</td>
<td class="docTableCell">
<p class="docText">Table</p>
</td>
<td class="docTableCell">
<p class="docText">Table</p>
</td>
<td class="docTableCell">
<p class="docText">Page (8 KB)</p>
</td>
<td class="docTableCell">
<p class="docText">Row</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Storage</p>
</td>
<td class="docTableCell">
<p class="docText">Split files</p>
</td>
<td class="docTableCell">
<p class="docText">In-memory</p>
</td>
<td class="docTableCell">
<p class="docText">Single file per table</p>
</td>
<td class="docTableCell">
<p class="docText">Tablespace(s)</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Isolation levels</p>
</td>
<td class="docTableCell">
<p class="docText">None</p>
</td>
<td class="docTableCell">
<p class="docText">None</p>
</td>
<td class="docTableCell">
<p class="docText">Read committed</p>
</td>
<td class="docTableCell">
<p class="docText">All</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Portable format</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
<td class="docTableCell">
<p class="docText">N/A</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Referential integrity</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Primary key with data</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">MySQL caches data records</p>
</td>
<td class="docTableCell">
<p class="docText">No</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
<td class="docTableCell">
<p class="docText">Yes</p>
</td>
</tr>
<tr>
<td class="docTableCell">
<p class="docText">Availability</p>
</td>
<td class="docTableCell">
<p class="docText">All versions</p>
</td>
<td class="docTableCell">
<p class="docText">All versions</p>
</td>
<td class="docTableCell">
<p class="docText">MySQL-Max</p>
</td>
<td class="docTableCell">
<p class="docText">All Versions</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://apusiczhang.javaeye.com/topic/211951#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, 05 Jul 2008 23:35:13 +0800</pubDate>
        <link>http://www.javaeye.com/topic/211951</link>
        <guid>http://www.javaeye.com/topic/211951</guid>
      </item>
      <item>
        <title>ruby+cas实现sso</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://liuqiang.javaeye.com">liuqiang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/210994" style="color:red;">http://www.javaeye.com/topic/210994</a>&nbsp;
          发表时间: 2008年07月03日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>之前做了几个基于ruby,java的系统，现在想把它们整合到一起，首先遇到了单点登录问题，开始是用跨域iframe来实现，效果还行，但安全性不大高，所以还是打算上cas，方案如下:</p>
<p>1 安装cas3.0并配置<a href="210679">http://liuqiang.javaeye.com/admin/blogs/210679</a>，保证<a href="http://localhost:8080/cas">http://localhost:8080/cas</a>能正常运行。</p>
<p>&nbsp;</p>
<p>2 安装ruby的cas客户端：进入项目根目录，运行ruby script/plugin install <a href="http://rubycas-client.googlecode.com/svn/trunk/rubycas-client">http://rubycas-client.googlecode.com/svn/trunk/rubycas-client</a></p>
<p>&nbsp;</p>
<p>3 打开<span style="font-family: Courier New;">config/environment.rb</span> ，在该文件最后也就是等rails初始化完毕，加上 CASClient::Frameworks::Rails::Filter.configure(<br />&nbsp;&nbsp;&nbsp; :cas_base_url =&gt; "<a href="http://localhost:8080/cas">http://localhost:8080/cas</a>"<br />&nbsp; )</p>
<p>&nbsp;</p>
<p>4 在需要校验的控制器中加入 before_filter CASClient::Frameworks::Rails::Filter</p>
<p>&nbsp;</p>
<p>5 在视图中加入登录链接：&lt;a href="/front/sessions/login"&gt;登录&lt;/a&gt;</p>
<p>&nbsp;</p>
<p>6 在负责处理登录的控制器中加上 before_filter :set_current_url , CASClient::Frameworks::Rails::Filter</p>
<pre name="code" class="ruby"> <pre name="code" class="java"> before_filter :set_current_url ,CASClient::Frameworks::Rails::Filter

  def set_current_url
#记下来源url,因为在之后的验证过程中，来源url会丢失
    cookies[:current_url] = request.referer
  end

 def cas_login
#跳到来源url
    redirect_to cookies[:cur