<?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>想询问下对日外包的工作</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://coreymylife.javaeye.com">coreymylife</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/216699" style="color:red;">http://www.javaeye.com/topic/216699</a>&nbsp;
          发表时间: 2008年07月20日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近在学习日语,不过在学习之前,先想来问问大牛们,<br />听说现在对日外包很火,我想问下待遇怎么样?如果学好日语,这方面的需求大不大<br />有没有前途,现在要这方面的人的公司多不多,主要在哪,薪筹怎么样,谢谢!
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/216699#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, 20 Jul 2008 15:28:06 +0800</pubDate>
        <link>http://www.javaeye.com/topic/216699</link>
        <guid>http://www.javaeye.com/topic/216699</guid>
      </item>
      <item>
        <title>广州Java开发工作, 基本工资4000元/月</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhanjia.javaeye.com">zhanjia</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219436" style="color:red;">http://www.javaeye.com/topic/219436</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          个人工作经验一年, 新公司给最高是4000元/月, 有餐补和通讯费, 大概是3~4百元/月.<br />社保和公积金说是按广州最高标准来缴纳, 说有项目奖金(这个很多公司都说说而已).<br />SSH方面的开发工作, 面向电信方面.<br />说要赶紧回复, 犹豫中啊!!!<br />大家给个建议或评价吧?
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219436#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, 25 Jul 2008 12:30:11 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219436</link>
        <guid>http://www.javaeye.com/topic/219436</guid>
      </item>
      <item>
        <title>把业务逻辑从存储过程中拿出来</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://hyhongyong.javaeye.com">hyhongyong</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219371" style="color:red;">http://www.javaeye.com/topic/219371</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>对于业务逻辑放在存储过程中的情况，目前比较有市场的看法是： &ldquo;不要把业务逻辑放在DB中，除非有性能问题&rdquo; <br />日前，我却遇到另外一种情况： <br />首先说一下业务（简化过的）： <br />酒店预订系统，酒店是按天计算价格的，酒店合同价格是按时间段的，后录的合同如果时间上与原来的重合，则使用后录合同的价格。 <br />现在的问题是从酒店合同价格计算预订时间段内的价格。主要有三个步骤： <br />1.分割：把合同价格的时间段按天分割到每天的价格 <br />2.选择：选择每天上比较后录的合同的价格 <br />3.归并：按价格相同与否，将每天的价格归并成时间段 <br />之前是用存储过程做的。（因为这样会减少网络传输），而且不是一个存储过程，因为不同的价格计算条件和方式有一些微小的差别。 <br />很不幸，业务有变化了，这些存储过程都要改动，而且目前有了一些性能方面的问题： <br />我们的DB是用的oracle 10 的RAC，AP服务器用的是weblogic 8 集群。在计算所有酒店的一天价格时，用存储过程要10多分钟。如果计算多几天的价格，则会因为存储过程时间过长，造成AP报timeout。 <br />为了应对业务的变化（也因为有了这些变化，才敢有以下的做法），也为了解决性能问题，我决定把这些业务逻辑从DB中移出来，放在程序中去。我们用面向对象的方法进行分析和设计，用若干业务领域类以及持久化DAO代替了这些存储过程。用了大约2个人月的时间，完成上线了。 计算一天价格的时间下降到3分钟，仔细检查了一下，业务接口中有个地方可以优化。优化后，计算一天价格的时间下降到不足一分钟了，多天的价格计算也可以进行了！ <br />总结一下这次过程： <br />1、存储过程处理的过程复杂时，性能未必好！ <br />2、程序中也有很多地方是可以优化的。 <br />3、面向对象的程序应对业务逻辑的变化，有时比存储过程还要好！</p>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219371#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, 25 Jul 2008 10:29:26 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219371</link>
        <guid>http://www.javaeye.com/topic/219371</guid>
      </item>
      <item>
        <title>spring AOP能否从session取数据</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://eseking.javaeye.com">eseking</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/216653" style="color:red;">http://www.javaeye.com/topic/216653</a>&nbsp;
          发表时间: 2008年07月20日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          大家好，对于spring 我只会基本的应用，这几天碰到这个需求不知道自己的思路是否正确。<br />spring aop目前我只是用它的事务管理器而已，会跑个简单的AOP。现在做一个小的权限系统，比如我的切面是叫做<br />PermissionManager,  调用的是我的 ACLManager中的 hasPermission(int userID,String sn)这个方法来判断某个用户对某个模块是否有操作权限。在不改变原有代码的基础上，我试着拦截所有的ADD方法，通过这个permissionManager 来实现拦截，没有权限就把异常向上抛出。<br />     现在的问题是，我用某个用户登陆，我发现我的切面不能获取当前登陆用户的ID，也就是说，我不知道使用AOP的时候怎么跟WEB交互。一个service 类怎么去获取session 对象。查了点资料，还是没有什么头绪。但是我觉得这个需求应该很多人都碰到过吧。希望大家指点 。
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/216653#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, 20 Jul 2008 09:49:52 +0800</pubDate>
        <link>http://www.javaeye.com/topic/216653</link>
        <guid>http://www.javaeye.com/topic/216653</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://superleo.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>发疯Hibernate分页问题,性能优化!</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://myprincejava.javaeye.com">myprincejava</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219595" style="color:red;">http://www.javaeye.com/topic/219595</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>最近写了一个Hibernate分页，之前用游标来实现得到count 总行数..用HQL语句查询!可是现在问题出现了，但数据达到海量的时候，出现比较慢,现在要进行优化:</p>
