todayx.org
todayx.org
posts - 39,comments - 60,trackbacks - 0
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
     其实写这篇博客的想法在年前已经有了,但一直在犹豫要不要写,一是因为写出来肯定会有人骂的了,刚过完春节的,在自己地头找骂,实在是晦气;二是因为我对 行业趋势的眼光向来不准,估计今天的想法也是十有八九会错,错了日后自己的看着也不爽。但是又觉得如果心里有想法,不记录下来,思绪就飘远了,年代久了之 后,都忘记自己曾经也有过“看法”,应该会为自己的庸碌后悔吧?所以还是写了。写了归写了,请各位看官往下读之前,先整理好心情,做到:一是自己对世界有 自己的看法;二是认同别人的看法可以跟自己不同;三是对别人的看法跟自己不同时不要生气因为气的是你自己别人替不了。如果做到了这三点,再往下读,因为下 文的观点会很偏激、很有态度,我欢迎你留言讨论、发表不同的见解,如果纯粹是谩骂(或有很多脏词),建议你自己开一篇博客或发到你的微博,不要评论本文, 因为我会删除“纯粹是谩骂(或有很多脏词)”的评论。

ActionScript/MXML

其实就是说 Adobe Flash 平台不值得进入。在 2011 年,Flash 终于能够开发 iOS/Android 应用,再加上网页游戏市场火爆,估计很多人会想要进入这个平台。但我有不同的看法,列几点理由:
1、 Adobe 是市场导向的,没有技术领袖气质。视频网站兴起后,Flash Player 的新版本就加强视频播放;网页游戏兴起后,新版本就加强图形渲染;移动设备开发兴起后,新版本就是能够运行在更多的平台上。一直在跟随,从来不能领导;选 择 Flash 平台就意味着你永远都不能走在时代前缘,只能吃别人吃剩下的;选择 Flash 平台就意味着你最急切的需求无法满足,比如最近他们都在忙着支持移动设备,我们做网页游戏的希望他们加强实时性小数据包网络传输的需求就根本没有人理会。
2、 HTML5 出来以后,Adobe 这个本来也没有多少技术人员的公司还分心去支持它,出把 swf 转为 html+js+css 工具,出图形化 html5+css3+js 编程的工具。它乐于革掉自己的命,因为它只是个卖工具的,支持 html5 就像是 photoshop 支持多一种图像格式;但是程序员你呢,你被革命后你的未来在哪里,见过当年的“中年下岗工人”不?
3、从 ActionScript 3 发布之后,这门语言基本上没有什么变化。你看从 Flash Player 9 发布 AS3 以来,连 C++、C 语言都出了新的标准,java/c# 这类有大公司支持的语言变化巨大,甚至 python 也出了 python 3,更别提 google 公司新出的 go 和 dart 两门优秀的语言。AS3 作为 ECMAScript 的一种方言,现在 ECMA-262 都发布到 5.1 版本了,它仍然没有想要跟进的样子。
4、Flex SDK 类库狗血地照抄了早期版本的 java 类库的设计,连缺陷也照抄不误。你有多少次为了截取 Array 的一部分元素而去看它的手册的?这也就算了,还有一堆的 bugs。你知不知道 Application.application 是会变的?
5、 虚拟机方面,javascript 都有了 V8 引擎,而 AVM 还是那个 AVM,无数用户抱怨它慢都没有用的,优先级高的需求永远是更能够直接赚钱的特性。选择 Flash 就好像你是一个赛车手选了一辆小马力的车,虽然你弯道转得很好,也从不撞车,但可能一辆大马力的车还是从容地超越你。js 有了 V8 后开发出了 Node.js 从前端转到后端,拓展了更加广阔的应用领域,AS 在可以预见的未来,还是逃脱不了“写点小动画”的命运。
6、Stage 3D 不是救世主。不要忘记“low-level”这个定语,如果你直接使用 Stage 3D APIs 来编写程序,你知道那得多么痛苦。选择 A3D、Away3D 能够减轻一定的工作量,但使用开源引擎支持较差、特性较少。客观地说,写 3D 应用现在应该选择 Unity3D 或 Unrel Engine 3,反正它们也能编译成 swf 了。
7、2012 年,网页游戏的冬天不来,起码也是秋天。网页游戏的增长将会放缓,其实从 2011 年第四季度可以看到各大公司都开始压缩产品线,开始不再大量招工,而是转向消化之前已经招到的技术人员。在 2012 年,将会有更多的页游创业公司倒闭或转向移动设备游戏开发,AS 开发人员将会过剩,薪资下降。如果你在 2012 年上半年开始进入 AS 领域,那么下半年刚有所成的时候,就会遇到一大批刚下岗的竞争者,高薪梦肯定要落空。
8、移动设备应用或游戏开发在 2012 年还会受到资本的热捧,但 AS 在这个领域的竞争力我心存疑虑。Flash 优势就是跨平台,而 Unity3D 和 UDK 同样可以跨平台,同样可以使用脚本语言开发,而且性能、效果都更加优秀。随着 Unity3D 和 UDK 可以编译成 swf 在 Flash Player 上运行,学习 AS 的必要性进一步降低。
综上 8 点,可以看到没有技术基因的 Adobe 公司引导下的 Flash 开发路线图缺乏方向,前景模糊,再加上 ActionScript 和 Flex SDK 本身的缺陷,又遇上 Unity3D 和 UDK 这样的强劲外敌,再加上网页游戏大盘下滑,内忧外患之下,实在不是明智之选。Adobe Flash 当然不会死掉,也不会在 2012 年大量失去市场份额,但 Flash 程序员的 2012 不好过,想活得轻松点,注意距离。


线程

