<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 120,  comments - 19,  trackbacks - 0
     
         摘要: 美洲豹 美洲豹汽車公司原是利蘭汽車公司的分部,素以生產豪華的美洲豹 ( 又稱捷豹 ...  閱讀全文
    posted @ 2006-05-23 08:47 阿成 閱讀(255) | 評論 (0)編輯 收藏

    用Validator(驗證器)提供的豐富的內置驗證方法簡化Struts的開發過程。

    Struts框架的一個主要好處是它提供了對接收到的表單數據進行驗證的內置界面。如果有任何驗證失敗,則應用程序都會重新顯示HTML表單,這樣就可以改正無效的數據了。如果驗證成功,則處理過程會繼續進行。Struts框架的簡單驗證界面會減少與處理數據驗證有關的令人頭疼的事情,這樣你就可以把精力集中到驗證代碼上,而不是放到捕獲數據、重新顯示不完整或無效數據的技巧上。

    但是,Struts內置的驗證界面也有缺點。例如,在整個應用程序中驗證代碼常常會大量重復,因為許多域需要相同的驗證邏輯。對一些相似字段的驗證邏輯進行任何修改都要求在幾個地方修改代碼,還要重新編譯受影響的代碼。為了解決這個問題并增強Struts驗證界面的功能,作為Struts的第三方附加件創建了Validator框架。后來,Validator被集成到核心Struts代碼庫中,并從Struts中分離出來,現在它是一個獨立的Jakarta Commons項目。雖然Validator是一個獨立的框架,但它仍能與其他程序封裝在一起后提供,并與Struts無縫集成。

    Validator概述

    沒有Validator,你就不得不編寫驗證表單數據所需的全部代碼,并把它放入Form Bean對象的validate( )方法中。對于想在其上進行數據驗證的每個Form Bean域來說,都需要編寫邏輯代碼來實現驗證。此外,你還必須編寫代碼來存儲驗證失敗時的出錯消息。

    有了Validator,你就不必在Form Bean中編寫用于驗證或存儲錯誤消息的任何代碼。相反,Form Bean提供了Validator的一個ActionForm子類,它提供驗證或存儲錯誤消息的功能。

    可把Validator框架作為一個可用于Form Bean驗證的可插入的驗證例行程序系統來進行安裝。每個驗證例行程序都只是一個Java方法,負責執行特定類型的驗證任務,驗證可能通過,也可能失敗。 默認情況下,Validator與幾個有用的驗證例行程序封裝在一起來提供,這些例行程序能滿足大多數情況下的驗證要求。但是,如果Validator框架沒有提供你需要的驗證例行程序,那么你可以自己創建定制的驗證例行程序,并將它插入到該框架中。此外,Validator還支持服務器端和客戶端(JavaScript)的驗證,而Form Bean只提供服務器端驗證界面。

    Validator使用兩個XML配置文件來分別確定安裝哪個驗證例行程序和如何將它們應用于給定的應用程序。第一個配置文件validator-rules.xml說明應該被插入到框架中的驗證例行程序,并提供每個驗證的邏輯的名稱。validator-rules.xml文件還定義了每個驗證例行程序的客戶端JavaScript代碼。可以配置Validator讓它把這個JavaScript代碼發送到瀏覽器上,這樣驗證就可以在客戶端和服務器端進行了。

    第二個配置文件validation.xml確定哪個驗證例行程序應用到哪個Form Bean。文件中的定義使用struts-config.xml文件給出的Form Bean的邏輯名稱以及validator-rules.xml文件給出的驗證例行程序的邏輯名稱,以便把二者關聯起來。

    使用Validator框架包括啟用Validator插件、配置Validator的兩個配置文件,以及創建提供Validator的ActionForm子類的Form Beans。下面詳細解釋如何配置和使用Validator。

    啟用Validator插件

    雖然Validator框架是與Struts封裝在一起提供的,但在默認狀況下Validator并不被啟用。為了啟用Validator,要向你的應用程序的struts-config.xml文件中添加下面的插件定義。

    <!-- Validator Configuration -->
    <plug-in className="org.apache.struts
    .validator.ValidatorPlugIn">
      <set-property property="pathnames"
                   value="/WEB-INF/
      validator-rules.xml, /WEB-INF/
    
      validation.xml"/>
    </plug-in>
    

    該定義告訴Struts為你的應用程序加載并初始化Validator插件。在初始化時,該插件裝入由路徑名屬性指定的、用逗號分隔的Validator配置文件清單。每個配置文件的路徑應該用與Web應用程序的相關的路徑來指定,如前面的例子所示。

    請注意,你的應用程序的struts-config.xml文件必須與Struts Configuration Document Type Definition(Struts配置文檔類型定義,DTD)一致,后者規定文件中元素出現的順序。所以,你必須把Validator插件定義放到該文件的適當位置。確保文件中元素適當排列的最簡便方法就是使用諸如Struts Console的工具,它自動格式化你的配置文件,以便與DTD保持一致。

    配置validator-rules.xml

    Validator框架可以設置為可插入系統,其驗證例行程序僅僅是插入到該系統中執行具體驗證的Java方法。validator-rules.xml文件說明性地插入Validator用于執行驗證的驗證例行程序中。Struts示例應用程序帶有這個文件的預配置拷貝。在大多數情況下,你不必修改這個預配置拷貝,除非你要向該框架中添加自己定制的驗證。

    清單1 是一個示例validator-rules.xml文件,說明如何將驗證例行程序插入到Validator中。validator-rules.xml文件中的每個驗證例行程序都有自己的定義,它用validator標記聲明,利用name屬性為該驗證例行程序指定邏輯名,并指定該例行程序的類和方法。該例行程序的邏輯名稱供該文件中的其他例行程序以及validation.xml文件中的驗證定義用于引用該例行程序。

    請注意,validator標記放在javascript的標記中,javascript標記用于定義客戶端JavaScript代碼,以便在客戶端執行與服務器端相同的驗證。

    提供的驗證程序

    默認情況下,Validator中包括幾個基本驗證例行程序,你可以用它們來處理大多數驗證問題。這些例行程序具有邏輯名稱,如required(用于輸入要求的值)、CreditCard(用于輸入信用卡號碼值)、email(用于輸入電子郵件地址值),等等。

    創建Form Bean

    為了使用Validator,你的應用程序的Form Bean必須歸到Validator的ActionForm的某一子類,而不是ActionForm本身。Validator的ActionForm子類提供了ActionForm的validate( )方法(它嵌入到Validator框架中)的實施過程。你不必從頭編寫驗證代碼并把它投入validate( )方法中,相反,可以完全忽略該方法,因為Validator為你提供了驗證代碼。

    與Struts提供的核心功能相類似,Validator提供給你兩種可供選擇的方法來創建Form Bean。 你可以選擇的第一種方法就是像下面這樣創建一個特定的Form Bean對象:

    package com.jamesholmes.minihr;
    
    import org.apache.struts.validator
    .ValidatorForm;
    
    
    public class LogonForm extends ValidatorForm {
      private String username;
      private String password;
      
      public String getUsername() {
        return username;
      }
      
      public void setUsername(String 
    username) {
        this.username = username;
      }
    
    
      public String getPassword() {
        return password;
      }
    public void setPassword(String 
    password) {
        this.password = password;
      }
    }
    

    這個類與你不是用Validator所創建的類相似,但它提供ValidatorForm而不是ActionForm。這個類也不提供ActionForm的空reset( )和validate( )方法的實施過程,因為ValidatorForm提供了相應過程。

    在struts-config.xml文件中配置這個特定Form Bean的方法與配置正則Form Bean的方法相同:

    <form-beans>
      <form-bean name="logonForm"
                type="com.jamesholmes
      .minihr.LogonForm"/>
    </form-beans>
    

    用表單標記的name屬性給特定Form Bean指定的邏輯名是在定義validation.xml文件中的驗證時所使用的名稱,如下所示:

    <!DOCTYPE form-validation 
    PUBLIC "-//Apache Software Foundation//
           DTD Commons Validator Rules
           Configuration 1.0//EN"
           "http://jakarta.apache.org/
          commons/dtds/validator_1_0.dtd">
    
    
    <form-validation>
      <formset>
        <form name="logonForm">
          <field property="username" 
                depends="required">
            <arg0 key="prompt.username"/>
          </field>
        </form>
      </formset>
    </form-validation>
    

    Validator使用該表單標記的name屬性的值將驗證定義與要應用這些定義的Form Bean的名稱相匹配。

    創建Form Bean時可以選擇的第二種方法是在struts-config.xml文件中定義一個動態Form Bean,如下所示:

    <form-beans>
      <form-bean name="logonForm"
                type="org.apache
    .struts.validator.DynaValidatorForm">
        <form-property name="username"
                type="java.lang.String"/>
        <form-property name="password"
                type="java.lang.String"/>
      </form-bean>
    </form-beans>
    

    動態Form Bean不要求創建特定的Form Bean對象;相反,要定義Form Bean應該具有的屬性和類型,而Struts為你動態創建Form Bean。 Validator允許你使用這個概念,就像在核心Struts中使用這個概念一樣。與使用Validator的惟一區別就是要指定Form Bean是org.apache.struts.validator.DynaValidatorForm類型,而不是org.apache.struts.action.DynaActionForm類型。

    分配給動態Form Bean的邏輯名是在定義validation.xml文件中的驗證時使用的名稱。Validator使用與之相匹配的名稱將這些驗證與Form Bean聯系在一起。

    除了創建Form Bean的這兩種標準方法之外,Validator還提供了一個高級特性,用于將多個驗證定義與一個Form Bean定義聯系起來。當你使用基于validatorForm或基于DynaValidatorForm的Form Bean時,Validator使用struts-config.xml文件中的Form Bean的邏輯名稱,將Form Bean映射到validation.xml文件中的驗證定義。這種機制在大多數情況下非常有用,但在某些時候,Form Bean要在多個操作中共享。 一個操作可能使用Form Bean的所有域(fields),而另一個操作可能只使用這些域的一個子集。因為驗證定義被連接到Form Bean,所以只使用域的一個子集的操作就無法繞過對未使用域的驗證。當驗證Form Bean時,就會對未使用的域生成錯誤消息,因為Validator無從知道不去驗證未使用的域,它只是簡單地把它們看作缺失或無效。

    為了解決這個問題,Validator提供了兩個附加的ActionForm子類,它使你能夠將驗證與操作相關聯,而不是與Form Bean相關聯。這樣你就可以根據哪個操作正在使用Form Bean來指定把哪些驗證用于該Form Bean了。對于特定的Form Bean,你要像下面這樣聲明org.apache.struts.validator.ValidatorActionForm子類:

    public class AddressForm extends ValidatorActionForm {
      ...
    }
    

    對于動態Form Bean,在struts-config.xml文件中為Form Bean定義指定org.apache.struts.validator.DynaValidatorActionForm的類型,如下所示:

    <form-bean name="addressForm"
              type="org.apache.struts
    .validator.DynaValidatorActionForm">
      ...
    </form-bean>
    

    在validation.xml文件中,把一組驗證映射到一個操作路徑,而不是映射到Form Bean名,因為如果你定義了Create Address和Edit Address兩個操作(它們使用同一個Form Bean),那么每個操作都會有一個惟一的操作名,如下所示:

    <action-mappings>
      <action path="/createAddress"
             type="com.jamesholmes
      .minihr.CreateAddressAction"
             name="addressForm"/>
      <action path="/editAddress"
             type="com.jamesholmes
      .minihr.EditAddressAction"
             name="addressForm"/>
    
    </action-mappings>
    

    下面的validation.xml文件片斷顯示了兩組驗證,它們用于同一個Form Bean,但卻有不同的操作路徑:

    <formset>
      <form name="/createAddress">
        <field property="city"
              depends="required">
          <arg0 key="prompt.city"/>
        </field>
      </form>
      <form name="/editAddress">
        <field property="state"
              depends="required">
          <arg0 key="prompt.state"/>
        </field>
      </form>
    </formset>
    

    因為Form Bean要么屬于ValidatorActionForm子類,要么屬于DynaValidatorActionForm子類,所以Validator知道用一個操作路徑代替Form Bean的邏輯名稱來找出用于Form Bean的驗證。

    配置validation.xml文件

    validation.xml文件用于聲明將應用到Form Beans的一組驗證。要驗證的每個Form Bean在這個文件中都有自己的定義。在這個定義中,指定要應用到該Form Bean的各域的驗證。下面是一個validation.xml文件的例子,說明如何定義驗證:

    <!DOCTYPE form-validation 
    PUBLIC "-//Apache Software Foundation//
           DTD Commons Validator Rules
           Configuration 1.0//EN"
           "http://jakarta.apache.org/
          commons/dtds/validator_1_0.dtd">
    
    <form-validation>
      <formset>
        <form name="logonForm">
          <field property="username"
                depends="required">
            <arg0 key="prompt.username"/>
    
          </field>
          <field property="password"
                depends="required">
            <arg0 key="prompt.password"/>
          </field>
        </form>
      </formset>
    </form-validation>
    

    validation.xml文件的第一個元素是form-validation。這個元素是該文件的主元素,而且只定義一次。在form-validation元素內定義form-set元素,它包括多個表單元素。一般來說,在文件中只定義一個form-set元素,但是如果要將驗證國際化,那就要在每個地方單獨使用一個form-set元素。

    每個表單元素使用name屬性將名稱與其所包含的域驗證集關聯起來。Validator使用這個邏輯名稱將這些驗證映射到在struts-config.xml文件中定義的一個Form Bean。根據要驗證的Form Bean的類型,Validator力求將該名稱與Form Bean的邏輯名稱或操作路徑相匹配。在表單元素內,field元素定義要應用到Form Bean的特定域的驗證。field元素的property屬性對應于特定Form Bean中的域名。depends屬性利用validator-rules.xml文件指定驗證例行程序的邏輯名稱,這些例行程序將應用到域驗證中。

    配置ApplicationResources.properties

    Validator使用Struts的資源綁定(Resource Bundle)機制將錯誤消息具體化。不用在框架中對錯誤消息進行硬編碼,Validator使你能在ApplicationResources.properties文件中為一個消息指定一個鍵值,如果驗證失敗則將返回該鍵值。validator-rules.xml文件中的每個驗證例行程序都用validator標記的msg屬性指定錯誤消息的鍵值,如下所示:

    <validator name="required"
              classname="org.apache
    
    .struts.validator.FieldChecks"
              method="validateRequired"
              methodParams="java.lang
    .Object, org.apache.commons.validator
    .ValidatorAction, org.apache.commons
    .validator.Field, org.apache.struts
    .action.ActionErrors, javax.servlet
    .http.HttpServletRequest"
              msg="errors.required">
    

    如果在驗證例行程序運行時驗證失敗,則返回與msg屬性指定的鍵值對應的消息。

    下面的片段顯示來自ApplicationResources.properties文件的驗證出錯時的默認消息集,它們由Struts示例應用程序提供。每個消息的鍵值對應于每個由validator-rules.xml文件中的驗證例行程序所指定的消息,它們由Struts示例應用程序提供。

    # Error messages for Validator framework validations
    errors.required={0} is required.
    errors.minlength={0} cannot be less than {1} characters.
    errors.maxlength={0} cannot be greater than {2} characters.
    errors.invalid={0} is invalid.
    errors.byte={0} must be a byte.
    errors.short={0} must be a short.
    errors.integer={0} must be an integer.
    errors.long={0} must be a long.0.   errors.float={0} must be a float.
    
    errors.double={0} must be a double.
    errors.date={0} is not a date.
    errors.range={0} is not in the range {1} through {2}.
    errors.creditcard={0} is not a valid credit card number.
    errors.email={0} is an invalid e-mail address.
    

    請注意,每條消息都有占位符,形式為{0}、{1}或{2}。在運行期間,占位符被另一個值代替,如所驗證的域的名稱。這一特性特別有用,它使你能夠創建可被幾個不同的域重復使用的通用驗證錯誤消息。

    例如,下面給出required驗證的錯誤消息errors.required:

    errors.required={0} is required.
    

    當你使用validation.xml文件中的該required驗證時,必須定義用于替換該錯誤消息中的{0}的值,如下所示:

    <form name="auctionForm">
      <field property="bid" depends="required">
        <arg0 key="prompt.bid"/>
      </field>
    </form>
    

    錯誤消息最多可以有4個占位符:{0}和{3}。這些占位符分別稱為arg0到arg3,你可以通過使用arg0~arg3標記來指定它們。在上面的例子中,arg0標記指定了用于替換{0}占位符的值。該標記的key屬性指定來自ApplicationResources.properties文件的一個消息鍵值,它的值用于替換占位符,如下所示:

    下一步

    閱讀
    關于Validator的更多文章
    jakarta.apache.org/commons/validator

    關于Struts Console的更多文章
    www.jamesholmes.com/struts

    prompt.bid=Auction Bid
    

    使用消息鍵值代替占位符的值,這一方法使你不必在validation.xml文件中對替換值反復硬編碼。但是,如果你不想使用Resource Bundle的鍵值/值機制來指定占位符的值,則可以使用arg0標記的如下語法顯式地指定占位符的值:

    <arg0 key="Auction Bid" resource="false"/>
    

    在這個例子中,resource屬性的值設為false,以便通知Validator要把該key屬性指定的值作為占位符的值,而不要作為ApplicationResources.properties文件中消息的一個鍵值。

    啟用客戶端驗證

    Validator除了提供了簡化服務器端表單數據驗證過程的框架外,它還提供了執行客戶端驗證時易于使用的方法。在validator-rules.xml文件中定義的每一個驗證例行程序都可以隨意指定JavaScript代碼,這些代碼可以在瀏覽器(客戶端上的)中運行,從而執行與服務器端進行的驗證相同的驗證過程。在客戶端進行驗證時,除非所有表單都通過驗證,否則這些表單不允許被提交。

    為了啟用客戶端驗證,必須在每個需要驗證的JSP中放上Struts HTML Tag Library(標記庫)的javascript標記,如下所示:

    <html:javascript formName="logonForm"/>
    

    javascript標記要求使用formName屬性來為想要對其執行驗證的表單指定validation.xml文件中給出的表單定義名,如下所示:

    <form name="logonForm">
      <field property="username"
            depends="required">
        <arg0 key="prompt.username"/>
      </field>
      <field property="password"
            depends="required">
        <arg0 key="prompt.password"/>
      </field>
    </form>
    

    為表單定義指定的服務器端的所有驗證都將在客戶端運行。由于客戶端驗證用JavaScript執行,所以可以有多種方法不去執行它。要確保驗證過程總是能運行,不論你是否選擇啟用了客戶端驗證,Validator都在服務器端執行這些驗證。

    結論

    Validator框架針對表單數據的驗證提供了可配置的系統,從而為核心Struts框架添加了很多有價值的功能。通過把Validator框架用于你的應用程序,你可以節約時間并簡化Struts應用程序的開發過程。

    posted @ 2006-05-11 14:52 阿成 閱讀(296) | 評論 (0)編輯 收藏

    工廠模式定義:提供創建對象的接口.
    為什么工廠模式是如此常用?因為工廠模式就相當于創建實例對象的new,
    我們經常要根據類Class生成實例對象,如A a=new A() 工廠模式也是用來
    創建實例對象的,所以以后new時就要多個心眼,是否可以考慮實用工廠模式,
    雖然這樣做,可能多做一些工作,但會給你系統帶來更大的可擴展性和盡量少
    的修改量。

    我們以類Sample為例, 如果我們要創建Sample的實例對象:
    ?Sample sample=new Sample();
    可是,實際情況是,通常我們都要在創建sample實例時做點初始化的工作,比如
    賦值 查詢數據庫等。首先,我們想到的是,可以使用Sample的構造函數,這樣
    生成實例就寫成: ?Sample sample=new Sample(參數);
    但是,如果創建sample實例時所做的初始化工作不是象賦值這樣簡單的事,可能
    是很長一段代碼,如果也寫入構造函數中,那你的代碼很難看了(就需要Refactor重整)。
    為什么說代碼很難看,初學者可能沒有這種感覺,我們分析如下,初始化工作如果
    是很長一段代碼,說明要做的工作很多,將很多工作裝入一個方法中,相當于將很多雞
    蛋放在一個籃子里,是很危險的,這也是有背于Java面向對象的原則,面向對象的
    封裝(Encapsulation)和分派(Delegation)告訴我們,盡量將長的代碼分派“切割”成
    每段,將每段再“封裝”起來(減少段和段之間偶合聯系性),這樣,就會將風險分散,
    以后如果需要修改,只要更改每段,不會再發生牽一動百的事情。
    在本例中,首先,我們需要將創建實例的工作與使用實例的工作分開, 也就是說,
    讓創建實例所需要的大量初始化工作從Sample的構造函數中分離出去。
    這時我們就需要Factory工廠模式來生成對象了,不能再用上面簡單new Sample(參數)。
    還有,如果Sample有個繼承如MySample, 按照面向接口編程,我們需要將Sample抽象成一個
    接口.現在Sample是接口,有兩個子類MySample 和HisSample .我們要實例化他們時,如下:
    Sample mysample=new MySample();
    Sample hissample=new HisSample();
    隨著項目的深入,Sample可能還會"生出很多兒子出來", 那么我們要對這些兒子一個個
    實例化,更糟糕的是,可能還要對以前的代碼進行修改:加入后來生出兒子的實例.這在傳
    統程序中是無法避免的.
    但如果你一開始就有意識使用了工廠模式,這些麻煩就沒有了.
    工廠方法
    你會建立一個專門生產Sample實例的工廠:
    public class Factory{
      public static Sample creator(int which){
      //getClass 產生Sample 一般可使用動態類裝載裝入類。
      if (which==1)
        return new SampleA();
      else if (which==2)
        return new SampleB();
      }
    }
    那么在你的程序中,如果要實例化Sample時.就使用
    Sample sampleA=Factory.creator(1);
    這樣,在整個就不涉及到Sample的具體子類,達到封裝效果,也就減少錯誤修改的機會,
    這個原理可以用很通俗的話來比喻:就是具體事情做得越多,越容易范錯誤.這每個做
    過具體工作的人都深有體會,相反,官做得越高,說出的話越抽象越籠統,范錯誤可能性
    就越少.好象我們從編程序中也能悟出人生道理?呵呵.
    使用工廠方法要注意幾個角色,首先你要定義產品接口,如上面的Sample,產品接口
    下有Sample接口的實現類,如SampleA,其次要有一個factory類,用來生成產品Sample。
    進一步稍微復雜一點,就是在工廠類上進行拓展,工廠類也有繼承它的實現類
    concreteFactory了。
    抽象工廠
    工廠模式中有: 工廠方法(Factory Method) 抽象工廠(Abstract Factory).
    這兩個模式區別在于需要創建對象的復雜程度上。如果我們創建對象的方法變得復雜了,
    如上面工廠方法中是創建一個對象Sample,如果我們還有新的產品接口Sample2.
    這里假設:Sample有兩個concrete類SampleA和SamleB,而Sample2也有兩個concrete類
    Sample2A和SampleB2,那么,我們就將上例中Factory變成抽象類,將共同部分封裝在抽
    象類中,不同部分使用子類實現,下面就是將上例中的Factory拓展成抽象工廠:
    public abstract class Factory{
      public abstract Sample creator();
      public abstract Sample2 creator(String name);
    }
    public class SimpleFactory extends Factory{
      public Sample creator(){
        .........
        return new SampleA
      }
      public Sample2 creator(String name){
        .........
        return new Sample2A
      }
    }
    public class BombFactory extends Factory{
      public Sample creator(){
        ......
        return new SampleB
      }
      public Sample2 creator(String name){
        ......
        return new Sample2B
      }
    }
    從上面看到兩個工廠各自生產出一套Sample和Sample2,也許你會疑問,為什么我
    不可以使用兩個工廠方法來分別生產Sample和Sample2?
    抽象工廠還有另外一個關鍵要點,是因為 SimpleFactory內,生產Sample和生產
    Sample2的方法之間有一定聯系,所以才要將這兩個方法捆綁在一個類中,這個工廠
    類有其本身特征,也許制造過程是統一的,比如:制造工藝比較簡單,所以名稱
    叫SimpleFactory。
    在實際應用中,工廠方法用得比較多一些,而且是和動態類裝入器組合在一起應用,
    舉例
    我們以Jive的ForumFactory為例,這個例子在前面的Singleton模式中我們討論過,
    現在再討論其工廠模式:
    public abstract class ForumFactory {
      private static Object initLock = new Object();
      private static String className = "com.jivesoftware.forum.database.DbForumFactory";
      private static ForumFactory factory = null;
      public static ForumFactory getInstance(Authorization authorization) {
        //If no valid authorization passed in, return null.
        if (authorization == null) {
          return null;
        }
        //以下使用了Singleton 單態模式
        if (factory == null) {
          synchronized(initLock) {
            if (factory == null) {
                ......
              try {
                  //動態轉載類
                  Class c = Class.forName(className);
                  factory = (ForumFactory)c.newInstance();
              }
              catch (Exception e) {
                  return null;
              }
            }
          }
        }

        //Now, 返回 proxy.用來限制授權對forum的訪問
        return new ForumFactoryProxy(authorization, factory,
                        factory.getPermissions(authorization));
      }

      //真正創建forum的方法由繼承forumfactory的子類去完成.
      public abstract Forum createForum(String name, String description)
      throws UnauthorizedException, ForumAlreadyExistsException;

      ....

    }
    因為現在的Jive是通過數據庫系統存放論壇帖子等內容數據,如果希望更改為通過文件系統實現,這個工廠方法ForumFactory就提供了提供動態接口:

    private static String className = "com.jivesoftware.forum.database.DbForumFactory";

    你可以使用自己開發的創建forum的方法代替com.jivesoftware.forum.database.DbForumFactory就可以.

    在上面的一段代碼中一共用了三種模式,除了工廠模式外,還有Singleton單態模式,以及proxy模式,proxy模式主要用來授權用戶對forum的訪問,因為訪問forum有兩種人:一個是注冊用戶 一個是游客guest,那么那么相應的權限就不一樣,而且這個權限是貫穿整個系統的,因此建立一個proxy,類似網關的概念,可以很好的達到這個效果.?

    看看Java寵物店中的CatalogDAOFactory:

    public class CatalogDAOFactory {

      /**

      * 本方法制定一個特別的子類來實現DAO模式。
      * 具體子類定義是在J2EE的部署描述器中。
      */

      public static CatalogDAO getDAO() throws CatalogDAOSysException {

        CatalogDAO catDao = null;

        try {

          InitialContext ic = new InitialContext();
          //動態裝入CATALOG_DAO_CLASS
          //可以定義自己的CATALOG_DAO_CLASS,從而在無需變更太多代碼
          //的前提下,完成系統的巨大變更。

          String className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS);

          catDao = (CatalogDAO) Class.forName(className).newInstance();

        } catch (NamingException ne) {

          throw new CatalogDAOSysException("
            CatalogDAOFactory.getDAO: NamingException while
              getting DAO type : \n" + ne.getMessage());

        } catch (Exception se) {

          throw new CatalogDAOSysException("
            CatalogDAOFactory.getDAO: Exception while getting
              DAO type : \n" + se.getMessage());

        }

        return catDao;

      }

    }

    CatalogDAOFactory是典型的工廠方法,catDao是通過動態類裝入器className獲得CatalogDAOFactory具體實現子類,這個實現子類在Java寵物店是用來操作catalog數據庫,用戶可以根據數據庫的類型不同,定制自己的具體實現子類,將自己的子類名給與CATALOG_DAO_CLASS變量就可以。

    由此可見,工廠方法確實為系統結構提供了非常靈活強大的動態擴展機制,只要我們更換一下具體的工廠方法,系統其他地方無需一點變換,就有可能將系統功能進行改頭換面的變化。

    設計模式如何在具體項目中應用見《Java實用系統開發指南》

    posted @ 2006-05-08 09:12 阿成 閱讀(346) | 評論 (0)編輯 收藏

    最近還算輕松,快到51了嘛,同事們回家的回家,不回家的想著去哪玩兒。

    過兩天我也回家了,這回可以好好玩兒和歇幾天了。

    posted @ 2006-04-29 08:34 阿成 閱讀(198) | 評論 (0)編輯 收藏
    EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在這里下載
    http://www.eclipse.org/downloads/index.php
    ?
    lomboz J2EE插件,開發JSP,EJB
    http://forge.objectweb.org/projects/lomboz


    1.MyEclipse J2EE開發插件,支持SERVLET/JSP/EJB/數據庫操縱等
    http://www.myeclipseide.com
    ?
    2.Properties Editor? 編輯java的屬性文件,并可以自動存盤為Unicode格式
    http://propedit.sourceforge.jp/index_en.html
    ?
    3.Colorer Take? 為上百種類型的文件按語法著色
    http://colorer.sourceforge.net/
    ?
    4.XMLBuddy 編輯xml文件
    http://www.xmlbuddy.com
    ?
    5.Code Folding? 加入多種代碼折疊功能(比eclipse自帶的更多)
    http://www.coffee-bytes.com/servlet/PlatformSupport
    ?
    6.Easy Explorer? 從eclipse中訪問選定文件、目錄所在的文件夾
    http://easystruts.sourceforge.net/
    ?
    7.Fat Jar 打包插件,可以方便的完成各種打包任務,可以包含外部的包等
    http://fjep.sourceforge.net/
    ?
    8.RegEx Test 測試正則表達式
    http://brosinski.com/stephan/archives/000028.php
    ?
    9.JasperAssistant 報表插件(強,要錢的)
    http://www.jasperassistant.com/
    ?
    10.Jigloo GUI Builder JAVA的GUI編輯插件
    http://cloudgarden.com/jigloo/
    ?
    11.Profiler 性能跟蹤、測量工具,能跟蹤、測量BS程序
    http://sourceforge.net/projects/eclipsecolorer/
    ?
    12.AdvanQas 提供對if/else等條件語句的提示和快捷幫助(自動更改結構等)
    http://eclipsecolorer.sourceforge.net/advanqas/index.html
    ?
    13.Log4E Log4j插件,提供各種和Log4j相關的任務,如為方法、類添加一個logger等
    http://log4e.jayefem.de/index.php/Main_Page
    ?
    14.VSSPlugin VSS插件
    http://sourceforge.net/projects/vssplugin
    ?
    15.Implementors 提供跳轉到一個方法的實現類,而不是接中的功能(實用!)
    http://eclipse-tools.sourceforge.net/implementors/
    ?
    16.Call Hierarchy 顯示一個方法的調用層次(被哪些方法調,調了哪些方法)
    http://eclipse-tools.sourceforge.net/call-hierarchy/index.html
    ?
    17.EclipseTidy 檢查和格式化HTML/XML文件
    http://eclipsetidy.sourceforge.net/
    ?
    18.Checkclipse 檢查代碼的風格、寫法是否符合規范
    http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm
    ?
    19.Hibernate Synchronizer Hibernate插件,自動映射等
    http://www.binamics.com/hibernatesync/
    ?
    20.VeloEclipse? Velocity插件
    http://propsorter.sourceforge.net/
    ?
    21.EditorList 方便的列出所有打開的Editor
    http://editorlist.sourceforge.net/
    ?
    22.MemoryManager 內存占用率的監視
    http://cloudgarden.com/memorymanager/
    ?
    23.swt-designer java的GUI插件
    http://www.swt-designer.com/
    ?
    24.TomcatPlugin 支持Tomcat插件
    http://www.sysdeo.com/eclipse/tomcatPlugin.html
    ?
    25.XML Viewer
    http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html
    ?
    26.quantum 數據庫插件
    http://quantum.sourceforge.net/
    ?
    27.Dbedit 數據庫插件
    http://sourceforge.net/projects/dbedit
    ?
    28.clay.core 可視化的數據庫插件
    http://www.azzurri.jp/en/software/index.jsp
    http://www.azzurri.jp/eclipse/plugins
    ?
    29.hiberclipse hibernate插件
    http://hiberclipse.sourceforge.net
    http://www.binamics.com/hibernatesync
    ?
    30.struts-console Struts插件
    http://www.jamesholmes.com/struts/console/
    ?
    31.easystruts Struts插件
    http://easystruts.sourceforge.net
    ?
    32.veloedit Velocity插件
    http://veloedit.sourceforge.net/
    ?
    33.jalopy 代碼整理插件
    http://jalopy.sourceforge.net/
    ?
    34.JDepend 包關系分析
    http://andrei.gmxhome.de/jdepend4eclipse/links.html
    ?
    35.Spring IDE Spring插件
    http://springide-eclip.sourceforge.net/updatesite/
    ?
    36.doclipse 可以產生xdoclet 的代碼提示
    http://beust.com/doclipse/

    posted @ 2006-04-27 16:57 阿成 閱讀(479) | 評論 (0)編輯 收藏

    <html>
    <head>
    <title>打造下拉菜單</title>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <style>
    body,td { font-size:12px; font-family:宋體}
    a:link {? color: #ffffff; text-decoration: none}
    a:visited {? color: #ffffff; text-decoration: none}
    a:hover {? color: #ff9933; text-decoration: none}
    table {? border: #000000; border-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px}
    </style>
    <script language="JavaScript">
    <!--
    <!--
    function MM_reloadPage(init) {? //reloads the window if Nav4 resized
    ? if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
    ??? document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }}
    ? else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload();
    }
    MM_reloadPage(true);
    // -->

    function MM_findObj(n, d) { //v4.0
    ? var p,i,x;? if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    ??? d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
    ? if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
    ? for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
    ? if(!x && document.getElementById) x=document.getElementById(n); return x;
    }

    function MM_showHideLayers() { //v3.0
    ? var i,p,v,obj,args=MM_showHideLayers.arguments;
    ? for (i=0; i<(args.length-2); i+=3) if ((obj=MM_findObj(args[i]))!=null) { v=args[i+2];
    ??? if (obj.style) { obj=obj.style; v=(v=='show')?'visible':(v='hide')?'hidden':v; }
    ??? obj.visibility=v; }
    }
    //-->
    </script>
    </head>

    <body bgcolor="#CCCCCC" text="#000000" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" scroll=auto>
    <div id="title" style="position:absolute; left:8px; top:15px; width:240px; height:15px; z-index:1; background-color: #006699; layer-background-color: #006699; border: 1px none #000000">
    ? <table width="480" cellspacing="0" cellpadding="2">
    ??? <tr>
    ????? <td width="120" onMouseOver="MM_showHideLayers('menu1','','show')" onMouseOut="MM_showHideLayers('menu1','','hide')"><b><font color="#FFFFFF"><a href="#">■
    ??????? 經典論壇</a></font></b> </td>
    ????? <td width="120" onMouseOver="MM_showHideLayers('menu2','','show')" onMouseOut="MM_showHideLayers('menu2','','hide')"><b><font color="#FFFFFF"><a href="#">■
    ??????? 天極網</a></font></b> </td>
    ????? <td width="120" onMouseOver="MM_showHideLayers('menu2','','show')" onMouseOut="MM_showHideLayers('menu2','','hide')">&nbsp;</td>
    ????? <td width="120" onMouseOver="MM_showHideLayers('menu2','','show')" onMouseOut="MM_showHideLayers('menu2','','hide')">&nbsp;</td>
    ??? </tr>
    ? </table>
    </div>
    <div id="menu1" style="position:absolute; left:8px; top:34px; width:120px; height:80px; z-index:2; background-color: #999966; layer-background-color: #999966; border: 1px none #000000; visibility: hidden" onMouseOver="MM_showHideLayers('menu1','','show')" onMouseOut="MM_showHideLayers('menu1','','hide')">
    ? <table width="100%" cellspacing="0" cellpadding="2" height="80">
    ??? <tr>
    ????? <td>&nbsp;<a href="#">Dreamweaver 專欄</a></td>
    ??? </tr>
    ??? <tr>
    ????? <td>&nbsp;<a href="#">Fireworks 專欄</a></td>
    ??? </tr>
    ??? <tr>
    ????? <td>&nbsp;<a href="#">Flash 基本操作</a></td>
    ??? </tr>
    ??? <tr>
    ????? <td>&nbsp;<a href="#">Flash 5 Action</a></td>
    ??? </tr>
    ? </table>
    </div>
    <div id="menu2" style="position:absolute; left:127px; top:34px; width:120px; height:80px; z-index:2; background-color: #999966; layer-background-color: #999966; border: 1px none #000000; visibility: hidden" onMouseOver="MM_showHideLayers('menu2','','show')" onMouseOut="MM_showHideLayers('menu2','','hide')">
    ? <table width="100%" cellspacing="0" cellpadding="2" height="80">
    ??? <tr>
    ????? <td>&nbsp;<a href="#">新聞</a>&nbsp;</td>
    ??? </tr>
    ??? <tr>
    ????? <td height="20">&nbsp;<a href="#">軟件</a></td>
    ??? </tr>
    ??? <tr>
    ????? <td>&nbsp;<a href="#">硬件</a>&nbsp;</td>
    ??? </tr>
    ??? <tr>
    ????? <td>&nbsp;<a href="#">商城</a></td>
    ??? </tr>
    ? </table>
    </div>

    </body>
    </html>


    http://www.blueidea.com/tech/web/2003/301.asp

    posted @ 2006-04-25 14:43 阿成 閱讀(632) | 評論 (0)編輯 收藏
    前些日子編了一陣子程序,有點累。

    最近工作稍微輕松了一些。現在每天晚上打籃球鍛煉身體和技術

    到5 ·1就可以回家好好玩會兒,休息休息了
    posted @ 2006-04-19 10:03 阿成 閱讀(205) | 評論 (0)編輯 收藏

    Spring是一個非常優秀的輕量級框架,通過Spring的IoC容器,我們的關注點便放到了需要實現的業務邏輯上。對AOP的支持則能讓我們動態增強業務方法。編寫普通的業務邏輯Bean是非常容易而且易于測試的,因為它能脫離J2EE容器(如Servlet,JSP環境)單獨進行單元測試。最后的一步便是在Spring框架中將這些業務Bean以XML配置文件的方式組織起來,它們就按照我們預定的目標正常工作了!非常容易!

    本文將給出一個基本的Spring入門示例,并演示如何使用Spring的AOP將復雜的業務邏輯分離到每個方面中。

    1.開發環境配置
    2.編寫Bean接口及其實現
    3.在Spring中配置Bean并獲得Bean的實例
    4.編寫Advisor以增強ServiceBean
    5.總結

    1.開發環境配置

    首先,需要正確配置Java環境。推薦安裝JDK1.4.2,并正確配置環境變量:

    JAVA_HOME=<JDK安裝目錄>
    CLASSPATH=.
    Path=%JAVA_HOME%\bin;……

    我們將使用免費的Eclipse 3.1作為IDE。新建一個Java Project,將Spring的發布包spring.jar以及commons-logging-1.0.4.jar復制到Project目錄下,并在Project > Properties中配置好Java Build Path:

    2.編寫Bean接口及其實現

    我們實現一個管理用戶的業務Bean。首先定義一個ServiceBean接口,聲明一些業務方法:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				/**
    ?* Interface of service facade.
    ?*
    ?* @author Xuefeng
    ?*/
    public interface ServiceBean {
    ??? void addUser(String username, String password);
    ??? void deleteUser(String username);
    ??? boolean findUser(String username);
    ??? String getPassword(String username);
    }

    然后在MyServiceBean中實現接口:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?*
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import java.util.*;
    		
    				public class MyServiceBean implements ServiceBean {
    		
    				??? private String dir;
    ??? private Map map = new HashMap();
    				??? public void setUserDir(String dir) {
    ??????? this.dir = dir;
    ??????? System.out.println("Set user dir to: " + dir);
    ??? }
    				??? public void addUser(String username, String password) {
    ??????? if(!map.containsKey(username))
    ??????????? map.put(username, password);
    ??????? else
    ??????????? throw new RuntimeException("User already exist.");
    ??? }
    				??? public void deleteUser(String username) {
    ??????? if(map.remove(username)==null)
    ??????????? throw new RuntimeException("User not exist.");
    ??? }
    				??? public boolean findUser(String username) {
    ??????? return map.containsKey(username);
    ??? }
    				??? public String getPassword(String username) {
    ??????? return (String)map.get(username);
    ??? }
    }

    為了簡化邏輯,我們使用一個Map保存用戶名和口令。

    現在,我們已經有了一個業務Bean。要測試它非常容易,因為到目前為止,我們還沒有涉及到Spring容器,也沒有涉及到任何Web容器(假定這是一個Web應用程序關于用戶管理的業務Bean)。完全可以直接進行Unit測試,或者,簡單地寫個main方法測試:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				public class Main {
    		
    				??? public static void main(String[] args) throws Exception {
    ??????? ServiceBean service = new MyServiceBean();
    ??????? service.addUser("bill", "hello");
    ??????? service.addUser("tom", "goodbye");
    ??????? service.addUser("tracy", "morning");
    ??????? System.out.println("tom's password is: " + service.getPassword("tom"));
    ??????? if(service.findUser("tom")) {
    ??????????? service.deleteUser("tom");
    ??????? }
    ??? }
    }

    執行結果:

    3.在Spring中配置Bean并獲得Bean的實例

    我們已經在一個main方法中實現了業務,不過,將對象的生命周期交給容器管理是更好的辦法,我們就不必為初始化對象和銷毀對象進行硬編碼,從而獲得更大的靈活性和可測試性。

    想要把ServiceBean交給Spring來管理,我們需要一個XML配置文件。新建一個beans.xml,放到src目錄下,確保在classpath中能找到此配置文件,輸入以下內容:

    				<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd ">
    <beans>
    ??? <bean id="service" class="com.crackj2ee.example.spring.MyServiceBean" />
    </beans>

    以上XML聲明了一個id為service的Bean,默認地,Spring為每個聲明的Bean僅創建一個實例,并通過id來引用這個Bean。下面,我們修改main方法,讓Spring來管理業務Bean:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    				public class Main {
    		
    				??? public static void main(String[] args) throws Exception {
    ??????? // init factory:
    ??????? XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
    ??????? // use service bean:
    ??????? ServiceBean service = (ServiceBean)factory.getBean("service");
    ??????? service.addUser("bill", "hello");
    ??????? service.addUser("tom", "goodbye");
    ??????? service.addUser("tracy", "morning");
    ??????? System.out.println("tom's password is \"" + service.getPassword("tom") + "\"");
    ??????? if(service.findUser("tom")) {
    ??????????? service.deleteUser("tom");
    ??????? }
    ??????? // close factory:
    ??????? factory.destroySingletons();
    ??? }
    }

    執行結果:
    ?

    由于我們要通過main方法啟動Spring環境,因此,首先需要初始化一個BeanFactory。紅色部分是初始化Spring的BeanFactory的典型代碼,只需要保證beans.xml文件位于classpath中。

    然后,在BeanFactory中通過id查找,即可獲得相應的Bean的實例,并將其適當轉型為合適的接口。

    接著,實現一系列業務操作,在應用程序結束前,讓Spring銷毀所有的Bean實例。

    對比上一個版本的Main,可以看出,最大的變化是不需要自己管理Bean的生命周期。另一個好處是在不更改實現類的前提下,動態地為應用程序增加功能。

    4.編寫Advisor以增強ServiceBean

    所謂AOP即是將分散在各個方法處的公共代碼提取到一處,并通過類似攔截器的機制實現代碼的動態織入。可以簡單地想象成,在某個方法的調用前、返回前、調用后和拋出異常時,動態插入自己的代碼。在弄清楚Pointcut、Advice之類的術語前,不如編寫一個最簡單的AOP應用來體驗一下。

    考慮一下通常的Web應用程序都會有日志記錄,我們來編寫一個LogAdvisor,對每個業務方法調用前都作一個記錄:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;
    				public class LogAdvisor implements MethodBeforeAdvice {
    ??? public void before(Method m, Object[] args, Object target) throws Throwable {
    ??????? System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");
    ??? }
    }

    然后,修改beans.xml:

    				<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd ">
    				<beans>
    ??? <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
    				??? <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
    		
    				??? <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
    ??????? <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
    ??????? <property name="target"><ref local="serviceTarget"/></property>
    ??????? <property name="interceptorNames">
    ??????????? <list>
    ??????????????? <value>logAdvisor</value>
    ??????????? </list>
    ??????? </property>
    ??? </bean>
    </beans>

    注意觀察修改后的配置文件,我們使用了一個ProxyFactoryBean作為service來與客戶端打交道,而真正的業務Bean即MyServiceBean被聲明為serviceTarget并作為參數對象傳遞給ProxyFactoryBean,proxyInterfaces指定了返回的接口類型。對于客戶端而言,將感覺不出任何變化,但卻動態加入了LogAdvisor,關系如下:
    ?

    運行結果如下,可以很容易看到調用了哪些方法:
    ?

    要截獲指定的某些方法也是可以的。下面的例子將修改getPassword()方法的返回值:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    				public class PasswordAdvisor implements MethodInterceptor {
    ??? public Object invoke(MethodInvocation invocation) throws Throwable {
    ??????? Object ret = invocation.proceed();
    ??????? if(ret==null)
    ??????????? return null;
    ??????? String password = (String)ret;
    ??????? StringBuffer encrypt = new StringBuffer(password.length());
    ??????? for(int i=0; i<password.length(); i++)
    ??????????? encrypt.append('*');
    ??????? return encrypt.toString();
    ??? }
    }

    這個PasswordAdvisor將截獲ServiceBean的getPassword()方法的返回值,并將其改為"***"。繼續修改beans.xml:

    				<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd ">
    <beans>
    ??? <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
    				??? <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
    		
    				??? <bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" />
    		
    				??? <bean id="passwordAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    ??????? <property name="advice">
    ??????????? <ref local="passwordAdvisorTarget"/>
    ??????? </property>
    ??????? <property name="patterns">
    ??????????? <list>
    ??????????????? <value>.*getPassword</value>
    ??????????? </list>
    ??????? </property>
    ??? </bean>
    				??? <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
    ??????? <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
    ??????? <property name="target"><ref local="serviceTarget"/></property>
    ??????? <property name="interceptorNames">
    ??????????? <list>
    ??????????????? <value>logAdvisor</value>
    ??????????????? <value>passwordAdvisor</value>
    ??????????? </list>
    ??????? </property>
    ??? </bean>
    </beans>

    利用Spring提供的一個RegexMethodPointcutAdvisor可以非常容易地指定要截獲的方法。運行結果如下,可以看到返回結果變為"******":
    ?

    還需要繼續增強ServiceBean?我們編寫一個ExceptionAdvisor,在業務方法拋出異常時能做一些處理:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import org.springframework.aop.ThrowsAdvice;
    		
    				public class ExceptionAdvisor implements ThrowsAdvice {
    ??? public void afterThrowing(RuntimeException re) throws Throwable {
    ??????? System.out.println("[Exception] " + re.getMessage());
    ??? }
    }

    將此Advice添加到beans.xml中,然后在業務Bean中刪除一個不存在的用戶,故意拋出異常:

    				service.deleteUser("not-exist");
    		

    再次運行,注意到ExceptionAdvisor記錄下了異常:
    ?

    5.總結

    利用Spring非常強大的IoC容器和AOP功能,我們能實現非常靈活的應用,讓Spring容器管理業務對象的生命周期,利用AOP增強功能,卻不影響業務接口,從而避免更改客戶端代碼。

    為了實現這一目標,必須始終牢記:面向接口編程。而Spring默認的AOP代理也是通過Java的代理接口實現的。雖然Spring也可以用CGLIB實現對普通類的代理,但是,業務對象只要沒有接口,就會變得難以擴展、維護和測試。

    可以從此處下載完整的Eclipse工程:
    http://www.crackj2ee.com/Article/UploadFiles/200604/SpringBasic.rar

    posted @ 2006-04-18 17:28 阿成 閱讀(2044) | 評論 (1)編輯 收藏

    1.刪除提示

    1)<a? href="#" onclick="return(confirm('刪除后無法恢復,您確定刪除嗎?'))">刪除</a>

    2)JS
    <a? href="#" >刪除</a>

    <script language="JavaScript" type="text/javascript">
    function delete_confirm(){
    ?if(event.srcElement.outerText=="刪除" || event.srcElement.value=="刪除")
    ? event.returnValue=confirm("刪除后將不能恢復,您確認執行刪除操作么?");
    ?}
    ?document.onclick=delete_confirm;
    </script>

    2.點擊按鈕探出提示
    ?<input type=button value="reload" onclick="javascript:reload()">

    <script type="text/javascript">
    function reload() {
    ?
    ?if (confirm("確認?"))
    ?{
    ?var url="#";
    ?window.location.href=url;
    ?}
    }
    3.點擊鏈接彈出提示

    <a? href="確認后的連接地址" onclick="return(confirm('想要的提示信息?'))">顯示信息</a>

    4.onchange()用法
    <select name="year" onchange="javascript:changeYear()">
    ?<OPTION OPTION>
    </SELECT>

    <SCRIPT language="javascript">
    function changeYear(){
    ??var url =?....;
    ?window.location.href = url;
    }
    </SCRIPT>

    4.根據選擇的radio轉向不同的URL
    <input type="Radio" name="id" value="1" checked></td>
    <input type="Radio" name="id" value="2" checked></td>
    <input type="Radio" name="id" value="3" checked></td>

    <SCRIPT language="javascript">
    function WhichOneisChecked(obj) {
    for (var i = 0;i < obj.elements.length;i++){
    if (obj.elements[i].checked == true){
    var weekLogId=obj.elements[i].value;
    var url="......";
    window.location.href = url;
    }
    }
    }
    </SCRIPT>

    5.radio 全選
    function checkAll(e, itemName)
    {
    ? var aa = document.getElementsByName(itemName);
    ? for (var i=0; i<aa.length; i++)
    ?? aa[i].checked = e.checked;
    }
    function check(e, allName)
    {
    ? var all = document.getElementsByName(allName)[0];
    ? if(!e.checked) all.checked = false;
    ? else
    ? {
    ??? var aa = document.getElementsByName(e.name);
    ??? for (var i=0; i<aa.length; i++)
    ???? if(!aa[i].checked) return;
    ??? all.checked = true;
    ? }
    ???
    <input type=checkbox checked name=allTeams onclick="checkAll(this, 'teamIds')">

    <input type="checkbox" name="teamIds" checked value="<%=.....%>" onclick="check(this, 'allTeams')">

    6.顯示、隱藏
    鏈接實現
    <script language="javascript">
    ??function showLay(divId){
    ??????? var objDiv = eval(divId);
    ??????? if (objDiv.style.display=="none"){
    ??????????????? eval("sp"+divId+".innerHTML='隱藏'");
    ??????????????? objDiv.style.display="";
    ??????? }else{
    ??????????????? eval("sp"+divId+".innerHTML='查看'");
    ??????????????? objDiv.style.display="none";
    ??????? }}
    ??</script>

    ???<td>
    ??????<a href="#"? onclick="showLay('Layer1')"><span id="spLayer1">查看</span></a>
    ??????<br>
    ??????<div id="Layer1" style="display:none;">......</div>
    ?????</td>

    按鈕實現
    <SCRIPT LANGUAGE="JavaScript">
    function hidden_show()
    {
    ?var obj = document.getElementById("Layer1");
    ?if(obj.style.visibility == "")
    ??obj.style.visibility = "hidden";
    ?else
    ??obj.style.visibility = "";
    }
    </SCRIPT>
    <td>
    ??????<INPUT TYPE="button" onclick="hidden_show();" value="hidden/show">
    ?????<br>
    ??????<div id="Layer1"?>
    ???????<%=weekPlan%>
    ??????</div>
    ?????</td>

    posted @ 2006-04-17 17:33 阿成 閱讀(552) | 評論 (0)編輯 收藏
    在計算機開發語言的歷史中,從來沒有哪種語言象Java那樣受到如此眾多廠商的支持,有如此多的開發工具,Java菜鳥們如初入大觀園的劉姥姥,看花了眼,不知該何種選擇。的確,這些工具各有所長,都沒有絕對完美的,就算是老鳥也很難做出選擇。在本文中我簡要介紹了常見的十五種Java開發工具的特點,管中窺“器”,希望能對大家有所幫助。

    ?? 1、JDK (Java Development Kit)

      SUN的Java不僅提了一個豐富的語言和運行環境,而且還提了一個免費的Java開發工具集(JDK)。開發人員和最終用戶可以利用這個工具來開發java程序。

    ?? JDK簡單易學,可以通過任何文本編輯器(如:Windows 記事本、UltrEdit、Editplus、FrontPage以及dreamweaver等)編寫Java源文件,然后在DOS狀況下利通過javac命令將Java源程序編譯成字節碼,通過Java命令來執行編譯后的Java文件,這能帶給DOS時代程序員美好的回憶。

    ? Java 初學者一般都采用這種開發工具。

    ? 2、Java Workshop

    1143135411556_3614.gif

    ??????Sun MicroSystems公司于1996年3月26日推出了Java WorkShop 1.0,這是業界出現的第一個供Internet網使用的多平臺開發工具,它可以滿足各公司開發Internet和Intranet網應用軟件的需要。Java WorkShop完全用Java語言編寫,是當今市場上銷售的第一個完全的Java開發環境,目前Java WorkShop的最性版本是3.0。Java Workshop的特點表現如下:

      1)結構易于創建:在創建平臺中立的網格結構方面,Java Workshop比其他任何一種Java開發工具都要方便。

      2)可視化編程:Java Workshop的可視化編程特性是很基本的。Java Workshop允許程序員重新安排這些操作,甚至可以確定觸發操作行為的過濾器。Java Workshop產生的模板帶有許多注釋,這對程序員是很有幫助的。

      此外,Java WorkShop支持JDK1.1.3以及JavaBeans組件模型,API和語言特征增加了編譯Java應用程序的靈活性。 Java WorkShop開發環境由于完全用Java寫成,所以可移植性極好,以致于多個平臺都能支持,目前Java WorkShop支持Solaris操作環境SPARC及Intel 版)、Windows95、WindowsNT、以及HP/Ux等平臺。適合于初學者進行一些簡單的Java編程。Java WorkShop的缺點是Java Workshop中的每一個可視化對象都遲早會用到網格布局,這種設計方法是許多人不習慣的;Java Workdshop的調色板是較差的,僅僅能滿足絕大部分應用的基本要求。

    ? 3、NetBeans 與Sun Java Studio 5

    1143135607062_8513.gif

    ??? NetBeans是開放源碼的Java集成開發環境(IDE),適用于各種客戶機和Web應用。 Sun Java Studio是Sun公司最新發布的商用全功能Java IDE,支持Solaris、Linux和Windows平臺,適于創建和部署2層Java Web應用和n層J2EE應用的企業開發人員使用。

      NetBeans是業界第一款支持創新型Java開發的開放源碼IDE。開發人員可以利用業界強大的開發工具來構建桌面、Web或移動應用。同時,通過NetBeans和開放的API的模塊化結構,第三方能夠非常輕松地擴展或集成NetBeans平臺。

      NetBeans3.5.1主要針對一般Java軟件的開發者,而Java One Studio5則主要針對企業做網絡服務等應用的開發者。Sun不久還將推出Project Rave,其目標是幫助企業的開發者進行軟件開發。NetBeans 3.5.1版本與其他開發工具相比,最大區別在于不僅能夠開發各種臺式機上的應用,而且可以用來開發網絡服務方面的應用,可以開發基于J2ME的移動設備上的應用等。在NetBeans 3.5.1基礎上,Sun開發出了Java One Studio5,為用戶提供了一個更加先進的企業編程環境。在新的Java One Studio5里有一個應用框架,開發者可以利用這些模塊快速開發自己在網絡服務方面的各種應用程序。

    4.Borland 的JBuilder

    ? Jbuilder進入了Java集成開發環境的王國,它滿足很多方面的應用,尤其是對于服務器方以及EJB開發者們來說。下面簡單介紹一下Jbuilder的特點:

      1)Jbuilder支持最新的Java技術,包括Applets、JSP/Servlets、JavaBean以及EJB(Enterprise JavaBeans)的應用。

      2)用戶可以自動地生成基于后端數據庫表的EJB Java類,Jbuilder同時還簡化了EJB的自動部署功能.此外它還支持CORBA,相應的向導程序有助于用戶全面地管理IDL(分布應用程序所必需的接口定義語言Interface Definition Language)和控制遠程對象。

      3)Jbuilder支持各種應用服務器。Jbuilder與Inprise Application Server緊密集成,同時支持WebLogic Server,支持EJB 1.1和EJB 2.0,可以快速開發J2EE的電子商務應用。

      4)Jbuilder能用Servlet和JSP開發和調試動態Web 應用。

      5)利用Jbuilder可創建(沒有專有代碼和標記)純Java2應用。由于Jbuilder是用純Java語言編寫的,其代碼不含任何專屬代碼和標記,它支持最新的Java標準。

      6)Jbuilder擁有專業化的圖形調試介面,支持遠程調試和多線程調試,調試器支持各種JDK版本,包括J2ME/J2SE/J2EE。

      JBuilder環境開發程序方便,它是純的Java 開發環境,適合企業的J2EE開發;缺點是往往一開始人們難于把握整個程序各部分之間的關系,對機器的硬件要求較高,比較吃內存,這時運行速度顯得較慢。

     5、Oracle 的JDeveloper

    ? Oracle9i JDeveloper(定為9.0版,最新為10g)為構建具有J2EE功能,XML和Web services的復雜的,多層的Java應用程序提供了一個完全集成的開發環境。它為運用Oracle9i數據庫和應用服務器的開發人員提供特殊的功能和增強性能,除此以外,它也有資格成為用于多種用途Java開發的一個強大的工具。

      Oracle9i JDeveloper的主要特點如下:

      ① 具有UML(Unified Modeling Language,一體化建模語言)建模功能。可以將業務對象及e-business應用模型化。

      ② 配備有高速Java調試器(Debuger)、內置Profiling工具、提高代碼質量的工具“CodeCoach”等。

      ③ 支持SOAP(Simple Object Access Protocol)“簡單對象訪問協議”、UDDI(Universal Description, Discovery and Integration)“統一描述、發現和集成協議”、WSDL(Web Services Description Language)“WEB服務描述語言”等Web服務標準。

      JDeveloper 不僅僅是很好的 Java 編程工具,而且是 Oracle Web 服務的延伸,支持 Apache SOAP,以及 9iAS ,可擴充的環境和 XML 和 WSDL 語言緊密相關。Oracle9i Jdeveloper完全利用Java編寫,能夠與以前的Oracle服務器軟件以及其他廠商支持J2EE的應用服務器產品相兼容,而且在設計時著重針對Oracle9i,能夠無縫化跨平臺之間的應用開發,提供了業界第一個完整的、集成了J2EE和XML的開發環境,允許開發者快速開發可以通過Web、無線設備及語音界面訪問的Web服務和交易應用,以往只能通過將傳統Java編程技巧與最新模塊化方式結合到一個單一集成的開發環境中之后才能完成J2EE應用開發生命周期管理的事實,從根本上得到改變。缺點就是對于初學者來說,較復雜,也比較難。

    ?? 6、IBM的Visual Age for Java

    ?? Visual Age for Java是一個非常成熟的開發工具,它的特性以于IT開發者和業余的Java編程人員來說都是非常用有用的。它提供對可視化編程的廣泛支持,支持利用CICS連接遺傳大型機應用,支持EJB的開發應用,支持與Websphere的集成開發,方便的bean創建和良好的快速應用開發(RAD)支持和無文件式的文件處理。

      IBM為建設Web站點所推出的WebSphere Studio Advanced Edition及其包含的VisualAge for Java Professional Edition軟件已全面轉向以Java為中心,這樣,Java開發人員對WebSphere全套工具的感覺或許會好了許多。Studio所提供的工具有:Web站點管理、快速開發 JDBC頁向導程序、HTML編輯器和HTML語法檢查等。這確實是個不錯的HTML站點頁面編輯環境。Studio和VisualAge集成度很高,菜單中提供了在兩種軟件包之間快速移動代碼的選項。這就讓使用Studio的Web頁面設計人員和使用VisualAge的Java程序員可以嗷ソ換晃募⑿ぷ鰲?BR>
      Visual Age for Java支持團隊開發,內置的代碼庫可以自動地根據用戶做出改動而修改程序代碼,這樣就可以很方便地將目前代碼和早期版本做出比較。與Visual Age緊密結合的Websphere Studio本身并不提供源代碼和版本管理的支持,它只是包含了一個內置文件鎖定系統,當編輯項目的時候可以防止其他人對這些文件的錯誤修改,軟件還支持諸如Microsoft Visual SourceSafe這樣的第三方源代碼控制系統。Visual Age for Java完全面向對象的程序設計思想使得開發程序非常快速、高效。你可以不編寫任何代碼就可以設計出一個典型的應用程序框架。Visual Age for Java作為IBM電子商務解決方案其中產品之一,可以無縫地與其他IBM產品,如WebSphere、DB2融合, 迅速完成從設計、開發到部署應用的整個過程。

      Visual Age for Java獨特的管理文件方式使其集成外部工具非常困難,你無法讓Visual Age for Java與其他工具一起聯合開發應用。

    7、BEA 的 WebLogic Workshop

    ??? BEA WebLogic Workshop是一個統一、簡化、可擴展的開發環境,使所有的開發人員都能在 BEA WebLogic Enterprise Platform之上構建基于標準的企業級應用,從而提高了開發部門的生產力水平,加快了價值的實現。

      WebLogic Workshop除了提供便捷的Web服務之外,它能夠用于創建更多種類的應用。作為整個BEA WebLogic Platform的開發環境。不管是創建門戶應用、編寫工作流、還是創建Web應用,Workshop 8.1都可以幫助開發人員更快更好地完成。

      WebLogic Workshop的主要特點如下:

      ① 使 J2EE 開發切實可行,提高開發效率

      BEA WebLogic Workshop 使開發人員遠離 J2EE 內在的復雜性,集中精力專注業務邏輯,無須操心單調乏味的基礎結構代碼。這種創新意味著,已被企業驗證的 J2EE 的強大功能,最終被大多數不熟悉 Java 和 J2EE 的應用開發人員所掌握,從而使 IT 部門的工作效率提高一個數量級。

      可視化設計器以及直觀的概念,如事件、屬性和控件等,實現了基于事件的開發。Workshop 簡化的程序設計模型,使開發人員不必掌握復雜的 J2EE API 和面向對象的程序設計原理。所有開發人員,包括 J2EE 專家和具有可視化和過程化語言技能的應用開發人員在內,都可以共同工作在 BEA WebLogic Enterprise Platform 之上。Workshop 的可視化開發環境,創建帶有代碼注釋的標準 Java 文件,用來說明由運行時框架實施的企業級需求。J2EE 和其他高級開發人員,借助功能強大的代碼編輯功能,可以訪問 Java 源代碼,從而彌補了可視化設計器的不足。

      ② 構建企業級應用

      通過在可伸縮、安全可靠的企業級架構上實施各種應用,BEA WebLogic Workshop 大大降低了開發風險。而且,所有應用的創建都使用標準的 J2EE 組件,既保護了您的技術投資,又保持了最大的靈活性。
    BEA WebLogic Workshop 運行框架,是統一整個架構的匯聚層,使單一、簡化的程序設計模型擴展到所有的 BEA WebLogic Enterprise Platform 應用類型。通過解釋設計時創建的注釋代碼,運行時框架可以實現必要的 J2EE 組件,并且提取出與 J2EE 應用開發有關的所有底層細節。

      ③ 降低 IT 復雜性

      BEA WebLogic Workshop 提供各種 Java 控件,使得與 IT 資源的連接更輕而易舉。另外,在構建任何 BEA WebLogic Platform 的應用中,Java 控件不僅可擴展而且完全相同。這種強大、有效的方法能夠:降低 IT 技術的復雜性,優化信息的可用性,推動包含"最佳業務方案"的可重用服務的開發,使開發人員能以更低的成本、更短的時間實現更大的產出。

      利用 BEA WebLogic Workshop,任何開發人員都能以最大的生產效率,構建各種 Web 服務、Web 應用、門戶和集成項目。BEA WebLogic Workshop是BEA的產品戰略核心,它幫助客戶接觸和利用面向服務架構(SOA)的強大功能。BEA Weblogic Workshop 8.1極大簡化了當前實際企業集成環境中企業級應用和服務的構建,并成為全面支持關鍵企業級應用(如異步、真正松耦合和粗粒度消息傳送等)的自然選擇。它的缺點就是過于復雜,對于初學者來說,理解起來較為困難。

    8、WebGain 的Visual Cafe for Java

    Visual Cafe 是只能在Symantec公司的Java虛擬機、Netscape公司的Java虛擬機和Microsoft虛擬機上工作的調試器。這對于開發者來講是一個重要的特性,因為用戶開發的Java代碼中的許多軟件bug就可能中會在某種特定的虛擬機上起作用。

      在修改后進行編譯基繼續進行調試時,Visual Cafe會自動將文件存盤,使用Visual Cafe創建的原生應用具有許多特點。除了明顯的速度提高之外,Symantec使類庫的二進制方式比正常的JDK小Visual Cafe為所指定的關系自動生成或更新必要的Java代碼。利用Visual Cafe,用戶可以從一個標準對象數據庫中集合完整的Java應用程序和Applet,而不必再編寫源代碼。Visual Cafe還提供了一個擴充的源代碼開發工具集。 

      Visual Cafe綜合了Java軟件的可視化源程序開發工具,它允許開發人員在可視化視圖和源視圖之間進行有效地轉換。在可視化視圖中進行的修改立即反映在源代碼中。對源代碼的改變自動更新可視化視圖。

      Visual Cafe具有許多源文件方面的特性,如全局檢索和替換。絕大多數Java開發工具的文獻的問題在于簡單地挨個介紹開發工具的每部分組件,但用戶在開應用時還需要一個面向任務的手冊,利用這個手冊你可以不必知道工具每一部分的特定功能就可以開始創建自己的應用。Visual Cafe提供了非常全面的用戶指南,它對最開始的安裝到創建第一個Java應用和Applet都提供了全面的幫助,Visual Cafe將自動生成所指明關系的必要Java代碼。Visual Cafe可以在Windows 95和Windows NT平臺下運行,Symantec公司為Java開發工作提供一個在Macintosh操作系統下可以運行的RAD工具。Visual Cafe編譯器速度很快,在國際化支持方面比較突出;缺點就是對于初學者來說,較復雜,也比較難。

    9、Macromedia的JRUN

    ??? Macromedia公司的JRun是一個具有最廣闊適用性的Java引擎,用于開發及實施由Java Servlets和JavaServer Pages編寫的服務器端Java應用。JRun是第一個完全支持JSP 1.0 規格書的商業化產品,全球有超過80,000名開發人員使用JRun在他們已有的Web服務器上添加服務器端Java的功能。其中Web服務器包括了Microsoft IIS,Netscape Enterprise Server,Apache等。

      JRun是開發實施服務器端Java的先進引擎。如果我們希望在我們的Web應用中添加服務器端Java功能,那么JRun將成為我們的正確選擇。

      JRun目前有3個版本,它是第一個支持Java Server Pages(JSP)規格書1.0的商業化產品。JSP是一種強大的服務器端技術,它是用于創建復雜Web應用的一整套快速應用開發系統。JRun可以使我們開始開發并測試Java應用。它最多接受5個并發的連接并且包括全部Java Servlet API,支持JavaServer Pages(JSP),支持所有主要的Web servers和計算機平臺。 JRun Pro能夠在生產環境下承受大訪問量的負載,幫助我們實施應用、服務或Web站點(包括內聯網)。JRun Pro 支持無限量并發式連接運行多個Java虛擬機,包括多個并發的Java虛擬機(JVM)。提供一個遠程管理applet以及一個遠程可再分布式的管理applet。JRun Pro Unlimited包括了所有JRun Pro的功能,除次以外,還可以運行無限量的,并發的JVM。

      JRun依靠其內置的JRun Web Server可以單獨運行。使用服務器端Java,用戶可以開發出復雜的商業應用系統。最重要的一點是,由于servlets的平臺獨立性,以及更加簡單的開發、更快速的實施、更經濟的維護成本,它是CGI(Common Gateway Interface)或Perl scripts的極佳的替代產品。缺點就是對于初學者來說,較復雜,也比較難。

    10、JCreator

    ??? JCreator 是一個Java程序開發工具,也是一個Java集成開發環境(IDE)。無論你是要開發Java應用程序或者網頁上的Applet元件都難不倒它。在功能上與Sun公司所公布的JDK等文字模式開發工具相較之下來得容易,還允許使用者自訂義操作窗口界面及無限Undo/Redo等功能。

      JCreator為用戶提供了相當強大的功能,例如項目管理功能,項目模板功能,可個性化設置語法高亮屬性、行數、類瀏覽器、標簽文檔、多功能編繹器,向導功能以及完全可自定義的用戶界面。通過JCreator,我們不用激活主文檔而直接編繹或運行我們的JAVA程序。

      JCreator能自動找到包含主函數的文件或包含Applet的Html文件,然后它會運行適當的工具。在JCreator中,我們可以通過一個批處理同時編繹多個項目。JCreator的設計接近Windows界面風格,用戶對它的界面比較熟悉。其最大特點是與我們機器中所裝的JDK完美結合,是其它任何一款IDE所不能比擬的。它是一種初學者很容易上手的java開發工具,缺點是只能進行簡單的程序開發,不能進行企業J2EE的開發應用。

    11、Microsoft VJ++
    ???? Visual J++ 是Microsoft 公司推出的可視化的Java 語言集成開發環境(IDE),為Java 編程人員提供了一個新的開發環境,是一個相當出色的開發工具。無論集成性、編譯速度、調試功能、還是易學易用性,都體現了Microsoft 的一慣風格。Visual J++ 具有下面的特點:

      1)Visual J++ 把Java 虛擬機(JVM)作為獨立的操作系統組件放入Windows,使之從瀏覽器中獨立出來。

      2)Microsoft 的應用基本類庫(AFC,Application Foundation Class Library)對SUN 公司的JDK 作了擴展,使應用基本類庫更加適合在Windows 下使用。

      3) Visual J++ 的調試器支持動態調試,包括單步執行、設置斷點、觀察變量數值等。

      4) Visual J++ 提供了一些程序向導(Wizards)和生成器(Builders),它們可以方便地幫助用戶快速地生成Java 程序,幫助你在自己的工程中創建和修改文件。

      5) Visual J++ 界面友好,其代碼編輯器具有智能感知、聯機編譯等功能,使程序編寫十分方便。Visual J++ 中建立了Java 的WFC,這一新的應用程序框架能夠直接訪問Windows 應用程序接口(API),使你能夠用Java 語言編寫完全意義上的Windows 應用程序。

      6)Visual J++ 中表單設計器的快速應用開發特性使用WFC 創建基于表單的應用程序變得輕松、簡單。通過WFC 可以方便地使用ActiveX 數據對象(ADO,ActiveX Data Objects)來檢索數據和執行簡單數據的綁定。通過在表單設計器中使用ActiveX 數據對象,可以快速地在表單中訪問和顯示數據。

      Visual J++能結合微軟的一貫的編程風格,很方便進行Java 的應用開發,但它的移植性較差,不是純的Java 開發環境。

    12、Eclipse

    ??? Eclipse是一種可擴展的開放源代碼IDE。2001年11月,IBM公司捐出價值4,000萬美元的源代碼組建了Eclipse聯盟,并由該聯盟負責這種工具的后續開發。集成開發環境(IDE)經常將其應用范圍限定在“開發、構建和調試”的周期之中。為了幫助集成開發環境(IDE)克服目前的局限性,業界廠商合作創建了Eclipse平臺。Eclipse允許在同一IDE中集成來自不同供應商的工具,并實現了工具之間的互操作性,從而顯著改變了項目工作流程,使開發者可以專注在實際的嵌入式目標上。

      Eclipse框架的這種靈活性來源于其擴展點。它們是在XML中定義的已知接口,并充當插件的耦合點。擴展點的范圍包括從用在常規表述過濾器中的簡單字符串,到一個Java類的描述。任何Eclipse插件定義的擴展點都能夠被其它插件使用,反之,任何Eclipse插件也可以遵從其它插件定義的擴展點。除了解由擴展點定義的接口外,插件不知道它們通過擴展點提供的服務將如何被使用。

      利用Eclipse,我們可以將高級設計(也許是采用UML)與低級開發工具(如應用調試器等)結合在一起。如果這些互相補充的獨立工具采用Eclipse擴展點彼此連接,那么當我們用調試器逐一檢查應用時,UML對話框可以突出顯示我們正在關注的器件。事實上,由于Eclipse并不了解開發語言,所以無論Java語言調試器、C/C++調試器還是匯編調試器都是有效的,并可以在相同的框架內同時瞄準不同的進程或節點。

      Eclipse的最大特點是它能接受由Java開發者自己編寫的開放源代碼插件,這類似于微軟公司的Visual Studio和Sun微系統公司的NetBeans平臺。Eclipse為工具開發商提供了更好的靈活性,使他們能更好地控制自己的軟件技術。Eclipse聯盟已經宣布將在2004年中期發布其3.0版軟件。這是一款非常受歡迎的java開發工具,這國內的用戶越來越多,實際上實用它java開發人員是最多的。缺點就是較復雜,對初學者來說,理解起來比較困難。

    13、Ant

    ??? Another Neat Tool(Ant)是一種基于Java的build工具。理論上來說,它有些類似于(Unix)C中的make ,但沒有make的缺陷。因為Ant的原作者在多種(硬件)平臺上開發軟件時,無法忍受這些工具的限制和不便。類似于make的工具本質上是基于shell(語言)的:他們計算依賴關系,然后執行命令(這些命令與你在命令行敲的命令沒太大區別)。這就意味著你可以很容易地通過使用OS特有的或編寫新的(命令)程序擴展該工具;然而,這也意味著你將自己限制在了特定的OS,或特定的OS類型上,如Unix。Ant就不同了。與基于shell命令的擴展模式不同,Ant用Java的類來擴展。(用戶)不必編寫shell命令,配置文件是基于XML的,通過調用target樹,就可執行各種task。每個task由實現了一個實現了特定Task接口的對象來運行。

      Ant支持一些可選task,一個可選task一般需要額外的庫才能工作。可選task與Ant的內置task分開,單獨打包。這個可選包可以從你下載Ant的同一個地方下載。ANT本身就是這樣一個流程腳本引擎,用于自動化調用程序完成項目的編譯,打包,測試等。除了基于JAVA是平臺無關的外,腳本的格式是基于XML的,比make腳本來說還要好維護一些。Ant是Apache提供給Java開發人員的構建工具,它可以在Windows OS和Unix OS下運行,它不僅開放源碼并且還是一個非常好用的工具。Ant是Apache Jakarta中一個很好用的Java開發工具,Ant配置文件采用XML文檔編寫,所以Java程序員對其語法相當熟悉,Ant是專用于Java項目平臺,能夠用純Java來開發,它能夠運行于Java安裝的平臺,即體現了它的跨平臺功能。它的缺點顯示執行結果只能是DOS字符界面,不能進行復雜的java程序開發。

    14、IntelliJ

    ??? Intellij IDEA是一款綜合的Java 編程環境,被許多開發人員和行業專家譽為市場上最好的IDE。它提供了一系列最實用的的工具組合:智能編碼輔助和自動控制,支持J2EE,Ant,JUnit和CVS集成,非平行的編碼檢查和創新的GUI設計器。IDEA把Java開發人員從一些耗時的常規工作中解放出來,顯著地提高了開發效率。具有運行更快速,生成更好的代碼;持續的重新設計和日常編碼變得更加簡易,與其它工具的完美集成;很高的性價比等特點。在4.0版本中支持Generics,BEA WebLogic集成,改良的CVS集成以及GUI設計器。

      IntelliJ IDEA能盡可能地促進程序員的編程速度。它包括了很多輔助的功能,并且與Java結合得相當好。不同的工具窗口圍繞在主編程窗口周圍,當鼠標點到時即可打開,無用時也可輕松關閉,使用戶得到了最大化的有效屏幕范圍。以技術為導向的IDEA集成了調試器,支持本地和遠程的調試,即使我們需要修改一些設置上的東西使我們的工作順利進展。另外,它還提供了通常的監視,分步調試以及手動設置斷點功能,在這種斷點模式下,我們可以自動地在斷點之外設置現場訪問,甚至可以瀏覽不同的變量的值。IDE支持多重的JVM設置,幾個編譯程序和Ant建造系統,并且,它使得設置多重的自定義的類途徑變得簡單。

      IntelliJ Idea是一個相對較新的Java IDE。它是Java開發環境中最為有用的一個。高度優化的IntelleJ Idea使普通任務變得相當容易,Idea支持很多整合功能,更重要的使它們設計的好容易使用。Idea支持XML中的代碼實現,Idea同時還會校正XML,Idea支持JSP的結構。作用于普通Java代碼的眾多功能同樣適用于JSP(比如整合功能),同時支持JSP調試;支持EJB,盡管它不包括對個別應用服務器的特殊支持。Idea支持Ant建立工具,不僅是運行目標它還支持編譯與運行程序前后運行目標,另外也支持綁定鍵盤快捷鍵。在編輯一個Ant建立XML文件時,Idea還對組成Ant工程的XML部分提供支持。IntelliJ IDEA 被稱為是最好的JAVA IDE開發平臺,這套軟件就是以其聰明的即時分析和方便的 refactoring 功能深獲大家所喜愛。缺點是較復雜,對初學者來說,理解起來比較困難。

      小結

      現在常用的Java項目開發環境有:JBuilder、VisualAge for Java、Forte for Java, Visual Cafe、Eclipse、NetBeans IDE、JCreator +J2SDK、jdk+記事本、EditPlus+ J2SDK等等。一般開發J2EE項目時都需要安裝各公司的應用服務器(中間件)和相應的開發工具,在使用這些開發工具之前,我們最好能熟知這些軟件的優點和缺點,以便根據實際情況選擇應用。編程工具只是工具,為了方便人們工作而開發的,各有特點,因此,選工具主要的依據自己將要從事的領域是什么,而不是盲目的認為那種工具好,那種工具不好。最后希望大家都能找到自己合適的java 開發工具。

    posted @ 2006-04-05 13:37 阿成 閱讀(222) | 評論 (0)編輯 收藏
    僅列出標題
    共10頁: First 上一頁 2 3 4 5 6 7 8 9 10 下一頁 
    主站蜘蛛池模板: 99亚洲精品高清一二区| 亚洲黄色在线电影| 成人无码WWW免费视频| 久久亚洲精品中文字幕| 韩国二级毛片免费播放| 最近更新免费中文字幕大全| 亚洲国产中文在线二区三区免| 日本免费无遮挡吸乳视频电影| a级毛片无码免费真人久久| 亚洲一级视频在线观看| 久久久久亚洲爆乳少妇无| 美女网站免费福利视频| av成人免费电影| 亚洲欧洲另类春色校园网站| 亚洲高清无码综合性爱视频| 99爱在线精品免费观看| caoporm超免费公开视频| 亚洲精品无码成人| 久久亚洲精品中文字幕| 亚洲综合日韩久久成人AV| 好爽…又高潮了免费毛片| 全部免费毛片在线播放| 一级免费黄色毛片| 亚洲欧美日韩一区二区三区 | AV在线播放日韩亚洲欧| 国产精品免费网站| 免费国产成人午夜在线观看| 日韩亚洲翔田千里在线| 亚洲AV无码精品蜜桃| 亚洲国产综合专区在线电影| 亚洲国产精品自在拍在线播放| 青青草免费在线视频| 久久精品一区二区免费看| 天堂亚洲免费视频| 亚洲AV无码成人精品区日韩| 亚洲国产精品综合久久久| 亚洲大片在线观看| 亚洲日韩一页精品发布| 久久精品国产亚洲7777| 亚洲&#228;v永久无码精品天堂久久 | 四虎影在线永久免费观看|