<p>1.不能使用游标得到count总行数!</p>
<p>ScrollableResults rs = query.scroll(ScrollMode.SCROLL_INSENSITIVE);<br />&nbsp;&nbsp;rs.last();<br />&nbsp;&nbsp;return (rs.getRowNumber() + 1);</p>
<p>2.不能使用select count(*) from .....这样要得到count 和list 分布操作很麻烦!查询和count 都要同步!不想两次操作...</p>
<p>假如更改字段都要更改...不想这么做！要公用....</p>
<p>3.不能使用query.list().size()</p>
<p>&nbsp;int count=query.list().size();</p>
<p>除了这三种方法实现得到count,不知道还能用什么方法去实现!相信javaeye上面大师们应该会出现这样情况吧！遇到过的提提建议...</p>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219595#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, 25 Jul 2008 17:28:56 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219595</link>
        <guid>http://www.javaeye.com/topic/219595</guid>
      </item>
      <item>
        <title>原来找工作这么辛苦</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://nighthaven.javaeye.com">Nighthaven</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/216356" style="color:red;">http://www.javaeye.com/topic/216356</a>&nbsp;
          发表时间: 2008年07月18日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p style="TEXT-ALIGN: center"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">原来找工作这么辛苦</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;"><span style="font-size: medium;"><strong>当我坐在面试官面前时，脸上的表情分明写着：＂嘿！我已经在来的火车上连续站了２０个小时最近两天内只睡了不到５个小时现在非常疲惫你如果敢拒绝我的求职让我这个待业青年浪费来回接近１０００块的路费我一定砍死你＂，然而面试官果然是久经沙场，对于&ldquo;一切反动派都是纸老虎&rdquo;有着深刻的理解，没有被我凶残的表情所吓倒，１０分钟后拒绝了我的求职。</strong></span></span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　好吧，故事是不能这么讲的。这件事要从头说起：</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　大约两个星期前，因为觉得在公司里不会有前途，也因为公司给我安排了非常不喜欢的工作，我没有和以前一直实习的单位签约。本来这种感觉是早在去年开始在这公司家实习的时候就有的，只是我为人一向优柔寡断，外加对就业形势也不看好，居然恍恍惚惚的就在这家公司实习了接近６个月，以至于马上就要签劳动合同了。这时自己才突然猛醒，发现找一个自己不讨厌的工作是第一位的。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　然而，觉醒的有些晚，因为已经是７月初，我已经毕业了。此时后悔自己在１１月份时没有投递简历已然来不及，只好硬着头皮找工作了。花了两天时间找了找看着比较顺眼的公司，一共投了５份简历出去，各种工作岗位都有，文的武的，都是我比较喜欢的。听同学说，简历投出去一般都要等一个月以上才有答复，于是投完简历之后，我便开始自我催眠：&ldquo;不要急，不要急，如果短期内没有面试通知，只是招聘的人还没有空看你的简历而已。&rdquo;</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　然而实际情况大大出乎我的意料，投完简历的第二天，就接到一个约面试时间的电话。这时，我发现我犯了一个错误：之前投简历时，光顾着给比较知名的企业投递，没有考虑到公司的地点，投递的５家公司分布在广州、北京、上海三个城市。约我去面试的是一家北京的公司，而我现在人在珠海。不得已，我只好询问对方可否在电话上和面试官先谈谈，对方很干脆的回绝，说是技术总监直接面试，不能在电话上谈。这下我傻了眼，去吧，万一不成，平白浪费一大笔路费；不去吧，还不知道下个面试机会什么时候才来。于是我和对方约好下个星期和对方电话联系。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　所谓三思而后行，然而三思之后却不一定就能做出正确的决定。很快，找工作经验的匮乏和应届生的狂妄自大让我犯了又一个错误：自以为是的觉得自己一定能手到擒来。于是到了第二个星期，我查了一下列车时刻表，去北京的火车下午一点五十分到站，为了节约旅馆费用，我便和对方约定了下午三点面试。后来证明，这又是一个错误的决定。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　面试的时间是星期三。星期二，我早早的赶去广州，到火车站买票时却被告知只有站票可买了。从小没怎么吃过苦的我，从来就没买过站票。当时心想自己年轻力壮，从广州站到北京也只有二十多个小时，肯定没问题，于是就买了一张站票。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　事实很快就告诉我，站二十多个小时，还是很辛苦的。由于缺乏经验，没有及时占领水池等可以坐下的有利地形，我这站票真是不没有辜负了这个&ldquo;站&rdquo;字。即使同样是站，我所站的地方也可称得上是极品站位了。左边是垃圾箱，右边是厕所。也就是人们不需要消化就直接丢弃的物品放我左边，需要消化之后再丢弃的物品放我右边。各种味道还在其次，反正车厢里的空气质量已经很差了。问题在于，这个位置的交通流量太大，想要安静的站会都不行。外加我还背着个笔记本，大约五个小时之后，我就感觉很痛苦了。这时候餐车的人出来卖夜宵了。说是夜宵，其实就是花三十块钱，可以在餐车从晚上十点坐到早晨六点。这对于我来说简直就是救*命稻草<span style="font-size: small;">(JavaEye居然不能打救*命两个字，真是&hellip;&hellip;)，</span>二话不说，拿出三十块钱，直奔餐车去了。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　到了餐车坐下，座位居然还是软的。阿拉真主，我赞美你！为了明天面试的时候能精神点，我爬在桌子上决定睡觉。然而周围的人都没有睡意，打牌的，聊天的，有一桌是四个乘警，居然八卦警察界的腐败一直八卦到晚上三点多。于是我也一直到四点左右才睡着。其实我平时都是很容易睡着的，那天大概是心理素质不好，对面试有点紧张吧。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　第二天早晨五点半，我迷迷糊糊的醒了，发现流了不少口水在自己胳膊上。幸亏其他人都没发现，赶快擦掉。擦完口水，刚想睡个回笼觉，乘务员已经在赶我们离开了。唉，怎么有种难民的感觉呢。顾不上感慨，已经被从餐车赶到卧铺车厢，又从卧铺车厢被赶到了硬座车厢。此时，距离到郑州就只有两个小时了。我又天真了，以为到了郑州就会有座位。结果到了郑州，下没下几个人，反倒上来了更多的人。空出来的几个座位，我也抢不到。心说卧铺总是抢得慢些吧，想去补张卧铺票。结果发现自从排队这项活动引入了插队这项特殊条款以后，就变成了一项我完全不擅长的体育运动。无奈只得回去继续站着。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　在终点比较接近的时候，人总是更具有忍耐力。前一天站了五个小时就已经很累了，第二天因为快到终点了，从早晨六点站到中午一点也都没什么感觉了。我甚至已经有闲心在构思这篇博客了，预备着如果面试成功的话，开头就写：</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;"><span style="font-size: medium;"><strong>　　当我坐在面试官面前时，脸上的表情分明写着：＂嘿！我已经在来的火车上连续站了２０个小时最近两天内只睡了不到５个小时现在非常疲惫你如果敢拒绝我的求职让我这个待业青年浪费来回接近１０００块的路费我一定砍死你＂，然而面试官对我凶残的表情什么欣赏，决定将我招为公司保安。</strong></span></span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　在下午一点时，终于来到了这趟旅行的高潮部分：车厢里的空调坏了。整个车厢只有两个小窗户能打开，满满的一车人让车里的气温迅速升高，几分钟之后，车内温度就超过车外了。不过无所谓了，反正快到终点了。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　列车准时到站，我发现自己走路已经是一瘸一拐。面试是三点钟，而当时已经是一点五十分。我连忙叫了一辆出租车。说完要去学院路，司机却并不打表，张口就问我要七十块，我简直&hellip;&hellip;。没空和他较真，二话不说下车，走了几十米又打了一辆。这次的司机到是个实在人，问题是居然不认得我应聘的公司所在的大楼。我只得又打通公司前台的电话，让司机向前台问路。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　无论如何，最后还是到达了应聘的公司，时间也刚好是两点五十，差点迟到，吓出我一身冷汗。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　和前台说明来意之后，对方给了我一份笔试题，让我先做着，说是面试官一会就来。此时我才发现睡眠不足的后遗症还是很严重的。因为坐车前一天五点钟就起床，加上火车上一共只睡了两个小时。我两天之内只睡了不到５个小时。做笔试题的时候就明显的感觉到思维非常迟钝，有的话要看两遍才能明白是什么意思。不过还是顺利把笔试题写完，交过笔试题以后，才想起来自己现在外貌一定很糟糕。两天没刮胡子，裤子上有不知道什么时候蹭到的污渍，鞋面上有好几个脚印和一道火车上卖货小车的轮胎印。然而整理形象已经来不及了，面试官已经来了。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　具体面试情节我就不叙述了，总之表现的非常之差，思维很迟钝，很多东西想不起来，还被面试官评为口头表达能力不好。１０分钟后，面试就结束了。我离开公司大概半个小时后，收到一条短信，通知我面试没通过。唉！真是失败到极点。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　无论如何，失败归失败，也算是给我这个在校期间没有投过简历的人补补课吧。因为当天没有回广州的火车了（也许是我没找对地方，北京现在旅店的费用简直是打劫啊），我没从北京直接回珠海，而是先坐了七个小时的汽车到了在临近省份的家里。现在的我，刚刚睡了十二个小时，不过还是没什么精神，写篇博客发发牢骚吧。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　总结这次找工作的经历，可以说自己犯了无数错误。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　第一，投递简历没有选择性，全国各地瞎投，导致自己疲于奔命。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　第二，对自己的能力水平没有一个正确估计，以为自己十拿九稳，轻易同意去外地面试，结果白白付出大量时间和金钱。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　第三，面试时间预约的极不合理，为了省点住宿费，险些迟到，也让自己没有很好的休息。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　第四，没有旅行经验，对暑运的严峻程度估计不足。没有提前订票，只买到了站票，使得面试时自己的体能和精神状态都很差，直接导致了在面试时的糟糕表现。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　第五，面试准备不足，很多应该预先准备的问题没有想好，比如&ldquo;有什么优点&rdquo;之类的。（其实，我好像也有大略的想过，可能是面试时太累了吧）</span></span></p>