线程是指进程中的一个单一顺序的控制流,是操作系统能够调度的最小单位,一个进程中可以有多条线程,分别执行不同的任务。线程有内核线程和用户线程之分,但在本文中仅指内核线程。在软件开发中,使用线程有以下好处:
1、在多核或多路 CPU 的机器上多线程程序能够并发执行,提高运算速度;
2、把 I/O,人机交互等与密集运算部分分离,提升 I/O 吞吐量和增进用户体验。
线程的缺点也很明显:
1、创建一条线程需要较大的内存开销,导致不能创建海量的线程;
2、线程由操作系统调度(分配时间片),线程切换的 CPU 成本比较高,导致大量线程存在时大量 CPU 资源消耗在线程切换上;
3、同一进程的多条线程共享全部系统资源,在多线程间共享资源需要进入加锁,大量的锁开销不提,重要的是加大了编写程序的复杂性,这一点你看看有多少书名含有“多线程”三个字就明白写个多线程应用有多难了;
4、 I/O 方面,多线程帮助有限,以 TCP Socket Server 为例,如果每一个 client connection 由一条专属的线程服务,那么这个 server 可能并发量很难超过 1000。为了进一步解决并发带来的问题,现代服务器都使用 event-driven i/o 了。
event-driven i/o 解决了并发量的问题,但引入了“代码被回调函数分割得零零碎碎”的问题。特别是当 event-driven i/o 跟 multi-threading 结合在一起的时候,麻烦就倍增了。解决这个问题的办法就使用绿色线程,绿色线程可以在同一个进程中成千上万地存在,从而可以在异步 I/O 上封装出同步的 APIs,典型的就是用基于 greenlet + libevent 开发的 python 库 gevent。绿色线程的缺陷在于操作系统不知道它的存在,需要用户进行调度,也就无法利用到多核或多路 CPU 了。为了解决这个问题,很多大牛都做出了巨大的努力,并且成果斐然,scala、google go 和 rust 都较好地解决了问题,下文以 rust 的并发模型为例讲一下。
rust 提出一个 Task 的概念,Task 有一个入口函数,也有自己的栈,并拥有进程堆内存的一部分,为方便理解,你可以把它看作一条绿色线程。rust 进程可以创建成千上万个 Tasks,它们由内建的调度器进行调度,因为 Tasks 之间并不共享数据,只通过 channels/ports 通信,所以它们是可并行程度很高。rust 程序启动时会生成若干条(数量由 CPU 核数决定或运行时指定)线程,这些线程并行执行 Tasks,从而利用多个 CPU 核心。

如 上图,rust 应用程序不停地 spawn 出一个又一个 Tasks,它们由 tasks 调度器管理,在适当的时机,调度器会把某一个 Task 分配给原生线程执行,如果这个 Task 进入 I/O 等待或主动让出 CPU(sleep),那么这个 Task 会被交回给调度器,而相应的原生线程会执行另一个新分派的 Task。尽管使用 rust 编程语言是不能创建线程的(直接调用 C 函数不算),但 rust 应用程序实际上是多线程的(一般情况下),它能够充分地利用多核或多路 CPU。
综上,类似 rust 的 Task 的概念是比线程更好的并发模型,更安全,编写的代码也更加容易维护(关于维护性,我相信写过 gevent 程度或 go 程序的同学会认同的)。线程当然不会消亡,但随着 scala/go/rust 的成熟,在可以预见的将来,线程会退到它呆着的角落:远离普通程序员,只有少数人需要了解它的细节。



C++

