Yanchuan 的个人资料GillBates: I lead, other...照片日志列表更多 工具 帮助

日志


推荐Mac小软:DaisyDisk

分析磁盘使用的,data visualization做的无比漂亮,扫描时也是透明的。
DaisyDisk1[1]扫描后
DaisyDisk2[3]官网:http://www.daisydiskapp.com/
售价:19.95 usd,很超值:D  

在iPhone或者iTouch上用Keynote Remote控制Keynote播放

最近才发现的一个小tip,从此不用再多带一个Apple Remote了。
中心思想:通过MBP自己创建点对点的网络,让iTouch连上。
1,创建网络,如图箭头处:英文版这里是“Create Network …”
Bildschirmfoto%202009-10-06%20um%2012.40.28%20AM[1]2,要是临时讲演用,就不需要密码了,直接ok。
3,打开你的keynote,点 preference ,然后切换到 remote control,
Bildschirmfoto%202009-10-06%20um%2012.35.36%20AM[1]4,在iTouch上启用wifi,并加入才创建的网络。然后进入到Keynote Remote,点左上角的settings。
kr-1[1]
然后创建一个link,期间会在iTouch上生成一个4位数密码,在keynote(第三步)里输入就配对成功了。
Bildschirmfoto%202009-10-06%20um%2012.31.08%20AM[1] 5,配对成功后,Keynote Remote自动返回首页,就可以开始播放了:D
kr-2[1]请勿转载,否则一律跨国追捕!

软件推荐:Visor

visor[1]

作用:可以用快捷键从上往下滑动出terminal,失去焦点时自动隐藏。。。酷的一塌糊涂。。。
官网:http://visor.binaryage.com/

Digg This

iPhone web开发应知应会

  1. 必用到的meta标签
    <meta name="viewport" content="width=device-width, userscalable=no initial-scale = 1.0" />
    <link rel="apple-touch-icon" href="/my_custom_icon.png"/>   //当添加标签到homescreen的时候的图标
    <meta name="apple-mobile-web-app-status-bar-style"
    content="black" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <body onorientationchange="myOrientationChangeFunction()">
    <meta name="format-detection" content="telephone=no" />
  2. 必用到的css属性
    text-shadow
    text-fill-color
    text-stroke
    -webkit-tap-highlight-color
    -webkit-box-shadow
    -webkit-border-radius
    -webkit-border-image
  3. 最好自己写的event handler
    touchstart //当手指接触屏幕时触发
    touchend  //当手指离开屏幕时触发
    touchmove  //当已经接触屏幕的手指开始移动后触发
    touchcancel
    gesturestart  //当两个手指接触屏幕时触发
    gesturechange  //当两个手指接触屏幕后开始移动时触发
    gestureend  //
  4. 离线存储
    写一个manifest文件,然后在html的属性里引用:<html manifest="demo.manifest">
    CACHE MANIFEST
    demoimages/clownfish.jpg
    demoimages/clownfishsmall.jpg
    demoimages/flowingrock.jpg
    demoimages/flowingrocksmall.jpg
    demoimages/stones.jpg
    demoimages/stonessmall.jpg
  5. 暴露native iphone 的一些功能
    秘密就在于webview的windowScriptObject

    @interface BasicAddressBook: NSObject {}
    + (BasicAddressBook *)addressBook;
    - (NSString *)nameAtIndex:(int)index;
    @end
    BasicAddressBook *littleBlackBook = [BasicAddressBook addressBook];
    id win = [webView windowScriptObject];
    [win setValue:littleBlackBook forKey:@"AddressBook"];
    function printNameAtIndex(index) {
    var myaddressbook = window.AddressBook;
    var name = myaddressbook.nameAtIndex_(index);
    document.write(name);
    }
Digg This

关于Google Buffers序列化,JVM的classpath动态添加,jQuery小技巧,webkit下css3的硬件加速动画