<p align="left" lang="zh-CN">&nbsp;</p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　刚刚又收到北京某公司寄来的笔试题，居然要求先玩他们公司的某某游戏４－６天。我这次在家，离北京倒是比较近，问题是：我，待业，在家，玩网络游戏，这简直就是我爸最恐怖的噩梦现实加强版。没有去一直实习的公司已经给他老人家不小的打击，现在&hellip;&hellip;，唉，到底要不要应聘呢。</span></span></p>
<p align="left" lang="zh-CN">&nbsp;</p>
<p align="left" lang="zh-CN"><span style="font-family: 楷体_GB2312, monospace;"><span style="font-size: large;">　　经受这个打击，我已经急了。大致说说我自己的概况，谁认为我值得一试，请留下联系方式，或者用论坛短信联系我：</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">　　我今年（２００８年）毕业于某非２１１工程大学，获软件工程专业学士学位。一直非常喜欢</span></span><span style="font-family: 宋体;"><span style="font-size: small;">Java</span></span><span style="font-family: 宋体;"><span style="font-size: small;">编程语言。对于</span></span><span style="font-family: 宋体;"><span style="font-size: small;">JAVA SE</span></span><span style="font-family: 宋体;"><span style="font-size: small;">有比较牢固的掌握，熟悉一些经典设计模式。曾使用</span></span><span style="font-family: 宋体;"><span style="font-size: small;">Swing</span></span><span style="font-family: 宋体;"><span style="font-size: small;">、</span></span><span style="font-family: 宋体;"><span style="font-size: small;">Socket</span></span><span style="font-family: 宋体;"><span style="font-size: small;">以及</span></span><span style="font-family: 宋体;"><span style="font-size: small;">JMonkey</span></span><span style="font-family: 宋体;"><span style="font-size: small;">（一个基于</span></span><span style="font-family: 宋体;"><span style="font-size: small;">Java</span></span><span style="font-family: 宋体;"><span style="font-size: small;">的</span></span><span style="font-family: 宋体;"><span style="font-size: small;">3D</span></span><span style="font-family: 宋体;"><span style="font-size: small;">类库）等</span></span><span style="font-family: 宋体;"><span style="font-size: small;">API</span></span><span style="font-family: 宋体;"><span style="font-size: small;">开发过一些软件</span></span><span style="font-family: 宋体;"><span style="font-size: small;">(</span></span><span style="font-family: 宋体;"><span style="font-size: small;">包括几个小游戏，一个为学校制作的电子地图系统、一个基于</span></span><span style="font-family: 宋体;"><span style="font-size: small;">UDP</span></span><span style="font-family: 宋体;"><span style="font-size: small;">的即时通信软件等等</span></span><span style="font-family: 宋体;"><span style="font-size: small;">)</span></span><span style="font-family: 宋体;"><span style="font-size: small;">。由于学校课程和实习等原因，大量使用</span></span><span style="font-family: 宋体;"><span style="font-size: small;">C++,</span></span><span style="font-family: 宋体;"><span style="font-size: small;">对</span></span><span style="font-family: 宋体;"><span style="font-size: small;">C++</span></span><span style="font-family: 宋体;"><span style="font-size: small;">掌握有较好的理解。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">　　英语通过</span></span><span style="font-family: 宋体;"><span style="font-size: small;">CET-6</span></span><span style="font-family: 宋体;"><span style="font-size: small;">，读的能力不错，可以比较流畅的阅读英文资料，翻译英文文章；写的能力较差，很多时候要边查书边写；听的能力尚可，可以大致听懂</span></span><span style="font-family: 宋体;"><span style="font-size: small;">VOA</span></span><span style="font-family: 宋体;"><span style="font-size: small;">；很少有说的机会，所以说的能力应该也比较差。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">　　中文写作能力尚可，有一定古文功底，有比较强的文字表达和理解能力。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">　　学习、尤其是自学能力较强，喜欢新技术，工作努力。与人交往属于慢热型，和熟人话很多，喜欢帮助别人，也很有给别人解释问题的天分（可能是因为父母都是教师吧）。性格较温和，比较幽默，极少发脾气，可以积极看待别人对自己的批评。有团队观念，基本能正确掌握表达自己观点的时间、地点。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">　　缺点是，优柔寡断，喜欢把做决定的时间向后拖；工作中有时会计划不够充分，有时会边实现边设计（不是敏捷开发那种）；有时会容易陷入理论上的争执。以上三点都正在逐步改进中。此外我写的字非常之丑，这一点恐怕是不太可能会改善了。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">总的来说，我认为现在的我还无法立即成为一个公司的战斗力。但是经过适当培训之后，我可以成为一个团队中值得信赖的一员，也同时具备在极少监督和协助下完成任务的能力。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-family: 宋体;"><span style="font-size: small;">　　我的兴趣很广泛，程序员、游戏脚本策划、网站编辑&hellip;&hellip;都是我喜欢的工作。我对于由于项目进度紧张造成的适度加班没有排斥，也认同员工为了职业进步而主动自愿加班，但是不认同那些长期强迫员工大量加班（或者安排超额任务，美其名曰&ldquo;自愿加班&rdquo;）的公司的企业文化。</span></span></p>
<p align="left" lang="zh-CN"><span style="font-size: small; font-family: 宋体;">　　嗯，差不多就是这些了，有兴趣的话请联系我吧。</span></p>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/216356#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 Jul 2008 21:47:24 +0800</pubDate>
        <link>http://www.javaeye.com/topic/216356</link>
        <guid>http://www.javaeye.com/topic/216356</guid>
      </item>
      <item>
        <title>说说最近北京的工资行情</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://happydays.javaeye.com">HappyDays</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/218373" style="color:red;">http://www.javaeye.com/topic/218373</a>&nbsp;
          发表时间: 2008年07月22日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近一段时间在找工作，先说说本人的基本情况，一年工作经验，自认为工作能力较强，无聊的时候也研究技术，会的东西有:ajax,struts,webwork,spring,hibernate，一共面试过三家。<br /><br />第一家：笔试之后（笔试题很简单），人事部的问我工资要多少，我说4500~5000，人家听了之后说这次只是初试，还有复试，让我先回去等消息，然后就没有下文了。<br /><br />第二家：问我要多少，这次我要的低了点，说4500,对方说，你要的薪金我们达不到，我就问他，那你最多能给多少，他说，3000，还说现在行情就是这样，你有几年工作经验就给你几年的工资，本科生刚毕业时三千，一年后能达到3500<br /><br />第三家：这次我要的更低，4000，对方说超出他的预算了，现在北京的工资行情都是很虚的，说他们能给3200+午餐补助=3500<br />难道上面两家的说的行情是真的吗！！！？？？？？？
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/218373#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, 22 Jul 2008 21:10:15 +0800</pubDate>
        <link>http://www.javaeye.com/topic/218373</link>
        <guid>http://www.javaeye.com/topic/218373</guid>
      </item>
      <item>
        <title>一个有趣的问题: 如何获取引用名?</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rubynroll.javaeye.com">rubynroll</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219175" style="color:red;">http://www.javaeye.com/topic/219175</a>&nbsp;
          发表时间: 2008年07月24日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我们知道, 对于<br />  <pre name="code" class="ruby">a = 100</pre><br />这样的一条语句, a是一个指向 "100" 这个对象的引用. 那么, 如何根据a得到它的名字"a"或者符号:a ?<br /><br /><br />我现在实现了一个'swap'函数,它的作用是交换两个变量的值, 由于Ruby没有类似C的'指针',所以这个swap实现起来还真有点麻烦:<br /><br /><pre name="code" class="ruby">a = 100
b = 200
def swap(x, y, &block)
  bind = block.binding
  vx = eval("lambda { #{x} }", bind).call
  vy = eval("lambda { #{y} }", bind).call
  eval("lambda {|v| #{y.to_s} = v }", bind).call(vx)
  eval("lambda {|v| #{x.to_s} = v }", bind).call(vy)
end

puts "a = #{a}, b = #{b}"

swap(:a, :b){}

puts "a = #{a}, b = #{b}"

</pre><br /><br />好了, 这个swap有两个缺陷:<br /><br />1) 为了获取caller's binding, 需要带一个空的闭包. 不过这个问题好解决, rails中有Binding.of_caller的实现,用它就可以省去那个空闭包.<br /><br />2) 为了获取待交换的变量名, 传入swap的参数不能是a,b本身,而需要对应的symbol或string, 看起来有点别扭. 如果存在一个函数get_ref_name(x)返回x的名字, 那么问题就解决了.<br /><br /><strong>那么, get_ref_name 存在么? 该如何实现?</strong><br /><br /><br />(注: 不要告诉我用a,b = b,a来实现变量交换, 这个不是要讨论的问题)
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219175#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, 24 Jul 2008 17:26:40 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219175</link>
        <guid>http://www.javaeye.com/topic/219175</guid>
      </item>
      <item>
        <title>对null Object的使用的认识和思考</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://hoorace.javaeye.com">hoorace</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219117" style="color:red;">http://www.javaeye.com/topic/219117</a>&nbsp;
          发表时间: 2008年07月24日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          本次编码的时候犯了一个愚蠢的错误，在几乎所有的biz和manager层加了一个public static final String NULL = null;以此来作为统一的空对象，而这个完全是多次一举，因为null就可以直接代替，就此看来自己完全没有一点点面向对象的概念。为了防止犯类似的错误，决定查询资料好好讨论一下null Object的使用。<br /><br />1：返回一个空的域对象而不是null；<br />	在基于领域模型的设计中，在底层定义的domain Object在数据库查询的时候可以返回为空，在此我们先定义一个Do对象。<br />	public class Tree{<br />		private Integer height;<br />		private Integer age;<br />		private String name;<br />		private Double diameter;<br />		//树叶的域对象；<br />		private Leaves leaves;<br />		// get set methods……<br />	}<br />	在DAO层封装和数据库交互的基本方法后，我们在business层开始对业务逻辑进行简单的封装。当我们提供一个findTree的方法的时候，如果在数据库中查询一个年龄为16岁的tree对象为空，一般的情况下我们返回为null对象，这样就会导致程序在要取值的时候必须判断是否为空，实例如下：<br />	public class TreeBiz{<br />		public Tree findTree(Tree tree){<br />			//在这个地方思考一下，如果返回的tree为空的话，下面的方法调用的问题；<br />			// treeDao.findTree(tree)……<br />		}<br />		public String treeName(Tree tree){<br />			return tree.getName();<br />		}<br />	}<br />	如果获取的tree对象为空的话，就会报空指正的错误。所以必须加上if(tree != null)……而这样就会导致程序中过多的判断了空，不够简洁，同时也很容易出错。<br />	如果我们在域对象中重新定义一个空的对象，然后在dao层封装一下，代码的健壮性就会增强了很多。示例如下：<br />	public class Tree{<br />		//增加一个空的tree对象<br />		public static final Tree NULL = new Tree();<br />		private Integer height;<br />		private Integer age;<br />		private String name;<br />		private Double diameter;<br />		//树叶的域对象；<br />		private Leaves leaves;<br />		// get set methods……<br />	}<br />	然后在DAO层封装一下获取tree对象的方法<br />	public class TreeDao{<br />		public Tree findTree(Tree tree){<br />			Tree tree = ……<br />			if(tree == null){<br />				//返回一个空的Tree对象<br />				return Tree.NULL;<br />			}else{<br />				return tree;<br />			}<br />		}<br />	}<br />	这样在业务逻辑层调用TreeDao方法的时候就很不会出现对象空指针的问题，增强了程序的健壮性。<br />	有人或许会问，为什么在为空的时候不直接 new Tree()， 首先：new一个对象需要分配新的内存开销，而static final的NULL对象则在内存中有一块无法改变的存储空间，降低了系统的开销；其次，NULL对象在执行期就被初始化，返回NULL只用指向该内存地址，而不是重新分配地址，提高的性能。<br />	使用NULL Object模式可以确保在DAO层返回有效的对象，及时在查询失败的时候也是如此。这些代表失败的对象“什么也没有做”！
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219117#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>Thu, 24 Jul 2008 16:18:17 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219117</link>
        <guid>http://www.javaeye.com/topic/219117</guid>
      </item>
      <item>
        <title>DIV自适应高度</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://terryang.javaeye.com">terryang</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219612" style="color:red;">http://www.javaeye.com/topic/219612</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
div高度自适应是个比较麻烦的问题，Div即父容器不根据内容自适应高度，我们看下面的代码： 
</p>
<pre name="code" class="html">&lt;div id=&quot;main&quot;&gt;
&lt;div id=&quot;content&quot;&gt;&lt;/div&gt;
&lt;/div&gt; </pre>
<p>&nbsp;试了网上很多的方法都不行，看了javaeye页面的代码终于解决了（我使用firebug查看的），写出来共享一下。</p>
<p>很简单</p>
<pre name="code" class="html">#main{ 
  height:100%;
  overflow:hidden;
  display: inline;
}</pre>
<p>&nbsp;源文件也得改一下</p>
<pre name="code" class="html">&lt;div id=&quot;main&quot;&gt;
&lt;div id=&quot;content&quot;&gt;&lt;/div&gt;
&lt;br style=&quot;clear:both;&quot; /&gt;   //多了这个东西
&lt;/div&gt; 
</pre>
&nbsp;
<p>&nbsp;</p>
<p>网上有一中方法只说加个</p>
<pre name="code" class="html">overflow:hidden;</pre>
<p>
我试过了不行，原来还得加一个</p>
<pre name="code" class="html"> display: inline;</pre>
<p>
ok！这个主要是解决firefox的问题。</p>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219612#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, 25 Jul 2008 18:06:16 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219612</link>
        <guid>http://www.javaeye.com/topic/219612</guid>
      </item>
      <item>
        <title>找工作遇到无耻公司</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://nj-racoon.javaeye.com">nj-racoon</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/218652" style="color:red;">http://www.javaeye.com/topic/218652</a>&nbsp;
          发表时间: 2008年07月23日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>事情是这样的，昨天同学遭遇到了一个无耻公司的无耻经理，他是上周五去面试的，面了6轮，最终跟人力就工资，待遇啥的都谈妥了，那个人事经理让他尽快办理离职手续，尽快去他们公司报道。昨天我同学打电话给该公司人事经理说已经跟原公司提辞职了，月底正式离职，问他们什么时候可以去他们公司上班，但是这时那个人事经理却说了一句无耻之极的话，<span style="font-size: small; color: #ff0000;">说我们暂时不需要了，由于部门调整，暂时这个岗位不需要了</span>，而且一点道歉之意都没有，也没其他任何解释，<span style="color: #000000;">我同学听了就很气愤，但是当时他气的懵了，就说好，也没问他们所以然。</span></p>