C++ 在 2011 年其实风头甚劲,C++2011 标准出台,gcc/msvc/clang 都很快速地支持了许多新特性,新兴的移动设备的性能较差,更是 C++ 的新舞台,在这个时候唱衰 C++,压力很大。我使用 C++ 年头不少,但除了在校的时候写过两个小游戏参加过两个比赛(分别是面向社会和面向大学生的)弄些证书好找工作以外,在工作中只用过大概不到一年半,做《斩 魂》(http://zh.163.com)的早期版本,写了服务器端的几条进程和客户端的 GameAI 部分。经验少,而且写得不好,所以基本上有人在 weibo 上问我 C++ 的问题,我都是转发给 @bnu_chenshuo@miloyip 等真正的行家去回答的。所以实际上今天写这一篇,我底气很是不足,但是朋友们给前两篇很大面子,弄得我骑虎难下,只好硬着头皮写了。
前 文提到 C++ 的新标准,很有必要提一下标准化对 C++ 的影响。首先我们要肯定标准定制对 C++ 的积极作用,但标准化过程中的超长流程,一次次将 C++ 推向深渊。C++ 的第一个标准是 1998 年的 ISO/IEC 14882:1998,距离整个 90 年代最流行的 C++ 程序库 MFC(Microsoft Foundation Class Library)的第一个版本发行时间已经整整  6 年。1998 年,MFC 版本号为 6.0,与其一起发布的 Visual C++ 6.0 占有了巨大的市场。因为 MFC 发布得标准制定的时间早,所以 MFC 内部实现了许多后来标准库里也有的组件,比如各种数据结构容器。VC6 的市场占有率让 windows 平台下开发的许多 C++ 程序员甚至不知道有 STL,同时也无视 C++98 标准,从更兼容标准的 VC2002/2003 的市场占有率就可以看出来,直到今天,我知道国内不少公司还是只用 VC6 的。
其实在 90 年代,计算机的运算能力有限,市场上非常需要一款性能较高、抽象较强的编程语言,C++ 获得了成功,但它标准化的时间过长,造成各种编译器有各自互不兼容的“方言”,成了它的第一个软肋。第一个瞄准这个软肋的就是 java,java 在 1995 年推出,虽然性能稍逊,但它有更高的抽象能力、也更安全,并且更容易跨平台,所以迅速获得了成功;第二个瞄准这个软肋的是 C#,微软不能推动 C++ 发展,又不愿 C++ 的市场被 java 鲸吞,于是在 2001 年推出了 C#,经过 10 年的发展和微软大量的金钱推广,C# 已经成功获得了它应有的江湖地位。
虽然 java/c# 都不是善类,但 C++ 在 21 世纪的第一个十年里仍然地位稳固,这是因为 Linux 和 MacOS X 大获成功,在这两个平台上 C++ 都是非常有竞争力的编程语言,C++ 自然水涨船高。但随着 web2.0 和 web app 概念的兴起,以及 CPU 的主频进一步提升,服务器端编程语言渐渐地对执行效率不再敏感,而是更在意程序员的开发效率,众多的脚本语言开始蚕食 C++ 的市场份额,从早期的 perl 到后期的 python/php/ruby,在 2005 年以后,C++/java/C# 等静态类型的编译型语言的市场份额都下降了,新兴的贵族是动态语言。面对动态语言在开发效率上的强劲挑战,C++ 社区除了在 2003 年对 C++98 做了小小的 patch,基本上睡着了,完全没有应对之策,哦不,连应用的姿态都没有。
进入 21 世纪的第二个十年,市场又发生了变化,云计算越走越近,也许我们中的大部分人今天还可以说只闻其声不见其形,但 The Data Center Is the Computer 这句话大家应该觉得很务实:完成一个用户操作,在服务器端的进程间通信次数前所未有地多。在这个十年,我们需要这样的编程语言:
1、能充分利用现代 CPU 的计算能力,不仅仅是多个核心,更是巨大的 L1/L2/L3 Cache、超线程等;
2、能够大量减小异步 I/O 的性能提升的同时带来的副作用:异步编程的复杂性以及对可维护性的伤害;
两 句话其实也可以压缩为一句:需要有更好的并发模型的语言。一开始大家都在已有的编程语言中寻找,然后找到了 erlang,实践证明 erlang 自有其局限,所以 google go/scala/rust 等新语言如同雨后春笋般拨地而出。C++2011 标准努力降低 C++ 的编程难度,并提供了线程库以支持现代 CPU,如果在 2005 年,这个标准绝对有竞争力,但在今天,它只能成为新的编程语言的垫脚石。正如 IE 最大的用处是用来下载其它浏览器,不久之后,也许会流行新的冷笑话:C++ 最大的用处就是用来实现其它编程语言。
市场一直在寻找一门中间的高级 语言,它上承 C 语言和汇编语言,下启脚本语言。C++ 最先抢占了高地,并在与 java/c# 的争斗中不落下风,但新的十年,它的对手又增加了 google go/scala/rust 等新锐,并且新的标准不可能在两三年内再次出台,两三年内新锐成长起来后,留给它的位置就不多了。
上 文讨论的基本上都是服务器编程,有必要再来看一下桌面和移动设备领域。首先看桌面软件,rust 是 mozilla 基金会开发系统程序语言的,它的定位是部分取代 C++ 开发 firefox 的浏览器,所以 rust 会进入桌面开发,google go 肯定会顺道啃一口。移动设备方面,主要是 android、ios 和 windows phone,随着移动设备性能增强,编译型语言加脚本的模式就会占大头,编译型语言方面主要是 C++ 和 Objective-C 在竞争,C++ 会占上风(但需求量远远小于脚本,从 lua 在 2011 年的增长速度可以印证),但是谁知道 rust 之类的会不会进入移动设备呢,毕竟移动设备的 CPU 核心也越来越多了呀,C++ 还是前景堪忧。
回首 C++ 的 30 年,展望它的未来,总结起来可能就是:标准化流程拖死人了。如果不是 15 年不能标准化,java/c# 的搅局可能不会出现;如果在 2005 年能够应对动态语言……如果云时代有更好的并发模型……
题 外话:java/c# 不会有 C++ 的问题,因为它们有自己的平台,有巨大的财富支撑。特别是平台的作用非常巨大,你可以想像一下如果 Adobe 有自己的浏览器或手机操作系统 ActionScript/MXML 会不会是今天的境地;也可以想像一下 google go 的飞速发展动力是什么。

两点解释

1、 我觉得有必要解释“不宜进入”一下这四个字,我想要表达的意思就是如果你现在不是这三个技术点的专家,并且手上没有使用这三个技术点的项目,进入这三个技 术点仅为技术储备,那么就“不宜进入”。另外我不是说用了这三个技术点的项目就死,学了这三个技术点的人就找不到工作,或者这三个技术点明天或明年就 game over,渣都没得剩,不是这样的意思,它们还会存在很长一段时间。本文不是叫专家自废武功,也不是叫已经做好技术造型的项目赶紧儿换技术,举例说,如果 你选择了用 java 做服务器端,flash 做客户端开发一个 webgame,那你最好玩命儿地把 ActionScript/MXML 和 java 多线程编程(及异步 I/O)给钻透,不然可能随时掉陷阱里。
2、新年新气象,工作和家庭都有很重要的事情压在肩上,大家的评论我不逐条回复了,我会在一两个星期后再统一写一篇《2012 不宜进入的三个技术点(Q&A)》统一回答,还请见谅。

posted @ 2012-02-04 23:19 todayx.org 阅读(177) | 评论 (0)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

劳动密集型公司

这样的公司以业务为导向,市场团队在公司中占据较高的地位。每一个技术人员最终被折算到了“人天”里面去,团队规模相对较大,所有技术人员都比较容 易被替代,能力强的可以做更多的事情,能力弱的就少做一些。通过强有力的制度、政策和流程的规约,团队有条不紊地运作起来。业务氛围强势,技术通道升级较 慢,需要非常长期的积累才可以获得丰厚的回报,诸多优秀人才脱离编码,而潜心转管理、谈需求并获得回报。愿意招纳毕业生编码,以减小运营成本。只鼓励小范 围、浅层次的创新,对于优秀的创意、想法,必须转化为生产力才能够被认可。

 

技术密集型公司

这样的公司较为重视技术和创新,敢于在产品中使用预期能够带来收益的技术。公司非常愿意招聘一些有丰富研发经验、有广泛阅历的程序员加入,同时也能 吸引一些比较优秀的技术人才,并且长期为公司工作。团队人员较少,研发过程无论是从时间还是环境来看,通常比较宽松,用较少约束、任务驱动的形式,鼓励程 序员按期完成下发的任务。技术人员层次划分较多,不同层次技术人员在一起办公,往往都不脱离编码,和项目结合紧密。愿意招不同层次的研发人员,不愿意招经 验丰富但脱离技术的人到研发团队。

 

思维密集型公司

这样的公司对研发人员思辨能力要求较高,愿意做一些创造性的产品。公司技术人员的招聘较为严格,更看重人员的创新气质、解决问题的思路、建模和抽象 的能力,而对于具体的某种技术实现,并没有很高的要求。团队人员不多,项目压力不大,任务给定的要求和流程约束较少,需要团队成员较强的自主能力来解决问 题。技术人员层次划分不多,讨论气氛浓厚,设计精益求精,创新的点子容易得到认可并尝试实现。

 

你所在的公司,属于哪一种?



历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-02-04 01:10 todayx.org 阅读(3295) | 评论 (5)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

渔夫 蛇 青蛙的故事

           渔夫看到船边有条蛇,口中正衔着一只青蛙。渔夫动了恻隐之心,把青蛙从蛇的口中救了出来。但渔夫又为蛇将挨饿而难过,便拿出一瓶酒,往蛇的口中滴了几滴。 蛇高兴地游走了,青蛙也为重获新生而高兴,渔夫则为自己的善举而感到快乐。他想,这真是皆大欢喜!没料到,仅仅过了几分钟,渔夫听到有东西在叩击他的船 板。他低头一看,那条蛇又回来了,而且嘴里咬着两只青蛙——它来讨要更多酒的奖赏!  

 

           渔夫的本意是希望蛇不再捕捉青蛙,但是由于怜悯而给了它几滴酒——这是奖励而不是惩罚,结果事与愿违。你奖励了什么行为,就会得到更多这样的行为。所以,这则寓言要告诉我们的是,别去奖励那些错误的行为。

 

我们再讲一个企业奖励错误行为的故事

           一家企业制定了一个规定,如果该企业的员工加班到晚上7 点可以获得10元钱的晚餐补助,如果加班到8点可以打出租车回家(平常5点下班)。该奖励制度执行了一段时间之后,公司管理者竟然发现,有很多员工在正常 下班前或者很早就已经完成了工作,但是他们居然不正常下班而是留下来继续加班,有的待到七点,有的待到八点以后。一个管理者亲眼看见一个员工在下午4点前 就完成了文档整理,然后一直在那里上网聊天一直到晚上8点。

 

           你也行会认为这些员工钻公司的空子有些不太好,但是这不能完全怪他们,因为早早的完成工作不见的会得到公司的奖励,相反有意把工作拖到晚上8点之后就可以拿到打车费,并且能免费获得一顿饭钱,多划算呀!

 

           管理者一定要牢记住这句话"受到奖励的事情人们都喜欢去做" 为此管理者应该仔细检测奖励制度,哪些是积极的 ,哪些可能带来消极的影响,修改掉哪些不合理的部分,通过奖励正确的行为来获得自己想要的结果。

 

           美国管理专家拉伯福认为,企业在奖励员工方面最常范的十个错误.

 

           1、需要好的结果,却奖励了那些看上去最忙碌,工作时间最长的人
          
2、要求工作的质量,却设下了不合理的完成工期
          
3、希望从根本上解决问题,却奖励那些治标不治本的人
          
4、要求员工对公司忠诚,却支付高薪给新来的员工或威胁要离职的员工
          
5、要求事情简单化,却奖励制造琐碎和使事情复杂化的人
          
6、想要创造和谐的工作环境,却奖励那些光说不做并且经常抱怨的人
          
7、要求员工有创意,却指责那些公司里有特立独行的人
          
8、要求节俭,却奖励那些浪费资源的人
          
9、要求员工有团队精神,却牺牲团队利益奖励那些投机取巧的人
          
10、要求创新,却奖励保守的人,责罚未能完成的创意

 

如何改进我们的奖励行为

 

           孔子云:举一而不能以三反,不可教也。每一个治理者都可以对照拉伯福所说的这十种错误,举一反三,验照一下自己是不是犯过类似的错误。例如:

          1、 我们 是不是口头上公布讲究实绩、注重实效,却往往奖励了那些专会做表面文章、投机取巧之人?

          2、 我们是不是口头上公布员工考核以业绩为主,却往往凭主观印象评价和奖励员工?

          3、 我们是不是口头上公布鼓励创新,却往往处罚了敢于创新之人?

          4、 我们是不是口头上公布鼓励不同意见,却往往处罚了敢于发表不同意见之人?

          5、 我们是不是口头上公布按章办事,却往往处罚了坚持原则的员工?

          6、 我们是不是口头上鼓励员工勤奋工作、努力奉献,却往往奖励了不干实事、专事捣鬼、钻营之人?

 

总结 

           总之,我们每一个治理者都要牢记:“在表现与奖励之间建立起正确的连带关系,是改进组织运作的唯一要诀”。在考核和奖励员工时非凡要注重的是,要注重其实 际业绩,而不要注重其口头上怎么说。不能奖励了投机取巧,冷落了埋头实干,否则以后我们指望谁来做事呢?

 

           治理大师卡耐基说过:我年纪越大,就越不重视别人说些什么,我只看他们做些什么。其实中国古贤更早就说过这样的话:“始吾于人也,听其言而信其行;今吾于 人也,听其言而观其行”。在奖罚问题上,每个治理者确实不可粗心大意,草率行事。否则,“种瓜得瓜,种豆得豆”,种下了苦果可是要自己吃的!


历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-02-04 01:08 todayx.org 阅读(1324) | 评论 (3)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

博士
   有一个博士分到一家研究所,成为学历最高的一个人。
   有一天他到单位后面的小池塘去钓鱼,正好正副所长在他的一左一右,也在钓鱼。
   他只是微微点了点头,这两个本科生,有啥好聊的呢?
   不一会儿,正所长放下钓竿,伸伸懒腰,蹭蹭蹭从水面上如飞地走到对面上厕所。
   博士眼睛睁得都快掉下来了。水上飘?不会吧?这可是一个池塘啊。
   正所长上完厕所回来的时候,同样也是蹭蹭蹭地从水上飘回来了。
   怎么回事?博士生又不好去问,自己是博士生哪!
   过一阵,副所长也站起来,走几步,蹭蹭蹭地飘过水面上厕所。这下子博士更是差点昏倒:不会吧,到了一个江湖高手集中的地方?
   博士生也内急了。这个池塘两边有围墙,要到对面厕所非得绕十分钟的路,而回单位上又太远,怎么办?
   博士生也不愿意去问两位所长,憋了半天后,也起身往水里跨:我就不信本科生能过的水面,我博士生不能过。
   只听咚的一声,博士生栽到了水里。
   两位所长将他拉了出来,问他为什么要下水,他问:“为什么你们可以走过去呢?”  
   两所长相视一笑:“这池塘里有两排木桩子,由于这两天下雨涨水正好在水面下。我们都知道这木桩的位置,所以可以踩着桩子过去。你怎么不问一声呢?”  


   这个故事告诉我们:学历代表过去,只有学习力才能代表将来。尊重经验的人,才能少走弯路。一个好的团队,也应该是学习型的团队。 

 

 

个人理解和感悟:看学历更要看能力

 

   招聘广告上面我们经常会看到“要求本科以上学历”,很少有企业招聘的时候 是不在乎学历的,而且在一些正规的企业里,如果没有足够的学历,是不予以考虑加薪升职的。企业在人才的竞争上面出现了一种盲目攀比学历的不良倾向,现在经 常可以看到在某些企业的官方介绍上面写“公司的本科以上学历占有xx比例”的字眼,,似乎聘用的人才学历越高
越好,在职员工高学历的越多越好。有一则消息称研究生学历的人比本科学历的人平均年薪要高出2w元,从这里看出,学历在企业招聘和考核中的重要性。

 


   现在越来越多的人坚持考研或者读MBA,他们认为一旦有了高的学历就可以“春风得意马蹄疾,一页看遍长安花”了。目前学历仍然是一个隐形的、力量巨大的“杀手”,生生的把没有一纸文凭的人拒之门外。


   有文凭不等于有水平,没有学历不等于没有能力,大量的事实说明, 不少才华横溢、能力卓越的人才,他们并没有高的学历,有的甚至没有大学文凭,例如爱迪生、高尔基诺贝尔 比尔盖茨 乔布斯等,这些人虽然没有高的学历,但是他们取得的成就是非凡的,同样现实中生活中也能轻易的发现,很多拥有高学历的人在工作中能力平平、毫无建树、庸庸 碌碌的过万了一生,管理者在选择人才时,只能把学历当作一种参考条件,更重要的是要看这个人的实际能力。如果企业不从实际出发,竞相制定一些高学历的规 定,对学历的要求过为严格,甚至唯学历取人,很难选拔出优秀的人才,衡量人才既要有文化程度方面的要求,更总要视履行岗位职责的能力,真正使那些有学历, 有智慧又有能力的人得到重用.

 

    伯 乐相马,主要是看马能否跑千里而不是看马的出身。近有消息说,有些用人单位招聘人才的取向已更加务实,选才标准正在由“学历型”向“能力型”转变,这是一 种令人欣慰的转变。毕竟,千里马是跑出来的,人才是干出来的。创造业绩主要不是靠职前的学历,而是靠任职后的实践经历和创造性努力。但愿我们公开选拔干部 时,能够更重任职的能力而不是更重职前的学历。

 

   一个人是否真正的有才能,并不能以学历作为衡量的唯一标准,管理者在选人、用人时,不要被学历遮住了视野,二应该把有实际能力的员工放在最重要的位置上



历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-02-03 00:00 todayx.org 阅读(1457) | 评论 (3)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

春节前和同事在回家的路上看到了建筑工地,不由的感慨建筑业相比软件业来讲实在是成熟太多了! 想想看,建筑师设计好图纸,交给建筑公司(大包工头), 大包工头再报给小包工头, 小包工头随便抓一些农民工就可以干活了! 农民工们可不懂得那么多高深的建筑原理, 对整个建筑也并不了解,可是他们只需要把自己的一砖一瓦做好,整个建筑就能做成了 -- 当然也有豆腐渣工程-- 但毕竟是少数,排除在外。

 

更重要的是他们根本不用担心项目的后期客户突然想改设计方案,客户不会也不可能要求你把朝北的窗户挪到南边去,也不会要求把10层楼中的第3层和第7层扒掉重盖。

 

我们这些苦苦挣扎的码农们肯定会想, 什么时候软件业也能这样啊,什么时候我们也能快乐编程,按时上下班,或者以后这些底层的Labor work都让机器人做了, 我们都去做需求,架构,设计, 然后项目按进度,高质量的完成, 大家都很happy...

 

但是无数的无情现实告诉教育我们:别做梦了,这是绝对不可能的, 至少在可以预见的时间段(比如50年)是不可能的, 原因就在于软件的复杂性,在现有的技术情况下, 软件的固有复杂性无法解决, 只有依靠我们这么码农们去弥补。

 

为什么软件这么复杂, 为什么我们无法像建筑业盖房子,汽车业装配汽车一样去写软件?

 

布鲁克斯 在著名的《人月神话》中提到软件的内在复杂性, 的确,软件系统的复杂性远远超过建筑业和制造业, 软件的需求是在人的脑子中的, 用自然语言都很难完整、准备的表达出来,更不用说用计算机(好吧,更好听的名字是”电脑“)这种原始的工具了。 不错,我用的正是”原始“这个词, 从二进制语言,到汇编语言,再到高级语言,其最基本的、最核心的东西依然是顺序,循环,分支, 即使加上面向对象,动态语言,库, 框架,计算机语言的本质仍然没有改变,我们只是在已经建好的大厦上做装饰而已。  使用这种原始的工具,怎么能够表示复杂的需求? 

 

程序员的出现正是为了填充这之间的巨大鸿沟,程序员需要用自己的大脑,使用极其”原始“的工具, 把无法准确表述的,尚在脑子中的需求映射到代码上,其难度可想而知!

 

当然我们程序员也不笨, 在长期的斗争中,我们学会了把一个问题用划分为一个一个的模块, 让这些模块低耦合,高内聚,  我们还学会了分层,让各个部分的联系达到最小, 可是所有的这些努力只是把复杂性降低了一点, 本质的复杂性依然存在。

 

未完待续。。。


历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-02-02 23:59 todayx.org 阅读(1554) | 评论 (2)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

酒宴开始。

 

酒杯盛酒,酒杯碰撞,这是物理层

你要根据不同人的外貌特征找到你要敬酒的人所坐的位置,这是IP协议网络层);

