JavaScript Eclipse 插件助您一臂之力,提高 JavaScript 生產力指日可待
JavaScript Development Toolkit(JSDT)是一種開放源碼插件,它將健壯的 JavaScript 編程工具引入到 Eclipse 平臺中。JSDT 使開發(fā)更加流暢、簡化了編碼并提高了純 JavaScript 源文件和 HTML 內置的 JavaScript 的生產力。
JavaScript 開發(fā)并不容易。瀏覽器兼容性參差不齊、文檔非常糟糕、工具貧乏,這些因素使問題進一步惡化。幸運的是,隨著最近針對 Eclipse 的插件集 JavaScript Development Toolkit(JSDT)的發(fā)布,工具匱乏的局面有望得到改善。
Eclipse 是一個開源的 IDE 框架,具有提高擴展性和靈活性的架構。JSDT 作為插件在 Eclipse 中運行。在 Eclipse 中,JavaScript 并不是什么新鮮的概念,因為已經可以從其他插件獲得 HTML 和一些 JavaScript 支持,但是 JSDT 的獨特之處在于其所提供的工具的健壯性和復雜性,這可顯著提高 Web 開發(fā)的生產力。
JSDT 提供的許多特性和核心設計都可以在 Java Development Toolkit(JDT)中找到。JSDT 將要代替 Web Tools Platform V3.0 發(fā)行版中當前的 JavaScript 編輯器。
您可能想知道為什么 JavaScript IDE 會如此流行。隨著 Web 2.0 的流行以及大量開發(fā)人員都熱衷于在博客和社區(qū)頁面中使用 JavaScript,大量新的 JavaScript 工具不斷出現。盡管如此,Notepad 和瀏覽器的 Refresh 按鈕仍然是大多數程序員首選的 JavaScript 開發(fā)環(huán)境。
問題在于 JavaScript 語言的解釋性。與 Java™ 或 C 語言不同,JavaScript 是一種松類型的語言,并且很難實現精確建模。對于較為正式的語言,需要優(yōu)先考慮已編譯代碼的效率,并且對語言的靈活性有所限制。JavaScript 的目標則不一樣。各種因素試圖分化趨向同一個平臺的開發(fā)人員,這導致了語言的不一致性。從工具和開發(fā)的角度來看,這些不一致性使問題更加復雜。
瀏覽器并不是惟一的問題。面向對象的 JavaScript 是一種補充而不是關注的焦點。Ajax 工具箱努力使 JavaScript 朝面向對象方面轉變 — 但是各自采取不同的方式。這可能會使標識對象和類結構變得很困難。這種語言有幾個嚴重的漏洞,程序員利用它們實現一些使用其他方式難以實現的技巧,這使問題更加嚴重(或者更好,取決于您詢問的對象)。其中一個例子是將主要的代碼塊封裝到一個 evalf(..)
函數中,使它只在運行時有效。我們目前仍然在克服這個問題,以便在 JSDT 中精確建模。
目前可以使用一些并不完整的 JavaScript 工具。但是很多流行的工具還不能提供真正的上下文感知內容幫助,因為它們缺少真正的 JavaScript 語言建模機制。在模型較少的 IDE 中,通過使用靜態(tài)平面文件列出可用的類型,可以實現內容完成和工具功能。這些類型根據輸入的部分字符動態(tài)調整,并且通常不會選擇代碼中定義的對象成員。內容完成對上下文不敏感,因為如果沒有模型的話,可實現的功能將受到很大限制。
如果沒有語言模型,則很難或者不可能將代碼放入到上下文中。由于很多編程元素都依賴于代碼的上下文,因此使用工具建立上下文十分重要。缺少模型和代碼上下文的 IDE 同樣也會缺少充分的類型解析和驗證、作用域、可視性,或者其他任何對簡化開發(fā)非常重要的良好驗證功能。
![]() ![]() |
JSDT 對 JavaScript 語言建模并實時隱含類結構,這通過一種全新的方式來實現。首先,構建基本的語言元素。其次,推理引擎或引擎幫助填補所有類結構和語言差異。
可以將推理和建模流程看作一個操作棧。模型的開始部分是 JavaScript 源代碼。通過使用類似 Eclipse JDT 的引擎,將源代碼轉換為私有的語言模型。語言的純模型遵守 ECMA-3 標準。
對 JavaScript 語言建模后,下一步是管理類型和類推理。許多基于 JavaScript 的工具箱(例如 Dojo、Rico、Prototype)通過自己的技術使 JavaScript 面向對象編程更加方便。JSDT 使用定制的、工具箱感知的推理引擎在工具箱內部識別類和類型結構。這些類和類型隨后可以添加到語言模型中。
最后,將私有模型及其推理部分轉換為公共語言模型。公共語言模型可用于源代碼、重構和 as-you-type 工具。如果其中一種工具需要修改一些 JavaScript 源代碼,就得先在公共模型中進行修改,并最終轉換到 JavaScript 源代碼。
即使語言模型為描述 JavaScript 源代碼和上下文提供了基礎,還需要另外一個重要因素:環(huán)境上下文。JSDT 必須在運行 JavaScript 的全局作用域時建立可用的變量和類型。這些變量和類型根據 JavaScript 的運行時環(huán)境而有所不同。當 JavaScript 在 Web 瀏覽器上下文中運行時,對象、類型、表示屏幕數據的字段以及瀏覽器對象在全局作用域中都是可用的。如果代碼是針對其他內容而不是瀏覽器,那么整個對象集可能會不同。
JSDT 使用庫機制管理項目中的通用對象、變量和類型。可以將庫添加到項目中,以提供特定于用戶目標運行時環(huán)境的對象和變量集。如果存在兩個定義沖突成員的庫,則在相應的用戶接口中聚合并注釋這些成員。這有助于創(chuàng)建在瀏覽器或環(huán)境之間通用的方法。
為流行的瀏覽器預打包庫非常簡單。庫被捆綁在一個插件中,該插件包含有定義對象和類型的 JavaScript 源文件。當 JSDT 對源代碼編輯器中打開的文件進行建模時,它首先對文件的源代碼建模,然后將項目的庫集合中的所有源文件添加到模型。庫源文件永遠不會進行驗證,只用于定義對象結構、附加在懸浮式幫助和內容完成中可見的 JsDoc。
雖然庫的主要功能是管理 JavaScript 的運行時上下文,但是它還提供了另一個重要特性 — 處理源文件交叉引用。純 JavaScript 不具備顯式的 include 函數。開發(fā)人員的一個不良習慣就是將函數散布到多個源文件中。庫配置頁面可以幫助管理源文件之間的交叉項目可見性。如果某個項目文件夾被標記為一個源文件,那么該文件夾中的所有 JavaScript 將包括在全局作用域中。使用 exclude 模式可以限制文件夾。
![]() ![]() |
![]() |
撇開較高層的設計不談,我們仔細看看這些特性。JSDT 的一些可視性較弱但非常重要的特性包括:相同文字突出顯示、自動閉合大括號(以及圓括號、引號)以及自動縮進等。因此可以說,“只要是良好 IDE 應該具備的,JSDT 都提供支持”。
內容完成可以通過 Ctrl+Space 鍵任意調用。圖 3 展示了內容幫助調用文檔對象。內容完成對上下文敏感,并且基于全局作用域和 JavaScript 模型。完成條目顯示字段名、字段類型和字段的聲明類型。
如果 IDE 可以主動確定代碼錯誤,它將非常有用。JSDT 可以檢測三種主要錯誤類型:語法/語言錯誤、類型/字段/方法可視性、流或邏輯錯誤。所有的錯誤警告級別都可以通過首選項頁面進行單獨配置。
JSDT 試圖解析對象的所有字段和方法。未解析的方法則標記為錯誤。
JSDT 還可以查找并標記語法錯誤。下面的 for()
語句丟失了一個分號。
圖 6 演示了流分析。由于 return
語句后面的所有代碼都不能執(zhí)行,因此將其標記為錯誤。
一些錯誤具有快速修復選項。在圖 7 中,當用戶單擊未解析變量 formyValue
旁邊的錯誤標記時,JSDT 將顯示一些糾正錯誤的選項。
源代碼有時會混亂。您可能期望易于閱讀、結構良好、格式化良好的代碼。這就需要在進行開發(fā)和調試時對代碼進行格式化。JSDT 支持許多 as-you-type 格式化特性,比如可配置自動縮進和字符成對匹配。這些特性都有助于加快開發(fā)和提高可讀性。
如果您收到的代碼非常混亂,該怎么辦?只需要單擊一下鼠標,JSDT 代碼格式化程序就可以整理并重新格式化混亂的 JavaScript 代碼。格式化引擎是高度可配置的,因此可以導出配置供團隊共享。
上面列出的僅是 JSDT 支持的特性的一部分。下面列出非常簡單但必須具備的 JSDT 特性:
![]() ![]() |
![]() |
如果需要一種免費的 Web 開發(fā)環(huán)境,請選擇 Eclipse。由于新增了 JSDT,Eclipse 的 JavaScript 能力超越了市場上其他同類產品。開放源碼項目促成了 JSDT 的快速發(fā)展,JSDT 將像 JavaScript 一樣快速地演進。
![]() |
||
|
![]() |
Bradley Childs 2004 年畢業(yè)于 Texas A&M University。他在 IBM 從事中間件開發(fā),后來又轉到新興技術方面。他和 Phil Berkland 密切合作開發(fā) JSDT。他在 Ajax Tooling Framework 項目社區(qū)中非常活躍。 |
下面是最新一期的Web服務器排名,其中Nginx已經上升到了第四位,太牛X了
Vendor | Product | Web Sites |
---|---|---|
Apache | Apache | 84,309,103 |
Microsoft | IIS | 60,987,087 |
GFE | 10,465,178 | |
Unknown | Unknown | 4,903,174 |
nginx | nginx | 2,125,160 |
Oversee | Oversee | 1,953,848 |
lighttpd | lighttpd | 1,532,952 |
Other | Other | 1,150,202 |
GNR | GNR | 425,029 |
Zeus | Zeus | 405,724 |
IdeaWebServer | IdeaWebServer | 382,524 |
Sun | Sun-ONE-Web-Server | 349,704 |
Apache | Coyote | 338,376 |
Resin | Resin | 321,746 |
Jetty | Jetty | 259,558 |
下載地址:http://www.myeclipseide.com/module-htmlpages-display-pid-4.html
另外還有
Blue Edition: ALM & Open Source for WebSphere
MyEclipse is proud to announce availability of MyEclipse 6.5 Blue Edition as well. This release introduces a new standard of ALM management and open source capabilities for WebSphere.
依然沒有Struts2,下個版本可能會支持Eclipse3.4了
http://www.sxin99.com
http://www.spitv.net
http://goku.spitv.net
最近學了一些PHP和Ruby的東西,忽然想把這些東西應用做個比較.
首先,我們把Java .Net PHP應用方面占有率做個比較,簡單的把目前主流應用分成兩個大類,一個是企業(yè)應用,一個是Web網站應用,下面這個表格是我歸納的,不一定準確,但是能說明一個大概.
應用 / 語言 | Java | .Net | PHP |
大型企業(yè)應用 | 多 | 少 | 少 |
中型企業(yè)應用 | 多 | 中 | 少 |
小型企業(yè)應用 | 中 | 中 | 少 |
大型Web應用 | 多 | 少 | 中 |
中型Web應用 | 中 | 中 | 多 |
小型Web應用 | 少 | 中 | 多 |
從表中可以看到,Java和PHP都有各自擅長的領域,但是.Net卻沒有突出的地方,從占有率來看情況十分尷尬.
我們再來看看技術方面,首先聲明,我對其中每種語言技術都不是很熟悉,只能大概分析一下...
先說說Java,在企業(yè)級方面,可以說是絕對的老大,許多企業(yè)級技術,開發(fā)思想都是由Java發(fā)展出來的.缺點是Java開發(fā)部署比較麻煩 ,不太適合超小型的項目.
再說.Net,在1.x時代,.Net可以說基本上沒有多少企業(yè)級開發(fā)的特性,到了3.0,微軟各種框架技術雖然彌補了這些不足,但是相對于Java世界,還是有一定距離. 在Web網站方面,.Net服務器控件的優(yōu)勢,變成了弱勢,由于服務器空間產生垃圾代碼,并且不方便美工調整,導致在前臺界面要求較高的門戶站點難以使用(雖然有第三方MVC框架,但是沒有IDE支持,體現不出.Net的優(yōu)勢)
再說說PHP,他的定位非常明顯,就是Web開發(fā),所以有很多適合Web開發(fā)的特性,比如部署十分簡單,幾個文件隨便找個虛擬主機扔上去就能運行.在國內因為Discuz , DedeCMS等著名產品的鼎立推廣,PHP在中小型網站開發(fā)中有很大的優(yōu)勢.,最近大量的開源框架出現,給PHP企業(yè)開發(fā)注入了一些生命力,可以說潛力十足.
綜合以上我們可以看到,.Net定位不太明確,微軟這個想吃那個也想吃,最后沒一個能吃飽吃好..
最后還想說一下Ruby,其實應該說ROR,大家喜歡的應該是ROR的特性,二Ruby是個怪怪的東西,如果沒有ROR框架,我想他也很難出名.因為ROR本身構架不是很復雜,眾多PHP框架可以說都是模仿他的思想來的,而且也學得7 8成功力了,個人認為ROR很難再做大起來,可能是個曇花一現的東西,只是思想新潮大家都來趕時髦學兩下,學到了,大家又都覺得其實也就那樣,其他語言也能做到.
http://goku.spitv.net/
http://www.spitv.net/
http://www.sxin99.com/
來自:http://www.netbeans.org
http://goku.spitv.net http://www.sxin99.com
從獲得一千萬美元風投開始算起剛滿一年,如今SpringSource(Spring框架背后的公司)搖身一變,成為應用服務器提供商,并且舉著SpringSource應用平臺(SpringSource Application Platform)的黃鉞白旄對現有的Java EE服務器陣營發(fā)起挑戰(zhàn)。SpringSource應用平臺是構建在Spring、OSGi和Apache Tomcat之上的應用服務器,這個新的應用服務器摒棄了原有的Java EE服務器標準,自然而然地將Spring編程模型展現其中,隨之而來的還有一套基于OSGi內核構建的全新部署和打包系統(tǒng)。今天是該項目在SpringSource評估許可下Beta發(fā)布版發(fā)布的重要里程碑。在隨后一個月內會有基于開源許可(GPLv3)版本和訂閱版本的通用發(fā)布版(General Availability,GA)放出。
SpringSource應用平臺不是Java EE應用服務器。盡管對于WAR部署它提供了支持,但EAR部署和其它EE的規(guī)范,如EJB等,都不在支持范圍之列。SpringSource應用平臺被重新設計,并把關注點直接放在對被開源項目所廣泛使用的Spring組合的支持上。特別地,這個應用服務器是基于Spring組合編程模型構建的,利用Spring Dynamic Module實現基于OSGi的部署。SpringSource在Eclipse基金會的Equinox OSGi運行時環(huán)境的基礎上創(chuàng)建了一個具備日志、跟蹤、啟動、類加載、管理和其它特性的“內核”,Tomcat被作為一個包(bundle)納入到平臺當中,從而實現對Web功能的支持。
InfoQ借此機會對Spring框架的共同創(chuàng)始人兼SpringSource的CEO Rod Johnson進行一次采訪,對這個新的應用服務器展開探討。在闡釋這個新平臺的必要性時,Rod一針見血地指向目前開發(fā)和生產環(huán)境的許多痛處,比如跨配置文件出現的元數據重復現象,還有本質上在項目中常常在服務器上再部署服務器(即在部署應用時,在同一個部署單元附帶部署許多工具和框架),而與此同時這些部件卻主要只使用它們應用服務器中的Web容器部分的事實。因此,SpringSource希望在當今的開發(fā)需要的基礎上提供一個更為簡單的平臺。
在談到這個新應用服務器的優(yōu)點時,Johnson強調了模塊化:對于服務器本身以及提供給開發(fā)人員的打包和部署模式來說,這是個兩全之策。通過利用OSGi,以及OSGi包之間依賴關系相互作用的性質,運行的應用服務器只會激活在它上面運行的應用所需要的特性,從而削減服務器的內存占用和啟動時間。這個依賴關系支持的功能還允許依賴類庫的多個版本共存,以支持不同應用;因而應用服務器的某些部分就可以很容易地更新和重啟,而無需重啟整個服務器。從開發(fā)的角度看,服務器的模塊化也使得在代碼變化時,可以很快地進行極其細粒度的重部署。
Johnson在言及OSGi和SpringSource對Eclipse Equinox OSGi的使用時,高度評價了OSGi規(guī)范的運行時實現所帶來的基礎平臺,但也表示OSGi在日常的應用開發(fā)上屬于比較底層的地位。Johnson闡述到,SpringSource希望幫助開發(fā)人員在企業(yè)環(huán)境中輕松獲得價值。在新的編程模式的構造背后,這個新的應用服務器將OSGi的許多復雜性抽象了出來。Johnson接著說,應用服務器將會支持PAR,一套新的可部署單元,簡化企業(yè)應用在使用OSGi上的復雜性(下文會詳細說明)。
當被問到對于沒有對OSGi提供原生支持的遺留類庫的支持時,Johnson回應到,他們已經在上面花費了很大心血,使得應用服務器環(huán)境和類加載功能能夠以兼容的方式和遺留類庫協作。
當被問到對不提供OSGi原生支持的類庫的遺留支持時,Johnson回答說他們已經在這方面投入了大量精力,保證應用服務器環(huán)境和類加載功能可以和遺留類庫兼容工作。SpringSource還會為他們在如Tomcat之類的項目上所做的任何變更給這些項目提交補丁,使這些類庫可以和OSGi包兼容。
Johnson解釋到,應用服務器的主題代碼將在GPL v3的許可證下發(fā)布。開發(fā)人員在服務器、編程模式和部署單元上要接觸到的所有部分都會以開源的形式提供。SpringSource還將提供應用服務器的商業(yè)版本,包括支持、保障、管理和監(jiān)控的功能。
談到Spring應用平臺發(fā)布之后對Spring組合繼續(xù)支持JavaEE有什么影響,Johnson回答說:
……我們從根本上說并不打算把Spring用戶社區(qū)驅趕到任何方向。我們僅僅是給用戶另一種選擇。Spring的哲學是用戶總是正確的。用戶是聰明的,他們完全明白自己的需要。不管用戶是否選擇SpringSource應用平臺,我們覺得用戶總會歡迎多一點選擇的……
Johnson保證SpringSource一定會繼續(xù)確保Spring組合以及其他SpringSource產品兼容于其它應用平臺。接著Johnson還評論了即將到來的Java EE 6規(guī)范:
Java EE 6重點在模塊性,這個方向是正確的。很可能SpringSource應用服務器會在一定程度上符合Java EE 6。Java EE 6分成A、B、C三種規(guī)格(profile)。我們幾乎肯定會實現A和B規(guī)格,C規(guī)格里面我非常確定將實現Entity Beans 1.1模型以及一些遺留技術。我還不能說是100%確定,因為Java EE 6規(guī)范還沒有定案。
最后,InfoQ和Johnson討論到了SpringSource應用平臺的大局方面。對于轉換到OSGi,他的回答是:
傳統(tǒng)的應用服務器模型正逐漸過時。BEA和IBM正在用OSGi逐步重新實現他們的應用服務器。 SpringSource現在就提供OSGi支持。從統(tǒng)計數字上看,大多數人都不會部署到完整的平臺上,他們部署到Tomcat。他們選擇了Spring 編程模型而非Java EE。市場已經作出了選擇,問題只是開發(fā)者還要和服務器斗爭多長時間。
Johnson解釋說他對SpringSource應用平臺成功的自信來自三個原因:
- 它是第一個建立在現代技術基礎上的產品。符合Java EE規(guī)范已經不是至高無上的目標。干凈的代碼基礎是我們的一項競爭優(yōu)勢。我們在設計和實現中滿足的是現今的需求,而不是10年前的需求。
- POJO編程是現在行業(yè)的方向所在。過去POJO編程是被強行嫁接到其它產品上的。在我們的產品中,POJO編程是設計的前提。
- SpringSource應用平臺采用的OSGi技術是下一代技術的基礎。
除了Rod Johnson,InfoQ還與SpringSource的Rob Harrop探討了新應用服務器的一些技術細節(jié)。對于與傳統(tǒng)Java EE應用服務器相比有何增減,他說:
……JPA和JMS都支持,但我們沒有包含任何特定實現。對于JPA,我們支持Hibernate、 OpenJPA和Toplink。我們在OSGi環(huán)境中增加了對加載時織入的支持,而且會尊重應用的邊界,因此不會意外污染應用間共享的庫。不包括 JNDI,我們用OSGi Service Registry來取代它。Servlets是通過內嵌的Tomcat來支持的。JEE中有而SpringSource應用平臺沒有的東西包括 Entity Beans等等。
接下來InfoQ問到Spring Dynamic Modules。Spring DM成為公開項目已經有一段時間了。對于模塊化部署,我們向Harrop詢問Spring DM是否增加了什么新東西:
這個平臺引入了應用的概念,應用由一個或多個Bundle組成。應用中的包有明確的作用域,可以防止發(fā)生應用間的沖突。在應用把服務發(fā)布到OSGi service registry的情況下,防止沖突尤其重要,誰也不想見到服務之間發(fā)生沖突。
我們引入了Import-Library語句,因此在應用中使用第三方庫變得更加簡單。你不需要再寫一大串不直觀的 Import-Package聲明,Import-Library可以自動為指定的庫引入所有必需的package。像Hibernate JPA這樣的庫還可以跨多個Bundle,可見Import-Library確實物有所值。
至于為了讓Spring DM在平臺中運行而進行的擴展,為數不多。
Harrop接下來說明了新的PAR格式:
Spring DM掌控下的Bundle(Spring DM powered bundles)是包含META-INF/spring/*.xml文件的普通OSG Bundle。Bundle啟動的時候META-INF/spring/*.xml文件會自動成為該Bundle的 ApplicationContext。Spring DM提供了一種機制讓各Bundle通過Spring NamespaceHandler導入和導出服務。
一個PAR(Platform ARchive)本質上是一組OSGi Bundle,通常其中有一部分是在Spring DM掌控下的。這些Bundle共同組成了一個邏輯上的應用。編程的時候完全是純粹的OSGi、Spring和Spring DM——PAR沒有改變什么。
以前一般用Buddy Classloaders之類的技術來解決遺留/非OSGi庫的問題,SpringSource這次是怎么做的呢?Rob回答說:
簡單來說我們避免做這樣的事。Buddy類裝載、動態(tài)import、require-bundle,這些我們都明確回避,因為維持一致的類空間太困難了。我們也不會提供任何專有的替代機制。
相反,我們給Equinox增加了一些低級的鉤子,以實現典型的場景下的資源裝載。我們擴展了類裝載來支持加載時織入,并且把裝載語義丟到一邊。我們操縱context classloader,讓第三方一如既往地看到類。PAR是其中的核心角色,因為它定義了上下文類裝載以及加載時織入的可見范圍。
對于一些最糟糕的情況,我們會提供修補版的庫,讓它們能在OSGi中工作。修補版的庫可以通過SpringSource Enterprise Bundle Repository獲得,我們的修改也會提交回相應的項目。
最后Harrrop著重強調了這個應用服務器在模塊化上的優(yōu)勢,應用服務器因此可以維持最低的內存占用。平臺在運行中才設置依賴項,因此只有確實用到的依賴項才會被裝載。
最近幾年中有過許多關于Java EE標準是否已經死亡的討論,而今天我們看到一個可能很重要的應用服務器不帶Java EE支持。這種變化對于未來有何影響?你怎么看?
雖然現在出現了很多ORM框架,可是還是有很多朋友也許還在使用JDBC,就像我現在一樣,除了學習的時候在使用Hibernate、Spring類似這些優(yōu)秀的框架,工作時一直都在使用JDBC。本文就簡單介紹一下利用Jakarta Commons旗下beanutils、dbutils簡化JDBC數據庫操作,以拋磚引玉,希望對像我一樣在使用JDBC的朋友有所幫助。
下面就分兩部分簡單介紹beanutils、dbutils在基于JDBC API數據庫存取操作中的運用。第一部分顯介紹beanutils在JDBC數據庫存取操作中的運用,第二部分介紹dbutils在JDBC數據庫存取操作中的運用,最后看看他們的優(yōu)缺點,談談本人在項目運用過程中對他們的一點心得體會,僅供參考,其中有錯誤的地方希望大蝦不吝賜教,大家多多交流共同進步。
一、Jakarta Commons beanutils
Beanutils是操作Bean的銳利武器,其提過的BeanUtils工具類可以簡單方便的讀取或設置Bean的屬性,利用Dyna系列,還可以在運行期創(chuàng)建Bean,符合懶人的習慣,正如LazyDynaBean,LazyDynaClass一樣,呵呵。這些用法已經有很多文章提及,也可以參考apache的官方文檔。
對于直接利用JDBC API訪問數據庫時(這里針對的是返回結果集ResultSet的查詢select),大多數都是采用兩種方式,一種是取出返回的結果集的數據存于Map中,另一種方式是Bean里。針對第二種方式,Beanutils里提供了ResultSetDynaClass結合DynaBean以及RowSetDynaClass結合DynaBean來簡化操作。下面用以個簡單的例子展示一下beanutils的這兩個類在JDBC數據庫操作中的運用。
請在本機建立數據庫publish,我用的是MySQL,在publish數據庫中建立表book,腳本如下:
CREATE TABLE book(
id int(11) NOT NULL auto_increment,
title varchar(50) character set latin1 NOT NULL,
authors varchar(50) character set latin1 default NULL,
PRIMARY KEY (id)
)
然后用你喜歡的編輯器建立一個類BeanutilsJDBCTest,我們先用ResultSetDynaClass來處理,然后再用RowSetDynaClass來實現同樣的類,之后看看他們之間有什么不同,用ResultSetDynaClass處理的源代碼如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Iterator;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.ResultSetDynaClass;
public class BeanutilsJDBCTest{
public static void main(String[] args) {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
con = DriverManager.getConnection(url, "root", "hyys");
st = con.createStatement();
rs = st.executeQuery("select * from book");
ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);
Iterator itr = rsDynaClass.iterator();
System.out.println("title-------------authors");
while (itr.hasNext()) {
DynaBean dBean = (DynaBean) itr.next();
System.out.println(PropertyUtils.getSimpleProperty(dBean,"title")
+ "-------------"+ PropertyUtils.getSimpleProperty(dBean, "authors"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
用RowSetDynaClass處理的源代碼如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.RowSetDynaClass;
public class BeanutilsJDBCTest{
public static void main(String[] args) {
List rsDynaClass = rsTest();
System.out.println("title ------------- authors ");
Iterator itr = rsDynaClass.iterator();
while (itr.hasNext()) {
DynaBean dBean = (DynaBean) itr.next();
try {
System.out.println(PropertyUtils.getSimpleProperty(dBean,"name")
+ "-------------"+ PropertyUtils.getSimpleProperty(dBean, "mobile"));
} catch (Exception e) {
// TODO 自動生成 catch 塊
e.printStackTrace();
}
}
}
private static List rsTest() {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
con = DriverManager.getConnection(url, "root", "hyys");
st = con.createStatement();
rs = st.executeQuery("select * from book");
RowSetDynaClass rsdc = new RowSetDynaClass(rs);
return rsdc.getRows();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
這兩個方法輸出的結果應該是一樣的。但是很顯然第二種方式比第一種方式要好,它把數據訪問部分抽取出來放到一個方法中,顯得簡單清晰。
其實在利用ResultSetDynaClass時,必須在ResultSet等數據庫資源關閉之前,處理好那些數據,你不能在資源關閉之后使用DynaBean,否則就會拋出異常,異常就是說不能在ResultSet之后存取數據(具體的異常名我也忘了),當然你也可以采用以前的方式一個一個的把數據放到Map里,如果你一定要那樣做,建議還是別用Beanutils,因為這沒帶給你什么好處。總之利用ResultSetDynaClass你的程序的擴展性非常部好。
從第二中方式可以看出,利用RowSetDynaClass可以很好的解決上述ResultSetDynaClass遇到的問題,RowSetDynaClass的getRows()方法,把每一行封裝在一個DynaBean對象里,然后,把說有的行放到一個List里,之后你就可以對返回的List里的每一個DynaBean進行處理,此外對于DynaBean你還可以采用標準的get/set方式處理,當然你也可以用PropertyUtils. getSimpleProperty(Object bean, String name)進行處理。
從上面的分析中,你應該可以決定你應該使用ResultSetDynaClass還是RowSetDynaClass了。
未完待續(xù)……
=============================
二、Jakarta Commons dbutils:
用JDBC API時最令人討厭的就是異常處理,也很煩瑣,而且很容易出錯,本人曾考慮過利用模板進行處理,后來看到了dbutils,之后就采用那個dbutils,采用模板的方式各位朋友可以參考Spring,Spring的JdbcTemplate不靈活而強大,呵呵,說句閑話,實在太佩服Rod Johnson了,Rod Johnson真的很令人尊敬。
Dbutils的QueryRunner把大多數與關閉資源相關的封裝起來,另外,你也可以使用DbUtils進行關閉,當然DbUtils提供的功能當然不止這些,它提過了幾個常用的靜態(tài)方法,除了上述的關閉資源外,DbUtils. commitAndClose(Connection conn)還提供事務提及等操作。
還是以一個例子來說說吧,畢竟我不是搞業(yè)務的,小嘴巴吧嗒吧噠不起來啊,呵呵。
為了和采用Beanutils更好的進行對比,這個例子還是實現同樣的功能,數據庫同樣采用前一篇文章中提到的publish。
同樣的,用你喜歡的編輯器建立一個類DbutilsJDBCTest,示例代碼如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
public class DbutilsJDBCTest{
public static void main(String[] args) {
Connection conn = null;
String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
String jdbcDriver = "com.mysql.jdbc.Driver";
try {
DbUtils.loadDriver(jdbcDriver);
// Username "root". Password "root"
conn = DriverManager.getConnection(jdbcURL, "root", "root");
QueryRunner qRunner = new QueryRunner();
System.out.println("***Using MapListHandler***");
//以下部分代碼采用Map存儲方式,可以采用Bean的方式代替進行處理
List lMap = (List) qRunner.query(conn,
"select title,authors from books", new MapListHandler());
//以下是處理代碼,可以抽取出來
System.out.println("title ------------- authors ");
for (int i = 0; i < lMap.size(); i++) {
Map vals = (Map) lMap.get(i);
System.out.println(vals.get("title")+"-------------"+ vals.get("authors"));
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
}
怎么樣?是不是比采用Beanutils的ResultSetDynaTrial和RowSetDynaClass好多了?采用Beanutils令人難纏的是關閉那些資源以及處理那些異常,而這里采用Dbutils顯然代碼量減少了很多。
上例在處理結果集時,它把數據庫中的每一行映射成一個Map,其中列名作為Key,該列對應的值作為Value存放,查詢的所有的數據一起放在一個List里,然后進行處理,當然,一個更明智的處理是直接返回List然后再單獨進行處理。
事實上上例返回的結果集中的每一行不必放在一個Map里,你可以放在一個Bean里,當然如果你真的很懶,你也可以使用Beanutils的LazyDynaClass和LazyDynaBean,不過也許沒有必要那么做,至于原因請看下文。
如果使用Bean而不是用Map,那么,你也許需要建立一個Bean,如下:
package cn.qtone.test;
public class Book {
public int id;
public String title;
public String authors ;
public StudentBean() {
}
public String getAuthors() {
return authors;
}
public void setAuthors(String authors) {
this.authors = authors;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
然后簡單修改一下DbutilsJDBCTest 中的部分代碼即可,代替之后的源代碼如下:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
public class DbutilsJDBCTest{
public static void main(String[] args) {
Connection conn = null;
String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
String jdbcDriver = "com.mysql.jdbc.Driver";
try {
DbUtils.loadDriver(jdbcDriver);
// Username "root". Password "root"
conn = DriverManager.getConnection(jdbcURL, "root", "root");
QueryRunner qRunner = new QueryRunner();
System.out.println("***Using BeanListHandler ***");
//以下部分代碼采用Map存儲方式,可以采用Bean的方式代替進行處理
List lBeans = (List) qRunner.query(conn," select title,authors from books ", new BeanListHandler(Book.class));
//以下是處理代碼,可以抽取出來
System.out.println("title ------------- authors ");
for (int i = 0; i < lBeans.size(); i++) {
Book vals = (Book) lBeans.get(i);
System.out.println(vals.getTitle ()+"-------------"+ vals. getAuthors ());
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
}
這兩種法輸出的結果應該是一樣的。兩種處理方式都差不多,但我更愿意采用第一種,因為第一種少寫一個bean,而且我測試過采用Map的方式即第一種方式性能要好的多,采用Bean性能比較低可能是因為采用反射的緣故,采用反射的東東性能和不采用反射的還是有點差距。也是這個原因,不推薦采用LazyDynaClass和LazyDynaBean,因為采用這二者是在運行期動態(tài)創(chuàng)建Bean類和Bean屬性,然后再創(chuàng)建Bean對象的,其性能可想而知了(不過我沒有測試過啊,所以我說這個話可說是沒有根據的,感興趣的朋友自己測試一下,記得告訴我結果哦,呵呵),除了MapListHandler以及BeanListHandler之外,DButils還提供了其他的Handler,如果這些不能滿足你的需求,你也可以自己實現一個Handler。
最后,也是最大的體會,也許是最大的收獲吧,那就是:對于每一個項目,在根據每一個需求獲取相應解決方案時,先尋找開源組件,看是否已經有滿足某些功能需求的開源組件,如果沒有,再考慮自主開發(fā)或者向第三方購買,否則盡量采用開源組件.
請盡量享用開源的魅力,盡情的擁抱開源吧。
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
30 | 31 | 1 | 2 | 3 | 4 | 5 | |||
6 | 7 | 8 | 9 | 10 | 11 | 12 | |||
13 | 14 | 15 | 16 | 17 | 18 | 19 | |||
20 | 21 | 22 | 23 | 24 | 25 | 26 | |||
27 | 28 | 29 | 30 | 1 | 2 | 3 | |||
4 | 5 | 6 | 7 | 8 | 9 | 10 |