1,最近google发布了一个序列化的库Protocol Buffers,尝试了下,在android下的表现很好。
首先看这个lib的大小
y1pOVck4VUZmLvya7bBxJrxkBss5UiRTpKi924pZuEH7Tyd7X10auP9Q9yVAkIRh9QEVKPkMyMyfiAC2H-r0Ou74VPk5shEWUhu[1] 
然后用官网的json库和google buffer在android上随机测试了一组性能,
下面是json的代码

   1. Item[] itemlist = new Item[10];  
   2. JSONArray items = new JSONArray(new String(buffer.toByteArray()));  
   3. final int max = items.length();  
   4. for (int i=0; i < max; i++){  
   5.     Item item  = new Item();  
   6.     item.title = items.getJSONObject(i).getString("title");  
   7.     item.text  = items.getJSONObject(i).getString("text");  
   8.     item.link  = items.getJSONObject(i).getString("url");  
   9.     item.image = Base64.decode(items.getJSONObject(i).getString("image"));  
  10.     itemlist[i] = item;  
  11. }  

结果:
y1p3qypF4ox7eDAYDggsFodEaV-k6qhP-OFKhdD2SIIYd7mNyC82VozmUhKDDIvMhJJLutx9OPr1Pi1xTAm3W7bKA[1]
明显在android上google buffer是很有优势的,但是这个jar有800k,而json是android sdk自带了已经。

2,关于JVM的动态classpath,很多同学都忽略了,下面的代码可以帮你动态加载lib到classpath里

   1:  URI clientJarUri = DynamicClasspath.class.getProtectionDomain().getCodeSource().getLocation().toURI();
   2:  Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] {URL.class});
   3:  addURL.setAccessible(true);
   4:  ClassLoader classLoader = ClassLoader.getSystemClassLoader();
   5:  for( URL jarUrl : classpathUrlsToAdd ){
   6:  addURL.invoke(classLoader, jarUrl);
   7:  }

3,jQuery的一些小技巧
3.1 最快选中父元素 $("#searchBox").closest("div"); 
3.2 Document Ready的另外一种写法

  1. //Instead of
  2. $(document).ready(function() {  
  3. //document ready
  4. });  
  5. //Use
  6. $(function(){  
  7. //document ready
  8. }); 

4,html里做元素的平移动画,传统方法,用timer移动元素的left坐标,但是在iphone的safari里有明显延迟,标准做法是用webkit支持的css来完成变换,这样得到硬件支持,完全无延迟。示例代码:

-webkit-transition: left 250ms ease;
-webkit-transform:translateX(-320px)
 
Digg This

RoR 与敏捷开发

最近1个月再次尝试了一把ROR,感觉在做prototype的时候ROR的优势很明显,但是一旦项目做到一定的规模。RoR和其所鼓吹的敏捷就越发的弱势起来。
1,对一定规模的系统来说,安全性,事物,与各种单元的异构集成服务要求很高,这方面java已经有无数成熟的库,而ruby还在摸索前进。
2,在做prototype的时候ruby的效率的确是分分钟的,但是其代码风格自由随意,一旦代码量大了,维护起来极其困难。

总结来说RoR的快速,很大程序上时因为你无从选择,从而节省了选择的成本,减去了面对种种选择重新学习的时间

Intellij IDEA 小Tips

1,实现eclipse文件保存后自动编译:
安装 Eclipse Mode 插件:http://plugins.intellij.net/plugin/?id=3822

2,编译前忽视其他文件错误
compiler设置里面选择eclipse compiler,然后在Additional command line parameters里加上-proceedOnError。

通过Google Ajax API获取来访用户的地理位置 和计算两地距离

获取来访用户地理位置
原理:google ajax api自动生成google.loader.ClientLocation 函数/数组,包含地理信息。
实现:
1. 引入js:
<script type="text/javascript" src="http://www.google.com/jsapi?key=API_KEY_GOES_HERE"></script>

2. 加入以下代码
if(google.loader.ClientLocation)
{
    visitor_lat = google.loader.ClientLocation.latitude;
    visitor_lon = google.loader.ClientLocation.longitude;
    visitor_city = google.loader.ClientLocation.address.city;
    visitor_region = google.loader.ClientLocation.address.region;
    visitor_country = google.loader.ClientLocation.address.country;
    visitor_countrycode = google.loader.ClientLocation.address.country_code;
}
else
{
    // ClientLocation not found or not populated
    // so perform error handling
}

3. 实际页面效果
继承上述代码后用下列输出
document.getElementById('yourinfo').innerHTML = '<p>Lat/Lon: ' + visitor_lat + ' / ' + visitor_lon + '</p><p>Location: ' + visitor_city + ', ' + visitor_region + ', ' + visitor_country + ' (' + visitor_countrycode + ')</p>';

Lat/Lon: 49.3 / 7.067
Location: Sulzbach/Saar, Saar, Germany (DE)