你明白,敬酒的实际目的是加深感情,这在应用层,而这酒中的感情,才是报文的数据部分

 

你和某位新见面的兄弟互相来回敬酒,这叫TCP

你给同一位好兄弟敬酒好多次,死命灌他,他也不回礼,这叫UDP

你对全桌的人说,来,咱们同归于尽,这叫广播

你在对这一桌的人顺序挨个敬酒,这叫令牌环

 

 

你对该兄弟说,初次见面,请多关照,请问阁下尊姓大名,敬酒一杯,这叫SYN报文

这位兄弟说,同是天涯沦落人,相逢何必曾相识,喝!这叫ACK报文

你一看,对方的啤酒怎么没有气泡啊,不行,你怎么能拿茶水当啤酒呢?这叫数据校验

 

 

有一个兄弟过来给你桌上的领导敬酒,你说不行,领导喝多了,不能再喝了,这叫防火墙

有一位兄弟过来敬酒,你说10分钟里面已经喝了5杯了,达到我极限了,这叫带宽

而且我还没回礼呢,现在喝不下了,先缓缓,这叫拥塞控制

 

你现在要给你最好的兄弟敬酒,于是你先找到了他所在的桌子(网络号),再找到他本人的位置(主机号);

从你要准备敬酒到敬酒完成,这叫时延,其中要经历倒酒(发送时延)、碰杯(传播时延)、你的兄弟被灌下(处理时延)这几个过程。

 

