2005年03月26日

 1.大学生活丰富多彩,会令你一生都难忘,但难忘有很多种,你可以学了很多东西而难忘,也会因为什么都没学到而难忘!

  2.计算机专业是一个很枯燥的专业,但即来之、则安之,只要你努力学,也会发现其中的乐趣的。

  3.记住:万丈高楼平地起!基础很重要,尤其是专业基础课,只有打好基础才能学得更深。

  4.C语言是基础,很重要,如果你不学好C语言,那么什么高级语言你都学不好。

  5.C语言与C++语言是两回事。就像大熊猫和小熊猫一样,只是名字很像。

  6.请先学习专业课《数据结构》、《计算机组成原理》,不要刚开始就拿着一本VC在看,你连面向对象都搞不清楚,看VC没有任何用处。

  7.对编程有一定的认识后,就可以学习C++了。(是C++而不是VC,这两个也是两码事。C++是一门语言,而VC教程则是讲解如何使用MFC类库,学习VC应建立在充分了解C++的基础之上。看VC的书,是学不了C++语言的。)

  8.学习编程的秘诀是:编程,编程,再编程;

  9.认真学习每一门专业课,那是你今后的饭碗。

  10.在学校的实验室就算你做错一万次程序都不会有人骂你,如果在公司你试试看!所以多去实验室上机,现在错得多了,毕业后就错得少了。

  11.从现在开始,在写程序时就要养成良好的习惯。

  12.不要漏掉书中任何一个练习题——请全部做完并记录下解题思路。

  13.你会买好多参考书,那么请把书上的程序例子亲手输入到电脑上实践,即使配套光盘中有源代码。

  14.VC、C#、.NET这些东西都会过时,不会过时的是数据结构和优秀的算法!

  15.记住:书到用时方恨少。不要让这种事发生在你身上,在学校你有充足的时间和条件读书,多读书,如果有条件多读原版书,你要知道,当一个翻译者翻译一本书时,他会不知不觉把他的理念写进书中,那本书就会变得像鸡肋!

  16.我还是强调认真听专业课,因为有些课像《数据结构》、《编译原理》、《操作系统》等等,这种课老师讲一分钟能让你明白的内容,你自己看要看好几个月,有的甚至看了好几年都看不明白。

  17.抓住在学校里的各种实践的机会,要为自己积累经验,就业时经验比什么都有用。

  18.多去图书馆,每个学校的图书馆都有很多好书等你去看!

  19.编程不是技术活,而是体力活。

  20.如果你决定了要当一个好的程序员,那么请你放弃游戏,除非你是那种每天只要玩游戏就能写出好程序的天才!

  21.你要有足够的韧性和毅力!有个高手出一一道题测试你的韧性和毅力:找个10000以内的素数表,把它们全都抄下来,然后再检查三遍,如果能够不间断地完成这一工作,你就可以满足这一条。

  22.找到只属于你自己的学习方法。不要盲目的追随别人的方法,适合自己的才是最好的!

Del.icio.us(美味书签)真是一个很cool的发明。它帮助你将Google到的网页(注意:是网页!)集中收藏起来,慢慢欣赏消化。这正好使得用Google进行的冲浪不会产生滞碍感,保证了网络冲浪的高速有效。当你Google得正来劲,好东西源源不断地涌出来时,你开始担心,这么多好资料怎么办啊,我如何能够马上理解和消化?收藏到IE的收藏夹慢慢看?这可不是好主意!别困扰了,用Del.icio.us吧!它简单易用,可分类,你还能分享众多馋嘴”美味迷”的收藏。寻找志趣相投的个人,你可以看看他们的收藏,免费得到个性化的”知识过滤”,大大减少搜寻的时间,提高网络学习的效率。Del.icio.us(美味书签)为我们将搜索信息分类保存,离网后消化吸收提供了便捷。

<简历制作>