计算两地距离
1. 初始化geocoder函数:
var geocoder= new GClientGeocoder();

2. 转换string到地理坐标:
var location1;
geocoder.getLocations(document.forms[0].address1.value, function (response){
location1 = {lat: response.Placemark[0].Point.coordinates[1], lon: response.Placemark[0].Point.coordinates[0], address:     response.Placemark[0].address};
}
同理得到location2;
geocoder.getLocations(document.forms[0].address2.value, function (response) {
location2 = {lat: response.Placemark[0].Point.coordinates[1], lon: response.Placemark[0].Point.coordinates[0], address: response.Placemark[0].address};    
}

3. 开始计算
function calculateDistance()
{
try
{
var glatlng1 = new GLatLng(location1.lat, location1.lon);
var glatlng2 = new GLatLng(location2.lat, location2.lon);
var miledistance = glatlng1.distanceFrom(glatlng2, 3959).toFixed(1);
var kmdistance = (miledistance * 1.609344).toFixed(1);
document.getElementById('results').innerHTML = '<strong>Address 1: </strong>' + location1.address + ' (' + location1.lat + ':' + location1.lon + ')<br /><strong>Address 2: </strong>' + location2.address + ' (' + location2.lat + ':' + location2.lon + ')<br /><strong>Distance: </strong>' + miledistance + ' miles (or ' + kmdistance + ' kilometers)';
}
catch (error)
{
alert(error);
}
}

4. 实际效果
Address 1: Peking, China (39.9081726:116.3979471)
Address 2: Frankfurt am Main, Deutschland (50.1115118:8.6805059)
Distance: 4834.5 miles (or 7780.4 kilometers)

最后送几张我关注的Jorge Colombo在iphone上的作品


10 大程序字体

先上我的eclipse和idea里面的截图!

10. Courier
系统默认

9. Andale Mono
稍微好点

8. Monaco
Mac的默认字体。
Monaco

Monaco 9-point, without anti-aliasing
 

7. Profont
 

6. Monofur

5. Proggy

4. Droid Sans Mono

3. Deja Vu Sans Mono

2. Consolas

1. Inconsolata

推荐:Wrox的Professional JavaScript for Web Developers 2nd Edition和How to Be A Even Better Manager

 
Michael Armstrong的书一直是实用速成派的代表。我们这把年龄已经禁不起风险了,领导任何一个中小型Proj之前都要经济搭台,技术唱戏。而场景与场景之间,各种真假面的转换,资源的合理利用,更是成为我每天都需要面对的经典问题。这里,我需要的不是教条,而是可以量化和科学运用的东西。
这个月,事情很多,闲暇期间读完这本《how to be an even better manager》,很多问题迎刃而解,毕竟我做的不是不够好,只是要做的比别人更好。
和几个同学讨论,关于软件定价,纷纷不解,我为什么要卖那么贵?同样的东西,你只有脚踏实地从客户的角度出发,帮他设计,优化流程,确立规范,从灵感到实施全程参与,才能真正的赢得客户,同时也提高了自己。这个时候脑子里完全没有价钱,有的只是客户的利益。毕竟,只要客户赠钱了,那你的一切都没有问题。而我向来认为,我们先是伙伴,再是买卖。
以前做项目,卖的是技术。现在,更多的是卖的思想,技术可以复制,思想不能。也只有有了这个,你做的东西才经的起考验。
同时:强烈推荐所有立志于做Consulting, Proj Leader,CXO的同学通读马克思的《1844年经济学哲学手稿》,我人生第一次有这么强烈的愿望去读这样一篇以前读书时死记硬背的东西,也确实,提高了不少认识。。。读完之后,相信你会和我一样在控制、运营项目,评估、保证软件质量,平衡社会关系,逻辑等方面有不少新的认识。。。
个人心得:我认为老马认为,这世界的逻辑建立在掠夺之上,而掠夺者和被掠夺者都同样不自由。只有超越了对物的臣服,落实到对人之为人的关怀,才有人的自由。同理,我们在采用Object Adapter或者Decorator模式的时候,也会有Object和object之间的继承,实现与依赖。这关系着系统设计出来是否健壮。而只有全盘超越了单纯的oo,把面向过程在恰当的时候融入进来,才会让object之间的互动更为良好,功能更加清晰,整个程序的动态结构也就更有弹性。


这本书很有名,在此号召大家都看看。
不要以为是老瓶装老酒,html5,canvas,js里的oo,闭包,js在各大浏览器里的异常策略,利用BEA的ECMAScript来构建xml,以及新兴的Client-Side storage都是很有趣的东西,值得关注。最后不要忘了就是js的性能和调优迟早成为未来面试中的难题!

JS小技巧:按需加载和延迟加载的小函数+ 推荐Firebug新欢:Widerbug….

为了加速我们的页面下载,除了把import语句从放在页面底部,删除多余的TAB,空格,简短函数/变量名这这俩方法之外,还可以像gmail那样按需延迟加载。下面的代码验证函数是否被加载:
if (myfunction){
  // The function has been loaded
}
else{ // Function has not been loaded yet, so load the javascript.
  $import('http://www.xxx.com/myfile.js');
}

验证完毕后,动态加载

function import(src){
  var scriptElem = document.createElement('script');
  scriptElem.setAttribute('src',src);
  scriptElem.setAttribute('type','text/javascript');
  document.getElementsByTagName('head')[0].appendChild(scriptElem);
}

// import with a random query parameter to avoid caching
function importNoCache(src){
  var ms = new Date().getTime().toString();
  var seed = "?" + ms; 
  $import(src + seed);
}



声明:这不是恶搞。。。一句话总结widerbug就是firebug的宽屏版。。。。
官网:http://www.command-tab.com/2008/01/19/widerbug-widescreen-firebug/
截图:

Intellij IDEA 集成 JavaRebel指南!!!

网上已经有如何在eclipse里集成的教程了,鉴于eclipse已经成为肥猪流/非主流。。。现特上idea集成javarebel指南。
1. 避免idea每次改动后重新打包war

2. 在编译器设置里取消改动后重新部署,并选中编译depenencies

3. 在服务器的VM Parameters里填写如下行:
-noverify
-javaagent:E:/MyJavaLibs/javarebel/javarebel.jar  
-Drebel.struts2-plugin=true 
-Drebel.spring_plugin=true
-Drebel.dirs=E:/Idea.Workspace/HikingWS/out/exploded/HikingWSWeb/WEB-INF/classes  //自行添加多处需要监视改动的路径

现在改程序那速度,杠杠滴!

google.load()

现在大家可以从页面直接从google那载入js啦。

<!-- Always need this javascript --> 
<script src="http://www.google.com/jsapi" type="text/javascript"></script> 
//get the latest moo 
google.load('mootools', '1.2.1'); 
//other examples 
google.load('jquery', '1.3.1'); 
google.load('jqueryui', '1.5.3'); 
google.load('prototype', '1.6.0.3'); 
google.load('scriptaculous', '1.8.2'); 
google.load('mootools', '1.2.1'); 
google.load('dojo', '1.2.3'); 
google.load('swfobject', '2.1'); 
google.load('yui', '2.6.0'); 

Boss探测器 V1.0 问世!

        经过几个月的努力,自己动手实现了一个基于超声波/体温距离探测器+红外线摄像头的老板探测器。
        目前分为2个版本:
        Basic版:当物体进入距离你10米范围内,能自动判定物体接近中,并启动红外线摄像头进行人脸识别。
        Pro版:多了一些摄像头和微型机械臂,能自动多角度进行图像修正,考虑到不同光源的情况下,单摄像头的图片质量可能不够理想。同时提供体温探测作为辅助手段。
        Basic版硬件成本大概1000RMB左右,实战效果一级棒,可支持蓝牙,以太网,USB,串口连接。注:蓝牙连接时,需要2节AA电池独立供电。
        传感器大小:42mm w x 21mm d x 16mm h
        注:    程序提供JAVA版和PYTHON版,以及MAC特别版,实现全系列跨平台。
        欢迎有兴趣的同学联系我进行商业洽谈,包装上市。:D

全家福:

焊接中:

超声波传感器:
 
自己买的导线和引脚

新书推荐:Practical API Design: Confessions of a Java™ Framework Architect

 
已于0714上市。
简介:
You might think more than enough design books exist in the programming world already. In fact, there are so many that it makes sense to ask why you would read yet another. Is there really a need for yet another design book? In fact, there is a greater need than ever before, and Practical API Design: Confessions of a Java Framework Architect fills that need!

    * Teaches you how to write an API that will stand the test of Time
    * Written by the designer of the NetBeans API at Sun
    * Based on best practices, scalability, and API design patterns

What you’ll learn

    * What an API is and what the theories are behind good API design
    * When and why to build an API
    * API design patterns applicable to all programming languages, especially modern, object–oriented languages
    * How to optimize and test APIs

Who is this book for?

This book is recommended to every API architect who prefers a bit more engineering design over a purely artistic one.

Author Information
  Jaroslav Tulach
  Jaroslav Tulach is the founder and initial architect of NetBeans, later acquired by Sun. As creator of the technology behind NetBeans, he is still with the project to find ways to improve the design skills among all the programmers who contribute to the success of NetBeans open source project.

我们为什么要学习汇编

前因:http://dreamramon.spaces.live.com/blog/cns!9615FB50FFDBCFD3!2387.entry

好,我们现在来科学的解释为什么三种方法速度不一样。Java程序如下:

public class Test{

    public static void main(String args[]) {
        int A = 200;
        int B = 300;
        int C;
    final int loop = 100000001;

        System.out.println("Object creating...");
        System.out.println("A=" + A);
        System.out.println("B=" + B);
        System.out.println("==================");
        System.out.println("Method 1 starting...");

        Long begin=System.nanoTime();

    for(int i = 0; i< loop; ++i) {
            C = A;
            A = B;
            B = C;
    }

        Long end=System.nanoTime();

        System.out.println("A=" + A);
        System.out.println("B=" + B);
        System.out.println("Start Time: "+begin);
        System.out.println("End Time: "+end);
        System.out.println("Last Time: "+(end-begin));
        System.out.println("==================");
        System.out.println("Method 2 starting...");

        begin=System.nanoTime();

    for(int i = 0; i < loop; ++i){
            A = A + B;
            B = A - B;
            A = A - B;
    }

        end=System.nanoTime();

        System.out.println("A=" + A);
        System.out.println("B=" + B);
        System.out.println("Start Time: "+begin);
        System.out.println("End Time: "+end);
        System.out.println("Last Time: "+(end-begin));
        System.out.println("==================");
        System.out.println("Method 3 starting...");

        begin=System.nanoTime();

    for(int i = 0; i < loop; ++i){
            A = A ^ B;
            B = A ^ B;
            A = A ^ B;
    }
    end = System.nanoTime();

        System.out.println("A=" + A);
        System.out.println("B=" + B);
        System.out.println("Start Time: "+begin);
        System.out.println("End Time: "+end);
        System.out.println("Last Time: "+(end-begin));
        System.out.println("==================");
    }

編譯出的Bytecode:

方法1:

93: iload 6
95: ldc #16; //int 100000001
97: if_icmpge 112
100: iload_1
101: istore_3
102: iload_2
103: istore_1
104: iload_3
105: istore_2
106: iinc 6, 1
109: goto 93

方法2:

284: iload 7
286: ldc #16; //int 100000001
288: if_icmpge 309
291: iload_1
292: iload_2
293: iadd
294: istore_1
295: iload_1
296: iload_2
297: isub
298: istore_2
299: iload_1
300: iload_2
301: isub
302: istore_1
303: iinc 7, 1
306: goto 284

方法3:

481: iload 7
483: ldc #16; //int 100000001
485: if_icmpge 506
488: iload_1
489: iload_2
490: ixor
491: istore_1
492: iload_1
493: iload_2
494: ixor
495: istore_2
496: iload_1
497: iload_2
498: ixor
499: istore_1
500: iinc 7, 1
503: goto 481

可以看出第一种方法在Stack based VM上编译的指令更简单一些。
运行的结果:

$java -hotspot -classpath ./ Test
Object creating...
A=200
B=300
==================
Method 1 starting...
A=300
B=200
Start Time: 21265732594226
End Time: 21265903045778
Last Time: 170451552
==================
Method 2 starting...
A=200
B=300
Start Time: 21265904274984
End Time: 21266211578007
Last Time: 307303023
==================
Method 3 starting...
A=300
B=200
Start Time: 21266212842414
End Time: 21266516976319
Last Time: 304133905
==================

Eclipse 3.4 代号Ganymede 新特性一窥

虽然myeclipse要这个月中的7.0才支持eclipse 3.4,但是Ramon大大最终还是迫于压力提早升级了eclipse,下面是一些网上找来的好用的新特性:

eclipse 3.4 代号为ganymede (G anymede (英语发音"GAN uh meed")为最大的木星已知卫星,也是第七颗发现的木星卫星,在伽利略发现的卫星中离木星第三近,在希腊神话中 Ganymede是一个特洛伊美人的男孩(一个美少男),被宙斯带去给众神斟酒)。

1,面包屑
其实就是当前类到项目(project)的路径,其中包括包和文件夹。 另外,使用者还可以自由地在同一路径下的某个节点处,纵向切换到其他元素。
 
在节点所在位置做一些操作,比如在同级新增一个类

纵向切换元素

2,针对有问题的代码,只要鼠标移动上去,就能提示解决方案信息

3,万能的快速协助(quick assist)
只要在任何代码处,按 ctrl + 1,就有可能出现相关的提示,预测你的下一步动作。
创建getter 和 setter
 
抽取方法

将低性能的字符串拼接,改用StringBuilder

将字符串拼接改用MessageFormat

4,按保存时,自动格式化代码(分格式化全文和格式化修改的代码)
省去了,保存前,按ctrl + shift + f 的时间。

5,当前元素的高亮功能,根据元素是被引用还是赋值(读或写),来 区分 不同的颜色 。

6,annotation 格式化
    * Annotations on members:

    * Annotations on parameters:

    * Annotations on local variables:

7, Junit 支持对线程内每个帧(方法)的调用时间输出

8,在outline里,支持对同一个类中,方法的重排序

9,查找某个元素的调用层次,支持更多,更细的内容,包括成员变量访问等,call hierarchy

10,更多的搜索选项

11,加强了debug 变量查看功能,不需要再按 ctrl + shift + i 来查看变量的值

12,新增模拟服务端监听的debug功能

Something to Think About

There are two ways of constructing a software design: one way is to make it so simple that there are obviously no deficiencies; the other is to make it so complicated that there are no obvious deficiencies.
—C. A. R. Hoare

Diablo 3: The heavens shall tremble!


想不到今天我们可爱的Blizzard居然放出了DIABLO 3的视频和原画。。。再度震惊。。。回想起了当年和TH在工作室利用实验室的电脑联diablo的热血情景。。。因为学校晚上是有宵禁的。。。如何避开学校守卫等都成了一系列有趣的要素。。。
游戏原画我已上传我BLOG,要高分辨率的同学可以自己批量添加如下地址到自己的下载程序里。
http://www.blizzard.com/diablo3/_images/artwork/ss1-hires.jpg
http://www.blizzard.com/diablo3/_images/artwork/ss2-hires.jpg

。。
。。。
http://www.blizzard.com/diablo3/_images/artwork/ss47-hires.jpg
游戏视频下载:http://us.media.blizzard.com/1901200114/_video/gameplay/diablo3-gameplay-en-US.flv


官方视频下载器:
实际游戏:http://us.media.blizzard.com/1901200114/_video/downloaders/gameplaytrailer/Diablo3-gameplaytrailer_en-US-downloader.exe
开场CG:http://us.media.blizzard.com/1901200114/_video/downloaders/cinematictrailer/Diablo3-cinematictrailer_en-US-downloader.exe
设定:http://us.media.blizzard.com/1901200114/_video/downloaders/artworktrailer/Diablo3-artworktrailer_en-US-downloader.exe

推荐:How Tomcat Works


今年已经过半了,JAVA类除了一本Effective JAVA 2ND 外还没啥重量级的好书。最近在给自己的WEB应用调优,居然发现很多市场上的container都提供eclipse plugin方便debug。而一直以来http://www.w3.org/Protocols/HTTP/1.1/rfc2616.pdf 一百多页的HTTP 1.1规范都没心思看。这次google到这本书确实不错,全书语言通俗易懂。第一章,作者从解释HTTP开始到JAVA SOCKET,带领读者建立一个超轻量级的HTTP SERVER。第二章,解释了如何为服务器上的静态资源创建request和response 对象。第三,四章,揭示了TOMCAT 4的connector原理。第五章讨论了容器的原理和他的实现org.apache.catalina。第六章,蛮有趣的,说明了J2EE怎么处理对象的生命周期。第十一章和十二章属于实用型,介绍了filter和context。其他的还未读。。就不做介绍了。。
后记:虽然TOMCAT现在没啥用,但是好在简单,作为新手入门的PROJ不错。源码结构和清晰,命名也易读,再配合这本书,更容易让你提升J2EE优化的能力。