终于,你醉了,你吐了一地,不省人事,这叫缓冲区溢出

历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

posted @ 2012-02-01 23:19 todayx.org 阅读(1695) | 评论 (3)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

 故事一
          去过庙的人都知道,一进庙门,首先是弥陀佛,笑脸迎客,而在他的北面,则是黑口黑脸的韦陀。
          但相传在很久以前,他们并不在同一个庙里,而是分别掌管不同的庙。 弥乐佛热情快乐,所以来的人非常多,但他什么都不在乎,丢三拉四,没有好好的管理账务,所以依然入不敷出。而韦陀虽然管账是一把好手,但成天阴着个脸,太 过严肃,搞得人越来越少,最后香火断绝。   
          佛祖在查香火的时候发现了这个问题,就将他们俩放在同一个庙里,由弥乐佛负责公关,笑迎八方客,于是香火大旺。而韦陀铁面无私,锱珠必较,则让他负责财务,严格把关。在两人的分工合作中,庙里一派欣欣向荣景象。


故事二

 

          在动物园里的小骆驼问妈妈:"妈妈妈妈,为什么我们的睫毛那么地长?" 
          骆驼妈妈说:"当风沙来的时候,长长的睫毛可以让我们在风暴中都能看得到方向。" 
          小骆驼又问:"妈妈妈妈,为什么我们的背那么驼,丑死了!"
          骆驼妈妈说:"这个叫驼峰,可以帮我们储存大量的水和养分,让我们能在沙漠里耐受十几天的无水无食条件。"
          小骆驼又问:"妈妈妈妈,为什么我们的脚掌那么厚?" 
          骆驼妈妈说:"那可以让我们重重的身子不至于陷在软软的沙子里,便于长途跋涉啊。"
          小骆驼高兴坏了:"哗,原来我们这么有用啊!!可是妈妈,为什么我们还在动物园里,不去沙漠远足呢?" 

 

故事三


          有个鲁国人擅长编草鞋,他妻子擅长织白绢。他想迁到越国去。友人对他说:“你到越国去,一定会贫穷的。”“为什么?”“草鞋,是用来穿着走路的,但越国人 习惯于赤足走路;白绢,是用来做帽子的,但越国人习惯于披头散发。凭着你的长处,到用不到你的地方去,这样,要使自己不贫穷,难道可能吗?”


          故事一告诉我们:其实在用人大师的眼里,没有废人,正如武功高手,不需名贵宝剑,摘花飞叶即可伤人,关键看如何运用。
          故事二告诉我们:天生我才必有用,可惜现在没人用。一个好的心态+一本成功的教材+一个无限的舞台=成功。每个人的潜能是无限的,关键是要找到一个能充分发挥潜能的舞台。
          故事二告诉我们:一个人要发挥其专长,就必须适合社会环境需要。如果脱离社会环境的需要,其专长也就失去了价值

 