飞达简历网[http://www.jianlishop.com] (精美的简历设计网站,大量免费资源)
无忧简历网[http://www.51jianli.com] (收费简历设计网站)
我的简历网[http://www.wdjl.net] (免费提供电子简历)
视频简历网[http://www.cnvhr.com](想试试视频简历吗)
中国简历网[http://www.5520.com](收费简历设计网站)
简历翻译网[http://www.jlok.com](简历翻译到这里,到外企少不了)
点睛简历网[http://www.doteye.com](收费简历设计)


<论文资源>

无 忧 论文网[http://www.51lw.com](免费论文下载)
论 文 在线网[http://www.lwzx.net](论文下载,大量免费资源)
论 文 帝国[http://www.papersempire.com](论文资源)
论 文 资料网[http://www.51paper.net](各专业论文下载)
论 文 快车网[http://www.lun-wen.com](各专业论文下载)
毕 业 论文网[http://www.bylw.com](论文发表等,不错的地方)
专 业 论文网[http://www.dtzcb.net/lunwen](专业论文下载,职称考试)
大学生论文库[http://www.syiae.com/lunwen](看看吧挺好)
轻 松 论文网[http://www.paperease.com](论文网站)
易 起 论文网[http://www.17net.net](不错的地方)


<考试资源>

考试163:http://www.test163.com (大量的资格认真考试试题,计算机,英语视听材料)
IT认证考试资源网[http://www.itexamprep.com](大量IT认证考试题库)
中国大学生网[http://www.chinadaxuesheng.com](题库,模拟题,论文,小学大学)
中国考试网网[http://www.sinoexam.com.cn](太多了)
中国考研网[http://www.chinakaoyan.com](想考研究生来看看吧,大量免费资源)
考研网[http://www.kaoyan.net](也是考研的网站,大量免费资源)
中国自考网[http://www.chinazikao.com](自学考试相关资源)
出国考试网[http://www.007test.com](出国考试过关习题等)
天下资源网[http://www.da126.com](出国考试过关习题,英语视听材料等)

<人才招聘>

eJobShow.NET人才网[http://www.ejobshow.com](非常好的求职招聘网站)
上海人才热线[http://www.shanghairc.com](大家应该知道,上海最好的)
天基人才网[http://www.tjinfo.com](挺著名的人才网站)
齐鲁人才热线[http://www.qlrc.com](山东最好的人才网,可以网上直接洽谈)
前程无忧[http://www.51job.com](中国三大人才网之一,非常好)
中华英才网http://www.chinahr.com](中国三大人才网之一,里面论坛不错)
528招聘网[http://www.528.com.cn](人才网站)
中智人才网[http://www.ciic.com.cn](关于高智力开发招聘网站)
天虎人才网[http://career.tyfo.com](天俯之国四川的人才网)
中国人才热线[http://www.cjol.com](看看就知道了)
高校毕业求职中心[http://www.cgcc.net](毕业生就业好去处)


<文学艺术>

白鹿书院[http://www.oklink.net](中国最好的网上读书站点,可以投稿赚稿费)
清韵书院[http://www.qingyun.com](有一大型网上读书站点,看看吧)
潇湘书院[http://www.xxsy.net](挺特别的地方,不过品类齐全)
黄金书屋[http://wenxue.myrice.com](网上看书好地方)
新时代书城[http://www.mypcera.com/book](网上看书好地方)
亦凡书库[http://www.yifan.net](网上看书,不错的地方)
校园文学网[http://www.okqq.net](学生读书的好地方)
中国诗人网[http://www.chinapoet.net](看看吧)
山阳书院[http://www.jzinfo.ha.cn/book](挺全的站点)
网天书城[http://www.net-sky.com/book](网上读书,看看吧)
中华电脑书库[http://www.pcbookcn.com](大量计算机方面图书,可以下载)
考试163[http://www.pcbookcn.com](大量考试方面的图书,可以下载)


<外语学习>

择校学习网[http://www.zexiao.com](出国学习外语,咨询等)
163考试网[http://www.test163.com](要过CET的朋友要去看看,还有听力资料啊)
英语之声[http://www.4english.cn](网上学习英语的好地方)
疯狂英语俱乐部[http://www.crazyenglish.org](想了解疯狂英语吗?)
在线英语杂志[http://www.englishcn.com](不错的地方)
英语写作网[http://www.4ewriting.com](英语协作技巧等)
英语周报[http://www.ew.com.cn](学习英语的好地方)
英语角[http://www.english-corner.com.cn](看看吧)

2005年03月25日

呵呵,昨天把我的blog整理了一遍,发现好多朋友对我的页面很感兴趣,不少朋友还给我留了言,在这里我就一并说了吧。这都是我从网络上收集到的。

注意:以下的代码都要写到静态新闻/声明里。

时钟

<!– 时钟clock_035.swf 的035为时钟样式,可自己选择 –>
 <EMBED SRC=http://www.butabon.com/Clock/clock_035.swf WIDTH=150 HEIGHT=150 wmode=transparent quality=high loop=true menu=false>

日历
<!– Blog日历表开始 –>
<script language=”javascript”>
var diarydays=”<2004-08-05><2004-08-09><2004-08-12><2004-08-17><2004-08-19><2004-07-14><2004-07-13><2004-07-08><2004-07-05><2004-07-04><2004-07-03><2004-06-27><2004-06-26><2004-06-25>”;
</script>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
<style>
.calendarBigBorder { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; text-decoration: none; width: 170; background-color: #FFFFFF; font-size: 9pt;border:1px dotted #999; }
.calendarTd { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #000000; background-color: #eeeeee; height: 18px; width: 11%; text-align: center;}
.calendarMInput { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; text-decoration: none; background-color: #FFFFFF; height: 15px; border: 1px solid #666666; width: 19px; color: #0099FF;}
.calendarYInput { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #0099FF; text-decoration: none; background-color: #FFFFFF; height: 15px; width: 34px; border: 1px solid #666666;}
.calendarMonthTitle { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: normal; height: 24px; text-align: center; color: #333333; text-decoration: none; background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-bottom-style: none; border-top-color: #999999; border-right-color: #999999; border-bottom-color: #999999; border-left-color: #999999;}
.calendarNow { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: bold; color: #000000; background-color: #C0C9D3; height: 18px; text-align: center;}
.calendarDaySat { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #333333; text-decoration: none; background-color: #eeeeee; text-align: center; height: 18px; width: 12%;}
.calendarDaySun { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #333333; text-decoration: none; background-color: #eeeeee; text-align: center; height: 18px; width: 12%;}
.calendarLink { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: normal; color: #333333; text-decoration: none; background-color: #E7E7F6; text-align: center; height: 18px;}
.categoryTxt { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; line-height: 23px; color: #333333; text-decoration: none;}
.categoryTable { border-right-width: 1px; border-bottom-width: 1px; border-right-style: solid; border-bottom-style: solid; border-left-style: none; border-right-color: #000000; border-bottom-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #71b99c;}
</style>
<SCRIPT LANGUAGE=”JavaScript”>
var months = new Array(“一”, “二”, “三”,”四”, “五”, “六”, “七”, “八”, “九”,”十”, “十一”, “十二”);
var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31,30, 31, 30, 31);
var days = new Array(“日”,”一”, “二”, “三”,”四”, “五”, “六”);
var classTemp;
var calendarHover=”calendarHover”;
var today=new getToday();
var year=today.year;
var month=today.month;
var newCal;
//得到某月天数
function getDays(month, year)
{ if (1 == month)
     return ((0 == year % 4) && (0 != (year % 100))) ||(0 == year % 400) ? 29 : 28;
  else
     return daysInMonth[month];
}
//得到当天时间信息
function getToday()
{  this.now = new Date();
   this.year = this.now.getFullYear();
   this.month = this.now.getMonth();
   this.day = this.now.getDate();
}
//生成日历
function Calendar()
{  newCal = new Date(year,month,1); //当前月的第一天
   today = new getToday();  
   var day = -1;   //用来判断日历中是否为当天
   var startDay = newCal.getDay(); //当月开始时间
   var endDay=getDays(newCal.getMonth(), newCal.getFullYear());//当月结束时间
   var daily = 0;   //用来生成日历中的天数值
   if ((today.year == newCal.getFullYear()) &&(today.month == newCal.getMonth()))
      day = today.day;
   var caltable = document.all.caltable.tBodies.calendar;  //得到日历表格的集合
   var intDaysInMonth =getDays(newCal.getMonth(), newCal.getFullYear()); //得到当月天数
   //生成日历
   for (var intWeek = 0; intWeek < caltable.rows.length;intWeek++)
     for (var intDay = 0;intDay < caltable.rows[intWeek].cells.length;intDay++)
     {
      var cell = caltable.rows[intWeek].cells[intDay];   //得到单元袼
   //生成字符串用于判断当天是否有日志
      var montemp=(newCal.getMonth()+1)<10?(“0″+(newCal.getMonth()+1)):(newCal.getMonth()+1);        
      if ((intDay == startDay) && (0 == daily)){ daily = 1;}
      var daytemp=daily<10?(“0″+daily):(daily);
      var d=”<”+newCal.getFullYear()+”-”+montemp+”-”+daytemp+”>”;
   //选择样式
      if(day==daily)
      cell.className=”calendarNow”;
      else if(diarydays.indexOf(d)!=-1)
         cell.className=”calendarLink”;
      else if(intDay==6)
      cell.className = “calendarDaySat”;
      else if (intDay==0)
      cell.className =”calendarDaySun”;
      else
      cell.className=”calendarTd”;
   //生成值
      if ((daily > 0) && (daily <= intDaysInMonth)) 
      {  cell.innerText = daily;
         daily++;
      }
      else
        cell.innerText = “”;
    }
  document.all.year.value=year;
  document.all.month.value=month+1;
}

function subMonth()
{
  if ((month-1)<0)
  {
     month=11;
  year=year-1;
  }
  else
  {
    month=month-1;
  }
  Calendar();
}
function addMonth()
{
  if((month+1)>11)
  {
    month=0;
    year=year+1;
  }
  else
  {
    month=month+1;
  }
  Calendar();
}
//得到响应事件
function getDiary()
{
  var mon=(newCal.getMonth()+1)<10?(“0″+(newCal.getMonth()+1)):(newCal.getMonth()+1);
  var day=event.srcElement.innerText<10?(“0″+event.srcElement.innerText):(event.srcElement.innerText);
  var d=”<”+newCal.getFullYear()+”-”+mon+”-”+day+”>”;
  if (“TD” == event.srcElement.tagName)
  if ((“” != event.srcElement.innerText)&&(diarydays.indexOf(d)!=-1))
  {
   diary.location=”/foxmail/archive/”+newCal.getFullYear()+”/”+mon+”/”+day+”.aspx”;
   window.location.href = diary.location;
  }
}

function setDate()
{
  if (document.all.month.value<1||document.all.month.value>12)
  {
    alert(“月的有效范围在1-12之间!”);
 return;
  }
  year=Math.ceil(document.all.year.value);
  month=Math.ceil(document.all.month.value-1);
  Calendar();
}
</SCRIPT>
<table border=”0″ cellpadding=”0″ cellspacing=”1″ class=”calendarBigBorder” id=”caltable” width=”200″>
<thead>
     <tr align=”center” valign=”middle”>
    <td colspan=”7″ class=”calendarMonthTitle”>
   <input name=”year” type=”text” class=”calendarYInput” size=”3″ maxlength=”4″ onkeydown=”if (event.keyCode==13){setDate()}” onkeyup=”this.value=this.value.replace(/[^0-9]/g,”)”  onpaste=”this.value=this.value.replace(/[^0-9]/g,”)”>年
   <input name=”month” type=”text” class=”calendarMInput” size=”1″ maxlength=”2″ onkeydown=”if (event.keyCode==13){setDate()}” onkeyup=”this.value=this.value.replace(/[^0-9]/g,”)”  onpaste=”this.value=this.value.replace(/[^0-9]/g,”)”>月 [<a onClick="addMonth()" href="javascript:;">下月</a>] [<a  onClick="subMonth()" href="javascript:;">上月</a>]</td>
  </tr>
 <tr align=”center” valign=”middle”>
 <SCRIPT LANGUAGE=”JavaScript”> 
 document.write(“<TD class=calendarDaySun id=diary>” + days[0] + “</TD>”);
 for (var intLoop = 1; intLoop < days.length-1;
 intLoop++)
 document.write(“<TD class=calendarTd id=diary>” + days[intLoop] + “</TD>”);
 document.write(“<TD class=calendarDaySat id=diary>” + days[intLoop] + “</TD>”);
 </SCRIPT>
 </TR>
</thead>
  <TBODY border=1 cellspacing=”0″ cellpadding=”0″ ID=”calendar” ALIGN=CENTER ONCLICK=”getDiary()” onmouseup=document.selection.empty() oncontextmenu=”return false” onselectstart=”return false” ondragstart=”return false” onbeforecopy=”return false” oncopy=document.selection.empty() onselect=document.selection.empty()>
    <SCRIPT LANGUAGE=”JavaScript”>
  for (var intWeeks = 0; intWeeks < 6; intWeeks++) {
  document.write(“<TR style=’cursor:hand’>”);
  for (var intDays = 0; intDays < days.length;intDays++)
  document.write(“<TD class=calendarTd onMouseover=’{classTemp=this.className;this.className=calendarHover}’ onMouseOut=’this.className=classTemp’></TD>”);
  document.write(“</TR>”);
  }
 </SCRIPT>
  </tbody>
 </table>
<script  LANGUAGE=”JavaScript”>
Calendar();
</script>
<!– Blog日历表结束 –>

天气预报

<!– 天气预报 注意这里涉及到编码问题,%B1%B1%BE%A9为城市代码,可用百度查一下,比如输入北京,地址栏中就会出现%B1%B1%BE%字样的内容–>
<center><iframe width=157 height=240 frameborder=0 scrolling=NO src=’http://appnews.qq.com/cgi-bin/news_qq_search?city=%B1%B1%BE%A9′></iframe></center>

MSN

<!– 显示msn在线状态,注意:必须在msn中设置允许所有人查看你的状态才有效,否则msn图标永远发灰 –>
<A HREF=”
http://snind.gotdns.com:8080/message/msn/你的msn用户名”>
<IMG SRC=”
http://snind.gotdns.com:8080/msn/你的msn用户名”
align=”absmiddle” border=”0″ ALT=”MSN Online Status Indicator”
onerror=”this.onerror=null;this.src=’http://snind.gotdns.com:8080/image/msnunknown.gif’;”>

QQ在线状态

<!– QQ在线状态显示 –>
</A><br>QQ:你的号码<img src=”
http://icon.tencent.com/你的号码/l/612/”>

<!– 时钟clock_035.swf 的035为时钟样式,可自己选择 –>
 <EMBED SRC=http://www.butabon.com/Clock/clock_035.swf WIDTH=150 HEIGHT=150 wmode=transparent quality=high loop=true menu=false>

日历
<!– Blog日历表开始 –>
<script language=”javascript”>
var diarydays=”<2004-08-05><2004-08-09><2004-08-12><2004-08-17><2004-08-19><2004-07-14><2004-07-13><2004-07-08><2004-07-05><2004-07-04><2004-07-03><2004-06-27><2004-06-26><2004-06-25>”;
</script>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
<style>
.calendarBigBorder { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; text-decoration: none; width: 170; background-color: #FFFFFF; font-size: 9pt;border:1px dotted #999; }
.calendarTd { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #000000; background-color: #eeeeee; height: 18px; width: 11%; text-align: center;}
.calendarMInput { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; text-decoration: none; background-color: #FFFFFF; height: 15px; border: 1px solid #666666; width: 19px; color: #0099FF;}
.calendarYInput { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #0099FF; text-decoration: none; background-color: #FFFFFF; height: 15px; width: 34px; border: 1px solid #666666;}
.calendarMonthTitle { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: normal; height: 24px; text-align: center; color: #333333; text-decoration: none; background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-bottom-style: none; border-top-color: #999999; border-right-color: #999999; border-bottom-color: #999999; border-left-color: #999999;}
.calendarNow { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: bold; color: #000000; background-color: #C0C9D3; height: 18px; text-align: center;}
.calendarDaySat { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #333333; text-decoration: none; background-color: #eeeeee; text-align: center; height: 18px; width: 12%;}
.calendarDaySun { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; color: #333333; text-decoration: none; background-color: #eeeeee; text-align: center; height: 18px; width: 12%;}
.calendarLink { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; font-weight: normal; color: #333333; text-decoration: none; background-color: #E7E7F6; text-align: center; height: 18px;}
.categoryTxt { font-family: “Arial”, “Helvetica”, “sans-serif”, “宋体”; font-size: 9pt; line-height: 23px; color: #333333; text-decoration: none;}
.categoryTable { border-right-width: 1px; border-bottom-width: 1px; border-right-style: solid; border-bottom-style: solid; border-left-style: none; border-right-color: #000000; border-bottom-color: #000000; border-top-width: 1px; border-top-style: solid; border-top-color: #71b99c;}
</style>
<SCRIPT LANGUAGE=”JavaScript”>
var months = new Array(“一”, “二”, “三”,”四”, “五”, “六”, “七”, “八”, “九”,”十”, “十一”, “十二”);
var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31,30, 31, 30, 31);
var days = new Array(“日”,”一”, “二”, “三”,”四”, “五”, “六”);
var classTemp;
var calendarHover=”calendarHover”;
var today=new getToday();
var year=today.year;
var month=today.month;
var newCal;
//得到某月天数
function getDays(month, year)
{ if (1 == month)
     return ((0 == year % 4) && (0 != (year % 100))) ||(0 == year % 400) ? 29 : 28;
  else
     return daysInMonth[month];
}
//得到当天时间信息
function getToday()
{  this.now = new Date();
   this.year = this.now.getFullYear();
   this.month = this.now.getMonth();
   this.day = this.now.getDate();
}
//生成日历
function Calendar()
{  newCal = new Date(year,month,1); //当前月的第一天
   today = new getToday();  
   var day = -1;   //用来判断日历中是否为当天
   var startDay = newCal.getDay(); //当月开始时间
   var endDay=getDays(newCal.getMonth(), newCal.getFullYear());//当月结束时间
   var daily = 0;   //用来生成日历中的天数值
   if ((today.year == newCal.getFullYear()) &&(today.month == newCal.getMonth()))
      day = today.day;
   var caltable = document.all.caltable.tBodies.calendar;  //得到日历表格的集合
   var intDaysInMonth =getDays(newCal.getMonth(), newCal.getFullYear()); //得到当月天数
   //生成日历
   for (var intWeek = 0; intWeek < caltable.rows.length;intWeek++)
     for (var intDay = 0;intDay < caltable.rows[intWeek].cells.length;intDay++)
     {
      var cell = caltable.rows[intWeek].cells[intDay];   //得到单元袼
   //生成字符串用于判断当天是否有日志
      var montemp=(newCal.getMonth()+1)<10?(“0″+(newCal.getMonth()+1)):(newCal.getMonth()+1);        
      if ((intDay == startDay) && (0 == daily)){ daily = 1;}
      var daytemp=daily<10?(“0″+daily):(daily);
      var d=”<”+newCal.getFullYear()+”-”+montemp+”-”+daytemp+”>”;
   //选择样式
      if(day==daily)
      cell.className=”calendarNow”;
      else if(diarydays.indexOf(d)!=-1)
         cell.className=”calendarLink”;
      else if(intDay==6)
      cell.className = “calendarDaySat”;
      else if (intDay==0)
      cell.className =”calendarDaySun”;
      else
      cell.className=”calendarTd”;
   //生成值
      if ((daily > 0) && (daily <= intDaysInMonth)) 
      {  cell.innerText = daily;
         daily++;
      }
      else
        cell.innerText = “”;
    }
  document.all.year.value=year;
  document.all.month.value=month+1;
}

function subMonth()
{
  if ((month-1)<0)
  {
     month=11;
  year=year-1;
  }
  else
  {
    month=month-1;
  }
  Calendar();
}
function addMonth()
{
  if((month+1)>11)
  {
    month=0;
    year=year+1;
  }
  else
  {
    month=month+1;
  }
  Calendar();
}
//得到响应事件
function getDiary()
{
  var mon=(newCal.getMonth()+1)<10?(“0″+(newCal.getMonth()+1)):(newCal.getMonth()+1);
  var day=event.srcElement.innerText<10?(“0″+event.srcElement.innerText):(event.srcElement.innerText);
  var d=”<”+newCal.getFullYear()+”-”+mon+”-”+day+”>”;
  if (“TD” == event.srcElement.tagName)
  if ((“” != event.srcElement.innerText)&&(diarydays.indexOf(d)!=-1))
  {
   diary.location=”/foxmail/archive/”+newCal.getFullYear()+”/”+mon+”/”+day+”.aspx”;
   window.location.href = diary.location;
  }
}

function setDate()
{
  if (document.all.month.value<1||document.all.month.value>12)
  {
    alert(“月的有效范围在1-12之间!”);
 return;
  }
  year=Math.ceil(document.all.year.value);
  month=Math.ceil(document.all.month.value-1);
  Calendar();
}
</SCRIPT>
<table border=”0″ cellpadding=”0″ cellspacing=”1″ class=”calendarBigBorder” id=”caltable” width=”200″>
<thead>
     <tr align=”center” valign=”middle”>
    <td colspan=”7″ class=”calendarMonthTitle”>
   <input name=”year” type=”text” class=”calendarYInput” size=”3″ maxlength=”4″ onkeydown=”if (event.keyCode==13){setDate()}” onkeyup=”this.value=this.value.replace(/[^0-9]/g,”)”  onpaste=”this.value=this.value.replace(/[^0-9]/g,”)”>年
   <input name=”month” type=”text” class=”calendarMInput” size=”1″ maxlength=”2″ onkeydown=”if (event.keyCode==13){setDate()}” onkeyup=”this.value=this.value.replace(/[^0-9]/g,”)”  onpaste=”this.value=this.value.replace(/[^0-9]/g,”)”>月 [<a onClick="addMonth()" href="javascript:;">下月</a>] [<a  onClick="subMonth()" href="javascript:;">上月</a>]</td>
  </tr>
 <tr align=”center” valign=”middle”>
 <SCRIPT LANGUAGE=”JavaScript”> 
 document.write(“<TD class=calendarDaySun id=diary>” + days[0] + “</TD>”);
 for (var intLoop = 1; intLoop < days.length-1;
 intLoop++)
 document.write(“<TD class=calendarTd id=diary>” + days[intLoop] + “</TD>”);
 document.write(“<TD class=calendarDaySat id=diary>” + days[intLoop] + “</TD>”);
 </SCRIPT>
 </TR>
</thead>
  <TBODY border=1 cellspacing=”0″ cellpadding=”0″ ID=”calendar” ALIGN=CENTER ONCLICK=”getDiary()” onmouseup=document.selection.empty() oncontextmenu=”return false” onselectstart=”return false” ondragstart=”return false” onbeforecopy=”return false” oncopy=document.selection.empty() onselect=document.selection.empty()>
    <SCRIPT LANGUAGE=”JavaScript”>
  for (var intWeeks = 0; intWeeks < 6; intWeeks++) {
  document.write(“<TR style=’cursor:hand’>”);
  for (var intDays = 0; intDays < days.length;intDays++)
  document.write(“<TD class=calendarTd onMouseover=’{classTemp=this.className;this.className=calendarHover}’ onMouseOut=’this.className=classTemp’></TD>”);
  document.write(“</TR>”);
  }
 </SCRIPT>
  </tbody>
 </table>
<script  LANGUAGE=”JavaScript”>
Calendar();
</script>
<!– Blog日历表结束 –>

天气预报

<!– 天气预报 注意这里涉及到编码问题,%B1%B1%BE%A9为城市代码,可用百度查一下,比如输入北京,地址栏中就会出现%B1%B1%BE%字样的内容–>
<center><iframe width=157 height=240 frameborder=0 scrolling=NO src=’http://appnews.qq.com/cgi-bin/news_qq_search?city=%B1%B1%BE%A9′></iframe></center>

MSN

<!– 显示msn在线状态,注意:必须在msn中设置允许所有人查看你的状态才有效,否则msn图标永远发灰 –>
<A HREF=”
http://snind.gotdns.com:8080/message/msn/你的msn用户名”>
<IMG SRC=”
http://snind.gotdns.com:8080/msn/你的msn用户名”
align=”absmiddle” border=”0″ ALT=”MSN Online Status Indicator”
onerror=”this.onerror=null;this.src=’http://snind.gotdns.com:8080/image/msnunknown.gif’;”>

QQ在线状态

<!– QQ在线状态显示 –>
</A><br>QQ:你的号码<img src=”
http://icon.tencent.com/你的号码/l/612/”>

TrackBack最早是Movable Type上的一个小功能。可以说就是这个小功能在blog界却掀起了一场革命。

TrackBack为将全世界无数个blog连接起来的功能。例如,当你读了某个网站的文章,想对此写下自己的感想。这个时候利用网站准备的讨论功能进行投稿是很最常见的做法。但这样只是把自己的评论意见写下来向别人的网站投稿,而你自己手里却什么也没留下。

TrackBack则与之有很大的区别。可以把评论写到自己网站上。然后向刊载原始文章的服务器发送该网页的URL及标题、部分正文、网站名称等信息(注)。尽管这一过程只是称之为“发送TrackBack Ping”,但通过这种办法,在原始文章的地方就留下了你的评论的URL、标题等部分信息。当然别人也可以向原始文章发送TrackBack Ping,所以在原始文章中就将包括你的TrackBack Ping在内的所有评论都记录了下来。

此外,如果你在自己网站上也设置了TrackBack Ping功能的话,那么谁都可以通过TrackBack Ping来发表针对你的意见了。这样,多家网站就通过相关话题而联接起来。各种评论在因特网上就像网眼一样联接起来。这样就创造出了与日记网站完全不同的文化。

注:发送地址采用原始文章指定的URL,这一URL就称为“TrackBack Ping URL”。最后的“128”为原始文章的专用数字,称为“TrackBack ID”。另外,TrackBack的技术标准刊登在“LowLife.jp”的blog网站上。

在我看来,NBA和足球的世界杯一样,是代表着该项运动最高竞技水平的平台,诸路英雄好汉逐鹿其间,一如金庸大侠笔下的江湖—残酷而又精彩,一场又一场精彩的较量既成就了英雄胜利的辉煌,同时也也记录了更多的好汉失意的瞬间。在此我就谈谈我心目中的几位失意的寂寥英雄。列位高人如有觉得可写之人,不妨也在此挥毫一二,以飨网友。我就先抛砖引玉了。
   失意英雄第10名—张伯伦
  
    当你看到我打出的这个名字的时候是否有大跌眼镜之感,或是觉得我的说法实在站不住脚呢?别急,请听我慢慢道来。没错,张伯伦是NBA有史以来最伟大的球员之一,也无疑是他那个时代最具有统治力的中锋,他所保持的NBA的诸项记录至今未有人打破,其中最让人津津乐道的单场100分记录更是惊世骇俗之作,只怕是前无古人,也后难有来者了。但是—–你看到这里的时候是不是已经偷偷在暗笑了呢?你一定以为我又会拿出那个难倒多少好汉的NBA总冠军戒指来摆平质疑吧!
  
    是的,张伯伦得过两枚总冠军戒指,但那是以他牺牲了自己的风格和投篮换来的,在他得到总冠军戒指的那个赛季,张伯伦的得分有了明显的缩水,换来的是队友的数据的全面提高,从而换取了夺取总冠军的先决条件——-一只优秀的球队,而张伯伦和他的球队的说法则不再被人们频繁提及了。
  
    但我还是认为,张伯伦是一个失意的英雄,因为他是寂寞的。公牛王朝之所以成为球迷心目中篮球的终极图腾,原因在于主角的强大和王朝成立途中的坎坷,有了坎坷,才会出现精彩。而精彩的出现,无疑是需要竞争者的。但凡赛场上的的较量,缺少了旗鼓相当的竞争者是不会给人留下深刻印象的。公牛王朝时代公牛的铁三角VS爵士的黄金搭档。90年代初湖人与活塞的经典战役中魔术师和微笑刺客的颠峰对决。火箭与尼克斯的制高点之争。无一不是针尖对麦芒似的激情碰撞。
  
    然而张伯伦没有,也许你会说拉塞尔———凯尔特人王朝时的象征人物,是的,凯尔特人或许可以借助全队的力量击败张伯伦所在的球队。但没有人可以在中锋这个位置上成为张伯伦的奥拉朱旺或是尤因。张伯伦超出那个时代的技术,身高,和全面使得他在同时代的人中显得格外突出。金庸在《神雕侠侣》和《笑傲江湖》中刻画的那个一生苦苦只求一败的独孤求败大侠无疑是寂寥的,没有对手的英雄是悲哀的,已然逝去的张伯伦在整个职业生涯中都没有遇到过真正意义上的挑战者,从这个意义上讲,他无疑是失意的。张伯伦如此,奥尼尔又何尝不是如此呢?——–至少现在如此……

失意英雄第9名—–萨博尼斯
  
    提起萨博尼斯,也许大多数NBA球迷的第一反应就是:噢,那个被奥尼尔在内线肆意蹂躏的白人大胖子,如果非要再详细些的话,还有:2。21米的身高,臃肿的体形,迟缓的脚步,近乎为零的弹跳高度。当然不可否认的是他的手感在中锋中是出类拔萃的:能投三分,大局观也还不错,及时的分球和精确的助攻是开拓者打开严密防线的利器之一。但问题的关键在于,他的体能似乎不足以让他在一场比赛中打满两节。
  
    从他在NBA时的技术统计看来,萨博尼斯似乎算不上一名超一流球星。是的,以上这些points of view都没有错,甚至能作为萨博尼斯在NBA的表现的客观评价。但由此就断言萨博尼斯是个LOSER,则未免有失片面。关于萨博尼斯的能力,有个例子或许能说明问题:当暂露头角的姚明第一次引起世界篮坛的注意时,一位前苏联名教头激动得如窥珍宝,宣称:给我两年时间,他(姚明)将成为下一个萨博尼斯。
  
    这固然是对姚明的肯定,而萨博尼斯的水准,也由此可见一斑。平心而论,现在的姚明,还未能超越萨博尼斯颠峰时期的水平。1988年的汉城奥运会上,前苏联男篮击败美国队登顶。当时队中的中锋便是萨博尼斯,在与海军上校的对决中,萨博尼斯占据了上风。得分,篮板,攻,盖帽,无所不能,甚至隔着罗宾逊的头上灌了一记,此时的萨博尼斯,哪里看得到后来那个开拓者的大胖子的半点影子。
  
    然而,美国和前苏联的敌对关系注定了萨博尼斯无法在其运动生涯的黄金时期出现在NBA的赛场上。与其说这是萨博尼斯的不幸,不如说这是NBA的遗憾。绚烂的NBA时也少了华丽的一笔。这不能不说是广大球迷的憾事1992年的巴塞罗那,立陶宛队不敌美国的梦之队区居第2,由苏维埃社会主义共和国公民变成了立陶宛国家队中一员的萨博尼斯已经度过了他风华正茂的颠峰期,伤痛和岁月已经让他庞大的身躯渐渐不再具有以往的能量和威慑力,但是他对罗宾逊(很凑巧,又是他)的连续两个大帽无疑是在向人们宣告着他的存在。
  
    萨博尼斯的NBA生涯可以用一句话来评价:他在错误的时间选择了错误的球队和错误的对手完成了一场比赛。也许唯一正确的事情就是他为自己退役后的生活赚取了足够多的养老金。当步履蹒跚的萨博尼斯塌上NBA的征程时,他无疑已不能主宰比赛了,而开拓者的气质决定了他们不可能成为最后的总冠军—-如果一只内讧不断,问题秤层出不穷的球队夺得了总冠军,那可真可谓奇迹了。
  
    美国球迷是挑剔的,在他们看来,没有在他们的联赛中得到证明的球员不能算成功球员。或许在萨博尼斯看来已无须向世人证明些什么,或许他已足够伟大。我们无从得知萨博尼斯的想法。但我有时禁不住会想:当年迈的萨博尼斯看到奥尼尔,姚明等一干小字辈驰骋于赛场时,他的脑海中会不会浮现出少年时意气风发的自己的身影呢?
  
    有实力,却得不到机遇,只能眼睁睁地看到白了少年头,而后惟有空叹一声造化弄人。这大概就是萨博尼斯的悲哀所在吧!


失意英雄第8名 莫宁
  
    不久前当莫宁宣布因为肾病而再度退出NBA时,大多数NBA球迷的感觉除了惋惜,还有震惊。事实上,没有人曾想到这个彪形大汉的肾病竟然严重到再比赛就会有生命危险的地步。就在此前不久同火箭的比赛前,看到身躯如铁塔般魁梧的莫宁将和姚明对阵时,我还曾想:”这样强壮的体魄,谁能看出他得过肾病呢?”然而赛后我却不得不接受这样一个事实:那就是—–尽管外表魁梧依旧,但莫宁已不是昨日的莫宁了。这点姚明的体会可能更深,相比于2年前悉尼的那个让他头痛不已的精壮汉子,现在的莫宁几乎很难在一对一中取得优势。
  
    2。08米的身高在中锋中实在不够醒目,没有过总冠军的履历更是让后辈无法从心底产生对莫宁的景仰之心(前不久不是传出消息说马丁对莫宁的篮板技术的风凉话吗?)然而,数年前莫宁所在的热队着实让不少球队头痛不已,作为金算子莱利麾下的得力干将,莫宁和他的队友所构建的防守体系让每一个与其对阵的对手都感到热浪般的窒息,而作为NBA最佳防守球员的莫宁更是当仁不让的成为了这架防守机器的核心,出色的爆发力使得莫宁的巨掌成为了笼罩在每一个靠近篮框者心头的梦魇。与其出色的篮板和防守技巧相比,稍显粗糙的进攻技术成为了莫宁战绩继续提高的桎梏。进攻套路的单调,也是莱利在热队始终未能真正解决的死穴。这无疑缩小了热队提升为超一流强队的空间。但这些都不能抹杀莫宁的出色,他的激情,他的斗志,他的灌篮,他自始自终灌注于比赛的拼劲,都是球迷推崇他的理由。记得再一场比赛的最后0。9秒,热队还落后一分,热队的半场边线球,只见皮球向篮框上高高抛出,莫宁从三秒区外拔地而起,单臂将球摁进了篮筐,之所以说是摁,是因为进筐前,篮球上还搭着两名防守队员的手。两名防守队员的手。
  
    莫宁的惊人爆发力让人记忆犹新,但这并不是我评他为失意英雄的理由。和莫宁一样出色的球星不在少数,比他更出色的也大有人在,至少罗得曼的的篮板就比莫宁好。但象莫宁那样勇于在疾病面前一次次对命运说NO的汉子并不多。当海明威笔下的老人面对几乎无法战胜的自然力高呼出”你尽可消灭一个人,但你就是打不败他”的豪言时,谁还会在乎他带回的是一条完整的鱼,还是一副骨架呢?也许疾病可以侵蚀莫宁的健康,也许莫宁从此无法有获得总冠军的机会,但谁又能由此说他是个失败者呢?
  
    相比于卖乖耍宝的奥尼尔在他的大脚趾上的喋喋不休,莫宁面对疾病时的坦然和坚韧更让人钦佩。如果没有肾病的困扰,如果他能到一个更强的球队?。。。”如果”有很多,但生活却只有一种可能性,莫宁的职业生涯也只有一条道路,前半程对于莫宁来说无疑是坎坷的,荆棘的。
  
    莫宁好象又快要复出了吧。无论复出与否,让我们对这位勇士由衷的说一声:”莫宁,后半程一路走好!

对于许多因为姚明才开始认识NBA的中国球迷来说,巴克利留给他们最深的印象就是那个赌输后不得不去亲驴腚的小丑。而在稍早一些开始关注NBA的球迷里,则几乎没有不知道”恶汉”的名头的,因为他曾是NBA中一股不可忽视的力量。
  
    身高仅有1。96米的大前锋;NBA史上最矮的篮板王;坦克一样进方式;直来直去而又不失讥诮的大嘴;大大咧咧的处世态度;和奥尼尔干仗的壮举;还有他恶汉的名头。。。这些似乎都还不足以使承载起”英雄”这个称谓。更为关键的是,巴克利还缺少了一个重要的荣誉——–总冠军戒指。众所周知,巴克利和乔丹是至交好友,也是竞争对手,这种竞争不仅仅出现在篮球场上,赌桌前,高尔夫球场上,都是他们暗中教劲的竞技场。或许,巴克利的牌技比乔丹强,高尔夫比乔丹专业,但惟独在篮球场上,巴克利只能接受一次次输给乔丹的命运。不管巴克利的表现多么出色,乔丹总能挡住他通往的胜利的道路。也许不光是巴克利,大多数和乔丹同时代的球星也曾都有过 “既生瑜,何生亮” 的慨叹。
  
    乔丹的第一次退役让众多为总冠军戒指折磨得近乎疯狂的豪杰门看到了问鼎的希望,巴克利和他的太阳自然也不例外。然而,这次是另一位和乔丹同时步入NBA的天才—–奥拉朱旺挡在了他的前面。火箭的突然爆发让巴克利再度失意。好吧!既然击败不了它,那就加入它,巴克利也正是这么做的。然而,命运跟为了一枚戒指而牺牲了许多的巴克利又开了个玩笑,宣布回到篮球场上的乔丹没有再给雄心勃勃的挑战者们任何机会,此后三年的三座总冠军奖杯都留在了芝加哥,从而也确立了公牛王朝的地位。火箭的爆发随着大梦的状态下滑和老将们的离去成为了过去时,他们甚至没有再进过总决赛。
  
    时光荏苒,光阴似箭,不经意间,巴克利的黄金时期已然逝去,他不再是球场上的主角,尽管他努力依旧,大嘴也依然犀利风趣,精彩的灌篮也层出不穷。但他的落寂是显而易见的,因为此时的西部,爵士如日中天。巴克利的另一位好友—马龙和他的搭档斯托克顿牢牢把持着向公牛王朝挑战的资格。失意的巴克利终究没有象大卫。罗宾逊那样,熬到公牛王朝分崩离析的那一天。
  
    几乎与乔丹退出篮坛的同时,心灰意懒的巴克利也选择了退役,因为膝伤,因为新规则。
  
    关于新规则,巴克利曾有过这样的调侃:也许以后人们只会以”巴克利式的犯规”之类的话来记住我了。这固然是调侃,但却又折射出几多巴克利的辛酸。退役后的巴克利当起了电视评论员,以发挥大嘴的余热,和搭档的插浑打科并不能让巴克利忘记他所热爱的篮球场,更不能让他忘记曾为之了魂牵梦萦的总冠军。所以,当乔丹第二次复出时,巴克利也嚷嚷着要陪他的老伙计一起打拼。
  
    但是日益见增的体重和臃肿得有些夸张的体形让巴克利的复出梦想成为了一个不可能实现的任务。一个人不得不告别他所心爱的事业,不得不接受梦想的幻灭——-这委实是一件让人心碎的事情。相信大家对2003年全明星赛上乔丹噙着泪水告别的那一幕还记忆犹新吧,英雄的离去总是让人感到痛苦的。当一颗冠军的心却不得不接受没有总冠军戒指的命运时,他的心情尤其如此,比如尤因,比如—巴克利。
  
    远离了球员生活的巴克利的生活是充实的,虽然职业生涯并不完美。但谁又能说他不是个英雄呢?至少,他战斗过了!至少,他给我们带来过快乐和精彩。这就够了!
  
    让我们伸出大拇指,由衷的赞一声:”巴克利,是条汉子!”


生命中不能承受之轻———-第6名 格兰特•希尔
  
    失意英雄列传写了5个,却突然发现自己实在写不下去了。不是我所选择的球员不够伟大,亦非他们的经历不足以吸引人们的关注。托尔斯泰曾云:幸福的家庭大多相似,不幸的家庭则各有各的不幸。然而对于失意英雄列传中的那些球员而言,他们的失意的缘由却都是那么的类似:或是无缘冠军戒指的悲怆;或是为伤病困扰的抑郁。对于一名职业球员而言:最痛苦的事情并非晚年的穷困潦倒,而是在回首自己的运动生涯时,却发现没有多少值得骄傲的回忆,人生中最痛苦的事情莫过于如此了,因为这意味着他们人生的黄金阶段虚度了。如果他们的失意不是因为自身条件的局限,而是缘于造化的弄人时,这种遗憾造成的痛苦就会尤其令人心碎。
  
    有潜质,但却无法将它释放为职业生涯中的辉煌——这也正是希尔的抑郁之处吧。
  
    没有人会否认希尔的超凡实力,因为被誉为有史以来最全面的小前锋的希尔自然不会是浪得虚名。29次三双的骄人记录也似乎证实了人们对他的的期望并非毫无缘由。出道伊始的希尔听到的除了赞赏还是赞赏。甚至一向挑剔的乔大爷也钦许地称希尔为他的接班人。一切都是那样的一帆风顺,一位伟大球星的诞生似乎也只是迟早的事情。如果没有后来的意外。
  
    西谚云:上帝在一个地方关上一扇门,就会在另一个地方为你打开一扇窗。我不知道上帝是否真的如这句话说的那般仁慈,相反我觉得上帝就象希腊神话中的小心眼的宙斯一样,是吝啬的——-如果他真的存在的话。因为他从来都不会满足人们所有的愿望。古人云:天妒英才。也许是希尔的前半生的过于一帆风顺实在令这个老头子嫉妒了吧。
  
    与大多数NBA球员不同的是,希尔出生在一个富足的中产阶级家庭中,生活无忧的他也继承了曾为职业橄榄球运动员的父亲的运动基因。可以说:希尔从事篮球运动是出于对这份事业的热爱,因为他的肩上没有挣钱养家的担子。在希尔从活塞转投魔术之前,一切都是那样的完美。但命运就在此时跟希尔开了个残酷的玩笑。第一次脚踝受伤并不会改变人们对希尔的期望。一次不够,那两次呢?三个月的伤病困扰不足以磨灭人们的记忆,那六个月呢?甚至一年呢。。。再伟大的球星也会随着岁月的流逝而被遗忘,何况是还没有完全成为巨星的希尔呢?所以我们不能苛求外星人(罗纳尔多)变回以前那个意气风发的追风少年,因为经历过伤病重创和世态炎凉的外星人更加明白这样一个道理:离开了足球场,他只是一个名字而已。
  
    一次次充满希望的复出,换来的却一次次悲壮地被同一个敌人干净利落地击倒在地,任何一个人的锐气都会被消磨殆尽,难道这次又轮到希尔了吗?巴乔把伤病称为他一生的情人,如果伤病注定要成为运动员甩不掉的情人的话,那么这个情人无疑对希尔太苛刻,也太任性了些。多少伟大的球星因为这个”情人”的不离不弃而不得不黯然泪别运动场,巴斯滕,加林查。。。希尔的运动生涯的黄金时期就快要离去了。对于这个和伤病抗争了太久了的斗士,我们惟有送上最真挚的祝福,惟有乞盼他的职业生涯的顶峰不要象《等待戈多》中等待戈多的到来那样令人绝望,那样遥遥无期。
  
    希尔又快要复出了吧,但愿他能抓住这为数不多的机会,因为无论是对于麦蒂还是魔术的球迷,这一切实在是太久,太久了。
  
    没有人猜到希尔的职业生涯会如此坎坷,那么会有人猜到最后的结局吗?难道脚踝注定要成为希尔生命中不能承受之轻吗?至少保险公司不会喜欢这个结局,你呢?


孤独刺客————–第5名 雷吉·米勒
  
    读过武侠小说的朋友都知道:一个真正出色的杀手,他不必有慑人的气势,但他一定会在他的行动中保持绝对冷静的头脑。他会耐心地等待,蛰伏,在必要的时候甚至会忍辱负重。但却绝不肯为在此之外的事物浪费半点多余的力气。如果你不能在他流尽最后一滴血之前把他彻底记垮,或是在对决中显示出了半点懈怠,那么,等待你的,将是迅雷不及掩耳般的致命一击。也许这一击不若”天外飞仙”之类的招数那般雍容华贵,亦不会象降龙十八掌那样气势惊人,但绝对会快得出乎你的意料,也许不会多刺入你的体内一分,但一定见血封喉。此刻伴随着无尽的悔意而同时降临的,还有你不得不接受的,失败的命运。
  
    绿茵场上的杀手是菲利浦。因扎吉。而在篮球场上最接近刺客本质的人,我以为非雷吉。米勒莫属。与大多数出名的球星不同的是,米勒并没有出众的身体素质,没有绝对的身高优势,没有值得夸耀的弹跳力,甚至连移动素质也称不上出色。但在篮球场上,你最好不要忽视他的存在,更不要激怒他———如果你没有绝对的把握在他出手之前把他击倒的话。相信关于这句话,纽约人一定有深刻的体会。和纽约尼克斯的超级拥趸,著名导演斯派克。李的嘴仗转化为了单节25分的惊人记录。米勒几乎是以一己之力击摧垮了拥有最疯狂主场之称的纽约人。这种在一般人看来几乎是不可能完成的任务并非偶然,而是源于从高中起便不断外出征战的经历所磨砺出的超凡的心理素质。
  
    在NBA的总经理间流传着一条不成文的定律,即:如果你想得总冠军,那么永远不要选自家后院有三个车库的新秀。因为在他们看来,这样的球员在打球时会过于”礼貌”,从而缺乏一股必胜的信念。无论是先前的格兰特。希尔,或是后来的文斯。卡特似乎都不足以打破人们的这种偏见。但没有人会这么评价同样出身于中产阶级家庭的雷吉。米勒。因为他天生就是为了冠军而生的,尽管他还没有得到他梦寐以求的总冠军戒指。米勒时间的缔造者不可能是懦夫,任何一个被乔丹视作真正对手的球员也绝不可能是孬种。NBA历史上的经典对决告诉我们:相距甚远的两个球员,或许能成为对友,但绝不可能成为对手。
  
    关于米勒的刺客本质的最好注释自然少不了提及米勒时间,和掘金的最后9秒抢下10分的神来之笔便是这个名词的最好商标。但在我看来,真正能体现出米勒内部世界的例子便是他和乔丹之间说不完,也道不尽的恩怨。毕竟,对于任何一个和乔丹同时代的球员而言,乔丹都是一块无法绕过的试金石。说来有趣,每次公牛和步行者的比赛前夕,媒体总会大肆炒作一番,弄得双方的球员都肾上腺素猛增。其热度决不逊于今天关于姚鲨对决的关注。确实,能让一贯以激怒对手为己任的乔大爷暴跳如雷,乃至大打出手,的确不是一件容易的事情。这固然说明米勒的垃圾话技巧高超,还证明了他~~~如蛆附骨般的贴身+若有若无小动作的防守技术以臻出神入化之境地。这也正是一名出色的杀手的素质之一———-尽一切可能去激怒对手,从而使之心浮气躁,破绽百出。
  
    这是米勒的高明之处,也是他不高明的地方。高明,是因为他的策略对于大多数对手而言都是有效的。而不高明的地方则在于:他施展此术的对象不幸也包括了迈克尔。乔丹。激怒乔丹或许可以换来一次胜利,但换来的绝对会是被激怒的飞人的更猛烈的报复。
  
    米勒应该算是幸运的了,古人云:人生之事不如意者,十之八九。充实的生活,美丽的妻子,可爱的儿女,队友的尊敬,球迷的拥戴。除了,除了近乎完美却又不无遗憾的职业生涯。。。。。。
  
    在职业生涯的黄金时期与乔丹联手制造了针尖对麦芒似的经典对决的米勒也渐渐步入了职业生涯的夕阳时期,而耐不住离开篮球后的寂寞的飞人在经历了不惑之年时的再度复出后也不得不永远地淡出了NBA这个舞台。蓦然回首,时间这个无情的裁判已经将几多我们似曾相识的球星”驱逐出场”。而他们的表演却宛如就发生在昨日一样历历在目,令人难忘。
  
    时间的流逝不可抗拒,属于米勒他们的时代随着新一代球星的崛起也成为了球迷心中的回忆。即使步行者还有夺取总冠军的希望,这种希望也不再更多的来源于米勒了。也许多少年后,已然老去的乔丹和米勒再度聚首之时,对于那曾充斥了他们半个职业生涯的,纠缠不清的恩恩怨怨也该释然了吧。相逢一笑泯仇恩,矛盾可以冰释,但人亦非人,时光也再也回不到过去了。这份遗憾也不得不永远留在米勒的记忆之中了。
  
    如果时间真的能如《大话西游》一般,我们能借助月光宝盒将一切重来的话,一切又将会是怎样的呢?


NBA失意英雄并列第3名———–斯托克顿&马龙
  
    不要抗议,不要质疑,也不要不满。是的,这次是并列,但我并非在偷懒。如果你一定要在他们两人间分出一个高下来,我只有无奈的说一声:sorry!I can‘t。不是我不能分开,但从感情上我着实不愿拆散这对并肩奋战了十数载的搭档,他们就好比carrots and peas(秤不离砣)提到斯托克顿,我们的脑海中就会很自然地联想到马龙。而谈及马龙,人们的第一印象也只会是三角中心的那个十八载守时如一日的老邮差,那个战斗在在斯托克顿身边的老搭档,哪怕他可能在湖人找到他在盐湖城未曾找到总冠军的感觉。
  
    如果非要评选出NBA史上最经典的战术配合之一,那么一定少不了马龙和斯托克顿的挡拆。谈到战术,我常常会不自觉地想到金庸老先生笔下的关于武功招术的妙评——倘若你的对手的出手根本无招,乃至无迹可寻的时候,你又怎么能找到他的破绽呢?
  
    这样的对手委实是令人胆寒的。但我们不妨再设想一下另一种情形:如果对手的招数你知道一清二楚,甚至知道他将刺向你的哪个部位,但你却就是无法阻止他给你的致命一击的时候,此刻的心情恐怕只能用绝望来形容了吧。用这样的评价来形容爵士双雄的挡拆未免有些言过其实,但这种看似简单却具有极强杀伤力的战术的威慑性确是不容置疑的。至少上个世纪90年代中期每个和爵士交手过的对手都知道,当马龙和斯托克顿的状态都正常的时候,恐怕就惟有祈祷上帝站在自己这边了。
  
    看过马龙和斯托克顿的比赛的朋友对于他们的配合只会有一个感受——-默契!而这种令人叹为观止的默契来源于十九年如一日的并肩战斗。对于”铁打的营盘流水的兵”的NBA,存在搭档这么久的组合,若非绝迹,也当是另类了吧。但也惟有这样的搭档,才能创造出连续十八个赛季创入季后赛的令人惊叹的记录,而在这个惊人记录的背后,是两个人数十年来始终如一日的努力与勤勉。与天赋神力的奥尼尔不同,马龙的粗壮的上肢是后天不懈的力量练习的成果。而斯托克顿的控球能力和开阔的视野则更是千万次触球的结晶。对于这两个先天条件都称不上出类拔萃的球员来说,勤奋就是他们共同的商标。每年的夏天,当大多数球员忙里偷闲地享受着不多的假期的时候,马龙和斯托克顿就仿佛事先约定好了的一般从城市中消失,马龙躲进自家的农场,斯托克顿则埋头于一个大学城的没有空调的球馆中,而他们每天的日程中的主旋律也只有一个————篮球。
  
  
悲情纽约客———–第2名 帕特里克•尤因
  
    2000年的6月,从这一刻起:对于所有的纽约尼克斯球迷而言,尤因将注定成为他们心中一个无法回避的情节。
  
    不管你是不是喜欢过这个大个子,也不管你是不是他的球迷,无法否认的一点是:他(帕特里克•尤因)肯定是尼克斯这个NBA的插班生的不长的历史中最具统治力的中锋之一。从这个球风剽悍然而其貌不扬的大个子来到尼克斯的那一刻起,纽约人就没有停止过对于总冠军的梦想,但没有人会料到这将会是一个令人痛苦的等待,一个似乎永远也不会如期而至的戈多。
  
    正如热爱篮球的人们所了解的那样:尼克斯的主场——麦迪逊花园是所有的出色篮球运动员所热衷的舞台,因为这里聚集了全美最出色的记者;全美最狂热的球迷;最奢华的硬件设施。在整个火爆的90年代,在这个创造过连续爆满记录最多的球场里,纽约都是所有球队的一块试金石。缺少过硬心理素质的人不会成为比赛的主角,在尼克斯的以尤因为核心的肉搏式防守面前,在纽约人近乎疯狂的助威声中,缺少足够的心理素质的人会因为紧张而手足无措,并导致最终的失利。在自信的纽约人看来:没有什么是不可能发生的,也没有什么对手是不可击败的(拥有乔丹的公牛可能除外),然而也正是由于这种自信得近乎自负的浮躁,失败在纽约人看来就显得尤其地令人无法接受——-如果还是当离胜利只有一步之遥却最终被翻盘的时候,那就简直是不可饶恕。
  
    纽约人的自信并非毫无缘由:这里是全美最大的城市,是世界经济的脉搏,是美国自由主义文化的象征,也是联合国的总部所在地——-那么,全美最优秀的球队,WHY NOT?你不能说纽约人不懂篮球,对于球队的打法,几乎每个坐在观众席上的人都能说出个一二三,而且绝非信口开河。在给球员的开出的薪水方面,纽约的老板的慷慨也常常令人瞠目结舌。很难想象在一个如此商业化的城市里会屡屡出现在旁人看来几乎是不可思议的疯狂合同。也许这只能用纽约人对他们的总冠军的极度渴望来解释了,他们是如此的渴望以至于他们竟失去了应有的理性的头脑。诚然,竞技体育离不开金钱的支持,但金钱就一定能换来总冠军么?高额的待遇的确是吸引优秀球员眼球的得力武器,然而一旦他们在球场上的表现不佳,铺天盖地的批评则足以让任何一个球员崩溃。高额的薪水也立刻会成为球迷和刻薄的媒体攻击的对象,哪怕这个球员为之付出过他所有的青春和心血。这样的合同,你会接受么?
  
    有人曾说:爱他吗?送他去纽约吧,那里是天堂。你恨他吗?送他去纽约吧,因为那里也是地狱。不知道尤因在选择了纽约时,他是否听过这段话。但他终究没能跨过天堂的门槛。一枚总冠军的戒指就足够使他成为这个城市的英雄,如果有了这样一枚戒指,以后的一切都将不同,也许。。。
  
    也许有很多种,但残酷的是,结局却永远只有一个——冠军不属于纽约。
  
    。。。。。。
  
    2003年3月2日晚9:00,麦迪逊花园广场,一件球衣,帕特里克。尤因的33号球衣在体育馆的上空冉冉升起。这一刻,在场的所有球迷都见证了一位伟大的球员的离去,也见证了一个时代的结束。尤因的眼里的泪水和语无伦次的离别演说是他心里复杂感受的体现,他不会忘记自己曾留在这里的峥嵘岁月,不会忘记每一次大力灌篮后全场山鸣海啸般的欢呼,更不会忘记那两次足以刻骨铭心的总决赛之旅。两次杀进总决赛,却两次败在两个不同的老对头的手下。和乔丹同时代的球员是不幸的,无论他们多么伟大,却永远只有一个划分球员的标准:乔丹和其他人。在这一切都成为历史之时,人们或许会因为乔丹离去时的两个总冠军而记住”大梦”奥拉朱旺,或许也会因为后乔丹时代的缩水赛季候赛冠军而回忆起大卫。罗宾逊。但谁还会记得那个总是一脸沧桑的大猩猩尤因呢?因为两次总决赛亚军的称号么?
  
    从某种意义上讲,尤因称不上真正的球星。和另两位同样出色的中锋比起来,他实在是太缺乏星味了,场上奥拉朱旺的梦幻步伐令人如痴如醉,而场下的大梦庄重的仪表让人不自觉的肃然起敬;总是一副谦谦君子形象的罗宾逊完全足以成为一名外交官;尤因呢?离开了他熟悉的篮球场,我们实在看不出这个老实巴交的大个子有什么值得称道的地方,没有巴克利的俏皮话,更没有乔丹特立独行的酷。当NBA的老兄弟们纷纷为昔日的老相识莫宁的肾病表示美好的祝愿时,尤因也只有一句:麻烦跟莫宁说一声,如果需要,可以把我的拿去。寥寥数语,没有过多的辞藻,没有祝福,也没有美国人惯有的幽默感。但却禁不住让人潸然泪下。这就是那个因为不肯为球迷签名而被纽约记者批判为没有责任感的尤因?这就是那个纽约报纸的体育专栏上丑陋而固执的大猩猩?
  
    也许,尤因来到纽约本身就是个错误;也许,尤因从来就不曾真正属于过纽约;也许,尤因本来注定就是这个城市的一名过客而已——虽然他在这里待了15年。他的老伙计马龙在盐湖城待了18年,如果不是因为圆总冠军的梦,马龙无疑还能待在三角中心,领着已不完全匹配其水准的巨额薪水,直到光荣地退役,因为爵士的球迷热爱他,他们能理解马龙对于他们的巨大贡献,他们是懂得感恩的。纽约是怎么做的呢?当为他们带来过希望的”尤因股”没有了升值空间的时候也似乎理所当然地是被卖出之时。在他们看来,浑身伤病,两次失意于总决赛的尤因已经彻底沦为了尼克斯版块上的垃圾股。于是,一个可笑的,不为球迷签名的理由也成了尤因必须滚开的理所当然的罪证。天真地原本希望能体面的在尼克斯结束职业生涯的尤因不得不背起他的行囊,带着伤痕累累的躯体,还有满腹的委屈,孤单地去了西雅图。
  
    两次满怀希望却又再次失望,不难理解纽约人的失落和伤心。然而当他们将这一切的不满和失落转化为莫名的怒气宣泄到尤因的头上,甚至将曾为他们带来过胜利和快乐的城市英雄贬低得一无是处时。这如何能不教人心寒。又如何能让有意于纽约的球星不望而却步呢?
  
    姚明登陆NBA伊始,纽约人也曾热烈地追逐过这个潜在的NBA第一中锋。甚至于一些尼克斯球迷见到中国记者就请求记者转达他们对姚的欢迎和期盼。然而但当记者问起尤因时,得到的答案却是:纽约队从来就没有过真正的中锋。绝情至此,也无怪乎姚明明确表示不愿去纽约的意向了——-也许姚明不得不想:谁能保证他将来不会象尤因那样被无情地扔出去呢?
  
    更具有讽刺意味的是,在摆脱了似乎是所有麻烦的根源的尤因之后,尼克斯并没有获得预想的新生,相反却更陷入了战绩一蹶不振的泥潭。此时,已经冷静下来的纽约人才不得不重新审视了过去对尤因的态度,那个被视作包袱的糖果人中锋,那个曾被纽约人无情地撵出去的尤因。也许只有经历了失去的遗憾,人们才能更懂得珍惜。
  
    时光荏苒,当一切都已成为了记忆之时,裂痕或能弥合。然而,那份已然失去的感觉还能重温么?但愿经历了这一切的尤因和球迷真的能如我们所期望的那样相逢一笑泯仇恩。毕竟,又有什么样的结是时间所不能化开的呢?
  
    现在,已经身居火箭助理教练一职的尤因还在为了他在球员时代所未曾圆了的同样一个梦想而继续努力着。纽约带给他的回忆不再是他生活里的主旋律。
  
    在另一个城市,另一个曾带给他失落和遗憾的球队里,在另一个同样让人充满了希望的小巨人的身上,尤因正在找回他的失去的梦想。
  
    有了希望,还怕什么呢?尤因!Good luck


NBA失意英雄第一名——永远的蝙蝠侠 斯科特。皮蓬
  
    A:”皮蓬?皮蓬是谁?他是打篮球的吗?”
  
    B:”是的,而且他还是NBA有史以来最出色的小前锋……绰号‘蝙蝠侠‘……他还得过6次总冠军……”(汗)
  
    A:”是吗?这么厉害,但能不能再提示下……”{木鸡状}
  
    B:”好吧!他曾和迈克尔。乔丹是队友……”(无奈)
  
    A:”噢,我有点想起来了。对对对,是他!当年公牛王朝的成员,很不错的球员。你早这么说不就明白了!”(得意状)
  
    B:”……”(#$—%*~$%—*—)
  
    B:不过他真的很出色,你应该知道啊。”(晕厥状)
  
    A:”of course!他是乔丹的队友,怎么会差!对了,他叫什么来着?皮蓬?对对,斯科特。皮蓬!”
  
    B……(扑通)
  
    当你看完了上面的对白,请不要嘲笑A的孤陋寡闻。也许这样的对白的确是夸张了些。许若干年后,这就是一个普通的NBA球迷听到斯科特。皮蓬后最真实的反应。
  
    诚然,作为一名拿过六枚总冠军戒指的球星,和他入选NBA最佳阵容的显赫经历,都足以使他声名远播,相比较同时代的斯托克顿和尤因一生与总冠军无缘的命运。皮蓬似乎也没有理由成为失意英雄列传中的一员。
  
    是的,对于其他的任何一名球员而言,他似乎都应该感谢命运之神的眷顾了。但对于皮蓬,这些还远远不够。作为一名极有天赋而又努力的球员,6次总冠军的成绩无疑是对他的最好奖励。但对于心高气傲的皮蓬来说,在被提及他的出众履历的同时却不得不忍受另一个称谓——乔丹的队友”或是”乔丹的前队友”。这对于皮蓬与生俱来的强烈自尊心无疑是一种侮辱。所以我们不难理解皮蓬为什么在功成名就之时加盟开拓者而不是选择颐养天年。乔丹第一次退役后的那个季后赛,为什么皮蓬在队友没有将最后一投的机会让给他的时候会那样愤怒也就不难解释了。
  
    对于大多数从公牛王朝时代才开始认识NBA的中国球迷而言,在相当长的一段时间内,乔丹就是NBA的代名词。而NBA球员的划分标准也只有一个:乔丹 和 其他人。甚至在乔丹离开后的很长一段时间内,对于30分以下的数据被称作表现出色都很让我们费解。——这也叫出色?
  
    乔丹的伟大毋庸置疑,但不得不忍受不断以乔丹的标准来被衡量无疑是让人无奈的。特别是当你是他的队友,而且在球场上的所处的角色相近的时候。你永远没有在比赛中针锋相对的机会,这着实是一件很让人郁闷的事实。所以,当训练中乔丹和皮蓬一对一的斗牛的时候——用他们的队友科尔的话说:那简直就是一场战争!对决双方都恨不得将对手置于死地。
  
    但训练毕竟只是训练,在球迷看来,他们(公牛队)只需要按部就班的打球。然后在适当的时候以适当的方式将球交到乔丹的手上就OK了。比赛如果获胜(经常的)事情,那自然是大家和乔丹的功劳,倘若不幸饮恨,那也没关系,再伟大的球员也有失手的时候嘛。总而言之,如果说比赛是一场精彩的演出的话,作为乔丹的队友,你只需要做好自己的配角工作就可以了。而”the one”的角色,自然非乔丹莫属。公牛阵中,有最佳第6人库科奇,篮板王罗德曼,射手科尔,组织后卫哈伯,内线屏障 澳大利亚人朗利。似乎只有这个皮蓬,时不时地冒出些牢骚和小不满。当然,他的能力也是不容忽视的,但总有些喧宾夺主之嫌。
  
    当人们对一件事情已经形成了一种约定俗成的默契,而你要想推翻这种观念的时候,你就必须拥有能改变人们观念的超人一筹的实力,必须比对手付出更多的汗水和努力。如果皮蓬是科尔或是哈珀,他或许会放弃这种努力而顺由天意。但皮蓬之所以成为皮蓬,就在于这个其貌不扬的男人在挑战面前永远不会轻言放弃。明知几乎不可为而勉力为之——这也正是他的性格中最贵的一点。
  
    皮蓬从来没有放弃过挑战乔丹地位的每一个机会。对于一个天赋绝对不在自己之下的”对手”,超越他的唯一方法就是更加刻苦的训练,然而,乔丹之所以成为乔丹,就在于他永远不会懈怠,对于乔丹来说,篮球已经成为了他身体的另一个心脏。所以——皮蓬的机会是:零。
  
    或许这就是皮蓬注定的悲剧吧,对于一项运动来说,出现乔丹式的人物,无疑是它的大幸。也正是由于有了乔丹时代的出现,才激得有更多的后来者去努力超越这个图腾式的神话。譬如科比,譬如麦蒂,譬如——皮蓬。只有了竞争和不断超越的信念,篮球这项运动的魅力才能得到真正意义上的升华。
  
    皮蓬的开拓者之旅和萨博尼斯一样,可以用一句话来形容:他在一个错误的时间,在一支错误的球队,和一群错误的队友,经历了一段错误的NBA生涯。开拓者的老板远不如他电脑方面的眼光来得高明。一支人心不齐,互不买帐的球队,是不可能夺得最后的胜利的。
  
    职业生涯已经寥寥无几的皮蓬希望在没有乔丹的队伍中夺得总冠军的夙愿已经无情地破灭了。也许,他真的无法超越乔丹,也许没有了乔丹,公牛永远不可能获得总冠军。但如果没有了皮蓬,情况又会是怎样呢?如果没有了皮蓬,乔丹能不能完成他的霸业呢?没有人考虑过这种情形,而这种假设,也永远只能作为一个假设了。
  
    当你对乔丹的经典时刻能如数家珍的时,当你对爵士和公牛的颠峰对决耳熟能详的时候;当你对中锋时代的巨匠们的技术特点了若指掌时候;当你为米勒时刻欢呼雀跃的时候;当你为魔术师的传球眼花缭乱的时候……希望你不要忘却了在这个时代里,NBA的球场上还曾有过一位同样伟大的球员——他的名字叫斯科特。皮蓬——他的外号是蝙蝠侠.

问: 如何设置Java 2(JDK1.2)的环境变量?

答: Java 2安装后,需要设置PATH和JAVA_HOME环境变量.与JDK1.1不同的是:设置好JAVA_HOME环境变量后,JVM将自动搜索系统类库以及用户的当前路径。
Java 2环境变量的设置如下例所示:
Solaris平台: setenv JAVA_HOME Java2的安装路径
setenv PATH $JAVA_HOME/bin:${PATH}
Windows平台: set JAVA_HOME=Java2的安装路径
set PATH=$JAVA_HOMEbin;%PATH%

问: 哪些Java集成开发工具支持Java 2?

答: 目前流行的Java集成开发环境,如Inprise的JBuilder,Symantec的Visual Cafe, Sybase的PowerJ,都支持Java 2.

问: 如果在Netscape或IE浏览器中运行Java applet时出现了错误,如何确定错误范围?

答: 当java applet在浏览器中运行时,使用的是浏览器本身的缺省JVM.而不同浏览器对JDK的支持程度也不尽相同. 因此,在Netscape或IE浏览器中运行Java applet出现了错误,建议使用JDK提供的工具appletviewer或Sun公司的Hotjava浏览器来测试该applet,以确定错误的产生是与浏览器相关。
  
  如果applet在appletviewer或Hotjava中运行一切正常,则错误的产生是由于浏览 器不完全兼容JDK而引起的. 此时,解决方法可以是使用Hotjava浏览器或者安装 Sun公司的Java Plugin.
  如果applet在Hotjava浏览器或appletviewer中运行即发生错误,则应当根据错误 提示检查applet程序.

问: 当用Servlet来处理http请求并产生返回的HTML页面时,如何使HTML页面中的中文字符能够正常显示?

答: javax.servlet.http.HttpResponse类用于产生返回页面.通过HttpResponse定义的方法 getOutputStream()可以获得ServletOutputStream的实例,这样用户就可以利用 ServletOutputStream.write方法向输出流中写入返回页面的内容. 但是ServletOutputStream使用的是缺省的编码方式,如果要使返回页面中的中文字符能够正常显示,最好显示地指定所用的字符编码方式. 通常需要构造一个 OutputStreamWriter , 例程如下:


  public void doGet (HttpServletRequest req, HttpServletResponse res)

  throws ServletException, IOException

  {

  res.setContentType(“text/html”);

  ServletOutputStream out = res.getOutputStream();

  OutputStreamWriter ow = new OutputStreamWriter(out,”GB2312″);

  ow.write(“这是测试”);

  ow.flush();

  ow.close();

  }


问: 如何设置Java WebServer的CLASSPATH,以包含用户的class文件?

答: 有两种方法可以设置Java WebServer的CLASSPATH环境变量,以使用户编写的Servlet能够调用用户的class文件.
  将用户的class文件放到 JavaWebServer_Dir/classes目录下,在Java WebServer 启动时,classes目录被自动加入到CLASSPATH环境变量中了.
  修改httpd.nojre文件,将用户class文件所在的路径名加到CLASSPATH环境变量中.

问: 为什么在Windows平台上用Naming.lookup来获取远程RMI对象时会很慢?

答: 机器的网络设置不正确很可能会引起该问题的发生.
  RMI使用了Java网络类,特别是java.net.InetAddress类,它将查询TCP/IP的主机名, 包括IP地址到主机名的映射和主机名到IP地址的映射.在Windows平台,这种查询功能 是由本地的Windows Socket库来实现的. 因此延时是发生在Windows库中,而非RMI中.

  如果你的机器设置成使用DNS,问题通常是DNS服务器查不到主机名,你所发现的延时 是DNS查询的延时. 请尝试将RMI通信中涉及到的所有主机名/IP地址加到本地文件 winntsystem32driversetchosts或windowshosts中. 格式如下:

  IP地址 主机名

  如此设置应当可以明显地减少查询所花的时间.

问: 编写Java application时,如何设置proxy的信息,以便访问外部网站?

答: 若在java application中访问外部网站,首先应设置proxy信息,样例代码如下:


  import java.util.properties;

  …..

  Properties sys = System.getProperties();

  sys.put(“proxySet”,”true”);

  sys.put(“proxyHost”,”myHTTP.proxyserver.com”);

  sys.put(“proxyPort”,”80″);

  System.setProperties(sys);

  u = new URL(website);

  connect = (HttpURLConnection)u.openConnection();

  …..

  
问: Swing组件JList的列表数据修改了,如何通知JList改变显示?

答: JList组件有一个单独的显示模式ListModel来表示JList的显示数据.
  JList创建以后,JList数据元素的值及数据元素的数量可以动态地改变.
  JList在它的数据模式ListModel中观察数据的改变.因此,一个ListModel 的正确实现应当在每次数据发生改变时,通知事件的监听者.
  当使用构造函数JList(Object[])创建一个JList的实例时,系统将自动创建一个DefaultListModel的实例来存储JList的显示数据, 可以调用 DefaultListModel中定义的简便方法来动态地修改JList的数据,如 removeElementAt(index),addElement(Object)等. DefaultListModel 在修改数据的同时,将通知JList关于数据的改变.

问: 在Java applet中如何实现一个模式对话框?

答: 在Java applet中实现模式对话框的关键就是在创建一个对话框的时候要为该对话框指定一个正确的父窗口.因为Applet是Panel类的子类,不可以作为对话框的父窗口,所以首先要获得applet所在的窗口,作为模式 对话框的父窗口. 样例代码如下:


  …..

  Dialog d = new Dialog( getParentWindow(comp),title);

  // comp为applet上的任意一个组件

  ….

  public void getParentWindow(Component compOnApplet,String title){

  Container c = compOnApplet.getParent();

  while (c != null) {

  if (c instanceof Frame)

  return (Frame) c;

  c = c.getParent();

  }

  return null;

  }


问: 在Java applet中如何显示另外一个HTML页面?

答: 通过 java.applet.Applet.getAppletContext()方法可以获得与该applet相关的AppletContext, AppletContext.showDocument(URL)方法就可以使applet所在的浏览器显示另外一个网页.

问: 用JDK实现的签名applet,可否在Netscape或IE中运行?

答: 用JDK实现的签名applet,不可以在Netscape或IE中运行,但是可以在Hotjava浏览器中运行.

  不同的浏览器提供了不同的签名applet机制,如Netscape提供了zigbert工具和 Capability API, 而IE则需要使用CAB文件. 但是,无论是Netscape工具产生的签名applet,还是用IE产生的签名applet,都不可以在其它的浏览器中运行.

  如果要使JDK产生的签名applet能够在Netscape或IE中运行,解决方法是在 Netscape或IE中安装Java Plugin,则用JDK实现的签名applet就可以在这两种 浏览器中运行.

问: 用JNI技术可以从Java应用中调用C程序库,但是如何使该C程序库可以调用另外的C程序库?

答: 如果一个被Java调用的C程序库C1仍需要调用另外一个C程序库C2,那么在编译C1的时候应当联接程序库C2,步骤如下(Solaris平台):
  编写调用C库的Java文件,并编译.
  javac java文件名

  产生C程序头文件
  javah -jni java文件名(不带后缀.java)

  编写被Java调用的C程序C1.c,以及被C1调用的C2.c,并编译.
  cc -G -Iinclude路径名 C2.c -o libC2.so
  cc -G -Iinclude路径名 -lC2 C1.c -o libC1.so

  设置环境变量
  setenv LD_LIBRARY_PATH libC1.so,libC2.so所在路径
  :${LD_LIBRARY_PATH}

  运行java应用

问: 在Java语言中,如何列出PC机文件系统中的所有驱动器名?

答: 在Java 2版本中,java.io包中的File类新增加了方法listRoots()可以实现这一功能.

问: 为什么Runtime.exec(“ls”)没有任何输出?

答: 调用Runtime.exec方法将产生一个本地的进程,并返回一个Process子类的实例,该实例可用于控制进程或取得进程的相关信息. 由于调用Runtime.exec方法所创建的子进程没有自己的终端或控制台,因此该子进程的标准IO(如stdin,stdou,stderr)都通过 Process.getOutputStream(),Process.getInputStream(), Process.getErrorStream()方法重定向给它的父进程了.用户需要用这些stream来向 子进程输入数据或获取子进程的输出. 所以正确执行Runtime.exec(“ls”)的例程如下:


  try

  {

  process = Runtime.getRuntime().exec (command);

  InputStreamReader ir=newInputStreamReader(process.getInputStream());

  LineNumberReader input = new LineNumberReader (ir);

  String line;

  while ((line = input.readLine ()) != null)

  System.out.println(line);

  }

  catch (java.io.IOException e){

  System.err.println (“IOException ” + e.getMessage());

  }



问: 使用JDBC编程,应如何控制结果集ResultSet的指针,使之能够上下移动,以及移动到结果集的第一行和最后一行?

答: 在JDK1.1中,ResultSet类中只定义了next()方法支持数据指针的下移.但在Java 2中,ResultSet类增加了如下方法支持数据指针的移动,包括:

  ResultSet.first():将数据指针移到结果集的第一行

  ResultSet.last(): 将数据指针移到结果集的最后一行

  ResultSet.previous(): 将数据指针上移一行


  以上的方法定义在JDBC2.0的规范中,所有支持JDBC 2.0的JDBC驱动程序都可以支持上述方法.目前Intersolv和OpenLink等JDBC驱动程序厂商均有产品支持JDBC 2.0 .

问: 哪几种Web Server支持Servlet?如何使IIS支持Servlet?

答: 目前,支持Servlet的服务器端产品主要有: Sun公司的Java WebServer,Lotus DominoGo WebServer,BEA weblogic Tengah Server,Jigsaw,NetForge,AcmeServer和Mot Bays Jetty等.

  此外,一些第三方厂商也开发了Servlet engine,以使其它WebServer(如Netscape Web Server,IIS等)能够运行Servlet,如LiveSoftware的Jrun(http://www.livesoftware.com/products/jrun/)等.

问: 如何在Java应用中将图像存储到图像文件中?

答: Java Advanced Imaging API(包含在Java Media API中)允许在Java应用中执行复杂的,高性能的图像处理.JAI API提供了存储图像的能力.目前,JAI API支持以下几种图像文件格式:BMP,JEPG,PNG,PNM,TIFF.下面给出了将图像存储到BMP文件的一段代码:


  OutputStream os = new FileOutputStream(fileToWriteTo);

  BMPEncodeParam param = new BMPEncodeParam();

  ImageEncoder enc = ImageCodec.createImageEncoder(“BMP”, os, param);

  enc.encode(img);

  os.close();

  有关存储图像文件的编程指南请参考以下网页:

  http://java.sun.com/products/java-media/jai/forDevelopers/jai-guide/

问: 如何用Java语言向串口读写数据

答: Sun公司的Java Communication API2.0可用于读写串口,它支持RS232串口和IEEE 1284 并口,提供了一种与平台无关的串/并口通信机制.

一、 JDK (Java Development Kit)
JDK 是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具和Java基础的类库(rt.jar)。不论什么Java应用服务器实质都是内置了某个版本的JDK。因此掌握 JDK是学好Java的第一步。最主流的JDK是Sun公司发布的JDK,除了Sun之外,还有很多公司和组织都开发了自己的JDK,例如IBM公司开发的JDK,BEA公司的Jrocket,还有GNU组织开发的JDK等等。其中IBM的JDK包含的JVM(Java Virtual Machine)运行效率要比Sun JDK包含的JVM高出许多。而专门运行在x86平台的Jrocket在服务端运行效率也要比Sun JDK好很多。但不管怎么说,我们还是需要先把Sun JDK掌握好。

1、 JDK的下载和安装
JDK又叫做J2SE (Java2 SDK Standard Edition),可以从Sun的Java网站上下载到,http://java.sun.com/j2se/downloads.html ;,JDK当前最新的版本是J2SDK1.4.2,建议下载该版本的JDK,下载页面在这里:http: //java.sun.com/j2se/1.4.2/download.html。

下载好的JDK是一个可执行安装程序,默认安装完毕后会在C:\Program Files\Java\目录下安装一套JRE(供浏览器来使用),在C:\j2sdk1.4.2下安装一套JDK(也包括一套JRE)。然后我们需要在环境变量PATH的最前面增加java的路径C:\j2sdk1.4.2\bin。这样JDK就安装好了。

2、 JDK的命令工具
JDK的最重要命令行工具:
java: 启动JVM执行class
javac: Java编译器
jar: Java打包工具
javadoc: Java文档生成器
这些命令行必须要非常非常熟悉,对于每个参数都要很精通才行。对于这些命令的学习,JDK Documentation上有详细的文档。

二、 JDK Documentation

Documentation 在JDK的下载页面也有下载连接,建议同时下载Documentation。Documentation是最最重要的编程手册,涵盖了整个Java所有方面的内容的描述。可以这样说,学习Java编程,大部分时间都是花在看这个Documentation上面的。我是随身携带的,写Java代码的时候,随时查看,须臾不离手。

三、 应用服务器(App Server)

App Server是运行Java企业组件的平台,构成了应用软件的主要运行环境。当前主流的App Server是BEA公司的Weblogic Server和IBM公司的Websphere以及免费的Jboss,选择其中一个进行学习就可以了,个人推荐Weblogic,因为它的体系结构更加干净,开发和部署更加方便,是Java企业软件开发人员首选的开发平台。下面简要介绍几种常用的App Server:

1、 Tomcat
Tomcat 严格意义上并不是一个真正的App Server,它只是一个可以支持运行Serlvet/JSP的Web容器,不过Tomcat也扩展了一些App Server的功能,如JNDI,数据库连接池,用户事务处理等等。Tomcat被非常广泛的应用在中小规模的Java Web应用中,因此本文做一点下载、安装和配置Tomcat的介绍:

Tomcat是Apache组织下Jakarta项目下的一个子项目,它的主网站是:http://jakarta.apache.org/tomcat/ ;,Tomcat最新版本是Tomcat4.1.27,软件下载的连接是:http: //www.apache.org/dist/jakarta/tomcat-4/binaries/ ;。

下载Tomcat既可以直接下载zip包,也可以下载exe安装包(个人建议zip更干净些),不管哪种情况,下载完毕安装好以后(zip直接解压缩就可以了)。需要设置两个环境变量:

JAVA_HOME=C:\j2sdk1.4.2
CATALINA_HOME=D:\tomcat4 (你的Tomcat安装目录)

这样就安装好了,启动Tomcat运行CATALINA_HOME\bin\startup.bat,关闭Tomcat运行shutdown.bat脚本。 Tomcat启动以后,默认使用8080端口,因此可以用浏览器访问http://localhost:8080来测试Tomcat是否正常启动。

Tomcat提供了两个Web界面的管理工具,URL分别是:
http://localhost:8080/admin/index.jsp ;
http://localhost:8080/manager/html ;
在启用这两个管理工具之前,先需要手工配置一下管理员用户和口令。用一个文本工具打开CATALINA_HOME\conf\tomcat-users.xml这个文件,加入如下几行:

<role rolename=”manager”/>
<role rolename=”admin”/>
<user username=”robbin” password=”12345678″ roles=”admin,manager,tomcat”/>

这样用户“robbin”就具备了超级管理员权限。重新启动Tomcat以后,你就可以使用该用户来登陆如上的两个管理工具,通过Web方式进行Tomcat的配置和管理了。

2、 BEA Weblogic
Weblogic 可以到BEA的网站上免费注册之后下载到最新的Weblogic8.1企业版,License可以免费使用1年时间,其实这已经完全足够了。 Weblogic的下载连接:http://commerce.bea.com/index.jsp,Weblogic的在线文档:http: //edocs.bea.com/ ;。

3、 IBM Webshpere
Websphere同样可以下载到免费的试用版本,到IBM的developerWorks网站可以看到Websphere试用产品的下载和相关的Websphere的资料, developerWorks中文网站的连接是:http://www-900.ibm.com/developerWorks/cn/wsdd/ ;,Websphere的下载连接:http: //www7b.software.ibm.com/wsdd/downloads/WASsupport.html ;。

4、 Jboss
Jboss 是免费开源的App Server,可以免费的从Jboss网站下载:http://www.jboss.org/index.html,然而Jboss的文档是不免费,需要花钱购买,所以为我们学习Jboss设置了一定的障碍。在Jdon上有几篇不错的Jboss配置文档,可以用来参考:http: //www.jdon.com/idea.html ;

四、 Java应用的运行环境

Java的应用可以简单分为以下几个方面:

1、 Java的桌面应用
桌面应用一般仅仅需要JRE的支持就足够了。

2、 Java Web应用
Java的Web应用至少需要安装JDK和一个web容器(例如Tomcat),以及一个多用户数据库,Web应用至少分为三层:
Browser层:浏览器显示用户页面
Web层:运行Servlet/JSP
DB层:后端数据库,向Java程序提供数据访问服务

3、 Java企业级应用
企业级应用比较复杂,可以扩展到n层,最简单情况会分为4层:
Browser层:浏览器显示用户页面
Client层:Java客户端图形程序(或者嵌入式设备的程序)直接和Web层或者EJB层交互
Web层:运行Servlet/JSP
EJB层:运行EJB,完成业务逻辑运算
DB层:后端数据库,向Java程序提供数据访问服务

4、 Java嵌入式应用
Java嵌入式应用是一个方兴未艾的领域,从事嵌入式开发,需要从Sun下载J2ME开发包,J2ME包含了嵌入式设备专用虚拟机KVM,和普通的JDK中包含的JVM有所不同。另外还需要到特定的嵌入式厂商那里下载模拟器。

Java Learning Path(二)、书籍篇

学习一门新的知识,不可能指望只看一本,或者两本书就能够完全掌握。需要有一个循序渐进的阅读过程。我推荐Oreilly出版的Java系列书籍。

在这里我只想补充一点看法,很多人学习Java是从《Thinking in Java》这本书入手的,但是我认为这本书是不适合初学者的。我认为正确的使用这本书的方法应该是作为辅助的读物。《Thinking in Java》并不是在完整的介绍Java的整个体系,而是一种跳跃式的写作方法,是一种类似tips的方法来对Java很多知识点进行了深入的分析和解释。

对于初学者来说,最好是找一本Java入门的书籍,但是比较完整的循序的介绍Java的语法,面向对象的特性,核心类库等等,在看这本书的同时,可以同步来看《Thinking in Java》,来加深对Java的理解和原理的运用,同时又可以完整的了解Java的整个体系。

对于Java的入门书籍,蔡学镛推荐的是Oreilly的《Exploring Java, 2nd Edition》 或者《Java in a Nutshell,2nd Edition(针对C++背景)》,我并没有看过这两本书。其实我觉得电子工业出版社的《Java 2编程详解》或者《Java 2从入门到精通》就很不错。

在所有的Java书籍当中,其实最最有用的,并不是O′reilly的 Java Serials,真正最最有用处是JDK的Documentation!几乎你想获得的所有的知识在Documentation里面全部都有,其中最主要的部分当然是Java基础类库的API文档,是按照package来组织的,对于每一个class都有详细的解释,它的继承关系,是否实现了某个接口,通常用在哪些场合,还可以查到它所有的public的属性和方法,每个属性的解释,意义,每个方法的用途,调用的参数,参数的意义,返回值的类型,以及方法可能抛出的异常等等。可以这样来说,所有关于Java编程方面的书籍其实都不过是在用比较通俗易懂的语言,和良好的组织方式来介绍 Documentation里面的某个package里面包含的一些类的用法而已。所以万变不离其宗,如果你有足够的能力来直接通过 Documentation来学习Java的类库,那么基本上就不需要看其他的书籍了。除此之外,Documentation也是编程必备的手册,我的桌面上有三个Documentation的快捷方式,分别是J2SDK1.4.1的Documentation,Servlet2.3的 Documentation和J2SDKEE1.3.1的Documentation。有了这个三个Documentation,什么其他的书籍都不需要了。

对于Java Web 编程来说,最核心的是要熟悉和掌握HTTP协议,这个就和Java无关了,在熟悉HTTP协议之后,就需要熟悉Java的实现HTTP协议的类库,也就是 Servlet API,所以最重要的东西就是Servlet API。当然对于初学者而言,直接通过Servlet API来学习Web编程有很大的难度,我推荐O′reilly的《Java Server Pages 》这本书来学习Web 编程。

EJB 的书籍当中,《Enterprise JavaBeans, 2nd Edition》是一本很不错的书, EJB的学习门槛是比较高,入门很难,但是这本书完全降低了学习的难度,特别重要的一点是,EJB的学习需要结合一种App Server的具体实现,所以在学习EJB的同时,必须同步的学习某种App Server,而这本书相关的出了三本书,分别是Weblogic6.1,Websphere4.0和JBoss3.0上面部署书中例子的实做。真是既有理论,又有实践。在学习EJB的同时,可以边看边做,EJB的学习会变得很轻松。

但是这本书也有一个问题,就是版本比较旧,主要讲 EJB1.1规范和部分EJB2.0的规范。而Ed Roman写的《Mastering EJB 2.0》这本书完全是根据EJB2.0规范写的,深入浅出,覆盖了EJB编程的各个方面,并且还有很多编程经验tips,也是学习EJB非常推荐的书籍之一。

如果是结合Weblogic来学习J2EE的话,《J2EE应用与BEA Weblogic Server》绝对是首选读物,虽然是讲述的Weblogic6.0,仍然值得购买,这本书是BEA官方推荐的教材,作者也是BEA公司的工程师。现在中文版已经随处可见了。这本书结合Weblogic介绍了J2EE各个方面的技术在Weblogic平台上的开发和部署,实践指导意义非常强。

在掌握了Java平台基础知识和J2EE方面的知识以后,更进一步的是学习如何运用OO的方法进行软件的设计,那么就一定要学习“设计模式”。Sun公司出版了一本《J2EE核心模式》,是每个开发Java企业平台软件的架构师必备的书籍。这本书全面的介绍了J2EE体系架构的各种设计模式,是设计师的必读书籍。

Java Learning Path(三)过程篇

每个人的学习方法是不同的,一个人的方法不见得适合另一个人,我只能是谈自己的学习方法。因为我学习Java是完全自学的,从来没有问过别人,所以学习的过程基本上完全是自己摸索出来的。我也不知道这种方法是否是比较好的方法,只能给大家提供一点参考了。

学习Java的第一步是安装好JDK,写一个Hello World,? 其实JDK的学习没有那么简单,关于JDK有两个问题是很容易一直困扰Java程序员的地方:一个是CLASSPATH的问题,其实从原理上来说,是要搞清楚JRE的ClassLoader是如何加载Class的;另一个问题是package和import问题,如何来寻找类的路径问题。把这两个问题摸索清楚了,就扫除了学习Java和使用JDK的最大障碍。推荐看一下王森的《Java深度历险》,对这两个问题进行了深入的探讨。

第二步是学习Java的语法。Java的语法是类C++的,基本上主流的编程语言不是类C,就是类C++的,没有什么新东西,所以语法的学习,大概就是半天的时间足够了。唯一需要注意的是有几个不容易搞清楚的关键字的用法,public,protected,private,static,什么时候用,为什么要用,怎么用,这可能需要有人来指点一下,我当初是完全自己琢磨出来的,花了很久的时间。不过后来我看到《Thinking in Java》这本书上面是讲了这些概念的。

第三步是学习Java的面向对象的编程语言的特性的地方。比如继承,构造器,抽象类,接口,方法的多态,重载,覆盖,Java的异常处理机制。对于一个没有面向对象语言背景的人来说,我觉得这个过程需要花很长很长时间,因为学习Java之前没有 C++的经验,只有C的经验,我是大概花了一个月左右吧,才彻底把这些概念都搞清楚,把书上面的例子反复的揣摩,修改,尝试,把那几章内容反复的看过来,看过去,看了不下5遍,才彻底领悟了。不过我想如果有C++经验的话,应该一两天时间足够了。那么在这个过程中,可以多看看《Thinking in Java》这本书,对面向对象的讲解非常透彻。可惜的是我学习的时候,并没有看到这本书,所以自己花了大量的时间,通过自己的尝试和揣摩来学会的。

第四步就是开始熟悉Java的类库。Java的基础类库其实就是JDK安装目录下面jre\lib\rt.jar这个包。学习基础类库就是学习rt.jar。基础类库里面的类非常非常多。据说有3000多个,我没有统计过。但是真正对于我们来说最核心的只有4个,分别是
java.lang.*;
java.io.*;
java.util.*;
java.sql.*;

这四个包的学习,每个包的学习都可以写成一本厚厚的教材,而O′reilly也确实是这样做的。我觉得如果时间比较紧,是不可能通过读四本书来学习。我觉得比较好的学习方法是这样的:
首先要通读整个package的框架,了解整个package的class,interface,exception的构成,最好是能够找到介绍整个包框架的文章。这些专门介绍包的书籍的前几章应该就是这些总体的框架内容介绍。

对包整体框架的把握并不是要熟悉每个类的用法,记住它有哪些属性,方法。想记也记不住的。而是要知道包有哪些方面的类构成的,这些类的用途是什么,最核心的几个类分别是完成什么功能的。我在给人培训的时候一般是一次课讲一个包,所以不可能详细的介绍每个类的用法,但是我反复强调,我给你们讲这些包的不是要告诉你们类的方法是怎么调用的,也不要求你们记住类的方法调用,而是要你们了解,Java给我们提供了哪些类,每个类是用在什么场合,当我遇到问题的时候,我知道哪个类,或者哪几个类的组合可以解决我的问题,That′all!,当我们具体写程序的时候,只要你知道该用哪个类来完成你的工作就足够了。编码的时候,具体的方法调用,是边写代码,边查Documentation,所有的东西都在Documentation里面,不要求你一定记住,实际你也记不住 3000多个类的总共将近10万个方法调用。所以对每个包的总体框架的把握就变得极为重要。

第五步,通过上面的学习,如果学的比较扎实的话,就打好了Java的基础了,剩下要做的工作是扫清Documentation里面除了上面4个包之外的其他一些比较有用处的类。相信进展到这一步,Java的自学能力已经被培养出来了,可以到了直接学习Documentation的水平了。除了要做GUI编程之外,JDK里面其他会有用处的包是这些:
java.text.*;
java.net.*;
javax.naming.*;
这些包里面真正用的比较多的类其实很少,只有几个,所以不需要花很多时间。

第六步,Java Web 编程
Web 编程的核心是HTTP协议,HTTP协议和Java无关,如果不熟悉HTTP协议的话,虽然也可以学好Servlet/JSP编程,但是达不到举一反三,一通百通的境界。所以HTTP协议的学习是必备的。如果熟悉了HTTP协议的话,又有了Java编程的良好的基础,学习Servlet/JSP简直易如反掌,我学习Servlet/JSP就用了不到一周的时间,然后就开始用JSP来做项目了。

在Servlet/JSP的学习中,重头仍然是Servlet Documentation。Servlet API最常用的类很少,花比较少的时间就可以掌握了。把这些类都看一遍,多写几个例子试试。Servlet/JSP编程本质就是在反复调用这些类来通过 HTTP协议在Web Server和Brower之间交谈。另外对JSP,还需要熟悉几个常用JSP的标记,具体的写法记不住的话,临时查就是了。

此外Java Web编程学习的重点要放在Web Application的设计模式上,如何进行业务逻辑的分析,并且进行合理的设计,按照MVC设计模式的要求,运用Servlet和JSP分别完成不同的逻辑层,掌握如何在Servlet和JSP之间进行流程的控制和数据的共享,以及Web Application应该如何配置和部署。

第七步,J2EE编程
以上的学习过程如果是比较顺利的话,进行到这一步,难度又陡然提高。因为上面的知识内容都是只涉及一个方面,而像EJB,JMS,JTA等核心的J2EE规范往往是几种Java技术的综合运用的结晶,所以掌握起来难度比较大。

首先一定要学习好JNDI,JNDI是App Server定位服务器资源(EJB组件,Datasouce,JMS)查找方法,如果对JNDI不熟悉的话,EJB,JMS这些东西几乎学不下去。 JNDI其实就是javax.naming.*这个包,运用起来很简单。难点在于服务器资源文件的配置。对于服务器资源文件的配置,就需要看看专门的文档规范了,比如web.xml的写法,ejb-jar.xml的写法等等。针对每种不同的App Server,还有自己的服务资源配置文件,也是需要熟悉的。

然后可以学习JTA,主要是要理解JTA对于事务的控制的方法,以及该在什么场合使用JTA。这里可以简单的举个例子,我们知道一般情况可以对于一个数据库连接进行事务控制(conn.setAutoCommit (false),….,conn.commit()),做为一个原子操作,但是假设我的业务需求是要把对两个不同数据库的操作做为一个原子操作,你能做的到吗?这时候只能用JTA了。假设操作过程是先往A数据库插一条记录,然后删除B数据库另一个记录,我们自己写代码是控制不了把整个操作做为一个原子操作的。用JTA的话,由App Server来完成控制。

在学习EJB之前要学习对象序列化和RMI,RMI是EJB的基础。接着学习JMS和EJB,对于EJB来说,最关键是要理解EJB是如何通过RMI来实现对远端对象的调用的,以及在什么情况下要用到EJB。

在学习完EJB,JMS这些东西之后,你可能会意识到要急不可待学习两个领域的知识,一个是UML,另一个是Design Pattern。Java企业软件的设计非常重视框架(Framework)的设计,一个好的软件框架是软件开发成功的必要条件。在这个时候,应该开始把学习的重点放在设计模式和框架的学习上,通过学习和实际的编程经验来掌握EJB的设计模式和J2EE的核心模式。

J2EE规范里面,除了EJB,JMS,JTA,Servlet/JSP,JDBC之外还有很多很多的企业技术,这里不一一进行介绍了。

另外还有一个最新领域Web Services。Web Services也完全没有任何新东西,它像是一种黏合剂,可以把不同的服务统一起来提供一个统一的调用接口,作为使用者来说,我只要获得服务提供者给我的WSDL(对服务的描述),就够了,我完全不知道服务器提供者提供的服务究竟是EJB组件,还是.Net组件,还是什么CORBA组件,还是其他的什么实现,我也不需要知道。Web Services最伟大的地方就在于通过统一的服务提供方式和调用方式,实现了整个Internet服务的共享,是一个非常令人激动的技术领域。Web Services好像目前还没有什么很好的书籍,但是可以通过在网络上面查资料的方式来学习。

Java Learning Path(四) 方法篇

Java 作为一门编程语言,最好的学习方法就是写代码。当你学习一个类以后,你就可以自己写个简单的例子程序来运行一下,看看有什么结果,然后再多调用几个类的方法,看看运行结果,这样非常直观的把类给学会了,而且记忆非常深刻。然后不应该满足把代码调通,你应该想想看如果我不这样写,换个方式,再试试行不行。记得哪个高人说过学习编程就是个破坏的过程,把书上的例子,自己学习Documentation编写的例子在运行通过以后,不断的尝试着用不同的方法实现,不断的尝试破坏代码的结构,看看它会有什么结果。通过这样的方式,你会很彻底的很精通的掌握Java。

举个例子,我们都编过Hello World

public class HelloWorld {
public static void main(String[] args) {
System.out.println(“Hello World”);
}
}

很多初学者不是很理解为什么main方法一定要这样来定义public static void main(String[] args),能不能不这样写?包括我刚学习Java的时候也有这样的疑问。想知道答案吗?很简单,你把main改个名字运行一下,看看报什么错误,然后根据出错信息进行分析;把main的public取掉,在试试看,报什么错误;static去掉还能不能运行;不知道main方法是否一定要传一个 String[]数组的,把String[]改掉,改成int[],或者String试试看;不知道是否必须写args参数名称的,也可以把args改成别的名字,看看运行结果如何。

我当初学习Java的时候就是这样做的,把Hello World程序反复改了七八次,不断运行,分析运行结果,最后就彻底明白为什么了main方法是这样定义的了。

此外,我对于staic,public,private,Exception,try{ }catch {}finally{}等等等等一开始都不是很懂,都是把参考书上面的例子运行成功,然后就开始破坏它,不断的根据自己心里面的疑问来重新改写程序,看看能不能运行,运行出来是个什么样子,是否可以得到预期的结果。这样虽然比较费时间,不过一个例子程序这样反复破坏几次之后。我就对这个相关的知识彻底学通了。有时候甚至故意写一些错误的代码来运行,看看能否得到预期的运行错误。这样对于编程的掌握是及其深刻的。

其中特别值得一提的是JDK有一个非常棒的调试功能,-verbose
java ?Cverbose
javac ?Cverbose 以及其它很多JDK工具都有这个选项
-verbose 可以显示在命令执行的过程中,JVM都依次加载哪里Class,通过这些宝贵的调试信息,可以帮助我们分析出JVM在执行的过程中都干了些什么。

另外,自己在学习过程中,写的很多的这种破坏例程,应该有意识的分门别类的保存下来,在工作中积累的典型例程也应该定期整理,日积月累,自己就有了一个代码库了。遇到类似的问题,到代码库里面 Copy & Paste ,Search & Replace,就好了,极大提高了开发速度。最理想的情况是把一些通用的例程自己再抽象一层,形成一个通用的类库,封装好。那么可复用性就更强了。

所以我觉得其实不是特别需要例程的,自己写的破坏例程就是最好的例子,如果你实在对自己写的代码不放心的话,我强烈推荐你看看JDK基础类库的Java源代码。在JDK安装目录下面会有一个src.zip,解开来就可以完整的看到整个JDK基础类库,也就是rt.jar的Java源代码,你可以参考一下 Sun是怎么写Java程序的,规范是什么样子的。我自己在学习Java的类库的时候,当有些地方理解的不是很清楚的时候,或者想更加清晰的理解运作的细节的时候,往往会打开相应的类的源代码,通过看源代码,所有的问题都会一扫而空。

Java Learning Path(五)资源篇

1、 http://java.sun.com/ ;(英文)
Sun的Java网站,是一个应该经常去看的地方。不用多说。

2、 http://www-900.ibm.com/developerWorks/cn/ ;
IBM的developerWorks网站,英语好的直接去英文主站点看。这里不但是一个极好的面向对象的分析设计网站,也是Web Services,Java,Linux极好的网站。强烈推荐!!!

3、 http://www.java-cn.com/ ;(中文)
JAVA 中文站,目前国内资料最全、会员最多的JAVA技术网站,人气极高。有《JAVA电子书库》、《JAVA视频库》(国内唯一)、《JAVA技术文摘库》、《JAVA源代码库》、《JAVA工具库》、《招聘求职广场》等主要栏目,还有一些专家栏目。目前会员有5万多,VIP会员近1000人。无论是菜鸟还是老鸟,都能在此网站中找到自己所需要的东东!! 最强烈推荐!!!!!!

4、 http://www.javaworld.com/ ;(英文)
关于Java很多新技术的讨论和新闻。想多了解Java的方方面面的应用,这里比较好。

5、 http://dev2dev.bea.com.cn/index.jsp ;
BEA的开发者园地,BEA作为最重要的App Server厂商,有很多独到的技术,在Weblogic上做开发的朋友不容错过。

6、 http://www.huihoo.com/ ;
灰狐动力网站,一个专业的中间件网站,虽然不是专业的Java网站,但是在J2EE企业应用技术方面有深厚的造诣。

7、 http://www.theserverside.com/home/ ;(英文)
TheServerSide是一个著名的专门面向Java Server端应用的网站。

8、 http://www.javaresearch.org/ ;
Java研究组织,有很多优秀的Java方面的文章和教程,特别是在JDO方面的文章比较丰富。

9、 http://www.cnjsp.org/ ;
JSP技术网站,有相当多的Java方面的文章和资源。

10、 http://www.jdon.com/ ;
Jdon论坛,是一个个人性质的中文J2EE专业技术论坛,在众多的Java的中文论坛中,Jdon一个是技术含量非常高,帖子质量非常好的论坛。

11、 http://sourceforge.net/ ;
SourgeForge是一个开放源代码软件的大本营,其中也有非常非常丰富的Java的开放源代码的著名的软件。

和Java类路径(classpath)打交道的过程中,开发者偶尔会遇到麻烦。这是因为,类装载器实际装入的是哪一个类有时并不显而易见,当应用程序的classpath包含大量的类和目录时,情况尤其严重。本文将提供一个工具,它能够显示出被装入类文件的绝对路径名。

  一、Classpath基础

  Java虚拟机(JVM)借助类装载器装入应用程序使用的类,具体装入哪些类根据当时的需要决定。CLASSPATH环境变量告诉类装载器到哪里去寻找第三方提供的类和用户定义的类。另外,你也可以使用JVM命令行参数-classpath分别为应用程序指定类路径,在-classpath中指定的类路径覆盖CLASSPATH环境变量中指定的值。

  类路径中的内容可以是:文件的目录(包含不在包里面的类),包的根目录(包含已打包的类),包含类的档案文件(比如.zip文件或者.jar文件)。在Unix家族的系统上,类路径的各个项目由冒号分隔,在MS Windows系统上,它们由分号分隔。

  类装载器以委托层次的形式组织,每一个类装载器有一个父类装载器。当一个类装载器被要求装载某个类时,它在尝试自己寻找类之前会把请求先委托给它的父类装载器。系统类装载器,即由安装在系统上的JDK或JRE提供的默认类装载器,通过CLASSPATH环境变量或者-classpath这个JVM命令行参数装入第三方提供的类或者用户定义的类。系统类装载器委托扩展类装载器装入使用Java Extension机制的类。扩展类装载器委托自举类装载器(bootstrap class loader)装入核心JDK类。

  你可以自己开发特殊的类装载器,定制JVM如何动态地装入类。例如,大多数Servlet引擎使用定制的类装载器,动态地装入那些在classpath指定的目录内发生变化的类。

  必须特别注意的是(也是令人吃惊的是),类装载器装入类的次序就是类在classpath中出现的次序。类装载器从classpath的第一项开始,依次检查每一个设定的目录和压缩文件,尝试找出待装入的类文件。当类装载器第一次找到具有指定名字的类时,它就把该类装入,classpath中所有余下的项目都被忽略。

  看起来很简单,对吧?

  二、可能出现的问题

  不管他们是否愿意承认,初学者和富有经验的Java开发者都一样,他们都曾经在某些时候(通常是在那些最糟糕的情形下)被冗长、复杂的classpath欺骗。应用程序所依赖的第三方类和用户定义类的数量逐渐增长,classpath也逐渐成了一个堆积所有可能的目录和档案文件名的地方。此时,类装载器首先装载的究竟是哪一个类也就不再显而易见。如果classpath中包含重复的类入口,这个问题尤其突出。前面已经提到,类装载器总是装载第一个它在classpath中找到的具有合适名字的类,从实际效果看,它“隐藏”了其他具有合适名字但在classpath中优先级较低的类。

  如果不小心,你很容易掉进这个classpath的陷阱。当你结束了一天漫长的工作,最后为了让应用程序使用最好、最新的类,你把一个目录加入到了classpath,但与此同时,你却忘记了:在classpath的另一个具有更高优先级的目录下,存放着该类的另一个版本!

三、一个简单的classpath工具

  优先级问题是扁平路径声明方法与生俱来固有的问题,但它不是只有Java的classpath才有的问题。要解决这个问题,你只需站到富有传奇色彩的软件巨构的肩膀上:Unix操作系统有一个which命令,在命令参数中指定一个名字,which就会显示出当这个名字作为命令执行时执行文件的路径名。实际上,which命令是分析PATH变量,然后找出命令第一次出现的位置。对于Java的类路径管理来说,这应该也是一个好工具。在它的启发之下,我着手设计了一个Java工具JWhich。这个工具要求指定一个Java类的名字,然后根据classpath的指引,找出类装载器即将装载的类所在位置的绝对路径。

  下面是一个JWhich的使用实例。它显示出当Java类装载器装载com.clarkware.ejb.ShoppingCartBean类时,该类第一次出现位置的绝对路径名,查找结果显示该类在某个目录下:


> java JWhich com.clarkware.ejb.ShoppingCartBean

Class ‘com.clarkware.ejb.ShoppingCartBean’ found in
‘/home/mclark/classes/com/clarkware/ejb/ShoppingCartBean.class’


  下面是第二个JWhich的使用实例。它显示出当Java类装载器装载javax.servlet.http.HttpServlet类时,该类第一次出现位置的绝对路径名,查找结果显示该类在某个档案文件中:


> java JWhich javax.servlet.http.HttpServlet

Class ‘javax.servlet.http.HttpServlet’ found in
‘file:/home/mclark/lib/servlet.jar!/javax/servlet/http/HttpServlet.class’


  四、JWhich的工作过程

  要精确地测定classpath中哪一个类先被装载,你必须深入到类装载器的思考方法。事实上,具体实现的时候并没有听起来这么复杂——你只需直接询问类装载器就可以了!


1: public class JWhich {
2:
3: /**
4: * 根据当前的classpath设置,
5: * 显示出包含指定类的类文件所在
6: * 位置的绝对路径
7: *
8: * @param className <类的名字>
9: */
10: public static void which(String className) {
11:
12: if (!className.startsWith(“/”)) {
13: className = “/” + className;
14: }
15: className = className.replace(‘.’, ‘/’);
16: className = className + “.class”;
17:
18: java.net.URL classUrl =
19: new JWhich().getClass().getResource(className);
20:
21: if (classUrl != null) {
22: System.out.println(“\nClass ‘” + className +
23: “‘ found in \n’” + classUrl.getFile() + “‘”);
24: } else {
25: System.out.println(“\nClass ‘” + className +
26: “‘ not found in \n’” +
27: System.getProperty(“java.class.path”) + “‘”);
28: }
29: }
30:
31: public static void main(String args[]) {
32: if (args.length > 0) {
33: JWhich.which(args[0]);
34: } else {
35: System.err.println(“Usage: java JWhich “);
36: }
37: }
38: }


  首先,你必须稍微调整一下类的名字以便类装载器能够接受(12-16行)。在类的名字前面加上一个“/”表示要求类装载器对classpath中的类名字进行逐字精确匹配,而不是尝试隐含地加上调用类的包名字前缀。把所有“.”转换为“/”的目的是,按照类装载器的要求,把类名字格式化成一个合法的URL资源名。

  接下来,程序向类装载器查询资源,这个资源的名字必须和经过适当格式化的类名字匹配(18-19行)。每一个Class对象维护着一个对装载它的ClassLoader对象的引用,所以这里是向装载JWhich类的类装载器查询。Class.getResource()方法实际上委托装入该类的类装载器,返回一个用于读取类文件资源的URL;或者,当指定的类名字不能在当前的classpath中找到时,Class.getResource()方法返回null。

  最后,如果当前的classpath中能够找到指定的类,则程序显示包含该类的类文件所在位置的绝对路径名(21-24行)。作为一种调试辅助手段,如果当前classpath中不能找到指定的类,则程序获取java.class.path系统属性并显示当前的classpath(24-28行)。

  很容易想象,在使用Servlet引擎classpath的Java Servlet中,或者在使用EJB服务器classpath的EJB组件中,上面这段简单的代码是如何运作。例如,如果JWhich类是由Servlet引擎的定制类装载器装入,那么程序将用Servlet引擎的类装载器去寻找指定的类。如果Servlet引擎的类装载器不能找到类文件,它将委托它的父类装载器。一般地,当JWhich被某个类装载器装入时,它能够找出当前类装载器以及所有其父类装载器所装入的所有类。

  【结束语】

  如果需要是所有发明之母,那么帮助我们管理Java类路径的工具可以说迟到了很长时间。Java新闻组和邮件列表中充塞着许多有关classpath的问题,现在JWhich为我们提供了一个简单却强大的工具,帮助我们在任何环境中彻底玩转Java类路径。


常常在网上看到有人询问:如何把 java 程序编译成 .exe 文件。通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像.chm 文档一样双击运行了;而另一种是使用 JET 来进行 编译。但是 JET 是要用钱买的,而且据说 JET 也不是能把所有的 Java 程序都编译成执行文件,性能也要打些折扣。所以,使用制作可执行 JAR 文件包的方法就是最佳选择了,何况它还能保持 Java 的跨平台特性。

  下面就来看看什么是 JAR 文件包吧:

  1. JAR 文件包

  JAR 文件就是 Java Archive File,顾名思意,它的应用是与 Java 息息相关的,是 Java 的一种文档格式。JAR 文件非常类似 ZIP 文件——准确的说,它就是 ZIP 文件,所以叫它文件包。JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中,包含了一个 META-INF/MANIFEST.MF 文件,这个文件是在生成 JAR 文件的时候自动创建的。举个例子,如果我们具有如下目录结构的一些文件:

  ==

  `– test

    `– Test.class

  把它压缩成 ZIP 文件 test.zip,则这个 ZIP 文件的内部目录结构为:

  test.zip

  `– test

    `– Test.class

  如果我们使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,则这个 JAR 文件的内部目录结构为:

  test.jar

  |– META-INF

  |  `– MANIFEST.MF

  `– test

    `–Test.class

  2. 创建可执行的 JAR 文件包

  制作一个可执行的 JAR 文件包来发布你的程序是 JAR 文件包最典型的用法。

  Java 程序是由若干个 .class 文件组成的。这些 .class 文件必须根据它们所属的包不同而分级分目录存放;运行前需要把所有用到的包的根目录指定给 CLASSPATH 环境变量或者 java 命令的 -cp 参数;运行时还要到控制台下去使用 java 命令来运行,如果需要直接双击运行必须写 Windows 的批处理文件 (.bat) 或者 Linux 的 Shell 程序。因此,许多人说,Java 是一种方便开发者苦了用户的程序设计语言。

  其实不然,如果开发者能够制作一个可执行的 JAR 文件包交给用户,那么用户使用起来就方便了。在 Windows 下安装 JRE (Java Runtime Environment) 的时候,安装文件会将 .jar 文件映射给 javaw.exe 打开。那么,对于一个可执行的 JAR 文件包,用户只需要双击它就可以运行程序了,和阅读 .chm 文档一样方便 (.chm 文档默认是由 hh.exe 打开的)。那么,现在的关键,就是如何来创建这个可执行的 JAR 文件包。

  创建可执行的 JAR 文件包,需要使用带 cvfm 参数的 jar 命令,同样以上述 test 目录为例,命令如下:

jar cvfm test.jar manifest.mf test

  这里 test.jar 和 manifest.mf 两个文件,分别是对应的参数 f 和 m,其重头戏在 manifest.mf。因为要创建可执行的 JAR 文件包,光靠指定一个 manifest.mf 文件是不够的,因为 MANIFEST 是 JAR 文件包的特征,可执行的 JAR 文件包和不可执行的 JAR 文件包都包含 MANIFEST。关键在于可执行 JAR 文件包的 MANIFEST,其内容包含了 Main-Class 一项。这在 MANIFEST 中书写格式如下:

  Main-Class: 可执行主类全名(包含包名)

  例如,假设上例中的 Test.class 是属于 test 包的,而且是可执行的类 (定义了 public static void main(String[]) 方法),那么这个 manifest.mf 可以编辑如下:

Main-Class: test.Test <回车>

  这个 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且该行以一个回车符结束即可。创建了 manifest.mf 文件之后,我们的目录结构变为:

  ==

  |– test

  |  `– Test.class

  `– manifest.mf

  这时候,需要到 test 目录的上级目录中去使用 jar 命令来创建 JAR 文件包。也就是在目录树中使用“==”表示的那个目录中,使用如下命令:

jar cvfm test.jar manifest.mf test

  之后在“==”目录中创建了 test.jar,这个 test.jar 就是执行的 JAR 文件包。运行时只需要使用 java -jar test.jar 命令即可。

  需要注意的是,创建的 JAR 文件包中需要包含完整的、与 Java 程序的包结构对应的目录结构,就像上例一样。而 Main-Class 指定的类,也必须是完整的、包含包路径的类名,如上例的 test.Test;而且在没有打成 JAR 文件包之前可以使用 java <类名> 来运行这个类,即在上例中 java test.Test 是可以正确运行的 (当然要在 CLASSPATH 正确的情况下)。

3. jar 命令详解

  jar 是随 JDK 安装的,在 JDK 安装目录下的 bin 目录中,Windows 下文件名为 jar.exe,Linux 下文件名为 jar。它的运行需要用到 JDK 安装目录下 lib 目录中的 tools.jar 文件。不过我们除了安装 JDK 什么也不需要做,因为 SUN 已经帮我们做好了。我们甚至不需要将 tools.jar 放到 CLASSPATH 中。

  使用不带任何的 jar 命令我们可以看到 jar 命令的用法如下:

  jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目录] 文件名 …

  其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一个,它们分别表示:

   -c 创建新的 JAR 文件包

   -t 列出 JAR 文件包的内容列表

   -x 展开 JAR 文件包的指定文件或者所有文件

   -u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中)

     [vfm0M] 中的选项可以任选,也可以不选,它们是 jar 命令的选项参数

   -v 生成详细报告并打印到标准输出

   -f 指定 JAR 文件名,通常这个参数是必须的

   -m 指定需要包含的 MANIFEST 清单文件

   -0 只存储,不压缩,这样产生的 JAR 文件包会比不用该参数产生的体积大,但速度更快

   -M 不产生所有项的清单(MANIFEST〕文件,此参数会忽略 -m 参数

     [jar-文件] 即需要生成、查看、更新或者解开的 JAR 文件包,它是 -f 参数的附属参数

     [manifest-文件] 即 MANIFEST 清单文件,它是 -m 参数的附属参数

     [-C 目录] 表示转到指定目录下去执行这个 jar 命令的操作。它相当于先使用 cd 命令转该目录下再执行不带 -C 参数的 jar 命令,它只能在创建和更新 JAR 文件包的时候可用。  

  文件名 … 指定一个文件/目录列表,这些文件/目录就是要添加到 JAR 文件包中的文件/目录。如果指定了目录,那么 jar 命令打包的时候会自动把该目录中的所有文件和子目录打入包中。

  下面举一些例子来说明 jar 命令的用法:

  1) jar cf test.jar test

  该命令没有执行过程的显示,执行结果是在当前目录生成了 test.jar 文件。如果当前目录已经存在 test.jar,那么该文件将被覆盖。

  2) jar cvf test.jar test

  该命令与上例中的结果相同,但是由于 v 参数的作用,显示出了打包过程,如下:

  标明清单(manifest)

  增加:test/(读入= 0) (写出= 0)(存储了 0%)

  增加:test/Test.class(读入= 7) (写出= 6)(压缩了 14%)

  3) jar cvfM test.jar test

  该命令与 2) 结果类似,但在生成的 test.jar 中没有包含 META-INF/MANIFEST 文件,打包过程的信息也略有差别:

  增加:test/(读入= 0) (写出= 0)(存储了 0%)

  增加:test/Test.class(读入= 7) (写出= 6)(压缩了 14%)

  4) jar cvfm test.jar manifest.mf test

  运行结果与 2) 相似,显示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 内容不同,是包含了 manifest.mf 的内容

  5) jar tf test.jar

  在 test.jar 已经存在的情况下,可以查看 test.jar 中的内容,如对于 2) 和 3) 生成的 test.jar 分别应该此命令,结果如下;

  对于 2)

  META-INF/

  META-INF/MANIFEST.MF

  test/

  test/Test.class

  对于 3)

  test/

  test/Test.class

  6) jar tvf test.jar

  除显示 5) 中显示的内容外,还包括包内文件的详细信息,如:

  0 Wed Jun 19 15:39:06 GMT 2002 META-INF/

  86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF

  0 Wed Jun 19 15:33:04 GMT 2002 test/

  7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class

  7) jar xf test.jar

  解开 test.jar 到当前目录,不显示任何信息,对于 2) 生成的 test.jar,解开后的目录结构如下:

  ==

  |– META-INF

  |  `– MANIFEST

  `– test

    `–Test.class

jar xvf test.jar

  运行结果与 7) 相同,对于解压过程有详细信息显示,如:

  创建:META-INF/

  展开:META-INF/MANIFEST.MF

  创建:test/

  展开:test/Test.class

  9) jar uf test.jar manifest.mf

  在 test.jar 中添加了文件 manifest.mf,此使用 jar tf 来查看 test.jar 可以发现 test.jar 中比原来多了一个 manifest。这里顺便提一下,如果使用 -m 参数并指定 manifest.mf 文件,那么 manifest.mf 是作为清单文件 MANIFEST 来使用的,它的内容会被添加到 MANIFEST 中;但是,如果作为一般文件添加到 JAR 文件包中,它跟一般文件无异。

  10) jar uvf test.jar manifest.mf

  与 9) 结果相同,同时有详细信息显示,如:

  增加:manifest.mf(读入= 17) (写出= 19)(压缩了 -11%)

  4. 关于 JAR 文件包的一些技巧

  1) 使用 unzip 来解压 JAR 文件

  在介绍 JAR 文件的时候就已经说过了,JAR 文件实际上就是 ZIP 文件,所以可以使用常见的一些解压 ZIP 文件的工具来解压 JAR 文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等来解压是因为它们解压比较直观,方便。而使用 unzip,则是因为它解压时可以使用 -d 参数指定目标目录。

  在解压一个 JAR 文件的时候是不能使用 jar 的 -C 参数来指定解压的目标的,因为 -C 参数只在创建或者更新包的时候可用。那么需要将文件解压到某个指定目录下的时候就需要先将这具 JAR 文件拷贝到目标目录下,再进行解压,比较麻烦。如果使用 unzip,就不需要这么麻烦了,只需要指定一个 -d 参数即可。如:

  unzip test.jar -d dest/

  2) 使用 WinZip 或者 WinRAR 等工具创建 JAR 文件

  上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR 等工具创建所需要 ZIP 压缩包,再往这个 ZIP 压缩包中添加一个包含 MANIFEST 文件的 META-INF 目录即可。对于使用 jar 命令的 -m 参数指定清单文件的情况,只需要将这个 MANIFEST 按需要修改即可。

  3) 使用 jar 命令创建 ZIP 文件

  有些 Linux 下提供了 unzip 命令,但没有 zip 命令,所以需要可以对 ZIP 文件进行解压,即不能创建 ZIP 文件。如要创建一个 ZIP 文件,使用带 -M 参数的 jar 命令即可,因为 -M 参数表示制作 JAR 包的时候不添加 MANIFEST 清单,那么只需要在指定目标 JAR 文件的地方将 .jar 扩展名改为 .zip 扩展名,创建的就是一个不折不扣的 ZIP 文件了,如将上一节的第 3) 个例子略作改动:

  jar cvfM test.zip test