todayx.org
          todayx.org
          posts - 39,comments - 60,trackbacks - 0
               摘要: JDBC模板類 概述        Spring JDBC抽象框架core包提供了JDBC模板類,其中JdbcTemplate是core包的核心類,所以其他模板類都是基于它封裝完成的,JDBC模板類是第一種工作模式。          JdbcTemplate類通過模板...  閱讀全文
          posted @ 2012-02-26 09:39 todayx.org 閱讀(2723) | 評論 (0)編輯 收藏

          在軟件這個行業(yè)里有些規(guī)則是很有殺傷力的,比如很有名的摩爾定律。

          總結(jié)出這些規(guī)則的意義在于可以大致的照明方向,免得努力來努力去卻走到了陰溝里。

          現(xiàn)實中種種利益紛爭、觀點之爭看似紛繁,但在大時間尺度下來看卻都是規(guī)則的實現(xiàn)手段。

          這就好比下圍棋,每一手都要為謀得利益而計算,但結(jié)局卻只有三種:贏、輸或和,這就是規(guī)則的力量。

           

          民以食為天,所以第一定律從收入開始。

           

          程序員第一定律可以表述為:程序員的收入是技能復(fù)雜度和技能實現(xiàn)可能程度的函數(shù)。

          如果程序員的工資是S,社會平均水平的工資為A,程序員掌握的技能復(fù)雜度為C,實現(xiàn)程度為P

          那么S = A x C x P。

           

          這里面的實現(xiàn)程度P不太好理解,額外做點說明。

          好比說有人在東北種了很多白菜,并獲得了大豐收。與此同時廣州也確實需要大白菜,按批發(fā)價他的這批白菜可以買10萬。

          但關(guān)鍵是這個人找不到車皮,大白菜就只能在當?shù)亓闶郏@個時候這批大白菜就只能買1萬塊錢。

          這就是實現(xiàn)程度。

          大白菜內(nèi)蘊了既定的價值,這種價值并不因為賣多少錢而改變,但這種價值能實現(xiàn)到什么程度則依賴于現(xiàn)實的可能性。

           

          這視乎很簡單,但其實不是,很多人的一生就籠罩在這條定律下面,我們來基于這第一定律繼續(xù)做些推導(dǎo)。

           

          • 推論1:越容易上手的技術(shù),其內(nèi)蘊價值越低。

           

          技能的復(fù)雜度C可以大致等價于掌握一門技術(shù)所需要的時間。

           

          各種集成的開發(fā)環(huán)境,各種容易學(xué)習(xí)的類庫等使軟件開發(fā)的門檻降得很低,這對整個產(chǎn)業(yè)是有利的,但對個體而言則是不利的。

          你花5個月可以學(xué)會的技術(shù),其他人花5個月也可以學(xué)會,而5個月可以學(xué)會的東西所蘊含的價值一定是低的。

          與之相對5年才可以學(xué)會的東西,其內(nèi)蘊價值一定是高的。

          內(nèi)蘊價值低,所對應(yīng)的收入必然偏低。

           

          為避免爭議,我這里就不寫技術(shù)的名字了,但大家可以從學(xué)習(xí)所需要的時間上來對各種技術(shù)做個分類。

           

          有時候很多人會有一種錯覺,認為越熱門的技術(shù)收益越好。

          這在大多時候是錯的。

          越熱的技術(shù),越成熟的技術(shù)越是大眾的,而越是大眾的技術(shù)內(nèi)蘊價值越低,所以收益越不好。

          熱度能夠幫助找到工作,但對技能復(fù)雜度C沒有影響。

           

          • 推論2:單純的涉獵廣泛,沒有專精,對收入的影響是負面的。

          各種技術(shù)的復(fù)雜度大概是呈指數(shù)增長的,越到后面前進一步越困難。

          好比說學(xué)會5門語言所需要的時間大多時候遠比學(xué)精一門語言要短。

          在特定年紀尚,每樣技術(shù)都會一點,對提高實現(xiàn)程度P略有幫助,但自身可替代性很強,對技能復(fù)雜度C的影響為負面。

          長期來看得不償失。

           

          • 推論3:實現(xiàn)程度P越高,風(fēng)險越大。

          有些技術(shù)領(lǐng)域很窄,上手也慢,實現(xiàn)程度卻高,比如顯卡驅(qū)動,打印驅(qū)動等。

          但這類工作好比在鋼絲上跳舞:只要能實現(xiàn)自己的價值,那么回報大體不錯,但最怕技術(shù)更迭。

          技術(shù)一換代,可能多年積累十去六七。

           

          總結(jié)來看,程序員要想獲得不錯的收入,第一要掌握稀缺的技術(shù),即技術(shù)的內(nèi)蘊價值要高;第二要找到實現(xiàn)稀缺技術(shù)的場景。

          《微軟的秘密》一書中提到,微軟里面優(yōu)秀的程序員是可以擁有許多輛保時捷的。

          用上面兩條做分解,就會發(fā)現(xiàn)原因很簡單:

          一是這樣的人是NT的核心開發(fā)人員,這類人員內(nèi)蘊價值極高,處于稀缺狀態(tài);二是微軟提供了實現(xiàn)這種技能內(nèi)蘊價值的機會。

          這二者缺一不可。

          #根據(jù)大家的回復(fù)做了點修改把"實現(xiàn)可能性"替換成了"實現(xiàn)程度"。


          2012世界末日暨環(huán)境保護主題站,關(guān)注國內(nèi)外最新2012世界末日信息,旨在通過關(guān)注,收集,展示2012世界末日相關(guān)資料的方式,喚醒并提高人們保護環(huán)境與愛護地球的意識,引導(dǎo)人類保護環(huán)境.
          posted @ 2012-02-14 22:03 todayx.org 閱讀(557) | 評論 (4)編輯 收藏

          什么是HTTP協(xié)議

          協(xié)議是指計算機通信網(wǎng)絡(luò)中兩臺計算機之間進行通信所必須共同遵守的規(guī)定或規(guī)則,超文本傳輸協(xié)議(HTTP)是一種通信協(xié)議,它允許將超文本標記語言(HTML)文檔從Web服務(wù)器傳送到客戶端的瀏覽器

           

          目前我們使用的是HTTP/1.1 版本

          Web服務(wù)器,瀏覽器,代理服務(wù)器

          當我們打開瀏覽器,在地址欄中輸入URL,然后我們就看到了網(wǎng)頁。 原理是怎樣的呢?

          實際上我們輸入URL后,我們的瀏覽器給Web服務(wù)器發(fā)送了一個Request, Web服務(wù)器接到Request后進行處理,生成相應(yīng)的Response,然后發(fā)送給瀏覽器, 瀏覽器解析Response中的HTML,這樣我們就看到了網(wǎng)頁,過程如下圖所示

           

           

           

          我們的Request 有可能是經(jīng)過了代理服務(wù)器,最后才到達Web服務(wù)器的。

          過程如下圖所示

           

          代理服務(wù)器就是網(wǎng)絡(luò)信息的中轉(zhuǎn)站,有什么功能呢?

          1. 提高訪問速度, 大多數(shù)的代理服務(wù)器都有緩存功能。

          2. 突破限制, 也就是翻-墻了

          3. 隱藏身份。

           

          URL詳解

           URL(Uniform Resource Locator) 地址用于描述一個網(wǎng)絡(luò)上的資源,  基本格式如下

          schema://host[:port#]/path/.../[?query-string][#anchor]

          scheme               指定低層使用的協(xié)議(例如:http, https, ftp)

          host                   HTTP服務(wù)器的IP地址或者域名

          port#                 HTTP服務(wù)器的默認端口是80,這種情況下端口號可以省略。如果使用了別的端口,必須指明,例如 http://www.cnblogs.com:8080/

          path                   訪問資源的路徑

          query-string       發(fā)送給http服務(wù)器的數(shù)據(jù)

          anchor-             錨

           

          URL 的一個例子

          http://www.mywebsite.com/sj/test/test.aspx?name=sviergn&x=true#stuff  Schema:                 http host:                   www.mywebsite.com path:                   /sj/test Query String:           name=sviergn&x=true Anchor:                 stuff

           

          HTTP協(xié)議是無狀態(tài)的

          http協(xié)議是無狀態(tài)的,同一個客戶端的這次請求和上次請求是沒有對應(yīng)關(guān)系,對http服務(wù)器來說,它并不知道這兩個請求來自同一個客戶端。 為了解決這個問題, Web程序引入了Cookie機制來維護狀態(tài).

           

          HTTP消息的結(jié)構(gòu)

          先看Request 消息的結(jié)構(gòu),   Request 消息分為3部分,第一部分叫Request line, 第二部分叫Request header, 第三部分是body. header和body之間有個空行, 結(jié)構(gòu)如下圖

          第一行中的Method表示請求方法,比如"POST","GET",  Path-to-resoure表示請求的資源, Http/version-number 表示HTTP協(xié)議的版本號

          當使用的是"GET" 方法的時候, body是為空的

          比如我們打開博客園首頁的request 如下

          GET http://www.cnblogs.com/ HTTP/1.1 Host: www.cnblogs.com

          下面我們打開Fiddler 捕捉一個博客園登錄的Request 然后分析下它的結(jié)構(gòu), 在Inspectors tab下以Raw的方式可以看到完整的Request的消息,   如下圖

           

          我們再看Response消息的結(jié)構(gòu), 和Request消息的結(jié)構(gòu)基本一樣。 同樣也分為三部分,第一部分叫Response line, 第二部分叫Response header,第三部分是body. header和body之間也有個空行,  結(jié)構(gòu)如下圖

          HTTP/version-number表示HTTP協(xié)議的版本號,  status-code 和message 請看下節(jié)[狀態(tài)代碼]的詳細解釋.

          我們用Fiddler 捕捉一個博客園首頁的Response然后分析下它的結(jié)構(gòu), 在Inspectors tab下以Raw的方式可以看到完整的Response的消息,   如下圖

           

           

          Get和Post方法的區(qū)別

          Http協(xié)議定義了很多與服務(wù)器交互的方法,最基本的有4種,分別是GET,POST,PUT,DELETE. 一個URL地址用于描述一個網(wǎng)絡(luò)上的資源,而HTTP中的GET, POST, PUT, DELETE就對應(yīng)著對這個資源的查,改,增,刪4個操作。 我們最常見的就是GET和POST了。GET一般用于獲取/查詢資源信息,而POST一般用于更新資源信息.

          我們看看GET和POST的區(qū)別

          1. GET提交的數(shù)據(jù)會放在URL之后,以?分割URL和傳輸數(shù)據(jù),參數(shù)之間以&相連,如EditPosts.aspx?name=test1&id=123456.  POST方法是把提交的數(shù)據(jù)放在HTTP包的Body中.

          2. GET提交的數(shù)據(jù)大小有限制(因為瀏覽器對URL的長度有限制),而POST方法提交的數(shù)據(jù)沒有限制.

          3. GET方式需要使用Request.QueryString來取得變量的值,而POST方式通過Request.Form來獲取變量的值。

          4. GET方式提交數(shù)據(jù),會帶來安全問題,比如一個登錄頁面,通過GET方式提交數(shù)據(jù)時,用戶名和密碼將出現(xiàn)在URL上,如果頁面可以被緩存或者其他人可以訪問這臺機器,就可以從歷史記錄獲得該用戶的賬號和密碼.

           

          狀態(tài)碼

          Response 消息中的第一行叫做狀態(tài)行,由HTTP協(xié)議版本號, 狀態(tài)碼, 狀態(tài)消息 三部分組成。

          狀態(tài)碼用來告訴HTTP客戶端,HTTP服務(wù)器是否產(chǎn)生了預(yù)期的Response.

          HTTP/1.1中定義了5類狀態(tài)碼, 狀態(tài)碼由三位數(shù)字組成,第一個數(shù)字定義了響應(yīng)的類別

          1XX  提示信息 - 表示請求已被成功接收,繼續(xù)處理

          2XX  成功 - 表示請求已被成功接收,理解,接受

          3XX  重定向 - 要完成請求必須進行更進一步的處理

          4XX  客戶端錯誤 -  請求有語法錯誤或請求無法實現(xiàn)

          5XX  服務(wù)器端錯誤 -   服務(wù)器未能實現(xiàn)合法的請求

           

          看看一些常見的狀態(tài)碼

          200 OK

          最常見的就是成功響應(yīng)狀態(tài)碼200了, 這表明該請求被成功地完成,所請求的資源發(fā)送回客戶端

          如下圖, 打開博客園首頁

           

          302 Found

          重定向,新的URL會在response 中的Location中返回,瀏覽器將會自動使用新的URL發(fā)出新的Request

          例如在IE中輸入, http://www.google.com. HTTP服務(wù)器會返回304, IE取到Response中Location header的新URL, 又重新發(fā)送了一個Request.

           

          304 Not Modified

          代表上次的文檔已經(jīng)被緩存了, 還可以繼續(xù)使用,

          例如打開博客園首頁, 發(fā)現(xiàn)很多Response 的status code 都是304

          提示: 如果你不想使用本地緩存可以用Ctrl+F5 強制刷新頁面

           

          400 Bad Request  客戶端請求與語法錯誤,不能被服務(wù)器所理解

          403 Forbidden 服務(wù)器收到請求,但是拒絕提供服務(wù)

          404 Not Found

          請求資源不存在(輸錯了URL)

          比如在IE中輸入一個錯誤的URL, http://www.cnblogs.com/tesdf.aspx

           

          500 Internal Server Error 服務(wù)器發(fā)生了不可預(yù)期的錯誤

          503 Server Unavailable 服務(wù)器當前不能處理客戶端的請求,一段時間后可能恢復(fù)正常

           

          HTTP Request header

          使用Fiddler 能很方便的查看Reques header, 點擊Inspectors tab ->Request tab-> headers  如下圖所示.

          header 有很多,比較難以記憶,我們也按照Fiddler那樣把header 進行分類,這樣比較清晰也容易記憶。

          Cache 頭域

          If-Modified-Since

          作用: 把瀏覽器端緩存頁面的最后修改時間發(fā)送到服務(wù)器去,服務(wù)器會把這個時間與服務(wù)器上實際文件的最后修改時間進行對比。如果時間一致,那么返回304,客戶端 就直接使用本地緩存文件。如果時間不一致,就會返回200和新的文件內(nèi)容。客戶端接到之后,會丟棄舊文件,把新文件緩存起來,并顯示在瀏覽器中.

          例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT

          實例如下圖

           

          If-None-Match

          作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 當用戶再次請求該資源時,將在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服務(wù)器驗證資源的ETag沒有改變(該資源沒有更新),將返回一個304狀態(tài)告訴客戶端使用 本地緩存文件。否則將返回200狀態(tài)和新的資源和Etag.  使用這樣的機制將提高網(wǎng)站的性能

          例如: If-None-Match: "03f2b33c0bfcc1:0"

          實例如下圖

           

          Pragma

          作用: 防止頁面被緩存, 在HTTP/1.1版本中,它和Cache-Control:no-cache作用一模一樣

          Pargma只有一個用法, 例如: Pragma: no-cache

          注意: 在HTTP/1.0版本中,只實現(xiàn)了Pragema:no-cache, 沒有實現(xiàn)Cache-Control

           

          Cache-Control

          作用: 這個是非常重要的規(guī)則。 這個用來指定Response-Request遵循的緩存機制。各個指令含義如下

          Cache-Control:Public   可以被任何緩存所緩存()

          Cache-Control:Private     內(nèi)容只緩存到私有緩存中

          Cache-Control:no-cache  所有內(nèi)容都不會被緩存

          還有其他的一些用法, 我沒搞懂其中的意思, 請大家參考其他的資料

           

          Client 頭域

          Accept

          作用: 瀏覽器端可以接受的媒體類型,

          例如:  Accept: text/html  代表瀏覽器可以接受服務(wù)器回發(fā)的類型為 text/html  也就是我們常說的html文檔,

          如果服務(wù)器無法返回text/html類型的數(shù)據(jù),服務(wù)器應(yīng)該返回一個406錯誤(non acceptable)

          通配符 * 代表任意類型

          例如  Accept: */*  代表瀏覽器可以處理所有類型,(一般瀏覽器發(fā)給服務(wù)器都是發(fā)這個)

           

          Accept-Encoding:

          作用: 瀏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支持壓縮,支持什么壓縮方法(gzip,deflate),(注意:這不是只字符編碼);

          例如: Accept-Encoding: gzip, deflate

           

          Accept-Language

          作用: 瀏覽器申明自己接收的語言。 

          語言跟字符集的區(qū)別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等;

          例如: Accept-Language: en-us

           

          User-Agent

          作用:告訴HTTP服務(wù)器, 客戶端使用的操作系統(tǒng)和瀏覽器的名稱和版本.

          我們上網(wǎng)登陸論壇的時候,往往會看到一些歡迎信息,其中列出了你的操作系統(tǒng)的名稱和版本,你所使用的瀏覽器的名稱和版本,這往往讓很多人感到很神 奇,實際上,服務(wù)器應(yīng)用程序就是從User-Agent這個請求報頭域中獲取到這些信息User-Agent請求報頭域允許客戶端將它的操作系統(tǒng)、瀏覽器 和其它屬性告訴服務(wù)器。

          例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)

           

          Accept-Charset

          作用:瀏覽器申明自己接收的字符集,這就是本文前面介紹的各種字符集和字符編碼,如gb2312,utf-8(通常我們說Charset包括了相應(yīng)的字符編碼方案);

          例如:

           

          Cookie/Login 頭域

          Cookie:

          作用: 最重要的header, 將cookie的值發(fā)送給HTTP 服務(wù)器

          Entity頭域

          Content-Length

          作用:發(fā)送給HTTP服務(wù)器數(shù)據(jù)的長度。

          例如: Content-Length: 38

           

          Content-Type

          作用:

          例如:Content-Type: application/x-www-form-urlencoded

           

          Miscellaneous 頭域

          Referer:

          作用: 提供了Request的上下文信息的服務(wù)器,告訴服務(wù)器我是從哪個鏈接過來的,比如從我主頁上鏈接到一個朋友那里,他的服務(wù)器就能夠從HTTP Referer中統(tǒng)計出每天有多少用戶點擊我主頁上的鏈接訪問他的網(wǎng)站。

          例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT

          Transport 頭域

          Connection

          例如: Connection: keep-alive   當一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉,如果客戶端再次訪問這個服務(wù)器上的網(wǎng)頁,會繼續(xù)使用這一條已經(jīng)建立的連接

          例如:  Connection: close  代表一個Request完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接會關(guān)閉, 當客戶端再次發(fā)送Request,需要重新建立TCP連接。

           

          Host(發(fā)送請求時,該報頭域是必需的)

          作用: 請求報頭域主要用于指定被請求資源的Internet主機和端口號,它通常從HTTP URL中提取出來的

          例如: 我們在瀏覽器中輸入:http://www.guet.edu.cn/index.html

          瀏覽器發(fā)送的請求消息中,就會包含Host請求報頭域,如下:

          Host:http://www.guet.edu.cn

          此處使用缺省端口號80,若指定了端口號,則變成:Host:指定端口號

           

          HTTP Response header

          同樣使用Fiddler 查看Response header, 點擊Inspectors tab ->Response tab-> headers  如下圖所示

           我們也按照Fiddler那樣把header 進行分類,這樣比較清晰也容易記憶。

          Cache頭域

          Date

          作用:  生成消息的具體時間和日期

          例如: Date: Sat, 11 Feb 2012 11:35:14 GMT 

           

          Expires

          作用: 瀏覽器會在指定過期時間內(nèi)使用本地緩存

          例如: Expires: Tue, 08 Feb 2022 11:35:14 GMT

           

          Vary

          作用:

          例如: Vary: Accept-Encoding

           

          Cookie/Login 頭域

          P3P

          作用: 用于跨域設(shè)置Cookie, 這樣可以解決iframe跨域訪問cookie的問題

          例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR

           

          Set-Cookie

          作用: 非常重要的header, 用于把cookie 發(fā)送到客戶端瀏覽器, 每一個寫入cookie都會生成一個Set-Cookie.

          例如: Set-Cookie: sc=4c31523a; path=/; domain=.acookie.taobao.com

           

          Entity頭域

          ETag

          作用:  和If-None-Match 配合使用。 (實例請看上節(jié)中If-None-Match的實例)

          例如: ETag: "03f2b33c0bfcc1:0"

           

          Last-Modified:

          作用: 用于指示資源的最后修改日期和時間。(實例請看上節(jié)的If-Modified-Since的實例)

          例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT

           

          Content-Type

          作用:WEB服務(wù)器告訴瀏覽器自己響應(yīng)的對象的類型和字符集,

          例如:

          Content-Type: text/html; charset=utf-8

          Content-Type:text/html;charset=GB2312

          Content-Type: image/jpeg

           

          Content-Length

          指明實體正文的長度,以字節(jié)方式存儲的十進制數(shù)字來表示。在數(shù)據(jù)下行的過程中,Content-Length的方式要預(yù)先在服務(wù)器中緩存所有數(shù)據(jù),然后所有數(shù)據(jù)再一股腦兒地發(fā)給客戶端。

          例如: Content-Length: 19847

           

          Content-Encoding

          WEB服務(wù)器表明自己使用了什么壓縮方法(gzip,deflate)壓縮響應(yīng)中的對象。

          例如:Content-Encoding:gzip

           

          Content-Language

          作用: WEB服務(wù)器告訴瀏覽器自己響應(yīng)的對象的語言者

          例如: Content-Language:da

           

          Miscellaneous 頭域

          Server:

          作用:指明HTTP服務(wù)器的軟件信息

          例如:Server: Microsoft-IIS/7.5

           

          X-AspNet-Version:

          作用:如果網(wǎng)站是用ASP.NET開發(fā)的,這個header用來表示ASP.NET的版本

          例如: X-AspNet-Version: 4.0.30319

          X-Powered-By:

          作用:表示網(wǎng)站是用什么技術(shù)開發(fā)的

          例如: X-Powered-By: ASP.NET

          Transport頭域

          Connection

          例如: Connection: keep-alive   當一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉,如果客戶端再次訪問這個服務(wù)器上的網(wǎng)頁,會繼續(xù)使用這一條已經(jīng)建立的連接

          例如:  Connection: close  代表一個Request完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接會關(guān)閉, 當客戶端再次發(fā)送Request,需要重新建立TCP連接。

          Location頭域

          Location

          作用: 用于重定向一個新的位置, 包含新的URL地址

           實例請看304狀態(tài)實例

           

          HTTP協(xié)議是無狀態(tài)的和Connection: keep-alive的區(qū)別

          無狀態(tài)是指協(xié)議對于事務(wù)處理沒有記憶能力,服務(wù)器不知道客戶端是什么狀態(tài)。從另一方面講,打開一個服務(wù)器上的網(wǎng)頁和你之前打開這個服務(wù)器上的網(wǎng)頁之間沒有任何聯(lián)系

          HTTP是一個無狀態(tài)面向連接的協(xié)議,無狀態(tài)不代表HTTP不能保持TCP連接,更不能代表HTTP使用的是UDP協(xié)議(無連接)

          從HTTP/1.1起,默認都開啟了Keep-Alive,保持連接特性,簡單地說,當一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉,如果客戶端再次訪問這個服務(wù)器上的網(wǎng)頁,會繼續(xù)使用這一條已經(jīng)建立的連接

           Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的服務(wù)器軟件(如Apache)中設(shè)定這個時間


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

          作為一個開發(fā)者,尤其是web開發(fā)人員,我想你有必要去了解這一系列的處理流程,在這期間,瀏覽器和服務(wù)器到底是如何打交道的?服務(wù)器又是如何處理的?瀏覽器又是如何將網(wǎng)頁顯示給用戶的呢?......

          疑惑和細節(jié)真是太多了。坦白講,要想徹徹底底的弄清楚以上每個疑惑和處理細節(jié),至少需要十本書的厚度,所謂“底層無極限”嘛,而且不同的web服務(wù) 器和服務(wù)器端編程語言的實現(xiàn)和處理流程不盡相同(但本質(zhì)都是相通的)。本文中,我將根據(jù)http協(xié)議的有關(guān)知識,跟大家講解一些web開發(fā)的本質(zhì)。不管你 是從事.NET,還是J2EE或者php開發(fā)等等,都離不開這些本質(zhì)。希望你讀完本文,能有新的收獲和見解。由于本人水平和經(jīng)驗有限,難免有誤,望讀者見 諒。

           

          何為http協(xié)議(Hypertext Transfer Protocol,超文本傳輸協(xié)議)?

          所謂協(xié)議,就是指雙方遵循的規(guī)范。http協(xié)議,就是瀏覽器和服務(wù)器之間進行“溝通”的一種規(guī)范。我們在看空間,刷微博...都是在使用http協(xié)議,當然,遠遠不止這些應(yīng)用。

          筆者一直聽說http是屬于“應(yīng)用層的協(xié)議”,而且是基于TCP/IP協(xié)議的。這個不難理解,如果你上大學(xué)時候?qū)W過“計算機網(wǎng)絡(luò)”的課程,就一定知 道OSI七層參考協(xié)議(我當時是死記硬背的)。如果你接觸過socket網(wǎng)絡(luò)編程,就應(yīng)該明白TCP和UDP這兩種使用廣泛的通信協(xié)議(建立連接、三次握 手等等,當然,這不是本文討論的重點)。如圖:

          既然TCP/UDP是廣泛使用的網(wǎng)絡(luò)通信協(xié)議,那為啥有多出個http協(xié)議來呢?

          筆者曾自己動手寫過一個簡單的web服務(wù)器處理軟件,根據(jù)我的推斷(不一定準確)。UDP協(xié)議具有不可靠性和不安全性,顯然這很難滿足web應(yīng)用的需要。

          而TCP協(xié)議是基于連接和三次握手的,雖然具有可靠性,但人具有一定的缺陷。但試想一下,普通的C/S架構(gòu)軟件,頂多上千個Client同時連接,而B/S架構(gòu)的網(wǎng)站,十萬人同時在線也是很平常的事兒。如果十萬個客戶端和服務(wù)器一直保持連接狀態(tài),那服務(wù)器如何滿足承載呢?

          這就衍生出了http協(xié)議?;赥CP的可靠性連接。通俗點說,就是在請求之后,服務(wù)器端立即關(guān)閉連接、釋放資源。這樣既保證了資源可用,也吸取了TCP的可靠性的優(yōu)點。

          正因為這點,所以大家通常說http協(xié)議是“無狀態(tài)”的,也就是“服務(wù)器不知道你客戶端干了啥”,其實很大程度上是基于性能考慮的。以至于后來有了session之類的玩意。

           

          實戰(zhàn)準備工作:

          在監(jiān)視網(wǎng)絡(luò)方面,windows平臺上有一款叫做Sniffer的優(yōu)秀軟件,這也是很多“黑客”經(jīng)常使用的嗅探工具。 在研究http協(xié)議時,推薦大家使用一款

          叫作httpwatch的工具。(遺憾的是,該工具是收費的。該咋辦就咋辦,你懂的)。安裝完成后,可以在IE瀏覽器的tools中直接打開(目前也支持firefox)。如圖所示:


           

           

           

           

           

           

          點擊Record,就可以開始監(jiān)視并記錄http消息了。stop、Clear等等按鈕的功能,這里就不一一介紹了。拿實例來說話,下面就是我記錄訪問main.aspx頁面的時候記錄的,能夠清晰的看到http報文消息的詳細信息,如圖:

          學(xué)習(xí)http協(xié)議,主要需要了解http的請求和響應(yīng)(當然,還有g(shù)et、post等請求方式,狀態(tài)碼、URI、MIME等)


          首先看看http請求消息(就是瀏覽器丟給服務(wù)器的):


          一個http請求代表客戶端瀏覽器向服務(wù)器發(fā)送的數(shù)據(jù)。一個完整的http請求消息,包含一個請求行,若干個消息頭(請求頭),換行,實體內(nèi)容

          請求行:描述客戶端的請求方式、請求資源的名稱、http協(xié)議的版本號。 例如: GET/BOOK/JAVA.HTML HTTP/1.1

          請求頭(消息頭)包含(客戶機請求的服務(wù)器主機名,客戶機的環(huán)境信息等):
          Accept:用于告訴服務(wù)器,客戶機支持的數(shù)據(jù)類型  (例如:Accept:text/html,image/*)
          Accept-Charset:用于告訴服務(wù)器,客戶機采用的編碼格式
          Accept-Encoding:用于告訴服務(wù)器,客戶機支持的數(shù)據(jù)壓縮格式
          Accept-Language:客戶機語言環(huán)境
          Host:客戶機通過這個服務(wù)器,想訪問的主機名
          If-Modified-Since:客戶機通過這個頭告訴服務(wù)器,資源的緩存時間
          Referer:客戶機通過這個頭告訴服務(wù)器,它(客戶端)是從哪個資源來訪問服務(wù)器的(防盜鏈)
          User-Agent:客戶機通過這個頭告訴服務(wù)器,客戶機的軟件環(huán)境(操作系統(tǒng),瀏覽器版本等)
          Cookie:客戶機通過這個頭,將Coockie信息帶給服務(wù)器
          Connection:告訴服務(wù)器,請求完成后,是否保持連接
          Date:告訴服務(wù)器,當前請求的時間

          (換行)
          實體內(nèi)容:
          就是指瀏覽器端通過http協(xié)議發(fā)送給服務(wù)器的實體數(shù)據(jù)。例如:name=dylan&id=110
          (get請求時,通過url傳給服務(wù)器的值。post請求時,通過表單發(fā)送給服務(wù)器的值)
           
          再看看HTTP響應(yīng)消息(服務(wù)器返回給瀏覽器的):

          一個http響應(yīng)代表服務(wù)器端向客戶端回送的數(shù)據(jù),它包括:
          一個狀態(tài)行,若干個消息頭,以及實體內(nèi)容

          響應(yīng)頭(消息頭)包含:
          Location:這個頭配合302狀態(tài)嗎,用于告訴客戶端找誰
          Server:服務(wù)器通過這個頭,告訴瀏覽器服務(wù)器的類型
          Content-Encoding:告訴瀏覽器,服務(wù)器的數(shù)據(jù)壓縮格式
          Content-Length:告訴瀏覽器,回送數(shù)據(jù)的長度
          Content-Type:告訴瀏覽器,回送數(shù)據(jù)的類型
          Last-Modified:告訴瀏覽器當前資源緩存時間
          Refresh:告訴瀏覽器,隔多長時間刷新
          Content- Disposition:告訴瀏覽器以下載的方式打開數(shù)據(jù)。例如: context.Response.AddHeader("Content-Disposition","attachment:filename=aa.jpg");                                        context.Response.WriteFile("aa.jpg");
          Transfer-Encoding:告訴瀏覽器,傳送數(shù)據(jù)的編碼格式
          ETag:緩存相關(guān)的頭(可以做到實時更新)
          Expries:告訴瀏覽器回送的資源緩存多長時間。如果是-1或者0,表示不緩存
          Cache-Control:控制瀏覽器不要緩存數(shù)據(jù)   no-cache
          Pragma:控制瀏覽器不要緩存數(shù)據(jù)          no-cache

          Connection:響應(yīng)完成后,是否斷開連接。  close/Keep-Alive
          Date:告訴瀏覽器,服務(wù)器響應(yīng)時間

          理解了以上的http請求消息和響應(yīng)消息,相信你對于http協(xié)議已經(jīng)理解得足夠深刻了。關(guān)于http協(xié)議的更多具體細節(jié),可以參照http RFC文檔

          大致步驟就是:瀏覽器先向服務(wù)器發(fā)送請求,服務(wù)器接收到請求后,做相應(yīng)的處理,然后封裝好響應(yīng)報文,再回送給瀏覽器。瀏覽器拿到響應(yīng)報文后,再通過 瀏覽器引擎去渲染網(wǎng)頁,解析DOM樹,javascript引擎解析并執(zhí)行腳本操作,插件去干插件該干的事兒...關(guān)于瀏覽器渲染、解析的原理,可以參考 http://kb.cnblogs.com/page/129756/

          說白了,所謂web的本質(zhì),無非是:請求/處理/響應(yīng) ,任何的web服務(wù)器,任何的服務(wù)端編程語言,都沒法脫離這個本質(zhì)。 而瀏覽器端解析html、圖片等靜態(tài)內(nèi)容,呈現(xiàn)給用戶,腳本引擎執(zhí)行腳本代碼,完成腳本代碼要做的事兒(例如dom操作,css屬性更改,發(fā)送ajax請 求等等)。

          筆者淺淺的認為,其實瀏覽器就是一種特殊的Client,而B/S架構(gòu)也是一種特殊的C/S架構(gòu)。這里值得一提的是,不同的web服務(wù)器和編程語 言,又是如何接收用戶http請求。如何處理,如何響應(yīng)的呢?筆者拿熟悉的ASP.NET為例,通過反編譯工具查看源代碼(微軟這家伙實在封裝的太好了) 從底層進行了剖析,如圖:

          由于篇幅有限,無法再繼續(xù)將asp.net、iis web服務(wù)器的細節(jié)及底層實現(xiàn)再做進一步地進行剖析了。因為微軟的asp.net技術(shù)體系實在龐大,而且很復(fù)雜。有時間筆者會繼續(xù)更新系列文章,歡迎讀者繼續(xù)關(guān)注。


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-14 21:56 todayx.org 閱讀(279) | 評論 (0)編輯 收藏
               
          2012世界末日暨環(huán)境保護主題站,關(guān)注國內(nèi)外最新2012世界末日信息,旨在通過關(guān)注,收集,展示2012世界末日相關(guān)資料的方式,喚醒并提高人們保護環(huán)境與愛護地球的意識,引導(dǎo)人類保護環(huán)境.



                最近一直比較忙,所以一連幾天都沒有更新。本來覺得沒什么,后來有幾個網(wǎng)友都問起為什么沒有更新,才覺得大家對我的博客還是比較關(guān)心的。于是覺得挺對不起大家的。終于到了周末,昨天晚上忙乎了一晚上,寫了個Swing演示,今天把它共享出來,算是彌補。 

            

              收到一個朋友的郵件說如何在Swing中實現(xiàn)組件的動畫效果,就像JIDE的那些組件一樣。的確Swing框架的靈活性和可擴展性,使得它非常適合做這樣Makeover工作。我簡單總結(jié)一了以下,這種組件不外乎要有以下三種元素:

              1.外觀華麗。這包括使用漸變色,線條和字體反走樣,圖標設(shè)計漂亮搶眼,界面變化要柔和等等。但要避免設(shè)計太花哨,給人華而不實的感覺。原則上避免顏色太 碎,圖標應(yīng)以簡潔為主,不可濫用圖片等。技術(shù)上沒有多大要求,主要是美工,你需要掌握各種做圖工具,自己最好有好的審美和設(shè)計能力。

              2.動畫效果。組件行為變化要柔和化,盡量使用動畫效果,如淡入淡出、滾動彈出等等。技術(shù)上最常用的方法是使用javax.swing.Timer。為什 么要使用javax.swing.Timer,這是因為javax.swing.Timer觸發(fā)的事件都在EDT上執(zhí)行,是線程安全的。除此外還需掌握 Java 2D的常用接口及圖像處理的常見技巧。

              3.空間布局。這種組件空間布局的特點是立體、動態(tài)、拖拽式的。這和人的認知能力有關(guān)。人類認知的特點是具體到抽象。二維、靜態(tài)和鍵盤式操作對普通用戶來 說太過抽象和專業(yè)化,需要一定的輔助學(xué)習(xí)才能理解的。而三維、動態(tài)、拖拽式操作更貼近于感性的認知范疇。因此這類組件經(jīng)常有浮動式窗口、組件布局動態(tài)變化 及拖拽式操作等特征。實現(xiàn)技術(shù)包括布局管理器(LayoutManager)、Swing組件分層結(jié)構(gòu)、Swing事件體系結(jié)構(gòu)以及DnD接口等。   

              美工對于java程序員來說可能比較缺乏,但是華麗外觀不僅僅是美工技術(shù),這包括一些宏觀設(shè)計原則。java程序員完全可以通過掌握這些方針原則來提高自 己的設(shè)計水平。前面文章介紹那個《Swing外觀設(shè)計方針》就是一本這樣的書。至于美工,我覺得如果你有美術(shù)天分,那就要充分利用;如果沒有,那么你可以 模仿,熟悉幾種的圖形工具就完全可以不用自己的畫圖做出比較漂亮的圖標、圖片(當然沒有考慮版權(quán)問題)。我就是后者,但是我發(fā)現(xiàn)我平時只需要PrScrn 鍵(抓圖)、Paint(Windows 畫圖工具,切圖、剪裁、轉(zhuǎn)換格式)、PowerPoint/OpenOffice Imprise(畫圖)、Google Image(搜索圖片)就已經(jīng)足夠了。其他所需的技術(shù)就需要你掌握Swing和Java 2D方方面面的技術(shù)了。當然復(fù)雜的組件不僅僅是靠掌握這些技術(shù)能解決的,可能你還需要能比較好地熟悉各種編程模式。   

              這個朋友特別提到Windows上的折疊式操作面板,他說:   

              另外,我對JIDE中兩個東西很感興趣,一個是CollapsiblePanel(Windows Explorer左邊的常見任務(wù)),點擊后折疊、展開子面板,而且是動畫效果

              因此昨晚就特地試了一下。雖然以前就大概明白使用Timer和布局管理器以及圖像處理就可以實現(xiàn)這些東西,但一直沒有做。昨晚的實驗還是很成功的,大概花 了兩個小時就實現(xiàn)了這個面板。工作過程大概就是分解這些面板組件、解析那部分需要動畫、應(yīng)該在哪兒觸發(fā)何種事件。另外就是編寫這些組件,不斷調(diào)試。這個過 程的大部分時間都被效果調(diào)整占去了。你需要不斷的運行程序,抓取屏幕,然后將它帖到Paint中,然后放大,然后和Windows上的抓圖比較,包括大 小、尺寸、顏色、字體、微觀變化等等。最后算是基本實現(xiàn)了Windows這個折疊式的面板組件。下面的是我的演示程序的一個抓圖:

          高級Swing組件makeover的三要素   

          這個是淡出淡入動畫效果:

          高級Swing組件makeover的三要素   

              下面的Enable Animation的JCheckBox可以設(shè)置是否使用動畫效果。選擇上折疊和展開就具有動畫效果。   

              這個組件的類名是dyno.swing.beans.FolderPane。使用比較簡單: 

              FolderPane fp=new FolderPane();//設(shè)置是否有動畫效果,缺省沒有
              fp.setAnimated(true);//添加子面板      
              fp.addFolder("文件和文件夾任務(wù)", getFileFolderPane());      
              fp.addFolder("其他位置", getOtherPlacePane());      
              fp.addFolder("詳細信息", getDetailsPane());      
              add(fp, BorderLayout.CENTER);  

                  主要接口有兩個:  

              設(shè)置是否要動畫效果      
              public void setAnimated(boolean b)
              添加面板,title是面板標題文字,content是應(yīng)用程序組件
              public void addFolder(String title, JComponent content)
           
             這個演示的源碼可以從這兒下載,是一個NetBeans工程。編譯之后,直接雙擊foldered_pane.jar既可觀看效果。源代碼中有詳細的注解。

              更新:剛剛修改了一下,現(xiàn)在可以支持JScrollPane,即能放到JScrollPane,并能在動畫時動態(tài)的更新JScrollPane狀態(tài)。

          高級Swing組件makeover的三要素


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-08 21:26 todayx.org 閱讀(365) | 評論 (2)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          程序員到底可以做多久,這個職業(yè)是否真的到35歲就終止?帶著這個問題,和所有有此疑問和憂慮的朋友們探討。先說說我自己的觀點吧。要回答這個問題,我們首先要回答另外幾個問題。

           

               1. 人得學(xué)習(xí)能力是否會隨著年齡的增長而變差?

           

               可能是如此,我兩歲的兒子一首唐詩說兩遍就記住了,很長繞口的兒歌《小熊過橋》幾乎能一字不差的唱完;而我是顯然辦不到的。不過發(fā)現(xiàn)一個事實,就是人的學(xué) 習(xí)能力不僅僅是靠記憶能力,跟邏輯思維能力,還有人的經(jīng)驗也有很大的關(guān)系;我們每個人也許都發(fā)現(xiàn),你如果只是個優(yōu)秀的Java程序員,如果要你去維護一 個.net的系統(tǒng),不出兩個月, 你馬上就是一個.net專家。因為你知道相關(guān)的知識怎么學(xué)習(xí),知道如何才能最快定位問題的一般方法。我個人是個完全不懂php得人,結(jié)果被強拉過去搞了個 php的項目,結(jié)果被認為是php expert!  所以我的最終答案是,人得記憶力更年齡成反比,但是學(xué)習(xí)能力跟年齡成正比。

           

                2. 人的年齡越大,精力會跟不上程序員這樣高強度的工作嗎?

           

                我的答案也是否定的。首先這是個偽命題,沒有哪件事情是輕松的;你覺得別人比你輕松,那也只是你覺得而已。大體上個人的回報跟付出是成正比的。其實隨著你 的年齡增長,知識積累越多,經(jīng)驗越豐富,你的工作效率會更高。5年前你修一個Bug要一個星期,現(xiàn)在也許10分鐘就夠了,并且是又快又好。難道不是這樣 嗎?所以你的工作強度事實上會變得更低,因為你的效率更高,你會有更多時間喝咖啡,也會遭你鄰桌的同事低語“這家伙每天無所事事,咋工資比我高那么多?” 因為你的10分鐘就抵別人的一個星期。

           

               3. 人的年齡越大,就沒有激情學(xué)習(xí)新知識了嗎?

           

                對有些人是,對有些人不是。計算機科學(xué)日新月異,確實更新相當快。你真的會跟不上腳步嗎?可能會,如果你自己不學(xué)習(xí)。但我一定要亦步亦趨嗎?也不見得,無 論如何,即便是軟件開發(fā),也還是有方向,有領(lǐng)域,你只要更上你需要更上的節(jié)奏就夠了。今天請我的一個兄弟給我講了下Struts應(yīng)用,就是給我搞個最小化 的Struts項目,包含所有Struct的重要知識點,然后搬個椅子坐我旁邊,花上半個小時跟我講解;我現(xiàn)在儼然Struts專家了,不信,我跟你講講 看? 呵呵,開玩笑了。

              

              如果我們覺得每天吃飯不是件枯燥無趣的事,我們應(yīng)該也不太會拒絕不斷學(xué)習(xí);如果我們一定會因為自然規(guī)律而失去某些優(yōu)勢,記得你其實有更多的優(yōu)勢可以彌補;最重要的是,做你喜歡的事,做你能做的事情。


              正月十五,明月高懸;祝福各位龍圖大展!


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-07 13:46 todayx.org 閱讀(596) | 評論 (0)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          --核心類主要有:
          org.jfree.chart.JFreeChart :圖表對象,任何類型的圖表的最終表現(xiàn)形式都是在該對象進行一些屬性的定制。JFreeChart引擎本身提供了一個工廠類用于創(chuàng)建不同類型的圖表對象
          org.jfree.data.category.XXXDataSet: 數(shù)據(jù)集對象,用于提供顯示圖表所用的數(shù)據(jù)。根據(jù)不同類型的圖表對應(yīng)著很多類型的數(shù)據(jù)集對象類
          org.jfree.chart.plot.XXXPlot :圖表區(qū)域?qū)ο?,基本上這個對象決定著什么樣式的圖表,創(chuàng)建該對象的時候需要Axis、Renderer以及數(shù)據(jù)集對象的支持
          org.jfree.chart.axis.XXXAxis :用于處理圖表的兩個軸:縱軸和橫軸
          org.jfree.chart.render.XXXRender :負責(zé)如何顯示一個圖表對象
          org.jfree.chart.urls.XXXURLGenerator: 用于生成Web圖表中每個項目的鼠標點擊鏈接
          XXXXXToolTipGenerator: 用于生成圖象的幫助提示,不同類型圖表對應(yīng)不同類型的工具提示類


          JFreeChart類:
          void setAntiAlias(boolean flag) 字體模糊邊界
          void setBackgroundImage(Image image) 背景圖片
          void setBackgroundImageAlignment(int alignment) 背景圖片對齊方式(參數(shù)常量在org.jfree.ui.Align類中定義)
          void setBackgroundImageAlpha(float alpha) 背景圖片透明度(0.0~1.0)
          void setBackgroundPaint(Paint paint) 背景色
          void setBorderPaint(Paint paint) 邊界線條顏色
          void setBorderStroke(Stroke stroke) 邊界線條筆觸
          void setBorderVisible(boolean visible) 邊界線條是否可見

          -----------------------------------------------------------------------------------------------------------

          TextTitle類:
          void setFont(Font font) 標題字體
          void setPaint(Paint paint) 標題字體顏色
          void setText(String text) 標題內(nèi)容

          -----------------------------------------------------------------------------------------------------------

          StandardLegend(Legend)類:
          void setBackgroundPaint(Paint paint) 圖示背景色
          void setTitle(String title) 圖示標題內(nèi)容
          void setTitleFont(Font font) 圖示標題字體
          void setBoundingBoxArcWidth(int arcWidth) 圖示邊界圓角寬
          void setBoundingBoxArcHeight(int arcHeight) 圖示邊界圓角高
          void setOutlinePaint(Paint paint) 圖示邊界線條顏色
          void setOutlineStroke(Stroke stroke) 圖示邊界線條筆觸
          void setDisplaySeriesLines(boolean flag) 圖示項是否顯示橫線(折線圖有效)
          void setDisplaySeriesShapes(boolean flag) 圖示項是否顯示形狀(折線圖有效)
          void setItemFont(Font font) 圖示項字體
          void setItemPaint(Paint paint) 圖示項字體顏色
          void setAnchor(int anchor) 圖示在圖表中的顯示位置(參數(shù)常量在Legend類中定義)

          -----------------------------------------------------------------------------------------------------------

          Axis類:
          void setVisible(boolean flag) 坐標軸是否可見
          void setAxisLinePaint(Paint paint) 坐標軸線條顏色(3D軸無效)
          void setAxisLineStroke(Stroke stroke) 坐標軸線條筆觸(3D軸無效)
          void setAxisLineVisible(boolean visible) 坐標軸線條是否可見(3D軸無效)
          void setFixedDimension(double dimension) (用于復(fù)合表中對多坐標軸的設(shè)置)
          void setLabel(String label) 坐標軸標題
          void setLabelFont(Font font) 坐標軸標題字體
          void setLabelPaint(Paint paint) 坐標軸標題顏色
          void setLabelAngle(double angle) 坐標軸標題旋轉(zhuǎn)角度(縱坐標可以旋轉(zhuǎn))
          void setTickLabelFont(Font font) 坐標軸標尺值字體
          void setTickLabelPaint(Paint paint) 坐標軸標尺值顏色
          void setTickLabelsVisible(boolean flag) 坐標軸標尺值是否顯示
          void setTickMarkPaint(Paint paint) 坐標軸標尺顏色
          void setTickMarkStroke(Stroke stroke) 坐標軸標尺筆觸
          void setTickMarksVisible(boolean flag) 坐標軸標尺是否顯示

          ValueAxis(Axis)類:
          void setAutoRange(boolean auto) 自動設(shè)置數(shù)據(jù)軸數(shù)據(jù)范圍
          void setAutoRangeMinimumSize(double size) 自動設(shè)置數(shù)據(jù)軸數(shù)據(jù)范圍時數(shù)據(jù)范圍的最小跨度
          void setAutoTickUnitSelection(boolean flag) 數(shù)據(jù)軸的數(shù)據(jù)標簽是否自動確定(默認為true)
          void setFixedAutoRange(double length) 數(shù)據(jù)軸固定數(shù)據(jù)范圍(設(shè)置100的話就是顯示MAXVALUE到MAXVALUE-100那段數(shù)據(jù)范圍)
          void setInverted(boolean flag) 數(shù)據(jù)軸是否反向(默認為false)
          void setLowerMargin(double margin) 數(shù)據(jù)軸下(左)邊距
          void setUpperMargin(double margin) 數(shù)據(jù)軸上(右)邊距
          void setLowerBound(double min) 數(shù)據(jù)軸上的顯示最小值
          void setUpperBound(double max) 數(shù)據(jù)軸上的顯示最大值
          void setPositiveArrowVisible(boolean visible) 是否顯示正向箭頭(3D軸無效)
          void setNegativeArrowVisible(boolean visible) 是否顯示反向箭頭(3D軸無效)
          void setVerticalTickLabels(boolean flag) 數(shù)據(jù)軸數(shù)據(jù)標簽是否旋轉(zhuǎn)到垂直
          void setStandardTickUnits(TickUnitSource source) 數(shù)據(jù)軸的數(shù)據(jù)標簽(可以只顯示整數(shù)標簽,需要將AutoTickUnitSelection設(shè)false)

          NumberAxis(ValueAxis)類:
          void setAutoRangeIncludesZero(boolean flag) 是否強制在自動選擇的數(shù)據(jù)范圍中包含0
          void setAutoRangeStickyZero(boolean flag) 是否強制在整個數(shù)據(jù)軸中包含0,即使0不在數(shù)據(jù)范圍中
          void setNumberFormatOverride(NumberFormat formatter) 數(shù)據(jù)軸數(shù)據(jù)標簽的顯示格式
          void setTickUnit(NumberTickUnit unit) 數(shù)據(jù)軸的數(shù)據(jù)標簽(需要將AutoTickUnitSelection設(shè)false)

          DateAxis(ValueAxis)類:
          void setMaximumDate(Date maximumDate) 日期軸上的最小日期
          void setMinimumDate(Date minimumDate) 日期軸上的最大日期
          void setRange(Date lower,Date upper) 日期軸范圍
          void setDateFormatOverride(DateFormat formatter) 日期軸日期標簽的顯示格式
          void setTickUnit(DateTickUnit unit) 日期軸的日期標簽(需要將AutoTickUnitSelection設(shè)false)
          void setTickMarkPosition(DateTickMarkPosition position) 日期標簽位置(參數(shù)常量在org.jfree.chart.axis.DateTickMarkPosition類中定義)

          CategoryAxis(Axis)類:
          void setCategoryMargin(double margin) 分類軸邊距
          void setLowerMargin(double margin) 分類軸下(左)邊距
          void setUpperMargin(double margin) 分類軸上(右)邊距
          void setVerticalCategoryLabels(boolean flag) 分類軸標題是否旋轉(zhuǎn)到垂直
          void setMaxCategoryLabelWidthRatio(float ratio) 分類軸分類標簽的最大寬度

          -----------------------------------------------------------------------------------------------------------

          Plot類:
          void setBackgroundImage(Image image) 數(shù)據(jù)區(qū)的背景圖片
          void setBackgroundImageAlignment(int alignment) 數(shù)據(jù)區(qū)的背景圖片對齊方式(參數(shù)常量在org.jfree.ui.Align類中定義)
          void setBackgroundPaint(Paint paint) 數(shù)據(jù)區(qū)的背景圖片背景色
          void setBackgroundAlpha(float alpha) 數(shù)據(jù)區(qū)的背景透明度(0.0~1.0)
          void setForegroundAlpha(float alpha) 數(shù)據(jù)區(qū)的前景透明度(0.0~1.0)
          void setDataAreaRatio(double ratio) 數(shù)據(jù)區(qū)占整個圖表區(qū)的百分比
          void setOutLinePaint(Paint paint) 數(shù)據(jù)區(qū)的邊界線條顏色
          void setOutLineStroke(Stroke stroke) 數(shù)據(jù)區(qū)的邊界線條筆觸
          void setNoDataMessage(String message) 沒有數(shù)據(jù)時顯示的消息
          void setNoDataMessageFont(Font font) 沒有數(shù)據(jù)時顯示的消息字體
          void setNoDataMessagePaint(Paint paint) 沒有數(shù)據(jù)時顯示的消息顏色

          CategoryPlot(Plot)類:
          void setDataset(CategoryDataset dataset) 數(shù)據(jù)區(qū)的2維數(shù)據(jù)表
          void setColumnRenderingOrder(SortOrder order) 數(shù)據(jù)分類的排序方式
          void setAxisOffset(Spacer offset) 坐標軸到數(shù)據(jù)區(qū)的間距
          void setOrientation(PlotOrientation orientation) 數(shù)據(jù)區(qū)的方向(PlotOrientation.HORIZONTAL或PlotOrientation.VERTICAL)
          void setDomainAxis(CategoryAxis axis) 數(shù)據(jù)區(qū)的分類軸
          void setDomainAxisLocation(AxisLocation location) 分類軸的位置(參數(shù)常量在org.jfree.chart.axis.AxisLocation類中定義)
          void setDomainGridlinesVisible(boolean visible) 分類軸網(wǎng)格是否可見
          void setDomainGridlinePaint(Paint paint) 分類軸網(wǎng)格線條顏色
          void setDomainGridlineStroke(Stroke stroke) 分類軸網(wǎng)格線條筆觸
          void setRangeAxis(ValueAxis axis) 數(shù)據(jù)區(qū)的數(shù)據(jù)軸
          void setRangeAxisLocation(AxisLocation location) 數(shù)據(jù)軸的位置(參數(shù)常量在org.jfree.chart.axis.AxisLocation類中定義)
          void setRangeGridlinesVisible(boolean visible) 數(shù)據(jù)軸網(wǎng)格是否可見
          void setRangeGridlinePaint(Paint paint) 數(shù)據(jù)軸網(wǎng)格線條顏色
          void setRangeGridlineStroke(Stroke stroke) 數(shù)據(jù)軸網(wǎng)格線條筆觸
          void setRenderer(CategoryItemRenderer renderer) 數(shù)據(jù)區(qū)的表示者(詳見Renderer組)
          void addAnnotation(CategoryAnnotation annotation) 給數(shù)據(jù)區(qū)加一個注釋
          void addRangeMarker(Marker marker,Layer layer) 給數(shù)據(jù)區(qū)加一個數(shù)值范圍區(qū)域

          PiePlot(Plot)類:
          void setDataset(PieDataset dataset) 數(shù)據(jù)區(qū)的1維數(shù)據(jù)表
          void setIgnoreNullValues(boolean flag) 忽略無值的分類
          void setCircular(boolean flag) 餅圖是否一定是正圓
          void setStartAngle(double angle) 餅圖的初始角度
          void setDirection(Rotation direction) 餅圖的旋轉(zhuǎn)方向
          void setExplodePercent(int section,double percent) 抽取的那塊(1維數(shù)據(jù)表的分類下標)以及抽取出來的距離(0.0~1.0),3D餅圖無效
          void setLabelBackgroundPaint(Paint paint) 分類標簽的底色
          void setLabelFont(Font font) 分類標簽的字體
          void setLabelPaint(Paint paint) 分類標簽的字體顏色
          void setLabelLinkMargin(double margin) 分類標簽與圖的連接線邊距
          void setLabelLinkPaint(Paint paint) 分類標簽與圖的連接線顏色
          void setLabelLinkStroke(Stroke stroke) 分類標簽與圖的連接線筆觸
          void setLabelOutlinePaint(Paint paint) 分類標簽邊框顏色
          void setLabelOutlineStroke(Paint paint) 分類標簽邊框筆觸
          void setLabelShadowPaint(Paint paint) 分類標簽陰影顏色
          void setMaximumLabelWidth(double width) 分類標簽的最大長度(0.0~1.0)
          void setPieIndex(int index) 餅圖的索引(復(fù)合餅圖中用到)
          void setPieIndex(int index)    餅圖的索引(復(fù)合餅圖中用到)
          void setSectionOutlinePaint(int section,Paint paint) 指定分類餅的邊框顏色
          void setSectionOutlineStroke(int section,Stroke stroke) 指定分類餅的邊框筆觸
          void setSectionPaint(int section,Paint paint) 指定分類餅的顏色
          void setShadowPaint(Paint paint)   餅圖的陰影顏色
          void setShadowXOffset(double offset)   餅圖的陰影相對圖的水平偏移
          void setShadowYOffset(double offset)   餅圖的陰影相對圖的垂直偏移
          void setLabelGenerator(PieSectionLabelGenerator generator) 分類標簽的格式,設(shè)置成null則整個標簽包括連接線都不顯示
          void setToolTipGenerator(PieToolTipGenerator generator) MAP中鼠標移上的顯示格式
          void setURLGenerator(PieURLGenerator generator)   MAP中鉆取鏈接格式

          PiePlot3D(PiePlot)類:
          void setDepthFactor(double factor)   3D餅圖的Z軸高度(0.0~1.0)

          MultiplePiePlot(Plot)類:
          void setLimit(double limit)    每個餅圖之間的數(shù)據(jù)關(guān)聯(lián)(詳細比較復(fù)雜)  
          void setPieChart(JFreeChart pieChart)   每個餅圖的顯示方式(見JFreeChart類個PiePlot類)

          -----------------------------------------------------------------------------------------------------------


          AbstractRenderer類:
          void setItemLabelAnchorOffset(double offset)     數(shù)據(jù)標簽的與數(shù)據(jù)點的偏移
          void setItemLabelsVisible(boolean visible)     數(shù)據(jù)標簽是否可見
          void setItemLabelFont(Font font)      數(shù)據(jù)標簽的字體
          void setItemLabelPaint(Paint paint)      數(shù)據(jù)標簽的字體顏色
          void setItemLabelPosition(ItemLabelPosition position)    數(shù)據(jù)標簽位置
          void setPositiveItemLabelPosition(ItemLabelPosition position)   正數(shù)標簽位置
          void setNegativeItemLabelPosition(ItemLabelPosition position)   負數(shù)標簽位置
          void setOutLinePaint(Paint paint)      圖形邊框的線條顏色
          void setOutLineStroke(Stroke stroke)      圖形邊框的線條筆觸
          void setPaint(Paint paint)       所有分類圖形的顏色
          void setShape(Shape shape)       所有分類圖形的形狀(如折線圖的點)
          void setStroke(Stroke stroke)       所有分類圖形的筆觸(如折線圖的線)
          void setSeriesItemLabelsVisible(int series,boolean visible)   指定分類的數(shù)據(jù)標簽是否可見
          void setSeriesItemLabelFont(int series,Font font)    指定分類的數(shù)據(jù)標簽的字體
          void setSeriesItemLabelPaint(int series,Paint paint)    指定分類的數(shù)據(jù)標簽的字體顏色
          void setSeriesItemLabelPosition(int series,ItemLabelPosition position) 數(shù)據(jù)標簽位置
          void setSeriesPositiveItemLabelPosition(int series,ItemLabelPosition position) 正數(shù)標簽位置
          void setSeriesNegativeItemLabelPosition(int series,ItemLabelPosition position) 負數(shù)標簽位置
          void setSeriesOutLinePaint(int series,Paint paint)    指定分類的圖形邊框的線條顏色
          void setSeriesOutLineStroke(int series,Stroke stroke)    指定分類的圖形邊框的線條筆觸
          void setSeriesPaint(int series,Paint paint)     指定分類圖形的顏色
          void setSeriesShape(int series,Shape shape)     指定分類圖形的形狀(如折線圖的點)
          void setSeriesStroke(int series,Stroke stroke)     指定分類圖形的筆觸(如折線圖的線)

          AbstractCategoryItemRenderer(AbstractRenderer)類:
          void setLabelGenerator(CategoryLabelGenerator generator)   數(shù)據(jù)標簽的格式
          void setToolTipGenerator(CategoryToolTipGenerator generator)   MAP中鼠標移上的顯示格式
          void setItemURLGenerator(CategoryURLGenerator generator)   MAP中鉆取鏈接格式
          void setSeriesLabelGenerator(int series,CategoryLabelGenerator generator) 指定分類的數(shù)據(jù)標簽的格式
          void setSeriesToolTipGenerator(int series,CategoryToolTipGenerator generator) 指定分類的MAP中鼠標移上的顯示格式
          void setSeriesItemURLGenerator(int series,CategoryURLGenerator generator) 指定分類的MAP中鉆取鏈接格式

          BarRenderer(AbstractCategoryItemRenderer)類:
          void setDrawBarOutline(boolean draw)      是否畫圖形邊框
          void setItemMargin(double percent)      每個BAR之間的間隔
          void setMaxBarWidth(double percent)      每個BAR的最大寬度
          void setMinimumBarLength(double min)      最短的BAR長度,避免數(shù)值太小而顯示不出
          void setPositiveItemLabelPositionFallback(ItemLabelPosition position) 無法在BAR中顯示的正數(shù)標簽位置
          void setNegativeItemLabelPositionFallback(ItemLabelPosition position) 無法在BAR中顯示的負數(shù)標簽位置

          BarRenderer3D(BarRenderer)類:
          void setWallPaint(Paint paint)    3D坐標軸的墻體顏色

          StackedBarRenderer(BarRenderer)類:
          沒有特殊的設(shè)置

          StackedBarRenderer3D(BarRenderer3D)類:
          沒有特殊的設(shè)置

          GroupedStackedBarRenderer(StackedBarRenderer)類:
          void setSeriesToGroupMap(KeyToGroupMap map) 將分類自由的映射成若干個組(KeyToGroupMap.mapKeyToGroup(series,group))

          LayeredBarRenderer(BarRenderer)類:
          void setSeriesBarWidth(int series,double width) 設(shè)定每個分類的寬度(注意設(shè)置不要使某分類被覆蓋)

          WaterfallBarRenderer(BarRenderer)類:
          void setFirstBarPaint(Paint paint)   第一個柱圖的顏色
          void setLastBarPaint(Paint paint)   最后一個柱圖的顏色
          void setPositiveBarPaint(Paint paint)   正值柱圖的顏色
          void setNegativeBarPaint(Paint paint)   負值柱圖的顏色

          IntervalBarRenderer(BarRenderer)類:
          需要傳IntervalCategoryDataset作為數(shù)據(jù)源

          GanttBarRenderer(IntervalBarRenderer)類:
          void setCompletePaint(Paint paint)   完成進度顏色
          void setIncompletePaint(Paint paint)   未完成進度顏色
          void setStartPercent(double percent)   設(shè)置進度條在整條中的起始位置(0.0~1.0)
          void setEndPercent(double percent)   設(shè)置進度條在整條中的結(jié)束位置(0.0~1.0)

          StatisticBarRenderer(BarRenderer)類:
          需要傳StatisticCategoryDataset作為數(shù)據(jù)源

          LineAndShapeRenderer(AbstractCategoryItemRenderer)類:
          void setDrawLines(boolean draw)    是否折線的數(shù)據(jù)點之間用線連
          void setDrawShapes(boolean draw)   是否折線的數(shù)據(jù)點根據(jù)分類使用不同的形狀
          void setShapesFilled(boolean filled)   所有分類是否填充數(shù)據(jù)點圖形
          void setSeriesShapesFilled(int series,boolean filled) 指定分類是否填充數(shù)據(jù)點圖形
          void setUseFillPaintForShapeOutline(boolean use) 指定是否填充數(shù)據(jù)點的Paint也被用于畫數(shù)據(jù)點形狀的邊框

          LevelRenderer(AbstractCategoryItemRenderer)類:
          void setItemMargin(double percent)   每個分類之間的間隔
          void setMaxItemWidth(double percent)   每個分類的最大寬度

          CategoryStepRenderer(AbstractCategoryItemRenderer)類:
          void setStagger(boolean shouldStagger)   不同分類的圖是否交錯

          MinMaxCategoryRenderer(AbstractCategoryItemRenderer)類:
          void setDrawLines(boolean drawLines)   是否在每個分類線間畫連接線
          void setGroupPaint(Paint groupPaint)   一組圖形連接線的顏色
          void setGroupStroke(Stroke groupStroke)   一組圖形連接線的筆觸
          void setMaxIcon(Icon maxIcon)    最大值的ICON
          void setMinIcon(Icon minIcon)    最小值的ICON
          void setObjectIcon(Icon objectIcon)   所有值的ICON

          AreaRender(AbstractCategoryItemRenderer)類:
          沒有特殊的設(shè)置

          StackedAreaRender(AreaRender)類:
          沒有特殊的設(shè)置

          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-07 13:46 todayx.org 閱讀(263) | 評論 (0)編輯 收藏
               摘要: 歷史上的今天回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天http://www.todayx.org/每天在寫Java程序, 其實里面有一些細節(jié)大家可能沒怎么注意, 這不, 有人總結(jié)了一個我們編程中常見的問題. 雖然一般沒有什么大問題, 但是最好別這樣做. 另外這里提到的很多問題其實可以通過Findbugs( http:/...  閱讀全文
          posted @ 2012-02-05 22:56 todayx.org 閱讀(232) | 評論 (0)編輯 收藏
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          今天我不談抱負理想,也不談具體的技術(shù),我來談幾個看法上的典型錯誤。下面的這些問題都是我曾經(jīng)遇到,或者是我的朋友們遇到過的問題,這些都是我個人的理解,希望對大家有幫助。

           

          關(guān)于設(shè)計模式、設(shè)計原則

          有人認為,熟悉了設(shè)計模式、設(shè)計原則,就學(xué)會了設(shè)計。其實,設(shè)計模式和設(shè)計原則,只是前人根據(jù)設(shè)計實踐做的總結(jié)和提煉,設(shè)計,歸根到底是要解決問題的,把具體問題的解決辦法,經(jīng)過一定的抽象,變成程序員的語言

          我見過一些人,他們知識淵博、見識廣博,甚至理論可以給你闡述得冠冕堂皇,但是到了實際需要解決問題的時候,他們卻拿不出巧妙的、優(yōu)雅的辦法,這是典型的象牙塔人

          另一方面,也有一些人看不起學(xué)習(xí)設(shè)計模式的人,他們覺得他們已經(jīng)掌握了軟件設(shè)計的奧義,這些對他們來說是毫無意義的詞匯,對此大可以一笑置之。

          有時候我們反而被設(shè)計模式或設(shè)計原則粗暴的掌握束縛了手腳,譬如我遇到這樣一件事情,某位努力的程序員,設(shè)計的代碼用遍了組合(例如把User對象 放置到Administrator里面),我好奇地問,有一些類和對象之間的關(guān)系很明顯符合繼承的特征,為什么不愿意用它?他說,設(shè)計原則告訴我們,要多 用組合,少用繼承。我想,對這些優(yōu)秀的模式、原則、方法論,如果不能透徹地掌握,不能根據(jù)實際場景合適地運用,是不是反而不如對其不了解來的好呢?

           

          關(guān)于多種計算機語言的學(xué)習(xí)

          有人覺得學(xué)習(xí)一種語言就可以了,學(xué)習(xí)那么多語言沒有必要。事實上,多掌握一門合適的計算機語言不僅僅是多掌握一種謀生的工具,如果一種新的語言能夠很大程度上改變你對編程、對設(shè)計的看法,那么興許它就值得你去學(xué)習(xí)。

          譬如C語言,可以培養(yǎng)嚴謹?shù)乃季S;譬如動態(tài)語言,它可以幫助程序員更好地做面向?qū)ο蟮腸oding;譬如函數(shù)式語言,它在工業(yè)生產(chǎn)、運算領(lǐng)域有著不可替代的作用。

          當然話說回來,所謂術(shù)業(yè)有專攻,對于某一門計算機語言(包括該語言所需的運行時環(huán)境、其中的編譯或解釋的原理)深入的掌握,是很有必要的。

          另外,我們時??吹街T多計算機語言孰優(yōu)孰劣的爭論,計算機語言歸根到底是一種工具,工具是隨著時代發(fā)展升級和變更的,單純的優(yōu)劣爭論沒有太大意義。

           

          關(guān)于英語

          中國人為什么要學(xué)英語,程序員為什么要學(xué)英語,當我把那些方法名、變量名全部取成拼音,一樣可以,誰下的這個破規(guī)定?

          遺憾的是,諸多學(xué)習(xí)材料、論文、技術(shù)資料(尤其是一些剛出不久的技術(shù)),都是英語的;另一方面,國際標準、程序員交流的通用方式,都是英文的,我想肯定很難想象,那些有名的framework、lib的源碼,如果用拼音來寫變量名會成什么樣子。

          所以,如果你的英語不好(至少讀寫不好),就不要給自己找太借口,英語是一個掌握其他工具的工具,除非你堅信,中文很快就會在計算機界變成世界第一通用的語言。

           

          關(guān)于算法

          算法有多重要,這一件事的爭議一直都很大。

          軟件歸根到底是用來解決問題的,提到算法就不能不提到數(shù)學(xué)(這也是為什么很多軟件領(lǐng)域的大師都具備相當?shù)臄?shù)學(xué)背景),對于解決問題,這里可以簡單歸納成兩步:

          (1)把實際的問題抽象成簡化的數(shù)學(xué)模型

          (2)用算法去解決這個數(shù)學(xué)問題

          算法,在這里應(yīng)該是一個廣義的概念(這里的算法并不僅僅指大學(xué)里學(xué)習(xí)的狹義的具體算法),算法是解決上述數(shù)學(xué)問題的辦法。如果工作中你并未意識到它的存在,那只是說明,你抽象出的數(shù)學(xué)模型比較簡單,解決這個模型的辦法也很簡單,或者有現(xiàn)成的方式可以模仿,或者有現(xiàn)成的框架幫你完成了,以至于你不去關(guān)注它、在乎它

          如果你做的事情是充滿創(chuàng)新意義的,是別人從沒有做過的,這時候算法興許就成了決定你成敗的因素。

          在當前中國的環(huán)境下,視野廣闊和經(jīng)歷豐富的人很好找,但是企業(yè)要招到具備上述兩點能力來解決問題的人,其實是非常困難的。

           

          關(guān)于經(jīng)驗

          唯經(jīng)驗論者的人有很多,他們認為,在軟件企業(yè)的職位、薪水、甚至決策能力,都取決于經(jīng)驗,一個5年經(jīng)驗的工程師,肯定比3年經(jīng)驗的工程師能找到更好的飯碗:

          “我是老員工,我工作5年了,憑什么工作3年的他薪水比我高那么多”

          實際上,很多因素,包括領(lǐng)域積累(這是業(yè)務(wù)上的,例如互聯(lián)網(wǎng)領(lǐng)域、傳統(tǒng)軟件領(lǐng)域,這和所謂的純技術(shù)沒有直接關(guān)系)、視野、承受壓力的能力等等往往都 在很大程度上取決于“經(jīng)驗”的積累,但是,這并不是絕對的。有句話叫做“事業(yè)一半是干出來的,一半是總結(jié)出來的”,也確實有一些出色的程序員,他們善于總 結(jié)、善于觀察和積累,并且善于不斷地思考,這樣的程序員就是擁有更多優(yōu)秀的經(jīng)驗。

          另一方面,程序員是要來解決問題的,經(jīng)驗不能代替解決問題,有的人具備更優(yōu)秀的解決問題的能力,他為什么就不能得到更優(yōu)厚的薪水?


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

          越來越多人開始使用Java,但是他們大多數(shù)人沒有做好足夠的思想準備(沒有接受OO思想體系相關(guān)培訓(xùn)),以致不能很好駕馭Java項目,甚至導(dǎo)致 開發(fā)后的Java系統(tǒng)性能緩慢甚至經(jīng)常當機。很多人覺得這是Java復(fù)雜導(dǎo)致,其實根本原因在于:我們原先掌握的關(guān)于軟件知識(OO方面)不是太貧乏就是 不恰當,存在認識上和方法上的誤區(qū)。

            軟件的生命性

            軟件是有生命的,這可能是老調(diào)重彈了,但是因為它事關(guān)分層架構(gòu)的原由,反復(fù)強調(diào)都不過分。

            一個有生命的軟件首先必須有一個靈活可擴展的基礎(chǔ)架構(gòu),其次才是完整的功能。

            目前很多人對軟件的思想還是焦點落在后者:完整的功能,覺得一個軟件功能越完整越好,其實關(guān)鍵還是架構(gòu)的靈活性,就是前者,基礎(chǔ)架構(gòu)好,功能添 加只是時間和工作量問題,但是如果架構(gòu)不好,功能再完整,也不可能包括未來所有功能,軟件是有生命的,在未來成長時,更多功能需要加入,但是因為基礎(chǔ)架構(gòu) 不靈活不能方便加入,死路一條。

            正因為普通人對軟件存在短視誤區(qū),對功能追求高于基礎(chǔ)架構(gòu),很多吃了虧的老程序員就此離開軟件行業(yè),帶走寶貴的失敗經(jīng)驗,新的盲目的年輕程序員 還是使用老的思維往前沖。其實很多國外免費開源框架如ofbiz compiere和slide也存在這方面陷阱,貌似非常符合胃口,其實類似國內(nèi)那些幾百元的盜版軟件,擴展性以及持續(xù)發(fā)展性嚴重不足。

            那么選擇現(xiàn)在一些流行的框架如Hibernate、Spring/Jdonframework是否就表示基礎(chǔ)架構(gòu)打好了呢?其實還不盡然,關(guān)鍵還是取決于你如何使用這些框架來搭建你的業(yè)務(wù)系統(tǒng)。

            存儲過程和復(fù)雜SQL語句的陷阱

            首先談?wù)劥鎯^程使用的誤區(qū),使用存儲過程架構(gòu)的人以為可以解決性能問題,其實它正是導(dǎo)致性能問題的罪魁禍首之一,打個比喻:如果一個人頻臨死亡,打一針可以讓其延長半年,但是打了這針,其他所有醫(yī)療方案就全部失效,請問你會使用這種短視方案嗎?

            為什么這樣說呢?如果存儲過程都封裝了業(yè)務(wù)過程,那么運行負載都集中在數(shù)據(jù)庫端,要中間J2EE應(yīng)用服務(wù)器干什么?要中間服務(wù)器的分布式計算和 集群能力做什么?只能回到過去集中式數(shù)據(jù)庫主機時代。現(xiàn)在軟件都是面向互聯(lián)網(wǎng)的,不象過去那樣局限在一個小局域網(wǎng),多用戶并發(fā)訪問量都是無法確定和衡量, 依靠一臺數(shù)據(jù)庫主機顯然是不能夠承受這樣惡劣的用戶訪問環(huán)境的。(當然搞數(shù)據(jù)庫集群也只是五十步和百步的區(qū)別)。

            從分層角度來看,現(xiàn)在三層架構(gòu):表現(xiàn)層、業(yè)務(wù)層和持久層,三個層次應(yīng)該分割明顯,職責(zé)分明:持久層職責(zé)持久化保存業(yè)務(wù)模型對象,業(yè)務(wù)層對持久層 的調(diào)用只是幫助我們激活曾經(jīng)委托其保管的對象,所以,不能因為持久層是保管者,我們就以其為核心圍繞其編程,除了要求其歸還模型對象外,還要求其做其做復(fù) 雜的業(yè)務(wù)組合。打個比喻:你在火車站將水果和盤子兩個對象委托保管處保管,過了兩天來取時,你還要求保管處將水果去皮切成塊,放在盤子里,做成水果盤給 你,合理嗎?

            上面是談過分依賴持久層的一個現(xiàn)象,還有一個正好相反現(xiàn)象,持久層散發(fā)出來,開始擠占業(yè)務(wù)層,腐蝕業(yè)務(wù)層,整個業(yè)務(wù)層到處看見的是數(shù)據(jù)表的影子 (包括數(shù)據(jù)表的字段),而不是業(yè)務(wù)對象。這樣程序員應(yīng)該多看看OO經(jīng)典PoEAA.PoEAA 認為除了持久層,不應(yīng)該在其他地方看到數(shù)據(jù)表或表字段名。

            當然適量使用存儲過程,使用數(shù)據(jù)庫優(yōu)點也是允許的。按照Evans DDD理論,可以將SQL語句和存儲過程作為規(guī)則Specification一部分。

            Hibernate等ORM問題

            現(xiàn)在使用Hibernate人也不少,但是他們發(fā)現(xiàn)Hibernate性能緩慢,所以尋求解決方案,其實并不是 Hibernate性能緩慢,而是我們使用方式發(fā)生錯誤:

            "最近本人正搞一個項目,項目中我們用到了struts1.2+hibernate3, 由于關(guān)系復(fù)雜表和表之間的關(guān)系很多,在很多地方把lazy都設(shè)置false,所以導(dǎo)致數(shù)據(jù)一加載很慢,而且查詢一條數(shù)據(jù)更是非常的慢。"

            Hibernate是一個基于對象模型持久化的技術(shù),因此,關(guān)鍵是我們需要設(shè)計出高質(zhì)量的對象模型,遵循DDD領(lǐng)域建模原則,減少降低關(guān)聯(lián),通 過分層等有效辦法處理關(guān)聯(lián)。如果采取圍繞數(shù)據(jù)表進行設(shè)計編程,加上表之間關(guān)系復(fù)雜(沒有科學(xué)方法處理、偵察或減少這些關(guān)系),必然導(dǎo)致 系統(tǒng)運行緩慢,其實同樣問題也適用于當初對EJB的實體Bean的CMP抱怨上,實體Bean是Domain Model持久化,如果不首先設(shè)計Domain Model,而是設(shè)計數(shù)據(jù)表,和持久化工具設(shè)計目標背道而馳,能不出問題嗎?關(guān)于這個問題N多年就在Jdon爭論過。

            這里同樣延伸出另外一個問題:數(shù)據(jù)庫設(shè)計問題,數(shù)據(jù)庫是否需要在項目開始設(shè)計?

            如果我們進行數(shù)據(jù)庫設(shè)計,那么就產(chǎn)生了一系列問題:當我們使用Hibernate實現(xiàn)持久保存時,必須考慮事先設(shè)計好的數(shù)據(jù)庫表結(jié)構(gòu)以及他們的關(guān)系如何和業(yè)務(wù)對象實現(xiàn)映射,這實際上是非常難實現(xiàn)的,這也是很多人覺得使用ORM框架棘手根本原因所在。

            當然,也有腦力相當發(fā)達的人可以實現(xiàn),但是這種圍繞數(shù)據(jù)庫實現(xiàn)映射的結(jié)果必然扭曲業(yè)務(wù)對象,這類似于兩個板塊(數(shù)據(jù)表和業(yè)務(wù)對象)相撞,必然產(chǎn) 生地震,地震的結(jié)果是兩敗俱傷,軟的一方吃虧,業(yè)務(wù)對象是代碼,相當于數(shù)據(jù)表結(jié)構(gòu),屬于軟的一方,最后導(dǎo)致業(yè)務(wù)對象變成數(shù)據(jù)傳輸對象DTO, DTO滿天飛,性能和維護問題隨之而來。

            領(lǐng)域建模解決了上述眾多不協(xié)調(diào)問題,特別是ORM痛苦使用問題,關(guān)于 ORM/Hibernate使用還是那句老話:如果你不掌握領(lǐng)域建模方法,那么就不要用Hibernate,對于這個層次的你:也許No ORM 更是一個簡單之道: No ORM: The simplest solution

            Spring分層矛盾問題

            Spring是以挑戰(zhàn)EJB面貌出現(xiàn),其本身擁有的強大組件定制功能是優(yōu)點,但是存在實戰(zhàn)的一些問題,Spring作為業(yè)務(wù)層框架,不支持業(yè)務(wù)層Session 功能。

            具體舉例如下:當我們實現(xiàn)購物車之類業(yè)務(wù)功能時,需要將購物場合保存到 Session中,由于業(yè)務(wù)層沒有方便的Session支持,我們只得將購物車保存到 HttpSession,而HttpSession只有通過HttpRequest才能獲得,再因為在Spring業(yè)務(wù)層容器中是無法訪問到 HttpRequest這個對象的,所以,最后我們只能將"購物車保存到HttpSession"這個功能放在表現(xiàn)層中實現(xiàn),而這個功能明顯應(yīng)該屬于業(yè)務(wù) 層功能,這就導(dǎo)致我們的Java項目層次混亂,維護性差。 違背了使用Spring和分層架構(gòu)最初目的。

            領(lǐng)域驅(qū)動設(shè)計DDD

            現(xiàn)在回到我們討論的重點上來,分層架構(gòu)是我們使用Java的根本原因之一,域建模專家Eric Evans在他的"Domain Model Design"一書中開篇首先強調(diào)的是分層架構(gòu),整個DDD理論實際是告訴我們?nèi)绾问褂媚P蛯ο髈o技術(shù)和分層架構(gòu)來設(shè)計實現(xiàn)一個Java項目。

            我們現(xiàn)在很多人知道Java項目基本有三層:表現(xiàn)層 業(yè)務(wù)層和持久層,當我們執(zhí)著于討論各層框架如何選擇之時,實際上我們真正的項目開發(fā)工作還沒有開始,就是我們選定了某種框架的組合(如 Struts+Spring+Hibernate或Struts+EJB或Struts+ JdonFramework),我們還沒有意識到業(yè)務(wù)層工作還需要大量工作,DDD提供了在業(yè)務(wù)層中再劃分新的層次思想,如領(lǐng)域?qū)雍头?wù)層,甚至再細分為 作業(yè)層、能力層、策略層等等。通過層次細化方式達到復(fù)雜軟件的松耦合。DDD提供了如何細分層次的方式

            當我們將精力花費在架構(gòu)技術(shù)層面的討論和研究上時,我們可能忘記以何種依據(jù)選擇這些架構(gòu)技術(shù)?選擇標準是什么?領(lǐng)域驅(qū)動設(shè)計DDD 回答了這樣的問題,DDD會告訴你如果一個框架不能協(xié)助你實現(xiàn)分層架構(gòu),那就拋棄它,同時,DDD也指出選擇框架的考慮目的,使得你不會人云亦云,陷入復(fù) 雜的技術(shù)細節(jié)迷霧中,迷失了架構(gòu)選擇的根本方向。

            現(xiàn)在也有些人誤以為DDD是一種新的理論,其實DDD和設(shè)計模式一樣,不是一種新的理論,而是實戰(zhàn)經(jīng)驗的總結(jié),它將前人 使用面向模型設(shè)計的方法經(jīng)驗提煉出來,供后來者學(xué)習(xí),以便迅速找到駕馭我們軟件項目的根本之道。


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發(fā)生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted @ 2012-02-04 23:21 todayx.org 閱讀(185) | 評論 (0)編輯 收藏
          僅列出標題
          共4頁: 1 2 3 4 下一頁 
          主站蜘蛛池模板: 乡城县| 景德镇市| 陆川县| 徐闻县| 普兰店市| 开原市| 英山县| 那曲县| 罗城| 闽侯县| 靖安县| 涟水县| 阜宁县| 巍山| 安塞县| 长顺县| 长寿区| 清丰县| 高密市| 双辽市| 奇台县| 屯昌县| 枣庄市| 图木舒克市| 泰兴市| 贵定县| 石城县| 通州区| 宜黄县| 广南县| 太原市| 龙口市| 隆安县| 江孜县| 汾阳市| 芜湖市| 永新县| 吉安县| 上栗县| 乌拉特中旗| 惠州市|