个人理解和感悟:充分发挥员工的长处

 

          管理者的任务,简单的说就是找到对的人,把他们放到对的地方,然后鼓励他们充分发挥自己的创意,完成本职工作,在这个过程中管理者既要用人职场,又要容忍之短,使员工最大限度的发挥自己的才能,达到合理使用人才的目的。

          正确的用人之道,就是用人的长处,即让一个人的长处和优势得到充分的发挥,让一个人的短处和劣势得到有效的避免,正所谓“人尽其才,物尽其用”“木匠手中 无烂木”“智者不用其短,而用愚人之所长也”,从某种意义上说天下没有无用之人,一个擅长用人的管理者,能将每个人都派上用场

 

如何才能扬人之所长

 

          1、管理者必须做到客观公正。每个人都不可避免的会有自己的好恶,也会收到成见、偏见影响、管理者一定要待人宽容,心胸开阔,一切从公司的利益出发,不可错过一个人才
          2、管理者应该充分利用科学方法。人才入冰山,其优秀特质浮出水面的只有1/3 ,如果不运用一些科学的方法很难看出来,方法有很多,笔试、面试、心理测试、情景模拟、评价中心等,在使用的过程中要注意灵活运用
          3、将人才放到对的位置上。根据其特点,为其提供充分展示自己能力的平台,让其在实际的工作中不断锻炼
          4、适时展开具有针对性、个性化的培训。培训不但要补员工所短,同时应该培训员工长处,让员工之“长”根突出、更醒目。并让其在你的公司里面形成一定的品牌
          5、优化配置、平衡互补,取各家之“长”溶于一炉,并相互扬“长”,相互促“长”


历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-02-01 23:19 todayx.org 阅读(1496) | 评论 (0)编辑 收藏
     摘要: 历史上的今天回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天http://www.todayx.org/jdk1.5以后用Integer举例Integer a = 3;              ...  阅读全文
posted @ 2012-02-01 00:23 todayx.org 阅读(1671) | 评论 (0)编辑 收藏
历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/

等于还是不等于?

看来看下面的一段代码:

 

   代码片段1

Java代码  收藏代码
  1. public static void main(final String[] args) {  
  2.     Integer a = new Integer(100);  
  3.     Integer b = 100;  
  4.     System.out.println(a == b);   
  5. }  

 

 这段代码的输出是什么?相信很多人都会很容易的猜到:false,因为a、b两个对象的地址不同,用“==”比较时是false。恭喜你,答对了。

 

再看下面的一段代码:

  

   代码片段2

Java代码  收藏代码
  1. public static void main(final String[] args) {  
  2.     Integer a = 100;  
  3.     Integer b = 100;  
  4.     System.out.println(a == b);   
  5. }  

 

你可能会回答,这没什么不一样啊,所以还是false。很遗憾,如果你执行上面的一段代码,结果是true。

 

上面的代码可能让你有些意外,那好吧,再看看下面的这段代码:

 

    代码片段3

Java代码  收藏代码
  1. public static void main(final String[] args) {  
  2.     Integer a = 156;  
  3.     Integer b = 156;  
  4.     System.out.println(a == b);   
  5. }  

 结果是true吗?很遗憾,如果你执行上面的一段代码,结果是false。

 

 感到吃惊吗?那最后再看下面的一段代码:

 

    代码片段4

Java代码  收藏代码
  1. public static void main(final String[] args) {  
  2.     Integer a = Integer.valueOf(100);  
  3.     Integer b = 100;  
  4.     System.out.println(a == b);   
  5. }  

最后的结果,可能你已经猜到了,是true。

为什么会这样?

现在我们分析一下上面的代码。可以很容易的看出,这一系列代码的最终目的都是用“==”对两个对象进行比较。Java中,如果用“==”比较两个对象结果为true,说明这两个对象实际上是同一个对象,false说明是两个对象。

 

现在,我们来看看为什么会出现上面的现象。

 

我们先看代码片段4:最后的运行结果是true,说明a、b两个对象实际上是同一个对象。但是a对象是通过调用Integer的valueOf方法创建的,而b对象是通过自动装箱创建出来的,怎么会是同一个对象呢?难道问题在字节码那里,毕竟Java程序是依靠虚拟器运行字节码来实现的。

 

通过jdk中自带的工具javap,解析字节码,核心的部分摘取如下:

Java代码  收藏代码
  1. 0:  bipush  100  
  2. 2:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  
  3. 5:  astore_1  
  4. 6:  bipush  100  
  5. 8:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  

代码中我们只调用了一次Integer.valueOf方法,但是字节码中出现了两次对Integer.valueOf方法的调用。那么另一次是哪里呢?只可能在自动装箱时调用的。因此这段代码实际上等价于:

Java代码  收藏代码
  1. public static void main(final String[] args) {  
  2.     Integer a = Integer.valueOf(100);  
  3.     Integer b = Integer.valueOf(100);  
  4.     System.out.println(a == b);   
  5. }  

 现在问题就简单了:看jdk源代码,查看valueOf方法的具体实现:

Java代码  收藏代码
  1. public static Integer valueOf(int i) {  
  2.     final int offset = 128;  
  3.     if (i >= -128 && i <= 127) { // must cache   
  4.         return IntegerCache.cache[i + offset];  
  5.     }  
  6.     return new Integer(i);  
  7. }  

 

看到这儿,上面的代码就很明确了:对于-128到127的数字,valueOf返回的是缓存中的对象。所以两次调用Integer.valueOf(100)返回的都是同一个对象。

我们再先看代码片段3:根据上面的分析,代码片段3实际上等价于以下代码:

Java代码  收藏代码
  1. public static void main(final String[] args) {  
  2.     Integer a = Integer.valueOf(156);  
  3.     Integer b = Integer.valueOf(156);  
  4.     System.out.println(a == b);   
  5. }  

 由于156不在-128到127范围内,所以两个对象都是通过new Integer()的方式创建的,所以最后结果为false。

 

 片段1和片段2就不做具体分析了,相信读者可以自行分析。

 

 最后,请大家思考一下问题:通过上面的分析,了解到整数的自动装箱是通过Integer.valueOf(int number)实现的,那么自动拆箱是如何实现的呢?


历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-02-01 00:21 todayx.org 阅读(1964) | 评论 (3)编辑 收藏

1.关于JSP标签的好处就不再罗嗦

数据字典就是使用的下拉框,只要定义使用那个字典就会将这个字典可用的内容显示出来

显示字典时只要定义那个字典和属性值就可以显示出字典的显示值

 

