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 閱讀(195) | 評論 (0)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          勞動密集型公司

          這樣的公司以業務為導向,市場團隊在公司中占據較高的地位。每一個技術人員最終被折算到了“人天”里面去,團隊規模相對較大,所有技術人員都比較容 易被替代,能力強的可以做更多的事情,能力弱的就少做一些。通過強有力的制度、政策和流程的規約,團隊有條不紊地運作起來。業務氛圍強勢,技術通道升級較 慢,需要非常長期的積累才可以獲得豐厚的回報,諸多優秀人才脫離編碼,而潛心轉管理、談需求并獲得回報。愿意招納畢業生編碼,以減小運營成本。只鼓勵小范 圍、淺層次的創新,對于優秀的創意、想法,必須轉化為生產力才能夠被認可。

           

          技術密集型公司

          這樣的公司較為重視技術和創新,敢于在產品中使用預期能夠帶來收益的技術。公司非常愿意招聘一些有豐富研發經驗、有廣泛閱歷的程序員加入,同時也能 吸引一些比較優秀的技術人才,并且長期為公司工作。團隊人員較少,研發過程無論是從時間還是環境來看,通常比較寬松,用較少約束、任務驅動的形式,鼓勵程 序員按期完成下發的任務。技術人員層次劃分較多,不同層次技術人員在一起辦公,往往都不脫離編碼,和項目結合緊密。愿意招不同層次的研發人員,不愿意招經 驗豐富但脫離技術的人到研發團隊。

           

          思維密集型公司

          這樣的公司對研發人員思辨能力要求較高,愿意做一些創造性的產品。公司技術人員的招聘較為嚴格,更看重人員的創新氣質、解決問題的思路、建模和抽象 的能力,而對于具體的某種技術實現,并沒有很高的要求。團隊人員不多,項目壓力不大,任務給定的要求和流程約束較少,需要團隊成員較強的自主能力來解決問 題。技術人員層次劃分不多,討論氣氛濃厚,設計精益求精,創新的點子容易得到認可并嘗試實現。

           

          你所在的公司,屬于哪一種?



          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-04 01:10 todayx.org 閱讀(3306) | 評論 (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 閱讀(1335) | 評論 (3)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          博士
             有一個博士分到一家研究所,成為學歷最高的一個人。
             有一天他到單位后面的小池塘去釣魚,正好正副所長在他的一左一右,也在釣魚。
             他只是微微點了點頭,這兩個本科生,有啥好聊的呢?
             不一會兒,正所長放下釣竿,伸伸懶腰,蹭蹭蹭從水面上如飛地走到對面上廁所。
             博士眼睛睜得都快掉下來了。水上飄?不會吧?這可是一個池塘啊。
             正所長上完廁所回來的時候,同樣也是蹭蹭蹭地從水上飄回來了。
             怎么回事?博士生又不好去問,自己是博士生哪!
             過一陣,副所長也站起來,走幾步,蹭蹭蹭地飄過水面上廁所。這下子博士更是差點昏倒:不會吧,到了一個江湖高手集中的地方?
             博士生也內急了。這個池塘兩邊有圍墻,要到對面廁所非得繞十分鐘的路,而回單位上又太遠,怎么辦?
             博士生也不愿意去問兩位所長,憋了半天后,也起身往水里跨:我就不信本科生能過的水面,我博士生不能過。
             只聽咚的一聲,博士生栽到了水里。
             兩位所長將他拉了出來,問他為什么要下水,他問:“為什么你們可以走過去呢?”  
             兩所長相視一笑:“這池塘里有兩排木樁子,由于這兩天下雨漲水正好在水面下。我們都知道這木樁的位置,所以可以踩著樁子過去。你怎么不問一聲呢?”  


             這個故事告訴我們:學歷代表過去,只有學習力才能代表將來。尊重經驗的人,才能少走彎路。一個好的團隊,也應該是學習型的團隊。 

           

           

          個人理解和感悟:看學歷更要看能力

           

             招聘廣告上面我們經常會看到“要求本科以上學歷”,很少有企業招聘的時候 是不在乎學歷的,而且在一些正規的企業里,如果沒有足夠的學歷,是不予以考慮加薪升職的。企業在人才的競爭上面出現了一種盲目攀比學歷的不良傾向,現在經 常可以看到在某些企業的官方介紹上面寫“公司的本科以上學歷占有xx比例”的字眼,,似乎聘用的人才學歷越高
          越好,在職員工高學歷的越多越好。有一則消息稱研究生學歷的人比本科學歷的人平均年薪要高出2w元,從這里看出,學歷在企業招聘和考核中的重要性。

           


             現在越來越多的人堅持考研或者讀MBA,他們認為一旦有了高的學歷就可以“春風得意馬蹄疾,一頁看遍長安花”了。目前學歷仍然是一個隱形的、力量巨大的“殺手”,生生的把沒有一紙文憑的人拒之門外。


             有文憑不等于有水平,沒有學歷不等于沒有能力,大量的事實說明, 不少才華橫溢、能力卓越的人才,他們并沒有高的學歷,有的甚至沒有大學文憑,例如愛迪生、高爾基諾貝爾 比爾蓋茨 喬布斯等,這些人雖然沒有高的學歷,但是他們取得的成就是非凡的,同樣現實中生活中也能輕易的發現,很多擁有高學歷的人在工作中能力平平、毫無建樹、庸庸 碌碌的過萬了一生,管理者在選擇人才時,只能把學歷當作一種參考條件,更重要的是要看這個人的實際能力。如果企業不從實際出發,競相制定一些高學歷的規 定,對學歷的要求過為嚴格,甚至唯學歷取人,很難選拔出優秀的人才,衡量人才既要有文化程度方面的要求,更總要視履行崗位職責的能力,真正使那些有學歷, 有智慧又有能力的人得到重用.

           

              伯 樂相馬,主要是看馬能否跑千里而不是看馬的出身。近有消息說,有些用人單位招聘人才的取向已更加務實,選才標準正在由“學歷型”向“能力型”轉變,這是一 種令人欣慰的轉變。畢竟,千里馬是跑出來的,人才是干出來的。創造業績主要不是靠職前的學歷,而是靠任職后的實踐經歷和創造性努力。但愿我們公開選拔干部 時,能夠更重任職的能力而不是更重職前的學歷。

           

             一個人是否真正的有才能,并不能以學歷作為衡量的唯一標準,管理者在選人、用人時,不要被學歷遮住了視野,二應該把有實際能力的員工放在最重要的位置上



          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-03 00:00 todayx.org 閱讀(1462) | 評論 (3)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          春節前和同事在回家的路上看到了建筑工地,不由的感慨建筑業相比軟件業來講實在是成熟太多了! 想想看,建筑師設計好圖紙,交給建筑公司(大包工頭), 大包工頭再報給小包工頭, 小包工頭隨便抓一些農民工就可以干活了! 農民工們可不懂得那么多高深的建筑原理, 對整個建筑也并不了解,可是他們只需要把自己的一磚一瓦做好,整個建筑就能做成了 -- 當然也有豆腐渣工程-- 但畢竟是少數,排除在外。

           

          更重要的是他們根本不用擔心項目的后期客戶突然想改設計方案,客戶不會也不可能要求你把朝北的窗戶挪到南邊去,也不會要求把10層樓中的第3層和第7層扒掉重蓋。

           

          我們這些苦苦掙扎的碼農們肯定會想, 什么時候軟件業也能這樣啊,什么時候我們也能快樂編程,按時上下班,或者以后這些底層的Labor work都讓機器人做了, 我們都去做需求,架構,設計, 然后項目按進度,高質量的完成, 大家都很happy...

           

          但是無數的無情現實告訴教育我們:別做夢了,這是絕對不可能的, 至少在可以預見的時間段(比如50年)是不可能的, 原因就在于軟件的復雜性,在現有的技術情況下, 軟件的固有復雜性無法解決, 只有依靠我們這么碼農們去彌補。

           

          為什么軟件這么復雜, 為什么我們無法像建筑業蓋房子,汽車業裝配汽車一樣去寫軟件?

           

          布魯克斯 在著名的《人月神話》中提到軟件的內在復雜性, 的確,軟件系統的復雜性遠遠超過建筑業和制造業, 軟件的需求是在人的腦子中的, 用自然語言都很難完整、準備的表達出來,更不用說用計算機(好吧,更好聽的名字是”電腦“)這種原始的工具了。 不錯,我用的正是”原始“這個詞, 從二進制語言,到匯編語言,再到高級語言,其最基本的、最核心的東西依然是順序,循環,分支, 即使加上面向對象,動態語言,庫, 框架,計算機語言的本質仍然沒有改變,我們只是在已經建好的大廈上做裝飾而已。  使用這種原始的工具,怎么能夠表示復雜的需求? 

           

          程序員的出現正是為了填充這之間的巨大鴻溝,程序員需要用自己的大腦,使用極其”原始“的工具, 把無法準確表述的,尚在腦子中的需求映射到代碼上,其難度可想而知!

           

          當然我們程序員也不笨, 在長期的斗爭中,我們學會了把一個問題用劃分為一個一個的模塊, 讓這些模塊低耦合,高內聚,  我們還學會了分層,讓各個部分的聯系達到最小, 可是所有的這些努力只是把復雜性降低了一點, 本質的復雜性依然存在。

           

          未完待續。。。


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-02 23:59 todayx.org 閱讀(1560) | 評論 (2)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          酒宴開始。

           

          酒杯盛酒,酒杯碰撞,這是物理層

          你要根據不同人的外貌特征找到你要敬酒的人所坐的位置,這是IP協議網絡層);

          你明白,敬酒的實際目的是加深感情,這在應用層,而這酒中的感情,才是報文的數據部分

           

          你和某位新見面的兄弟互相來回敬酒,這叫TCP

          你給同一位好兄弟敬酒好多次,死命灌他,他也不回禮,這叫UDP

          你對全桌的人說,來,咱們同歸于盡,這叫廣播

          你在對這一桌的人順序挨個敬酒,這叫令牌環

           

           

          你對該兄弟說,初次見面,請多關照,請問閣下尊姓大名,敬酒一杯,這叫SYN報文

          這位兄弟說,同是天涯淪落人,相逢何必曾相識,喝!這叫ACK報文

          你一看,對方的啤酒怎么沒有氣泡啊,不行,你怎么能拿茶水當啤酒呢?這叫數據校驗

           

           

          有一個兄弟過來給你桌上的領導敬酒,你說不行,領導喝多了,不能再喝了,這叫防火墻

          有一位兄弟過來敬酒,你說10分鐘里面已經喝了5杯了,達到我極限了,這叫帶寬

          而且我還沒回禮呢,現在喝不下了,先緩緩,這叫擁塞控制

           

          你現在要給你最好的兄弟敬酒,于是你先找到了他所在的桌子(網絡號),再找到他本人的位置(主機號);

          從你要準備敬酒到敬酒完成,這叫時延,其中要經歷倒酒(發送時延)、碰杯(傳播時延)、你的兄弟被灌下(處理時延)這幾個過程。

           

          終于,你醉了,你吐了一地,不省人事,這叫緩沖區溢出

          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          posted @ 2012-02-01 23:19 todayx.org 閱讀(1711) | 評論 (3)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

           故事一
                    去過廟的人都知道,一進廟門,首先是彌陀佛,笑臉迎客,而在他的北面,則是黑口黑臉的韋陀。
                    但相傳在很久以前,他們并不在同一個廟里,而是分別掌管不同的廟。 彌樂佛熱情快樂,所以來的人非常多,但他什么都不在乎,丟三拉四,沒有好好的管理賬務,所以依然入不敷出。而韋陀雖然管賬是一把好手,但成天陰著個臉,太 過嚴肅,搞得人越來越少,最后香火斷絕。   
                    佛祖在查香火的時候發現了這個問題,就將他們倆放在同一個廟里,由彌樂佛負責公關,笑迎八方客,于是香火大旺。而韋陀鐵面無私,錙珠必較,則讓他負責財務,嚴格把關。在兩人的分工合作中,廟里一派欣欣向榮景象。


          故事二

           

                    在動物園里的小駱駝問媽媽:"媽媽媽媽,為什么我們的睫毛那么地長?" 
                    駱駝媽媽說:"當風沙來的時候,長長的睫毛可以讓我們在風暴中都能看得到方向。" 
                    小駱駝又問:"媽媽媽媽,為什么我們的背那么駝,丑死了!"
                    駱駝媽媽說:"這個叫駝峰,可以幫我們儲存大量的水和養分,讓我們能在沙漠里耐受十幾天的無水無食條件。"
                    小駱駝又問:"媽媽媽媽,為什么我們的腳掌那么厚?" 
                    駱駝媽媽說:"那可以讓我們重重的身子不至于陷在軟軟的沙子里,便于長途跋涉啊。"
                    小駱駝高興壞了:"嘩,原來我們這么有用啊!!可是媽媽,為什么我們還在動物園里,不去沙漠遠足呢?" 

           

          故事三


                    有個魯國人擅長編草鞋,他妻子擅長織白絹。他想遷到越國去。友人對他說:“你到越國去,一定會貧窮的。”“為什么?”“草鞋,是用來穿著走路的,但越國人 習慣于赤足走路;白絹,是用來做帽子的,但越國人習慣于披頭散發。憑著你的長處,到用不到你的地方去,這樣,要使自己不貧窮,難道可能嗎?”


                    故事一告訴我們:其實在用人大師的眼里,沒有廢人,正如武功高手,不需名貴寶劍,摘花飛葉即可傷人,關鍵看如何運用。
                    故事二告訴我們:天生我才必有用,可惜現在沒人用。一個好的心態+一本成功的教材+一個無限的舞臺=成功。每個人的潛能是無限的,關鍵是要找到一個能充分發揮潛能的舞臺。
                    故事二告訴我們:一個人要發揮其專長,就必須適合社會環境需要。如果脫離社會環境的需要,其專長也就失去了價值

           

          個人理解和感悟:充分發揮員工的長處

           

                    管理者的任務,簡單的說就是找到對的人,把他們放到對的地方,然后鼓勵他們充分發揮自己的創意,完成本職工作,在這個過程中管理者既要用人職場,又要容忍之短,使員工最大限度的發揮自己的才能,達到合理使用人才的目的。

                    正確的用人之道,就是用人的長處,即讓一個人的長處和優勢得到充分的發揮,讓一個人的短處和劣勢得到有效的避免,正所謂“人盡其才,物盡其用”“木匠手中 無爛木”“智者不用其短,而用愚人之所長也”,從某種意義上說天下沒有無用之人,一個擅長用人的管理者,能將每個人都派上用場

           

          如何才能揚人之所長

           

                    1、管理者必須做到客觀公正。每個人都不可避免的會有自己的好惡,也會收到成見、偏見影響、管理者一定要待人寬容,心胸開闊,一切從公司的利益出發,不可錯過一個人才
                    2、管理者應該充分利用科學方法。人才入冰山,其優秀特質浮出水面的只有1/3 ,如果不運用一些科學的方法很難看出來,方法有很多,筆試、面試、心理測試、情景模擬、評價中心等,在使用的過程中要注意靈活運用
                    3、將人才放到對的位置上。根據其特點,為其提供充分展示自己能力的平臺,讓其在實際的工作中不斷鍛煉
                    4、適時展開具有針對性、個性化的培訓。培訓不但要補員工所短,同時應該培訓員工長處,讓員工之“長”根突出、更醒目。并讓其在你的公司里面形成一定的品牌
                    5、優化配置、平衡互補,取各家之“長”溶于一爐,并相互揚“長”,相互促“長”


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-01 23:19 todayx.org 閱讀(1501) | 評論 (0)編輯 收藏
               摘要: 歷史上的今天回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天http://www.todayx.org/jdk1.5以后用Integer舉例Integer a = 3;              ...  閱讀全文
          posted @ 2012-02-01 00:23 todayx.org 閱讀(1692) | 評論 (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 閱讀(1976) | 評論 (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 閱讀(2778) | 評論 (0)編輯 收藏
          僅列出標題
          共4頁: 上一頁 1 2 3 4 下一頁 
          主站蜘蛛池模板: 凯里市| 金塔县| 格尔木市| 崇阳县| 手游| 大埔县| 友谊县| 丹江口市| 塔城市| 肥城市| 石渠县| 昌黎县| 呼和浩特市| 丹江口市| 辰溪县| 京山县| 枝江市| 昌乐县| 衢州市| 南丰县| 凤城市| 金坛市| 博野县| 梧州市| 临沭县| 临潭县| 清远市| 津南区| 江北区| 融水| 县级市| 延吉市| 汉源县| 永修县| 岑巩县| 潞西市| 崇礼县| 北宁市| 奉化市| 吉水县| 南岸区|