<p>今天中午给他们打电话要说法，但是那个人事经理依然很傲慢，一丝歉意都没有，我不知道是不是他们公司真的不要人，还是耍人玩呢，如果我同学不打电话，那个人事也就一直不通知他，他如果早点跟他说调整的话，我同学就不会这么着急的辞职了，现在辞职已经定局了，这边被那帮无耻的人耍了，我们都很气愤。大家支支招，咽不下这口气。</p>
<p>&nbsp;</p>
<p>PS:这家公司在南京，叫<strong><span style="font-size: small; color: #ff0000;">南京义铎科技</span></strong>，做网络安全设备的，老板据说是以前趋势科技出来的，对外宣称是欧美企业，其实是台资，以后如果有兄弟去这家公司面试，要擦亮眼睛，看清楚了。</p>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/218652#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, 23 Jul 2008 17:24:42 +0800</pubDate>
        <link>http://www.javaeye.com/topic/218652</link>
        <guid>http://www.javaeye.com/topic/218652</guid>
      </item>
      <item>
        <title>杭州的RUBY程序员大概工资在多少价位</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://tianma168.javaeye.com">tianma168</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219531" style="color:red;">http://www.javaeye.com/topic/219531</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          本人正从.NET转向RUBY 弱弱的问下
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219531#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, 25 Jul 2008 14:53:58 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219531</link>
        <guid>http://www.javaeye.com/topic/219531</guid>
      </item>
      <item>
        <title>适用于各类Swing应用的通用数据验证模块</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/216556" style="color:red;">http://www.javaeye.com/topic/216556</a>&nbsp;
          发表时间: 2008年07月19日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这段时间真是忙得要死，一方面要开发公司项目的系统框架，要将项目分成不同的子项目，编写核心代码；另一方面要将极限编程（XP）引入团队开发，部署各类XP需要的服务例如subversion啦，ant+ivy啦，Hudson啦等等。顺便说句题外话，ubuntu还真是不是一般的好用，建议有能力的全部转到ubuntu上去开发。<br /><br />我目前开发的这个框架的客户端是具肥的客户端，也就是Swing客户端了。Swing应用相对于Web应用有很多优势，因为它更肥。数据验证就是其中一个。当然现在的Web应用通过使用Ajax也要比以前强很多了，但是还是避免不了在验证数据时向服务段发出请求，至少你无法避免验证结果从Web服务器传输到用户浏览器上这段过程。而Swing这类肥客户端可以实现完全在本地对数据进行验证，甚至可以断网继续工作（这也是Web应用目前在研发的一个重要课题）。<br /><br />前段时间开发出了一个可以应用于所有Swing应用的通用数据验证模块，发现它在项目中使用后，对于普通的数据验证,程序员几乎不需要编码，效率提高了不少，就写了一篇博文拿出来和大家分享。原文是用英文写的，在这里：<a href="http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html" target="_blank">http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html</a>。英文好的朋友可以直接去那里看。<br /><br />编写这个模块使用了很多不同的开源框架和类库，其中很重要的一个就是JXLayer。文章写完后，我就跑去邀请JXLayer的作者Alexp来指点一下，然后就在我的文章后面开始了一段讨论，挺有意思的，他不愧为是Swing team里面的牛人啊！厉害啊！呵呵。<br /><br />ok，回到今天这篇文章的正题。今天的主要目的是将我的英文博文翻译成中文（自己的文章，我就不逐字逐句翻译了，意思到了就行了，可能还会随兴展开一番讨论）在这里展示给大家，与大家分享开发经验，希望大家能够从中获益，也希望能够以文会友，广交朋友。废话少说，切入正题。<br /><br />数据验证（Validation）一直是软件开发中非常重要的一环，有了它，你的系统会让客户感到更加友善，同时你的系统也得到了一定程度的保护。一般来说，数据验证既可以在客户端也可以在服务端。默认的JSF数据验证就是在服务端，数据只能在被提交以后才能够被验证，然后把错误信息传递回用户的浏览器。后来大规模使用Ajax后，基本可以实现对修改的数据“即时”验证，注意这里是个打了引号的即时，数据事实上还是要在浏览器和服务端之间进行传递的，只不过Ajax将这种传递改为隐式了而已，理论上并没有真正实现（断网）即时验证。而在Swing应用上就能够达成这种愿望。<br /><br />事实上，开发Swing应用时，数据验证一直比较棘手，需要手工编码的地方太多，效率不高。后来出了JGoodies Validation 结合JGoodies binding后，好了一些。这个JGoodies Validation既可以实现model层面的验证，也可以实现Bean层面的验证，但是多年使用下来，发现其实它比较适用于中小项目，而且要编写的代码其实一点不比自己手动编写的少。<br /><br />JGoodies流行了一段时间后，sun开始推出自己的bean绑定方案：beansbinding（JSR 295），我个人感觉要比JGoodies binding好用（JGoodies的作者Karsten也在专家组里，这个人我以前和他一起共事过，我的msn space里面还有跟他的合影，绝对是Swing界的牛人）。这个beansbinding也提供数据验证，但是它的这个数据验证只是在target被改动后，数据被同步回source之前才会起作用，使用起来局限性比较大，而且编码量也不小。<br /><br />由于目前绝大部分项目是基于POJO的，Hibernate validator已经提供了一个很好的数据验证框架，我们完全没必要再重复发明轮子，我们应该努力站在巨人的肩膀上，这样我们才能站得更高，看得更远。于是我考虑结合beansbinding和Hibernate Validator开发数据验证。还有一个重要的问题，那就是数据错误的时候，需要在用户界面上展示相应的信息，例如Error icon和错误提示，这部分我考虑使用JXLayer。<br /><br />你可以在如下链接中找到相关框架的具体信息： <br /><br />1. Hibernate Validator： <a href="http://www.hibernate.org/hib_docs/validator/reference/en/html_single/" target="_blank">http://www.hibernate.org/hib_docs/validator/reference/en/html_single/</a><br />2. Beansbinding: <a href="https://beansbinding.dev.java.net/" target="_blank">https://beansbinding.dev.java.net/</a><br />3. JXlayer: <a href="http://weblogs.java.net/blog/alexfromsun/" target="_blank">http://weblogs.java.net/blog/alexfromsun/</a><br /><br />阅读这篇文章，不需要你熟悉这些类库，不过了解这些类库能够帮助你更好地理解这篇文章。<br /><br />我的这个通用模块是参考JXLayer里面的一个demo类TextValidationDemo的，这个JXlayer是由Alexander Potochkin开发的，我很喜欢，使用起来很顺手，强烈推荐使用。<br /><br />下面开始介绍代码。首先是建立一个java项目，对于这个小项目，我使用netbeans。这里说句题外话，中型和大型的Swing应用，建议最好还是不要使用netbeans的GUI Builder，一方面它生成的代码超级烂，另一方面很难测试。目前市面上有很多好用的layout的框架，例如 JGoodies form和MigLayout，开发效率绝对不比netbeans的GUI builder差，你还不需要面对令人头疼的机器成的代码。<br /><br />项目创建好后，加入类库：<br /><br /><img src="http://bp2.blogger.com/_kE1wl-BJf90/SIBqgMo4shI/AAAAAAAAAAM/SMNf6l7bfw8/s320/image002.jpg" /><br /><br />然后写一个persistence bean:<br /><br /><pre name="code" class="java">