2.首先在web.xml中定义自定义标签加载的引用,两个属性分别是引用的URI和加载路径

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  6.     <welcome-file-list>  
  7.         <welcome-file>index.jsp</welcome-file>  
  8.     </welcome-file-list>  
  9.     <jsp-config>  
  10.         <taglib>  
  11.             <taglib-uri>/tld/web-html</taglib-uri>  
  12.             <taglib-location>  
  13.                 /WEB-INF/tlds/web-html.tld  
  14.             </taglib-location>  
  15.         </taglib>  
  16.     </jsp-config>  
  17. </web-app>  

 

 

 

3.在web-html.tld中定义自己的标签,数据字典应用的话我们需要一个标签库,三个标签。分别是,select标签,options标签,和现实数据字典的标签,每个标签都对应不同的实现类

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"    
  3.     "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">  
  4. <taglib>  
  5.     <tlib-version>1.0</tlib-version><!-- 标签库版本 -->  
  6.     <jsp-version>1.2</jsp-version>  <!-- 标签库要求的JSP规范版本 -->  
  7.     <short-name>html</short-name>   <!-- JSP页面编写工具可以用来创建助记名的可选名字 -->  
  8.     <tag>  
  9.         <name>select</name>  
  10.         <tag-class>com.SelectTag</tag-class>  
  11.         <body-content>JSP</body-content>  
  12.         <attribute>  
  13.             <name>name</name>  
  14.             <rtexprvalue>true</rtexprvalue>  
  15.         </attribute>  
  16.         <attribute>  
  17.             <name>style</name>  
  18.             <rtexprvalue>true</rtexprvalue>  
  19.         </attribute>  
  20.     </tag>  
  21.     <tag>  
  22.         <name>options</name>  
  23.         <tag-class>com.OptionsTag</tag-class>  
  24.         <body-content>JSP</body-content>  
  25.         <attribute>  
  26.             <name>collection</name>  
  27.             <rtexprvalue>true</rtexprvalue>  
  28.         </attribute>  
  29.     </tag>  
  30.     <tag>  
  31.         <name>selectDisplay</name>  
  32.         <tag-class>com.SelectDisplay</tag-class>  
  33.         <body-content>JSP</body-content>  
  34.         <attribute>  
  35.             <name>collection</name>  
  36.             <rtexprvalue>true</rtexprvalue>  
  37.         </attribute>  
  38.         <attribute>  
  39.             <name>name</name>  
  40.             <rtexprvalue>true</rtexprvalue>  
  41.         </attribute>  
  42.         <attribute>  
  43.             <name>value</name>  
  44.             <rtexprvalue>true</rtexprvalue>  
  45.         </attribute>  
  46.     </tag>  
  47. </taglib>  

 

 

 

 

4.实现类

实现类的作用就是在后台拼接所需HTML标签内容,然后由JSP进行输出

实现类最主要的两个方法,一个遇到这个标签开始时输出,一个是结束时输出

如果需要定义属性,可以参考实现类定义属性,并在TLD中定义,在JSP中使用标签时快捷键就可以出来这个属性

首先是select标签的代码:

 

Java代码  收藏代码
  1. package com;  
  2. import java.io.IOException;  
  3. import javax.servlet.jsp.JspException;  
  4. import javax.servlet.jsp.JspTagException;  
  5. import javax.servlet.jsp.tagext.BodyTagSupport;  
  6. /** 
  7.  * TagSupport与BodyTagSupport的区别: 
  8.  * 主要看标签处理类是否要读取标签体的内容和改变标签体返回的内容,如果不需要就用TagSupport,否则就用BodyTagSupport 
  9.  * 用TagSupport实现的标签,都可以用BodyTagSupport来实现,因为BodyTagSupport继承了TagSupport 
  10.  */  
  11. @SuppressWarnings("serial")  
  12. public class SelectTag extends BodyTagSupport {  
  13.     @Override  
  14.     public int doStartTag() throws JspException {  
  15.         try {  
  16.             StringBuffer results = new StringBuffer("<select");  
  17.             if(name != null){  
  18.                 results.append(" name=\"");  
  19.                 results.append(name);  
  20.                 results.append("\"");  
  21.             }  
  22.             if(style != null){  
  23.                 results.append(" style=\"");  
  24.                 results.append(style);  
  25.                 results.append("\"");  
  26.             }  
  27.             results.append(">");  
  28.             pageContext.getOut().write(results.toString());  
  29.         } catch (IOException ex) {  
  30.             throw new JspTagException("错误");  
  31.         }  
  32.         return EVAL_BODY_INCLUDE;  
  33.     }  
  34.     @Override  
  35.     public int doEndTag() throws JspException {  
  36.         try {  
  37.             StringBuffer results = new StringBuffer("");  
  38.             // 因为下拉中包含下拉内容,所以只能在遇到结束标签时才能写select结束  
  39.             results.append("</select>");            
  40.             pageContext.getOut().write(results.toString());  
  41.         } catch (IOException ex) {  
  42.             throw new JspTagException("错误");  
  43.         }  
  44.         return EVAL_PAGE;  
  45.     }  
  46.     // 样式  
  47.     protected String style;  
  48.     // 名字  
  49.     protected String name;  
  50.     public String getStyle() {  
  51.         return style;  
  52.     }  
  53.     public void setStyle(String style) {  
  54.         this.style = style;  
  55.     }  
  56.     public String getName() {  
  57.         return name;  
  58.     }  
  59.     public void setName(String name) {  
  60.         this.name = name;  
  61.     }     
  62.     /** 
  63.     doStartTag()方法是遇到标签开始时会呼叫的方法,其合法的返回值是EVAL_BODY_INCLUDE与SKIP_BODY,前者表示将显示标签间的文字,后者表示不显示标签间的文字 
  64.     doEndTag()方法是在遇到标签结束时呼叫的方法,其合法的返回值是EVAL_PAGE与SKIP_PAGE,前者表示处理完标签后继续执行以下的JSP网页,后者是表示不处理接下来的JSP网页 
  65.     doAfterBody(),这个方法是在显示完标签间文字之后呼叫的,其返回值有EVAL_BODY_AGAIN与SKIP_BODY,前者会再显示一次标签间的文字,后者则继续执行标签处理的下一步 
  66.     EVAL_BODY_INCLUDE:把Body读入存在的输出流中,doStartTag()函数可用 
  67.     EVAL_PAGE:继续处理页面,doEndTag()函数可用 
  68.     SKIP_BODY:忽略对Body的处理,doStartTag()和doAfterBody()函数可用 
  69.     SKIP_PAGE:忽略对余下页面的处理,doEndTag()函数可用 
  70.     EVAL_BODY_BUFFERED:申请缓冲区,由setBodyContent()函数得到的BodyContent对象来处理tag的body,如果类实现了BodyTag,那么doStartTag()可用,否则非法 
  71.     EVAL_BODY_AGAIN:请求继续处理body,返回自doAfterBody(),这个返回值在你制作循环tag的时候是很有用的   
  72.     预定的处理顺序是:doStartTag()返回SKIP_BODY,doAfterBodyTag()返回SKIP_BODY,doEndTag()返回EVAL_PAGE 
  73.     如果继承了TagSupport之后,如果没有改写任何的方法,标签处理的执行顺序是:doStartTag() ->不显示文字 ->doEndTag()->执行接下来的网页  
  74.     如果您改写了doStartTag(),则必须指定返回值, 
  75.     如果指定了EVAL_BODY_INCLUDE,则执行顺序是:doStartTag()->显示文字->doAfterBodyTag()->doEndTag()->执行下面的网页 
  76.      */  
  77. }  

 

 

