posts - 11,  comments - 41,  trackbacks - 0

          獲得一千萬美元風投開始算起剛滿一年,如今SpringSource(Spring框架背后的公司)搖身一變,成為應用服務器提供商,并且舉著SpringSource應用平臺(SpringSource Application Platform)的黃鉞白旄對現(xiàn)有的Java EE服務器陣營發(fā)起挑戰(zhàn)。SpringSource應用平臺是構建在Spring、OSGi和Apache Tomcat之上的應用服務器,這個新的應用服務器摒棄了原有的Java EE服務器標準,自然而然地將Spring編程模型展現(xiàn)其中,隨之而來的還有一套基于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實現(xiàn)基于OSGi的部署。SpringSource在Eclipse基金會的Equinox OSGi運行時環(huán)境的基礎上創(chuàng)建了一個具備日志、跟蹤、啟動、類加載、管理和其它特性的“內核”,Tomcat被作為一個包(bundle)納入到平臺當中,從而實現(xiàn)對Web功能的支持。

          InfoQ借此機會對Spring框架的共同創(chuàng)始人兼SpringSource的CEO Rod Johnson進行一次采訪,對這個新的應用服務器展開探討。在闡釋這個新平臺的必要性時,Rod一針見血地指向目前開發(fā)和生產(chǎn)環(huán)境的許多痛處,比如跨配置文件出現(xiàn)的元數(shù)據(jù)重復現(xiàn)象,還有本質上在項目中常常在服務器上再部署服務器(即在部署應用時,在同一個部署單元附帶部署許多工具和框架),而與此同時這些部件卻主要只使用它們應用服務器中的Web容器部分的事實。因此,SpringSource希望在當今的開發(fā)需要的基礎上提供一個更為簡單的平臺。

          在談到這個新應用服務器的優(yōu)點時,Johnson強調了模塊化:對于服務器本身以及提供給開發(fā)人員的打包和部署模式來說,這是個兩全之策。通過利用OSGi,以及OSGi包之間依賴關系相互作用的性質,運行的應用服務器只會激活在它上面運行的應用所需要的特性,從而削減服務器的內存占用和啟動時間。這個依賴關系支持的功能還允許依賴類庫的多個版本共存,以支持不同應用;因而應用服務器的某些部分就可以很容易地更新和重啟,而無需重啟整個服務器。從開發(fā)的角度看,服務器的模塊化也使得在代碼變化時,可以很快地進行極其細粒度的重部署。

          Johnson在言及OSGi和SpringSource對Eclipse Equinox OSGi的使用時,高度評價了OSGi規(guī)范的運行時實現(xiàn)所帶來的基礎平臺,但也表示OSGi在日常的應用開發(fā)上屬于比較底層的地位。Johnson闡述到,SpringSource希望幫助開發(fā)人員在企業(yè)環(huán)境中輕松獲得價值。在新的編程模式的構造背后,這個新的應用服務器將OSGi的許多復雜性抽象了出來。Johnson接著說,應用服務器將會支持PAR,一套新的可部署單元,簡化企業(yè)應用在使用OSGi上的復雜性(下文會詳細說明)。

          當被問到對于沒有對OSGi提供原生支持的遺留類庫的支持時,Johnson回應到,他們已經(jīng)在上面花費了很大心血,使得應用服務器環(huán)境和類加載功能能夠以兼容的方式和遺留類庫協(xié)作。

          當被問到對不提供OSGi原生支持的類庫的遺留支持時,Johnson回答說他們已經(jīng)在這方面投入了大量精力,保證應用服務器環(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產(chǎn)品兼容于其它應用平臺。接著Johnson還評論了即將到來的Java EE 6規(guī)范:

          Java EE 6重點在模塊性,這個方向是正確的。很可能SpringSource應用服務器會在一定程度上符合Java EE 6。Java EE 6分成A、B、C三種規(guī)格(profile)。我們幾乎肯定會實現(xiàn)A和B規(guī)格,C規(guī)格里面我非常確定將實現(xiàn)Entity Beans 1.1模型以及一些遺留技術。我還不能說是100%確定,因為Java EE 6規(guī)范還沒有定案。

          最后,InfoQ和Johnson討論到了SpringSource應用平臺的大局方面。對于轉換到OSGi,他的回答是:

          傳統(tǒng)的應用服務器模型正逐漸過時。BEA和IBM正在用OSGi逐步重新實現(xiàn)他們的應用服務器。 SpringSource現(xiàn)在就提供OSGi支持。從統(tǒng)計數(shù)字上看,大多數(shù)人都不會部署到完整的平臺上,他們部署到Tomcat。他們選擇了Spring 編程模型而非Java EE。市場已經(jīng)作出了選擇,問題只是開發(fā)者還要和服務器斗爭多長時間。

          Johnson解釋說他對SpringSource應用平臺成功的自信來自三個原因:

          • 它是第一個建立在現(xiàn)代技術基礎上的產(chǎn)品。符合Java EE規(guī)范已經(jīng)不是至高無上的目標。干凈的代碼基礎是我們的一項競爭優(yōu)勢。我們在設計和實現(xiàn)中滿足的是現(xiàn)今的需求,而不是10年前的需求。
          • POJO編程是現(xiàn)在行業(yè)的方向所在。過去POJO編程是被強行嫁接到其它產(chǎn)品上的。在我們的產(chǎn)品中,POJO編程是設計的前提。
          • SpringSource應用平臺采用的OSGi技術是下一代技術的基礎。

          除了Rod Johnson,InfoQ還與SpringSource的Rob Harrop探討了新應用服務器的一些技術細節(jié)。對于與傳統(tǒng)Java EE應用服務器相比有何增減,他說:

          ……JPA和JMS都支持,但我們沒有包含任何特定實現(xiàn)。對于JPA,我們支持Hibernate、 OpenJPA和Toplink。我們在OSGi環(huán)境中增加了對加載時織入的支持,而且會尊重應用的邊界,因此不會意外污染應用間共享的庫。不包括 JNDI,我們用OSGi Service Registry來取代它。Servlets是通過內嵌的Tomcat來支持的。JEE中有而SpringSource應用平臺沒有的東西包括 Entity Beans等等。

          接下來InfoQ問到Spring Dynamic Modules。Spring DM成為公開項目已經(jīng)有一段時間了。對于模塊化部署,我們向Harrop詢問Spring DM是否增加了什么新東西:

          這個平臺引入了應用的概念,應用由一個或多個Bundle組成。應用中的包有明確的作用域,可以防止發(fā)生應用間的沖突。在應用把服務發(fā)布到OSGi service registry的情況下,防止沖突尤其重要,誰也不想見到服務之間發(fā)生沖突。

          我們引入了Import-Library語句,因此在應用中使用第三方庫變得更加簡單。你不需要再寫一大串不直觀的 Import-Package聲明,Import-Library可以自動為指定的庫引入所有必需的package。像Hibernate JPA這樣的庫還可以跨多個Bundle,可見Import-Library確實物有所值。

          至于為了讓Spring DM在平臺中運行而進行的擴展,為數(shù)不多。

          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增加了一些低級的鉤子,以實現(xiàn)典型的場景下的資源裝載。我們擴展了類裝載來支持加載時織入,并且把裝載語義丟到一邊。我們操縱context classloader,讓第三方一如既往地看到類。PAR是其中的核心角色,因為它定義了上下文類裝載以及加載時織入的可見范圍。

          對于一些最糟糕的情況,我們會提供修補版的庫,讓它們能在OSGi中工作。修補版的庫可以通過SpringSource Enterprise Bundle Repository獲得,我們的修改也會提交回相應的項目。

          最后Harrrop著重強調了這個應用服務器在模塊化上的優(yōu)勢,應用服務器因此可以維持最低的內存占用。平臺在運行中才設置依賴項,因此只有確實用到的依賴項才會被裝載。

          最近幾年中有過許多關于Java EE標準是否已經(jīng)死亡的討論,而今天我們看到一個可能很重要的應用服務器不帶Java EE支持。這種變化對于未來有何影響?你怎么看?


          轉載自:InfoQ中文站 http://www.infoq.com/cn/
          posted @ 2008-05-01 20:37 GoKu 閱讀(1776) | 評論 (2)編輯 收藏

          雖然現(xiàn)在出現(xiàn)了很多ORM框架,可是還是有很多朋友也許還在使用JDBC,就像我現(xiàn)在一樣,除了學習的時候在使用Hibernate、Spring類似這些優(yōu)秀的框架,工作時一直都在使用JDBC。本文就簡單介紹一下利用Jakarta Commons旗下beanutils、dbutils簡化JDBC數(shù)據(jù)庫操作,以拋磚引玉,希望對像我一樣在使用JDBC的朋友有所幫助。

              下面就分兩部分簡單介紹beanutils、dbutils在基于JDBC API數(shù)據(jù)庫存取操作中的運用。第一部分顯介紹beanutils在JDBC數(shù)據(jù)庫存取操作中的運用,第二部分介紹dbutils在JDBC數(shù)據(jù)庫存取操作中的運用,最后看看他們的優(yōu)缺點,談談本人在項目運用過程中對他們的一點心得體會,僅供參考,其中有錯誤的地方希望大蝦不吝賜教,大家多多交流共同進步。

          一、Jakarta Commons beanutils

                 Beanutils是操作Bean的銳利武器,其提過的BeanUtils工具類可以簡單方便的讀取或設置Bean的屬性,利用Dyna系列,還可以在運行期創(chuàng)建Bean,符合懶人的習慣,正如LazyDynaBean,LazyDynaClass一樣,呵呵。這些用法已經(jīng)有很多文章提及,也可以參考apache的官方文檔。

          對于直接利用JDBC API訪問數(shù)據(jù)庫時(這里針對的是返回結果集ResultSet的查詢select),大多數(shù)都是采用兩種方式,一種是取出返回的結果集的數(shù)據(jù)存于Map中,另一種方式是Bean里。針對第二種方式,Beanutils里提供了ResultSetDynaClass結合DynaBean以及RowSetDynaClass結合DynaBean來簡化操作。下面用以個簡單的例子展示一下beanutils的這兩個類在JDBC數(shù)據(jù)庫操作中的運用。

          請在本機建立數(shù)據(jù)庫publish,我用的是MySQL,在publish數(shù)據(jù)庫中建立表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來實現(xiàn)同樣的類,之后看看他們之間有什么不同,用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;
                 }



          這兩個方法輸出的結果應該是一樣的。但是很顯然第二種方式比第一種方式要好,它把數(shù)據(jù)訪問部分抽取出來放到一個方法中,顯得簡單清晰。

          其實在利用ResultSetDynaClass時,必須在ResultSet等數(shù)據(jù)庫資源關閉之前,處理好那些數(shù)據(jù),你不能在資源關閉之后使用DynaBean,否則就會拋出異常,異常就是說不能在ResultSet之后存取數(shù)據(jù)(具體的異常名我也忘了),當然你也可以采用以前的方式一個一個的把數(shù)據(jù)放到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把大多數(shù)與關閉資源相關的封裝起來,另外,你也可以使用DbUtils進行關閉,當然DbUtils提供的功能當然不止這些,它提過了幾個常用的靜態(tài)方法,除了上述的關閉資源外,DbUtils. commitAndClose(Connection conn)還提供事務提及等操作。
          還是以一個例子來說說吧,畢竟我不是搞業(yè)務的,小嘴巴吧嗒吧噠不起來啊,呵呵。
              為了和采用Beanutils更好的進行對比,這個例子還是實現(xiàn)同樣的功能,數(shù)據(jù)庫同樣采用前一篇文章中提到的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顯然代碼量減少了很多。
          上例在處理結果集時,它把數(shù)據(jù)庫中的每一行映射成一個Map,其中列名作為Key,該列對應的值作為Value存放,查詢的所有的數(shù)據(jù)一起放在一個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對象的,其性能可想而知了(不過我沒有測試過啊,所以我說這個話可說是沒有根據(jù)的,感興趣的朋友自己測試一下,記得告訴我結果哦,呵呵),除了MapListHandler以及BeanListHandler之外,DButils還提供了其他的Handler,如果這些不能滿足你的需求,你也可以自己實現(xiàn)一個Handler。
              最后,也是最大的體會,也許是最大的收獲吧,那就是:對于每一個項目,在根據(jù)每一個需求獲取相應解決方案時,先尋找開源組件,看是否已經(jīng)有滿足某些功能需求的開源組件,如果沒有,再考慮自主開發(fā)或者向第三方購買,否則盡量采用開源組件.
              請盡量享用開源的魅力,盡情的擁抱開源吧。

          posted @ 2008-04-24 16:39 GoKu 閱讀(782) | 評論 (0)編輯 收藏
          僅列出標題
          共2頁: 上一頁 1 2 

          <2025年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          留言簿(1)

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 四会市| 博乐市| 北碚区| 富平县| 柳江县| 连城县| 延吉市| 崇州市| 麻阳| 桦甸市| 梧州市| 河北省| 马山县| 丰镇市| 宁国市| 宜黄县| 铅山县| 杭州市| 鲁山县| 台州市| 克什克腾旗| 武宁县| 九江县| 新沂市| 馆陶县| 柯坪县| 波密县| 武穴市| 密山市| 宁强县| 衡山县| 襄垣县| 方城县| 汾阳市| 广州市| 香格里拉县| 仙居县| 烟台市| 虞城县| 彭州市| 澄迈县|