package de.jingge.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;

/**
*
* @author Jing Ge gejing@gmail.com
*/
@Entity
public class Country extends AbstractBean {

private static final long serialVersionUID = 5341382564159667599L;
public static final String PROPERTYNAME_NAME = "name";
public static final String PROPERTYNAME_CODE = "code";
private String name;
private String code;
private Long id;

public Country() {
}

public Country(String code, String name) {
    super();
    setCode(code);
    setName(name);
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

@NotEmpty
public String getName() {
    return name;
}

public void setName(String name) {
    firePropertyChange(PROPERTYNAME_NAME, this.name, this.name = name);
}

@Length(min=2, max= 2, message="Code length must be 2")
@NotEmpty
public String getCode() {
    return code;
}

public void setCode(String code) {
    firePropertyChange(PROPERTYNAME_CODE, this.code, this.code = code);
}
}
</pre><br /><br />这里我为了强调可以在Swing客户端直接使用和验证persistence bean，故意写了一个persistence bean，实际应用中，这个类只需要是一个pojo就行了。<br /><br />这个Country类代表一个国家，它有两个属性，code和name，我给他们分别加上个各自的验证限制。code不能为空，且必须正好是两个字符，例如CN，DE，US。name不能为空。这些annotaion均出自Hibernate Validator。那个父类AbstractBean出自SwingX类库，我们的Country类继承了它之后就可以支持property change event了。<br /><br />ok, 下面可以开始编写这个模块的核心代码了。前面说过，我会使用JXlayer。使用它的好处是：所有JXlayer的painting event都会被转到UI类来，我们只需要编写一个集成Hibernate Validator的UI类就可以了，我称这个类为HibernateValidationUI，代码如下：<br /><br /><pre name="code" class="java">
package de.jingge.view;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.text.JTextComponent;

import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.jdesktop.beansbinding.ELProperty;
import org.jdesktop.beansbinding.PropertyStateEvent;
import org.jdesktop.beansbinding.PropertyStateListener;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;

/**
* Header:
* Description: A layerUI which will validate the referenced property value of
* the object each time when the paint(...) method is called.

* The value of the given object property will be observed.
* Note: This UI works only with {@link JXLayer}. Any change of the property
* will force repainting the UI. The work process looks like: property changed ->
* jxlayer will be repainted -> the paint(...) method of this UI will be called.
* The logic of validation will be handled by the Hibernate validator
* framework.
*
* @author Jing Ge gejing@gmail.com
*/
public class HibernateValidationUI extends AbstractLayerUI&lt;jTextComponent> {

private Object object;
private String propertyName;
private ClassValidator validator;
private ELProperty elProperty;
private PropertyStateListener propertyChangeHandler;

public HibernateValidationUI(Object obj, String propertyName) {
    this.object = obj;
    this.propertyName = propertyName;
    propertyChangeHandler = new PropertyChangeHandler();
    validator = new ClassValidator(obj.getClass());

    elProperty = ELProperty.create("${" + propertyName + "}");
}

public void installUI(JComponent c) {
    super.installUI(c);
    elProperty.addPropertyStateListener(object, propertyChangeHandler);
}

public void uninstallUI(JComponent c) {
    super.uninstallUI(c);
    elProperty.removePropertyStateListener(object, propertyChangeHandler);
}

protected void paintLayer(Graphics2D g2, JXLayer&lt;jTextComponent> l) {
    super.paintLayer(g2, l);
    InvalidValue[] validationMessages = validator.getInvalidValues(object,
            propertyName);
    if (validationMessages.length > 0) {
        BufferedImage image = Java2DIconFactory.createErrorIcon();
        g2.drawImage(image, l.getWidth() - image.getWidth() - 1,
                l.getHeight() - 8, null);
        l.getView().setToolTipText(validationMessages[0].getMessage());

        return;
    }
    l.getView().setToolTipText(null);
}

boolean isValid() {
    return validator.getInvalidValues(object, propertyName).length == 0;
}

class PropertyChangeHandler implements PropertyStateListener {