关于返回参数,返回具体数字也可以,不用过于纠结

然后是下拉内容实现类

 

Java代码  收藏代码
  1. package com;  
  2. import java.io.IOException;  
  3. import javax.servlet.jsp.JspException;  
  4. import javax.servlet.jsp.JspTagException;  
  5. import javax.servlet.jsp.tagext.BodyTagSupport;  
  6. @SuppressWarnings("serial")  
  7. public class OptionsTag extends BodyTagSupport {  
  8.     @Override  
  9.     public int doStartTag() throws JspException {  
  10.         return EVAL_BODY_INCLUDE;  
  11.     }  
  12.     @Override  
  13.     public int doEndTag() throws JspException {  
  14.         try {  
  15.             StringBuffer results = new StringBuffer("");  
  16.             if ("SEX".equals(collection)) {  
  17.                 results.append("<option value=\"0\"  selected=\"selected\">请选择</option>");  
  18.                 results.append("<option value=\"1\">男</option>");  
  19.                 results.append("<option value=\"2\">女</option>");  
  20.             }  
  21.             pageContext.getOut().write(results.toString());  
  22.         } catch (IOException ex) {  
  23.             throw new JspTagException("错误");  
  24.         }  
  25.         return EVAL_PAGE;  
  26.     }  
  27.     // collection只是传递一个标识,具体下拉值内容是从数据库取还是从请求中得到为不同具体实现  
  28.     protected String collection;  
  29.     public String getCollection() {  
  30.         return collection;  
  31.     }  
  32.     public void setCollection(String collection) {  
  33.         this.collection = collection;  
  34.     }  
  35. }  

 

 

具体你的字典数据从数据库中如何存储如何查询,可以自定义实现

显示的标签实现,为了将来可以在页面取到标签内容值,我们定义隐藏域来保存属性值,然后在显示显示内容

 

Java代码  收藏代码
  1. package com;  
  2. import java.io.IOException;  
  3. import javax.servlet.jsp.JspException;  
  4. import javax.servlet.jsp.JspTagException;  
  5. import javax.servlet.jsp.tagext.BodyTagSupport;  
  6. @SuppressWarnings("serial")  
  7. public class SelectDisplay extends BodyTagSupport {  
  8.     @Override  
  9.     public int doStartTag() throws JspException {  
  10.         try {  
  11.             StringBuffer results = new StringBuffer("");  
  12.             pageContext.getOut().write(results.toString());  
  13.         } catch (IOException ex) {  
  14.             throw new JspTagException("错误");  
  15.         }  
  16.         return EVAL_BODY_INCLUDE;  
  17.     }  
  18.     @Override  
  19.     public int doEndTag() throws JspException {  
  20.         try {  
  21.             StringBuffer results = new StringBuffer("");  
  22.             if ("SEX".equals(collection)) {  
  23.                 results.append("<span>");  
  24.                 results.append("<input type=\"");  
  25.                 results.append("hidden\" name=\"");  
  26.                 results.append(getName());  
  27.                 results.append("\"");  
  28.                 results.append(" value=\"");  
  29.                 results.append(getValue());  
  30.                 results.append("\">");                 
  31.                 if ("1".equals(getValue())) {  
  32.                     results.append("男");  
  33.                 } else if ("2".equals(getValue())) {  
  34.                     results.append("女");  
  35.                 } else {  
  36.                     results.append("请选择");  
  37.                 }  
  38.                 results.append("</span>");  
  39.             }  
  40.             pageContext.getOut().write(results.toString());  
  41.         } catch (IOException ex) {  
  42.             throw new JspTagException("错误");  
  43.         }  
  44.         return EVAL_PAGE;  
  45.     }  
  46.     // collection只是传递一个标识,具体下拉值内容是从数据库取还是从请求中得到为不同具体实现  
  47.     protected String collection;  
  48.     // 传递的值  
  49.     protected String value;  
  50.     // 该属性的名称  
  51.     protected String name;  
  52.     public String getCollection() {  
  53.         return collection;  
  54.     }  
  55.     public void setCollection(String collection) {  
  56.         this.collection = collection;  
  57.     }  
  58.     public String getName() {  
  59.         return name;  
  60.     }  
  61.     public void setName(String name) {  
  62.         this.name = name;  
  63.     }  
  64.     public String getValue() {  
  65.         return value;  
  66.     }  
  67.     public void setValue(String value) {  
  68.         this.value = value;  
  69.     }  
  70. }  

 

 

 

5.JSP中引用,直接在index.jsp中引用

需要引入相应的标签内容,引入的方式在JSP头部引用

标签的属性可以设置也可以不设置,标签的使用和HTML标签的使用是一样的,定义属性即可

 

Jsp代码  收藏代码
  1. <%@ page language="java" pageEncoding="UTF-8"%>  
  2. <%@ taglib uri="/tld/web-html" prefix="html"%>  
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  4. <html>  
  5.     <head>  
  6.         <title>JSP 自定义标签的实现</title>  
  7.     </head>  
  8.     <body>  
  9.         请选择:  
  10.         <html:select name="sex" style="width:100px">  
  11.             <html:options collection="SEX"></html:options>  
  12.         </html:select>  
  13.         显示性别:  
  14.         <html:selectDisplay collection="SEX" value="1" name="sex"></html:selectDisplay>       
  15.     </body>  
  16. </html>  

 

 

 

6.后话

访问项目就可以看到效果,附件是这个项目的源代码,导入到MyEclipse中可以查看

如果想要自己设计一个大的标签库,可以设计一个父类,包含一些主要的属性,例如name,id,style等属性。然后在子类中定义自己的特有属性

这个实现只是学习一下JSP自定义标签使用的HelloWorld程序,然后包含了字典应用的实际例子,程序简单,仅供参考

 

历史上的今天
回顾历史的今天,历史就像生活的一面镜子;可以了解历史的这一天发生的事件;借古可以鉴今;历史是不能忘记的.要记住历史的每一天
http://www.todayx.org/
posted @ 2012-01-30 23:00 todayx.org 阅读(2768) | 评论 (0)编辑 收藏
仅列出标题
共4页: 上一页 1 2 3 4 下一页