    @Override
    public void propertyStateChanged(PropertyStateEvent pse) {
        setDirty(true);
    }
}
}
</pre><br /><br />这个HibernateValidationUI类只有一个构建器，它接收两个参数，一个是source object，也就是我们要修改的那个Bean类的实例，另外一个是这个bean的一个属性，这个HibernateValidationUI就负责验证这个属性。<br /><br />在installUI()方法中，我们启动对属性变化的观察类，而在uninstallUI()方法里面，我们需要卸载这个观察类。<br /><br />当给定对象的属性值发生变化时，PropertyChangeHandler的propertyStateChanged（）方法就会被调用，这个功能是通过elProperty和PropertzChangeHandler相结合来实现的。在propertyStateChangeed()方法里UI类的方法setDirty()会被调用，该方法的调用会导致UI类的状态变化，进而引发(re)painting，之后经过一系列的方法调用传递，paintLayer(Graphics2D g2, JXLayer&lt;jTextComponent> l)这个方法将会被调用，这个方法要做的就是我们这个数据验证模块的核心功能：<br /><br />1. 调用Hibernate Validator验证该属性。<br />2. 如果数据不正确，则在GUI上显示一个error icon，并且将错误信息作为tooltip展示给用户。<br /><br />在第二点里面产生了一个问题，谢谢Alexp对我的指点。Swing team里面有一些规定，其中之一就是，在paint()方法里面最好不要改变Component的状态，而setTooltip()方法将会改变component的状态，因此需要在paint()方法之外调用。我目前使用下来，还没有发现什么严重的错误，决定暂时不改了，回头有时间在将这个代码翻新一下。<br /><br />类中用到的Java2DIconFactory代码如下：<br /><br /><pre name="code" class="java">
package de.jingge.view;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

/**
*
* @author gejing@gmail.com
*/
public class Java2DIconFactory {

public static BufferedImage createErrorIcon() {
    return createErrorIcon(7, 8);
}

public static BufferedImage createErrorIcon(int width, int height) {
    BufferedImage icon = new BufferedImage(width, height,
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = (Graphics2D) icon.getGraphics();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
            RenderingHints.VALUE_STROKE_PURE);
    g2.setColor(Color.RED);
    g2.fillRect(0, 0, width, height);
    g2.setColor(Color.WHITE);
    g2.drawLine(0, 0, width, height);
    g2.drawLine(0, height, width, 0);
    g2.dispose();
    return icon;
}
}
</pre><br /><br />没什么太多好解释的，就是使用Java 2D画一个Error icon。<br /><br />接着，我们需要编写一个Factory类，构建一个JTextField，尽量把复杂技术封装起来，这样程序员开发起来可以提高效率，代码如下：<br /><br /><pre name="code" class="java">
package de.jingge.view;

import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import org.jdesktop.beansbinding.AutoBinding;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.beansbinding.Bindings;
import org.jdesktop.beansbinding.ELProperty;
import org.jdesktop.jxlayer.JXLayer;
import static org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.*;

/**
*
* @author Jing Ge gejing@gmail.com
*/

public class GuiComponentFactory {

public static JXLayer&lt;jTextComponent> createTextField(
        BindingGroup bindingGroup, Object sourceObject,
        String sourceProperty) {
    JTextField field = new JTextField();
    AutoBinding binding = Bindings.createAutoBinding(READ_WRITE,
            sourceObject, ELProperty.create("${" + sourceProperty + "}"),
            field, BeanProperty.create("text"));
    bindingGroup.addBinding(binding);
    bindingGroup.bind();
    return new JXLayer&lt;jTextComponent>(field, new HibernateValidationUI(
            sourceObject, sourceProperty));
}
}
</pre><br /><br />createTextField()方法主要将给定对象属性的值与JTextField的text绑定，然后将JTextField纳入到JXLayer的管理之下。这样一来，一旦用户在JTextField里面修改数据，这个改变就会同步到该对象属性上，然后就引发了前面描述的一系列逻辑，最终改变的数据就会被Hiberante Validator加以验证。<br /><br />最后，我们可以编写一个Demo application来看看效果如何，代码如下：<br /><br /><pre name="code" class="java">
package de.jingge.main;

import de.jingge.domain.Country;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.JTextComponent;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.jxlayer.JXLayer;
import static de.jingge.view.GuiComponentFactory.*;

/**
*
* @author Jing Ge gejing@gmail.com
*/
public class ValidationApplicaton {

private BindingGroup bg;
private Country country;
private JXLayer&lt;jTextComponent> codeField;
private JXLayer&lt;jTextComponent> nameField;

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch (UnsupportedLookAndFeelException ex) {
        System.err.println(
                "Nimbus L&F does not support. Default L&F will be used.");
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    ValidationApplicaton app = new ValidationApplicaton();
    JFrame frame = new JFrame("Demo Validation Application");
    frame.setPreferredSize(new Dimension(360, 150));
    frame.getContentPane().add(app.buildPanel(), BorderLayout.CENTER);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setCenter(frame);
    frame.setVisible(true);
    frame.pack();

}

private static void setCenter(JFrame frame) {
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Dimension screenSize = toolkit.getScreenSize();

    // Calculate the frame location
    int x = (screenSize.width - (int) frame.getPreferredSize().getWidth()) / 2;
    int y = (screenSize.height - (int) frame.getPreferredSize().getHeight()) / 2;

    // Set the new frame location
    frame.setLocation(x, y);
}

public ValidationApplicaton() {
    country = new Country();
    bg = new BindingGroup();
}

private JPanel buildPanel() {

    codeField = createTextField(bg, country, Country.PROPERTYNAME_CODE);
    nameField = createTextField(bg, country, Country.PROPERTYNAME_NAME);
    JPanel panel = new JPanel(new MigLayout("",
            "[50px, right]10[200px:250px:300px]", "[center]"));
    panel.add(new JLabel("Code:"), "cell 0 0");
    panel.add(codeField, "cell 1 0, w 200px:250px:300px");
    panel.add(new JLabel("Name:"), "cell 0 1");
    panel.add(nameField, "cell 1 1, w 200px:250px:300px");
    return panel;
}
}

</pre><br /><br />这个类比较简单了，我简单解释一下：<br /><br />在main()方法里面，我们创建了一个JFrame，然后放入一个JPanel<br /><br />setCenter()方法负责将窗口至于屏幕的正中间。<br /><br />在构建器里面，我们创建了Country和BindingGroup的对象实例。<br /><br />在buildPanel()方法里面，我们使用MigLayout构建了一个Panel，其中codeField和nameField对应各自的对象属性。更多关于MigLayout的信息看这里：<a href="http://www.miglayout.com/" target="_blank">http://www.miglayout.com/</a>。这也是一个例子，大家可以看到使用MigLayout开发Swing真的是非常方便。<br /><br />从这个Demo里面也可以看出，编写好pojo后，程序员只需要调用createTextField(bg, country, Country.PROPERTYNAME_CODE); 就可以创建一个支持数据验证的JTextField，编码量已经可以说是最大限度的降低了。<br /><br />运行程序，你会看到：<br /><br /><img src="http://bp3.blogger.com/_kE1wl-BJf90/SIBsALelM7I/AAAAAAAAAAU/LTR5E4GXK5k/s320/image003.png" /><br /><br />这个code和name的数据都不合法，用户看到了error icon。<br /><br />将鼠标移到Text field上，你会看到：<br /><br /><img src="http://bp1.blogger.com/_kE1wl-BJf90/SIBsNdzmsxI/AAAAAAAAAAc/Wr1c-XSws8E/s320/image006.jpg" /><br /><br />填好合法数据后，Error icon就不见了：<br /><br /><img src="http://bp3.blogger.com/_kE1wl-BJf90/SIBsYfl8BwI/AAAAAAAAAAk/9GjuWe16qvc/s320/image007.png" /><br /><br />总结：<br /><br />使用这个通用数据验证模块有很多好处：<br /><br />1. 如果项目使用ORM，例如Hibernate，这个方案应该是解决数据验证的最好方案之一。<br />2. 对于普通的数据验证，例如非空，email，长度等等，程序员根本不需要编码，只要在POJO上使用相应的Hibernate Validator annotation就可以了。<br />3. 对于复杂的数据验证，Hibernate Validator提供了很好的扩展机制，只要写一个annotation外加一个Validator就可以了。Swing应用这边仍然不需要编写任何代码。<br /><br />综上所述，可以看出通过使用这个通用数据验证模块，开发效率会提高很多。<br /><br />对这个项目感兴趣的朋友可以给我留言，人数够多的话，我会考虑将整个netbeans项目上传到javaeye上来。
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/216556#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, 19 Jul 2008 18:24:10 +0800</pubDate>
        <link>http://www.javaeye.com/topic/216556</link>
        <guid>http://www.javaeye.com/topic/216556</guid>
      </item>
      <item>
        <title>求教于前辈们</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://chenpingtai2008.javaeye.com">chenpingtai2008</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/217320" style="color:red;">http://www.javaeye.com/topic/217320</a>&nbsp;
          发表时间: 2008年07月21日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: large">本人下学期大四了，在10月份就要面临的招聘会，现在有点迷茫，迷茫的是这段时间到10月份该干点什么。先说下本人的情况吧，本人会的有struts1.x,hibernate,spring,webwork,javascprit,jsp/servlet,ext,dwr.这些技术不算熟，因为不经常写代码。但理论大致上都能掌握，基本上都能知道怎么应用，用起来应该也比较容易上手。现在想请教一下各位师兄，长辈，对于应届毕业生的项目经验这块是怎么看的，是不是缺少这东西，竞争力将会大大折扣。<br />我认识的周围的一些大四的已经签了工作了的一些朋友，他们刚刚从培训学校出来后没多久就签了，也并没有项目经验。还有各位招人的hr们觉的培训学校里面的实习做的那些东西，你们看重这样的经验吗？？？<br />我现在在看java编程思想，以及数据结构这方面的书，打算打好基础（如果你们还有什么好的书请给点建议，本人感激不尽），我不是计算机专业的（数学的）。不知道，现在是应该停下来去做点东西出来以备招聘的时候用，还是继续看这样的书，可能有人会建议一边做东西，一边看这些书，但是我觉的有点忙不过来，比如象java编程思想就很厚，看完也要花很长时间，做东西也要花比较长时间。觉的两者总是不能兼顾，两者兼顾的话总有一样忙不好，本人找工作家里给的压力比较大（跟家境有关），所以很希望下学期招聘会就能把自己卖出去。请各位兄长，前辈们给点建议，给我点指导。还有如果你们有什么好东西，可以给我油箱里发<br />chenpingtai2005@163.com.谢谢你们！！！</span>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/217320#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 20:12:10 +0800</pubDate>
        <link>http://www.javaeye.com/topic/217320</link>
        <guid>http://www.javaeye.com/topic/217320</guid>
      </item>
      <item>
        <title>职业道路上的十字路口，路过的进来看看</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://happydays.javaeye.com">HappyDays</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219600" style="color:red;">http://www.javaeye.com/topic/219600</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近拿到两个offer：<br />  一个是做电子政务的，用的技术主要是JavaScript+SQL(这两个正好是我的弱项)<br />  一个是做电信项目的，用的技术面试官说的很模糊，说是大项目，主要是做网站，分期做的，里面涉及到的技术很多。<br />  本人对这两类项目不太了解，论坛里有做过这些项目的前辈吗，做哪个项目学到的东西多点呀
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219600#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, 25 Jul 2008 17:39:45 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219600</link>
        <guid>http://www.javaeye.com/topic/219600</guid>
      </item>
      <item>
        <title>Spring MVC 的 Controller 的 使用问题</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shanglo.javaeye.com">shanglo</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219061" style="color:red;">http://www.javaeye.com/topic/219061</a>&nbsp;
          发表时间: 2008年07月24日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><img src="../../../images/smiles/icon_mad.gif" alt="" />看了 几天的 Spring 的 mvc,&nbsp;&nbsp; 配置 确实相当的 灵活；&nbsp; 重要的 Controller 的子类 SimpleFormController 和 MultiActionController；</p>
<p>但是 对于 一个模块的 CRUD等相关方法， 如果用 MultiActionController的话， 也是可以绑定到 CommandBean， 但是这样用的话； Validator 就不能用了， 因为不能给 每个方法 配置一个 合适的&nbsp; Validator，这是 MultiActionController 弊端之一； 还有&nbsp; 在 绑定到CommandBean前， 必须保证 field的类型一致。</p>
<p>&nbsp;</p>
<p>&nbsp;所以 我觉得 使用 Spring的 MVC， 构建一个CRUD的模块， 使用它的 Validator类， 可以继承SimpleFormController&nbsp; 实现 Edit/ADD的 功能；&nbsp; 用 MultiActionController来实现&nbsp; 其他 不 提交 很多参数的 功能；&nbsp; </p>
<p>&nbsp;</p>
<p>或者 只是用 Spring的 MVC的 跳转， 不用 Validator， 数据校验 用js做， 用MultiActionController 实现 类似 Struts的 DispatchAction。</p>
<p>&nbsp;</p>
<p>以上 是 我的一些 认识，&nbsp; 欢迎大家讨论！</p>
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/219061#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, 24 Jul 2008 14:25:30 +0800</pubDate>
        <link>http://www.javaeye.com/topic/219061</link>
        <guid>http://www.javaeye.com/topic/219061</guid>
      </item>
      <item>
        <title>翻译：敏捷与CMMI：双剑合璧，更具威力！</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://movingboy.javaeye.com">movingboy</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/218142" style="color:red;">http://www.javaeye.com/topic/218142</a>&nbsp;
          发表时间: 2008年07月22日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          记得在JavaEye曾经有过关于敏捷与CMM之间的激烈讨论，但讨论后似乎没有谁认为对方已经说服了自己。因为我没有CMM方面的实际经验，我对CMM的了解仅限于教材、SEI网站上的电子文档和各个论坛的讨论，我只能作壁上观。不过那时我有一种朦朦胧胧的感觉：敏捷与CMM似乎并不是绝对对立的，但我无法说清楚为什么。<br /><br />在Scrum Alliance的网站上看到Cindy Shelton写的一篇文章：Agile and CMMI: Better Together（<a href="http://www.scrumalliance.org/articles/100-agile-and-cmmi-better-together" target="_blank">http://www.scrumalliance.org/articles/100-agile-and-cmmi-better-together</a>）。文章中的观点让我有些共鸣，所以不辞冒昧，翻译了出来，希望能给大家一点启发。<br /><br />因为自己的英语水平有限，翻译的过程中深感不易。原文中许多习惯用语没找到非常贴切的中文说法，某些段落的上下文也不容易理解。许多地方我按照自己的理解进行了意译，但我有点担心是否正确地表达了原文的意思，因此有兴趣对这篇文章深入了解的朋友请阅读原文。<br /><br /><strong><span style="font-size: x-large">敏捷与CMMI：双剑合璧，更具威力！</span></strong><br /><br />在追求卓越的过程中，组织会尝试多种途经，采用不同的原则、方法及技术。一个对敏捷实践感兴趣的组织可能也会对PMI的OPM3、ISO或能力成熟度模型集成（CMMI）感兴趣，因为这些都是通向卓越的手段。不过，我曾经看到一些组织同时尝试敏捷和PMI模型，但没有谁成功。实际上，去年我观察了两个很大的公司，它们主动在公司内同时采用敏捷与CMMI。在两家公司里，分别实施这两种方法的两个小组都把对方当作竞争对手，这令这两家公司严重受挫。（译注1）其实没必要这样子。CMMI与敏捷框架至少能够而且应该和平共处，甚至可能协同工作 - 我知道这对你们许多人来说是一种震动。<br /><br />许多人认为敏捷与CMMI是极端对立的，彼此抵消对方的成效。在传统方式与敏捷框架之间一直持续的论战中，各自的支持者纷纷列举出与对方水火不容的观点。但是这种对抗的态度不但毫无道理，也会对我们的工作-在尽可能短的时间内开发出高质量的软件-产生妨碍。想要获得最好的投资收益，最好是创建一组混合模型和方法，选择合适的技术来应对特定的挑战。<br /><br /><strong><span style="font-size: large">CMMI回顾</span></strong><br /><br />能力成熟度模型集成（CMMI）（注1）是一个过程改进方法，它为组织提供了实现高效的过程所必需的基本元素。它可以用来指导一个项目、一个部门甚至整个组织的过程改进。CMMI能帮助我们整合以往各自为政的组织功能，建立过程改进的目标与优先级，指导我们进行质量改进，还提供了评价现有过程的参照点。<br /><br /><img src="http://www.scrumalliance.org/system/resource_files/0000/0426/shelton_figure.jpg" /><br /><br />有趣的是，创建CMMI的初衷是为了应付一些软件开发相关的问题，而提出敏捷实践也是为了解决这些问题。在80年代早期，在SEI的资助下美国空军成立了一项研究来分析为什么许多软件合同都会超出工期和预算。他们的结论是：糟糕的过程。而另一方面，承包商认为无法按照预定的工期和预算完成合同的原因在于需求不断变更。研究中，为了在软件开发生命周期的后期应付这些变更而不增加返工，一个小组试图建立更多的过程，而另一个小组尝试应用不同的方法。这项研究一直持续到1998年，这一年，作为CMMI的补充，TSP诞生了。针对CMMI提出的“需要做什么”的目标，TSP指导团队“如何去做”，这加快了它的普及。但很多人忽视了敏捷实践也能指导我们“如何去做”。<br /><br />对新一代的敏捷实践者来说，CMMI似乎太臃肿、太枯燥、太缺乏创造性了。有人批评CMMI太官僚，过于关注过程而不是问题本身，削弱了应付日益严峻的需求变更的能力。同样，也有人批评敏捷对开发过程控制不力，导致隐性的变更和混乱。<br /><br />批评者还声称在CMMI提出的经典工程方法中，一些令项目成功的人类认知能力、组织及文化等方面的基本要素都没有考虑到。对于这些批评者（也是敏捷实践者）来说，从装配线式的过程模型中解脱出来，关注人与人的交流就是一种进步。Paulk (2001)（注2）更深入地探讨了为何这两种方法并非绝对冲突，并阐述了一个开发小组如何在遵循极限编程原则的同时拥抱CMM第3级。在第3级中，两种方法都可以衍生出不同的措施。Boehm and Turner（注3）强调不但要平衡地应用这两种方法相关的措施，而且要知道如何正确地应用才能显著改进组织的开发过程。<br /><br />CMMi提出，在组织中必须建立开发过程，必须采用同行评审来提高质量，必须有版本控制系统。如果我们发现一个跨国公司至今仍缺乏这些基本的“常识性”的控制手段，肯定不只我一个人会感到震惊和失望。如果能合理地应用两种方法中的原则、方法及技术，我们不至于陷入两难的境地。然而，要在现有的成熟度级别上同时应用敏捷，以及为敏捷团队找到最佳的成熟度级别都会是挑战。<br /><br /><strong><span style="font-size: large">实施敏捷的最佳时机</span></strong><br /><br />一项敏捷实践应该经过裁剪以适应组织实际的成熟度级别；特别是，如果组织的成熟度处于CMMI第3级，实施敏捷不但可以获得敏捷带来的重要好处，还可以减少返工，并全面提高推行CMMI的积极性。如果实施的软件开发过程既能遵循CMMI规范，又能符合敏捷原则，我们就可以真正获得CMMI提出的可重复性和可预测性的好处。敏捷特意设计得非常灵活，因此它可以在不违反敏捷宣言所规定的主要目标的前提下，裁剪为遵循CMMI规范的软件开发过程。<br /><br />当成熟度处于CMMI第3级，组织应该已经选定了适合团队及环境的过程，这些过程主要关注如何交付可正常运行的软件。此外，针对特定的项目，还要从组织的标准过程集中裁剪出相应的标准、过程描述及流程。因此，实施敏捷的主要工作就是为集成敏捷实践而修改那些标准过程。实施敏捷的风险集中在管理开销上，因为组织的管理模式可能会限制团队的自主决策权及灵活性。<br /><br /><strong><span style="font-size: large">在CMMI第3级上实施敏捷的挑战</span></strong><br /><br />如果成熟度未达CMMi第3级，说明组织缺乏稳定的项目管理、需求分析及配置管理相关的过程。正因为企业各个方面都缺乏训练，要实施敏捷还得提供缺失的软件开发过程。如果组织的成熟度未达CMMI第2级，过程常常会因为人为原因或外来事件而被迫改变。在这样的环境中，敏捷项目可能会成功，但成功的经验不见得能重用。如果组织没有一种稳定的环境，可能是因为组织还不清楚建立这样的环境需要哪些东西。这导致成功依赖于个人的专业知识、能力及英雄主义，而这些成效却可能被团队的其它因素抵消。<br /><br />CMMI第2级中的一些过程号称是可重复的，然而它们未必能在组织的所有项目中重用。实施敏捷实践和度量可以为组织提供达到CMMI第3级所需的管理架构和训练。在这一级，尽管实施敏捷可能导致成本增加，但也能获得与单独实施同样的好处。通过使用Burndown图和任务板，敏捷进度跟踪让组织很容易看到这种训练的效果，从而加快采用它的速度。敏捷框架的总体思想、方法及实践自然地解决了CMMI第2级的时间和成本超支的风险，能明显缩短提升到第3级的时间。我曾经成功地通过实施敏捷把成熟度级别从0提升到第2级，提高了客户满意度，最终达到了预期的效果。<br /><br />如果组织的成熟度高于第3级，流程已经基本可以在组织内通用了。这种情况下除非大幅改动那些在CMMI第4级中必需的成文的流程，否则敏捷所带来的灵活性将非常有限。其实，管理层希望能迅速找到合适的度量来控制项目的成本、进度与范围，而敏捷项目的进度已经是可视的，这与管理层的意图已经非常吻合了。此外，成熟度第3级与第4级之间的一个重大差别就是采用某组过程后的效果的可预测性：对于后者来说，过程的效果是通过统计及其它量化技术来控制的，可定量地预测。所以现在我还没兴趣在成熟度已达CMMI第4级的组织中推行敏捷。<br /><br /><strong><span style="font-size: large">结论</span></strong><br /><br />至此已经写了够多的内容来讲明CMM与敏捷实践之间的关系和协作效果。为了取得最好的效果，学习CMMI的各个过程域、各个成熟度级别并掌握如何在敏捷与CMMI之间过渡的能力非常重要。<br /><br />注：<br />1. 为了尽可能地准确，大多数关于CMMi的材料是从软件工程研究所（SEI）的网站（http://www.sei.cmu.edu/cmmi/）上照搬的。（译注2）其它来源的材料则单独说明。<br /><br />2. Paulk, 2001. M. Paulk, Extreme programming from a CMM perspective. IEEE Software 18 6 (2001), pp. 1–8.<br /><br />3. Boehm, B. and R. Turner (2003). Using Risk to Balance agile and Plan Driven Methods. Computer, IEEE Computer Society.<br /><br />译注：<br />1. 该句原文是I left both organizations frustrated.，我认为句首的I是It的笔误。因为我不是Scrum Alliance的会员，我没法跟帖或发邮件给作者求证。<br />2. 经过我的翻译，这些材料是否还能与SEI网站上提供的材料保持一致，需要各位朋友鉴别。
          <br/>
          <span style="color:red;">
            <a href="http://superleo.javaeye.com/topic/218142#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>Tue, 22 Jul 2008 15:42:32 +0800</pubDate>
        <link>http://www.javaeye.com/topic/218142</link>
        <guid>http://www.javaeye.com/topic/218142</guid>
      </item>
      <item>
        <title>struts上传下载</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yanghaiskys.javaeye.com">yanghaiskys</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/219585" style="color:red;">http://www.javaeye.com/topic/219585</a>&nbsp;
          发表时间: 2008年07月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="color: #ff0000;">最近要做上传下载，所以又把它翻出了，熟悉了一把，做了一下字节转换的调整及上传类型的限制，当然还有上传路径的限制。不过一直在考虑的问题是怎样找到减少服务器压力的具体方法，本列子贴出来是希望能给某些新手一些帮助，同时也希望各路大侠批评指点小弟的许多不足。</span></p>
<p>&nbsp;</p>
<p><span style="color: #ff0000;">首先建立一个FileAction</span></p>
<p>package com.action;<br />import org.apache.struts.action.*;<br />import javax.servlet.http.*;<br />import com.actionForm.FileActionForm;<br />import org.apache.struts.actions.DispatchAction;<br />import java.util.Date;<br />import java.text.*;<br />import org.apache.struts.upload.FormFile;<br />import java.io.*;<br />import java.net.URLEncoder;<br />import com.dao.*;</p>
<p>public class FileAction extends DispatchAction {</p>
<p>&nbsp;&nbsp;&nbsp; private JDBConnection connection =new <span style="background-color: #ffffff;">JDBConnection</span>();<br /><span style="background-color: #ff6600;"><span style="color: #ff0000; background-color: #ffffff;">//以下方法实现文件的上传</span><br /></span>&nbsp;&nbsp;&nbsp; public ActionForward upLoadFile(ActionMapping mapping, ActionForm form,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse response) throws<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exception {<br />&nbsp;&nbsp;&nbsp; &nbsp;ActionForward forward=null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date date = new Date();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileActionForm fileActionForm = (FileActionForm) form;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">//FormFile用于指定存取文件的类型<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FormFile file = fileActionForm.getFile(); <span style="color: #ff0000;">//获取当前的文件</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">// 获得系统的绝对路径</span>&nbsp; String dir = servlet.getServletContext().getRealPath("/image");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">//我上传的文件没有放在服务器上。而是存在D:D:\\loadfile\\temp\\</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String dir="D:\\loadfile\\temp\\";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 0;<br />&nbsp;&nbsp;String type = file.getFileName();<br />&nbsp;&nbsp;while(i!=-1){<br />&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp;//找到上传文件的类型的位置，这个地方的是'.'</span><br />&nbsp;&nbsp;&nbsp;i = type.indexOf(".");<br />&nbsp;&nbsp;/*&nbsp;System.out.println(i);*/<br /><span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;/*截取上传文件的后缀名,此时得到了文件的类型*/</span><br />&nbsp;&nbsp;&nbsp;type = type.substring(i+1);<br />&nbsp;&nbsp;}<br />&nbsp;<span style="color: #ff0000;">&nbsp;// 限制上传类型为jpg,txt,rar;</span><br />&nbsp;&nbsp;if (!type.equals("jpg") &amp;&amp; !type.equals("txt")&amp;&amp; !type.equals("bmp"))<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;<span style="color: #ff0000;">{//当上传的类型不为上述类型时，跳转到错误页面。</span><br />&nbsp;&nbsp;&nbsp; forward=mapping.findForward("error");<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;else<br />&nbsp;&nbsp;{&nbsp;&nbsp;<br /><span style="color: #ff0000;">//&nbsp;&nbsp;&nbsp; 将上传时间加入文件名（这个地方的是毫秒数）&nbsp;&nbsp;&nbsp;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp; String times = String.valueOf(date.getTime());<br />&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp; //组合成 time.type</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp; fname = times + "." + type;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">//InInputStream是用以从特定的资源读取字节的方法。<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream streamIn = file.getInputStream();&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;"> //创建读取用户上传文件的对象<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">//得到是字节数，即byte,我们可以直接用file.getFileSize(),也可以在创建读取对象时用streamIn.available();<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // int ok=streamIn.available();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int ok=file.getFileSize();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String strFee = null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;">&nbsp; //这个地方是处理上传的为M单位计算时，下一个是以kb,在下一个是byte;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ok&gt;=1024*1024)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;float ok1=(((float)ok)/1024f/1024f);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DecimalFormat myformat1 = new DecimalFormat("0.00");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strFee = myformat1.format(ok1)+"M";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(strFee+"M");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(ok&gt;1024 &amp;&amp; ok&lt;=1024*1024)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double&nbsp; ok2=((double)ok)/1024;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DecimalFormat myformat2=new DecimalFormat("0.00");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strFee = myformat2.format(ok2)+"kb";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(strFee+"kb");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(ok&lt;1024)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;System.out.println("aaaaaaaaa");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strFee=String.valueOf(ok)+"byte";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(strFee);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println( streamIn.available()+"文件大小byte");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp;&nbsp; //这个是io包下的上传文件类<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File uploadFile = new File(dir);&nbsp;&nbsp; //指定上传文件的位置<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!uploadFile.exists() || uploadFile == null) {&nbsp; //判断指定路径dir是否存在，不存在则创建路径<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uploadFile.mkdirs();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp;&nbsp; //上传的路径+文件名<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String path = uploadFile.getPath() + "\\" + fname;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">//OutputStream用于向某个目标写入字节的抽象类，这个地方写入目标是path，通过输出流FileOutputStream去写<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OutputStream streamOut = new FileOutputStream(path);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int bytesRead = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buffer = new byte[8192];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;"> //将数据读入byte数组的一部分，其中读入字节数的最大值是8192，读入的字节将存储到，buffer[0]到buffer[0+8190-1]的部分中<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //streamIn.read方法返回的是实际读取字节数目.如果读到末尾则返回-1.如果bytesRead返回为0则表示没有读取任何字节。<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ((bytesRead = streamIn.read(buffer, 0, 8192)) != -1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">&nbsp;//写入buffer数组的一部分，从buf[0]开始写入并写入bytesRead个字节，这个write方法将发生阻塞直至字节写入完成。<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamOut.write(buffer, 0, bytesRead);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">//&nbsp; 关闭输出输入流,销毁File流。<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamOut.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamIn.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file.destroy();&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String paths=path;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(paths);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">String fileName = Chinese.toChinese(fileActionForm.getFileName()); //获取文件的名称</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //String fileSize = String.valueOf(file.getFileSize());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String fileDate = DateFormat.getDateInstance().format(date);<br /><span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String sql = "insert into tb_file values('" + fileName + "','" +<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strFee + "','" + fileDate + "','" + paths + "')";</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.executeUpdate(sql);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.closeConnection();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; forward=mapping.findForward("upLoadFileResult");<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return forward;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; //实现文件的下载<br />&nbsp;&nbsp;&nbsp; public ActionForward downFile(ActionMapping mapping, ActionForm form,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse response) throws<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exception {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String path = request.getParameter("path");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(path+"111");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedInputStream bis = null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedOutputStream bos = null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OutputStream fos = null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream fis = null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp; //如果是从服务器上取就用这个获得系统的绝对路径方法。&nbsp; String filepath = servlet.getServletContext().getRealPath("/" + path);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp; filepath=path;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("文件路径"+filepath);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File uploadFile = new File(filepath);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fis = new FileInputStream(uploadFile);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bis = new BufferedInputStream(fis);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fos = response.getOutputStream();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bos = new BufferedOutputStream(fos);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp;&nbsp; //这个就就是弹出下载对话框的关键代码</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; response.setHeader("Content-disposition",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "attachment;filename=" +<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URLEncoder.encode(path, "utf-8"));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int bytesRead = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000;"> //这个地方的同上传的一样。我就不多说了，都是用输入流进行先读，然后用输出流去写，唯一不同的是我用的是缓冲输入输出流<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buffer = new byte[8192];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bos.write(buffer, 0, bytesRead);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bos.flush();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fis.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bis.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fos.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bos.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p><span style="color: #ff0000;">FileActionForm</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>package com.actionForm;</p>
<p>import org.apache.struts.action.*;<br />import org.apache.struts.upload.*;</p>
<p>public class FileActionForm extends ActionForm {<br />&nbsp;&nbsp;&nbsp; <span style="color: #ff0000;">private String fileName;//上传文件的名称<br />&nbsp;&nbsp;&nbsp; private String fileSize;//上传文件的大小<br />&nbsp;&nbsp;&nbsp; private String filePath;//上传文件到服务器的路径<br />&nbsp;&nbsp;&nbsp; private String fileDate;//上传文件的日期<br />&nbsp;&nbsp;&nbsp; private FormFile file;//上传文件</span></p>
<p>&nbsp;&nbsp;&nbsp; public String getFileName() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return fileName;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public FormFile getFile() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return file;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public String getFileSize() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return fileSize;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public String getFilePath() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return filePath;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public String getFileDate() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return fileDate;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setFileName(String fileName) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.fileName = fileName;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setFile(FormFile file) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.file = file;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setFileSize(String fileSize) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.fileSize = fileSize;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setFilePath(String filePath) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.filePath = filePath;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setFileDate(String fileDate) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.fileDate = fileDate;<br />&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p><span style="color: #ff0000;">index.jsp&nbsp; 此位置的form是javabeen的对象，这个javabeen中存取的图片的相关信息</span></p>
<p>&lt;table width="264" height="81" border="0" align="center" cellpadding="0" cellspacing="0"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width="115"&nbsp; rowspan="4" align="center"&gt;&lt;img src="&lt;%=<span style="color: #ff0000;">form</span>.getFilePath()%&gt;" width="100" height="100"&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td width="133" align="center"&gt;图片名称：&lt;%=<span style="color: #ff0000;">form</span>