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

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

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

    隨筆:45 文章:5 評論:25 引用:0
    BlogJava 首頁 發(fā)新隨筆
    發(fā)新文章 聯(lián)系 聚合管理

         摘要: 原因:首先,JFreeChart和中文驗(yàn)證碼的亂碼問題和jsp的編碼無關(guān),是由于Java虛擬機(jī)找不到字體文件造成的,所以同類的Swing或者AWT的中文亂碼問題也適用

      閱讀全文
    posted @ 2009-01-12 17:18 Hill 閱讀(4050) | 評論 (0)編輯 收藏
     
         摘要: JFreeChart真是個(gè)好東西,今天剛剛學(xué)習(xí)了一下,以后要是用時(shí),可以深入,大家要是不知道怎么在Web中畫出圖表,請參考,謝謝  閱讀全文
    posted @ 2009-01-12 16:41 Hill 閱讀(135) | 評論 (0)編輯 收藏
     

    Struts Validator驗(yàn)證器使用指南


    驗(yàn)證器:

    從0.5版,驗(yàn)證器在一些form中就已經(jīng)實(shí)現(xiàn)了,他最初包含在開發(fā)人員包中,后來核心代碼挪到Jakarta Commons包中和Struts特別擴(kuò)展中作為 Struts 1.1的一部分。許多開發(fā)者為方便一直使用struts驗(yàn)證器,這篇文檔首先概述驗(yàn)證器的核心功能性,然后大概介紹在 struts1.1中的變化和新增功能。

    如果你配置好驗(yàn)證器插件,你應(yīng)該擴(kuò)展ValidatorForm而不是ActionForm,以便它能加載你的Validator資源。他根據(jù)struts-config.xml文件中的action的name屬性為當(dāng)前form的調(diào)用相應(yīng)的驗(yàn)證器,因此在validator-rules.xml中的form元素的名稱屬性應(yīng)該與action的name屬性值相匹配。

    另外一種選擇是擴(kuò)展ValidatorActionForm 而不是ValidatorForm,ValidatorActionForm使用struts-config.xml中action的path屬性,所以path屬性的值相應(yīng)的應(yīng)該與validator-rules.xml中的Form的name屬性匹配。

    一個(gè)分離的action可以定義給多頁form的每個(gè)頁面,而且驗(yàn)證規(guī)則可以與action關(guān)聯(lián)而不是與頁碼,就像驗(yàn)證范例中的多頁form范例那樣。
    國際化

    在validator-rules.xml 文件中form的驗(yàn)證規(guī)則可以組織為FormSet。FormSet 有與java.util.Locale 類相應(yīng)的屬性:如語言, 國家以及變量型屬性,如果他們未定義,F(xiàn)ormSet 將把它設(shè)置為默認(rèn)值。一個(gè)FormSet 也可以有關(guān)聯(lián)的常量。另外還可以定義與FormSet 同一級(jí)別的全局global元素,他與FormSet同樣也有常量。

    注意:你必須在國際化的FormSet前聲明一個(gè)沒有國際化的默認(rèn)FormSet。這樣如果Validator沒有找到locale時(shí)可以有一個(gè)默認(rèn)版本。

            可插入驗(yàn)證器的默認(rèn)錯(cuò)誤信息值可以被msg元素覆蓋。所以為mask驗(yàn)證器生成錯(cuò)誤信息的替代方法就是使用msg屬性,如果字段的name屬性與驗(yàn)證器的name屬性匹配,那末將使用字段的msg屬性。

            error messages的可以設(shè)置arg0-arg3 等參數(shù)元素。如果沒有設(shè)置arg0-arg3的name屬性, error messages將使用他們作為默認(rèn)的構(gòu)建參數(shù)值。如果設(shè)置了name屬性,你就可以把參數(shù)指定給一特定的可插入驗(yàn)證器,然后這些參數(shù)將在構(gòu)造錯(cuò)誤信息時(shí)被使用。

    <field

    property="lastName"

    depends="required,mask">

    <msg

    name="mask"

    key="registrationForm.lastname.maskmsg"/>

    <arg0 key="registrationForm.lastname.displayname"/>

    <var>

    <var-name>mask</var-name>

    <var-value>^[a-zA-Z]*$</var-value>

    </var>

    </field>

    默認(rèn)的arg0-arg3元素將在消息資源中查找相應(yīng)的key,如果資源屬性設(shè)為false,她將把值直接傳進(jìn)去,而不從消息資源中查找。注意1.1版本中,你必須為每個(gè)模塊中明確地定義在驗(yàn)證中用到的消息資源,否則將使用top-level資源。

    <field

    property="integer"

    depends="required,integer,intRange">

    <arg0 key="typeForm.integer.displayname"/>

    <arg1

    name="range"

    key="${var:min}"

    resource="false"/>

    <arg2

    name="range"

    key="${var:max}"

    resource="false"/>

    <var>

    <var-name>min</var-name>

    <var-value>10</var-value>

    </var>

    <var>

    <var-name>max</var-name>

    <var-value>20</var-value>

    </var>

    </field>
    常量/變量

    全局的常量可以在全局標(biāo)簽中定義,F(xiàn)ormSet/本地常量能在formset 標(biāo)簽中創(chuàng)建。常量當(dāng)前僅僅是代替字段的property屬性,字段的var 元素的 value屬性,字段的msg 元素的 key屬性,字段的arg0-arg3 元素的 key屬性。字段的變量也可以在arg0-arg3 元素中被代替(例如:${var:min}))。替換的順序是FormSet/Locale常量第一,全局的常量第二,

    arg elements 變量最后。

    <global>

    <constant>

    <constant-name>zip</constant-name>

    <constant-value>^\d{5}(-\d{4})?$</constant-value>

    </constant>

    </global>

     

    <field

    property="zip"

    depends="required,mask">

    <arg0 key="registrationForm.zippostal.displayname"/>

    <var>

    <var-name>mask</var-name>

    <var-value>${zip}</var-value>

    </var>

    </field>

    驗(yàn)證器可以使用字段下面的變量部分來存儲(chǔ)變量,這些變量通過字段的getVar((String key)方法取得。

    <field

    property="integer"

    depends="required,integer,intRange">

    <arg0 key="typeForm.integer.displayname"/>

    <arg1

    name="range"

    key="${var:min}" resource="false"/>

    <arg2

    name="range"

    key="${var:max}" resource="false"/>

    <var>

    <var-name>min</var-name>

    <var-value>10</var-value>

    </var>

    <var>

    <var-name>max</var-name>

    <var-value>20</var-value>

    </var>

    </field>
    使用validwhen設(shè)計(jì)復(fù)雜的驗(yàn)證

    使用validwhen來設(shè)計(jì)復(fù)雜驗(yàn)證的一個(gè)經(jīng)常的要求就是根據(jù)一個(gè)字段驗(yàn)證另外一個(gè)字段(比如, 如果你要用戶兩次輸入口令來確認(rèn)值口令一致),另外一個(gè)就是表單中的一個(gè)字段只有另外一個(gè)字段有確定值的時(shí)候才是必須輸入的。新的validwhen驗(yàn)證規(guī)則將很快被包含在1.1后的STRUTS版本中,她就是用來處理這種情況的。

            validwhen 規(guī)則處理單個(gè)的變量字段,叫測試。這變量的值是一個(gè)布爾的表達(dá)式,如果驗(yàn)證有效則它必須為真??梢园@種變量的表達(dá)式有:

    u        單引號(hào)或雙引號(hào)字符串literals,

    u        十進(jìn)制、十六進(jìn)制、八進(jìn)制的Integer literals,

    u        null與null和空字符串匹配,

    u        其它可以用屬性名引用的form字段,例如customerAge,

    u        可以在外部因用得索引字段, 例如childLastName[2],

    u        可以默認(rèn)implicit因用得索引字段, 例如childLastName[], 她將作為被索引的字段使用同樣的索引到數(shù)組中,

    The literal *這里指它包含當(dāng)前測試字段的值,

    作為例子,考慮一個(gè)包含通訊地址和郵箱字段的form。如果通訊地址不為空則郵箱字段是必須的required。你能這樣定義validwhen 規(guī)則:

    <field property="emailAddress" depends="validwhen">

    <arg0 key="userinfo.emailAddress.label"/>

    <var>

    <var-name>test</var-name>

    <var-value>((sendNewsletter == null) or (*this* != null))</var-value>

    </var>

    </field>

    上面定義的意思是:如果通訊地址是空或不空時(shí)這個(gè)字段時(shí)有效的。

    這里有個(gè)稍微復(fù)雜的例子,它使用了索引字段。假定有一個(gè)表單,允許用戶輸入他們希望定購的部件號(hào)和數(shù)量。類orderLine 的bean的一數(shù)組被用來在稱為orderLines 的一屬性保持輸入項(xiàng)。

    If you wished to verify that every line with part number also had a quantity entered, you could do it with:

    如果你希望校驗(yàn)訂單中有數(shù)量輸入得每一行,你可以這樣:

    <field

    property="quantity"

    indexedListProperty="orderLines"

    depends="validwhen">

    <arg0 key="orderform.quantity.label"/>

    <var>

    <var-name>test</var-name>

    <var-value>((orderLines[].partNumber == null) or (*this* != null))</var-value>

    </var>

    </field>

    這里的意思是:如果相應(yīng)的partNumber 字段是空, 或這字段是不空的,則這字段是有效的。

    最后一個(gè)例子,想象一表單,用戶必須輸入他們的以英寸為單位的高度,如果他們在高度在60英寸以下,則出一錯(cuò)誤。(it is an error to have checked off nbaPointGuard as a career.)

    <field property="nbaPointGuard" depends="validwhen">

    <arg0 key="careers.nbaPointGuard.label"/>

    <var>

    <var-name>test</var-name>

    <var-value>((heightInInches >= 60) or (*this* == null))</var-value>

    </var>

    </field>

     

    給程序員的簡單說明:

    所有的比較關(guān)系必須在parens 封裝。All comparisons must be enclosed in parens.

    只有兩個(gè)itme時(shí)可以and或or鏈接。

    如果比較的兩item都可以轉(zhuǎn)為整數(shù),則使用numeric比較,否則使用字符串比較。
    可插入驗(yàn)證器

    驗(yàn)證是從validation.xml 文件中加載的,默認(rèn)的驗(yàn)證規(guī)則定義在validation.xml 文件中,默認(rèn)定義了required, mask ,byte, short, int, long, float, double, date (沒有本地支持), and a numeric range。

    " mask "方式依賴于默認(rèn)值安裝要求,那意味著"required "可以完成,在"'mask "將運(yùn)行以前"required "和" mask "方式被默認(rèn)包含進(jìn)框架中了。任何字段如果不是"required "而且是空或有零長度將跳過其他驗(yàn)證。

    如果使用了Javascript 標(biāo)簽,客戶端javascript在validator's javascript 屬性中查找值而且產(chǎn)生一個(gè)有驗(yàn)證form方法的對象,要得到更多的關(guān)于Javascript Validator 標(biāo)簽工作細(xì)節(jié)的詳細(xì)的解釋,參閱html標(biāo)簽API參考。

    "'mask' "方式讓你用一正則表達(dá)式掩碼驗(yàn)證字段,它使用jakarta的正規(guī)表達(dá)式包,所有的有效性規(guī)則存儲(chǔ)在validator-rules.xml 文件,使用的主類是org.apache.regexp.RE。

    validation.xml文件中的驗(yàn)證器配置范例:

    <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">

    <validator name="mask"

    classname="org.apache.struts.validator.FieldChecks"

    method="validateMask"

    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.invalid">


    定義可插入驗(yàn)證器

    方法的參數(shù)是用逗號(hào)分隔的一些類名稱列表,方法屬性需要有一個(gè)符合上面的列表的簽名。列表由以下組合而成:

    java.lang.Object – 要驗(yàn)證的Bean。

    org.apache.commons.validator.ValidatorAction – 當(dāng)前ValidatorAction。

    org.apache.commons.validator.Field – 要驗(yàn)證的字段

    org.apache.struts.action.ActionErrors – 如果驗(yàn)證錯(cuò)誤將加入ActionError的錯(cuò)誤對象javax.servlet.http.HttpServletRequest –當(dāng)前request 對象。

    javax.servlet.ServletContext – 應(yīng)用的ServletContext。

    org.apache.commons.validator.Validator–當(dāng)前的org.apache.commons.validator.Validator實(shí)例。

    java.util.Locale – 當(dāng)前用戶的Locale。
    多頁面form

    字段部分有一可選的頁面屬性,它可以被設(shè)為整數(shù),頁上字段的所有驗(yàn)證小于或等于服務(wù)器端驗(yàn)證的當(dāng)前頁,頁上字段的所有驗(yàn)證小于或等于客戶端頁上所有字段的驗(yàn)證小于或等于服務(wù)器端驗(yàn)證的當(dāng)前頁驗(yàn)證的當(dāng)前頁。一個(gè)mutli-part表單需要定義頁面屬性:

    <html:hidden property="page" value="1"/>。
    比較兩個(gè)字段

    這是一個(gè)展示你怎樣才能比較兩個(gè)字段是否有一樣的值的例子。比如“用戶改變他們的口令“一般會(huì)有口令字段和一確認(rèn)字段。

    <validator name="twofields"

    classname="com.mysite.StrutsValidator"

    method="validateTwoFields"

    msg="errors.twofields"/>

    <field property="password" depends="required,twofields">

    <arg0 key="typeForm.password.displayname"/>

    <var>

    <var-name>secondProperty</var-name>

    <var-value>password2</var-value>

    </var>

    </field>

     

    public static boolean validateTwoFields(

    Object bean, ValidatorAction va,  

    Field field, ActionErrors errors, HttpServletRequest request,  

    ServletContext application) {

    String value = ValidatorUtils.getValueAsString( bean,   field.getProperty());

    String sProperty2 = field.getVarValue("secondProperty");

    String value2 = ValidatorUtils.getValueAsString( bean,   sProperty2);

     

            if (!GenericValidator.isBlankOrNull(value)) {

    try {

    if (!value.equals(value2)) {

    errors.add(field.getKey(),

    Resources.getActionError( application, request, va, field));

                                 return false;

    }

    } catch (Exception e) {

    errors.add(field.getKey(), Resources.getActionError( application, request, va, field));

    return false;

    }

    }

    }
    已知的bug

    Struts Validator依賴于Commons Validator包,所以問題報(bào)告和增強(qiáng)需求可能在兩個(gè)產(chǎn)品中列出。

    ·    Struts Validator Bugzilla Reports

    ·    Commons Validator Bugzilla Reports
    變更和deprecations

    新建的標(biāo)記屬性。

    <html:javascript>標(biāo)記有新的屬性定義.

    使用commons-validator.jar中的DTD驗(yàn)證。

    當(dāng)前使用的驗(yàn)證XML文件是根據(jù)commons-validator.jar中的DTD。Struts不在為validator-rules.xml and validator.xml.單獨(dú)維護(hù)一個(gè)分離的DTD,另外,commons-validator 現(xiàn)在維護(hù)一個(gè)統(tǒng)一的validator.dtd。修改所有validator.xml文件的DTD引用為

    <!DOCTYPE form-validation PUBLIC

    "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"

    "

    空字段。

    當(dāng)前默認(rèn)在所有得基礎(chǔ)驗(yàn)證類型中忽略空白的字段,如果你要求一個(gè)字段必須輸入,那末在你的應(yīng)用的validator.xml 文件相應(yīng)的字段定義的depends屬性中添加 " required "。

    新建的范圍RANGE方法.

    JavaScript 和JAVA中都添加了intRange & floatRange 方法。

    有條件地REQUIRED字段.

    最大的修改是添加了基于其她字段的值的有條件地require驗(yàn)證的能力。它允許你定義邏輯如:“只有X字段非空的時(shí)候Y字段為’male’才有效”,這是實(shí)現(xiàn)上述邏輯的推薦方法,這種方法在1.1版后的第一版將實(shí)現(xiàn)。在1.1版中添加的Requiredif驗(yàn)證規(guī)則,將在新版中去掉。不過,如果你正準(zhǔn)備使用requiredif,這里有一個(gè)簡短的教程。

            讓我們假定你有一個(gè)有3個(gè)字段的醫(yī)藥的信息表單,性別sex,懷孕測試pregnancyTest,測試結(jié)果testResult,如果性別為'f' or 'F',則懷孕測試pregnancyTest是required,如果pregnancyTest不是空,測試結(jié)果testResult是required。

    你的validation.xml 文件的輸入項(xiàng)應(yīng)該是這樣的:

    <form name="medicalStatusForm">

    <field property="pregnancyTest" depends="requiredif">

    <arg0 key="medicalStatusForm.pregnancyTest.label"/>

    <var>

    <var-name>field[0]</var-name>

    <var-value>sex</var-value>

    </var>

    <var>

    <var-name>fieldTest[0]</var-name>

    <var-value>EQUAL</var-value>

    </var>

    <var>

    <var-name>fieldValue[0]</var-name>

    <var-value>F</var-value>

    </var>

    <var>

    <var-name>field[1]</var-name>

    <var-value>sex</var-value>

    </var>

    <var>

    <var-name>fieldTest[1]</var-name>

    <var-value>EQUAL</var-value>

    </var>

    <var>

    <var-name>fieldValue[1]</var-name>

    <var-value>f</var-value>

    </var>

    <var>

    <var-name>fieldJoin</var-name>

    <var-value>OR</var-value>

    </var>

    </field>

    <field property="testResult" depends="requiredif">

    <arg0 key="medicalStatusForm.testResult.label"/>

    <var>

    <var-name>field[0]</var-name>

    <var-value>pregnancyTest</var-value>

    </var>

    <var>

    <var-name>fieldTest[0]</var-name>

    <var-value>NOTNULL</var-value>

    </var>

    </field>

    </form>

     

    這里有一個(gè)使用索引的屬性更復(fù)雜的例子,如果你的struts-config.xml 有這下面:

    <form-bean name="dependentlistForm"

    type="org.apache.struts.webapp.validator.forms.ValidatorForm">

    <form-property

    name="dependents"

    type="org.apache.struts.webapp.validator.Dependent[]" size="10"/>

    <form-property name="insureDependents" type="java.lang.Boolean" initial="false"/>

    </form-bean>

    這里dependentlistForm bean有l(wèi)astName,firstName,dob,coverageType四個(gè)屬性,你可以這樣定義一驗(yàn)證規(guī)則:

    <form name="dependentlistForm">

    <field

    property="firstName" indexedListProperty="dependents" depends="requiredif">

    <arg0 key="dependentlistForm.firstName.label"/>

    <var>

    <var-name>field[0]</var-name>

    <var-value>lastName</var-value>

    </var>

    <var>

    <var-name>fieldIndexed[0]</var-name>

    <var-value>true</var-value>

    </var>

    <var>

    <var-name>fieldTest[0]</var-name>

    <var-value>NOTNULL</var-value>

    </var>

    </field>

     

    <field

    property="dob" indexedListProperty="dependents" depends="requiredif,date">

    <arg0 key="dependentlistForm.dob.label"/>

    <var>

    <var-name>field[0]</var-name>

    <var-value>lastName</var-value>

    </var>

    <var>

    <var-name>fieldIndexed[0]</var-name>

    <var-value>true</var-value>

    </var>

    <var>

    <var-name>fieldTest[0]</var-name>

    <var-value>NOTNULL</var-value>

    </var>

    </field>

     

    <field

    property="coverageType" indexedListProperty="dependents" depends="requiredif">

    <arg0 key="dependentlistForm.coverageType.label"/>

    <var>

    <var-name>field[0]</var-name>

    <var-value>lastName</var-value>

    </var>

    <var>

    <var-name>fieldIndexed[0]</var-name>

    <var-value>true</var-value>

    </var>

    <var>

    <var-name>fieldTest[0]</var-name>

    <var-value>NOTNULL</var-value>

    </var>

    <var>

    <var-name>field[1]</var-name>

    <var-value>insureDependents</var-value>

    </var>

    <var>

    <var-name>fieldTest[1]</var-name>

    <var-value>EQUAL</var-value>

    </var>

    <var>

    <var-name>fieldValue[1]</var-name>

    <var-value>true</var-value>

    </var>

    <var>

    <var-name>fieldJoin</var-name>

    <var-value>AND</var-value>

    </var>

    </field>

    </form>

    這里的意思是:

    如果lastName 字段是非空的,firstName 字段required。因?yàn)樽侄蜪ndexed 為真,這它意味著lastName的indexed 必須與firstName 的索引的一樣,dob同理,除非date不為空。

    如果lastName 用樣索引時(shí)的值不空, 而且非索引字段insureDependents為真,則coverageType 是only require。

    你可以對字段在[n]中使用任意數(shù)字,唯一的限制是他們必須都是AND或OR,你無法混合使用。

    Deprecation:

    u        JavaScript 和Java的range方法.

    u        StrutsValidator &StrutsValidatorUtil 類中的Deprecation方法
    驗(yàn)證器api指南

    一個(gè)簡明的Struts驗(yàn)證器API指南 可以幫助你開始。
    驗(yàn)證器資源

    Struts Validator: Validating Two Fields Match 作者M(jìn)att Raible。(兩個(gè)字段匹配驗(yàn)證)關(guān)于使用方法的文章。(范例部分為翻譯此文內(nèi)容)

    DynaForms and the Validator 作者James Turner and Kevin Bedell。Struts Kickstart的其中一章(動(dòng)態(tài)form和驗(yàn)證器),可以自由下載PDF).

    Validating user input 作者 David Winterfeldt and Ted Husted。Struts in Action的其中一章,可以自由下載(PDF)。

    posted @ 2009-01-07 09:52 Hill 閱讀(204) | 評論 (0)編輯 收藏
     

    首先,我先大概介紹一下jpetstore的整體架構(gòu),spring的這個(gè)版本主要使用了struts+spring+ibatis的框架組合,
    而在MVC層的框架,這個(gè)版本又同時(shí)提供了兩個(gè)實(shí)現(xiàn)版本,一個(gè)是struts,一個(gè)是spring 自帶的web框架,

    而數(shù)據(jù)庫持久層使用的是ibatis框架,這個(gè)框架是一個(gè)SQL映射框架,輕量級(jí)而且使用非常容易,基本上會(huì)

    使用JDBC的朋友看一兩個(gè)小時(shí)就會(huì)使用了。
    下圖是該應(yīng)用的一個(gè)簡略架構(gòu)圖,沒有什么好的工具,就大概畫了一個(gè),雖然比較簡單,不過也基本可以

    概括應(yīng)用的整體框架了,首先是JSP請求,通過struts-config.xml(這里只是根據(jù)struts來畫的,spring其實(shí)也差不多),

    請求轉(zhuǎn)到相應(yīng)的Action中,可以看到,這里有一個(gè)BaseAction,是所有Action實(shí)現(xiàn)的父類,這個(gè)類的作用稍后再講,

    然后就是每個(gè)Action通過PetStoreFacade的對象調(diào)用后臺(tái)DAO對象,從而通過ibatis進(jìn)行數(shù)據(jù)的持久操作,

    這里使用了門面(Facade)模式,隔離了前臺(tái)與后臺(tái)耦合度,而PetStoreFacade就是這個(gè)門面。結(jié)合下圖,

    相信大家對整個(gè)jpetstore會(huì)有個(gè)大概的了解。

     

     

    好了,大概的結(jié)構(gòu)講了下,接下來我們就從代碼入手,在這里考慮到struts大家比較熟悉,因此,

    本文是以struts版本來講,同時(shí)聲明,本文并不會(huì)一段段代碼詳細(xì)講述,而只是提供一個(gè)學(xué)習(xí)的參考,

    大概講解一下流程,讓大家不再茫然不知從哪開始,好了,廢話也不多說了。

    既然是WEB應(yīng)用,那當(dāng)然首先從配置文件看起,那就非web.xml莫屬了,打開WEB-INF目錄下的web.xml,

    我們挑出目前我們應(yīng)該關(guān)注的配置代碼:
    代碼  
    <servlet>    
       <servlet-name>petstore</servlet-name>    
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
       <load-on-startup>2</load-on-startup>    
    </servlet>    
       
    <servlet>    
       <servlet-name>action</servlet-name>    
       <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>    
       <load-on-startup>3</load-on-startup>    
    </servlet>    
       
    <servlet-mapping>    
       <servlet-name>petstore</servlet-name>    
       <!--   
       <servlet-name>action</servlet-name>   
       -->    
       <url-pattern>*.do</url-pattern>    
    </servlet-mapping>
    在這里可看到兩個(gè)servlet設(shè)置,以及一個(gè)servlet mapping,第一個(gè)petstore的servlet是用于spring web框架的,

    而第二個(gè)action的servlet就是用于struts的,而這個(gè)版本的mapping默認(rèn)的是使用spring web,可以看到,<servlet-name>action</servlet-name>這一行是被注釋掉了,我們要使用struts的話,那就把這個(gè)注釋去掉,

    改為注釋掉<servlet-name>petstore</servlet-name>,好了,如此注釋以后,整個(gè)應(yīng)用就會(huì)以struts的框架運(yùn)行。

    (這些配置是什么意思?如果你還搞不懂的話,建議你先去學(xué)學(xué)基礎(chǔ)再來研究應(yīng)用吧)

    接下來我們可以打開strutc-config.xml文件,這里就是struts的默認(rèn)配置文件,在這里可以看到struts的相關(guān)配置信息。

    好了,接下來我們就以一個(gè)請求來講述基本的請求流程,以search為例,生成項(xiàng)目,再啟動(dòng),

    成功之后進(jìn)入應(yīng)用的首頁,我們終于可以看到久違的鸚鵡界面了,激動(dòng)吧,呵呵,在界面的右上角,

    有一個(gè)Search文本框,我們就以這個(gè)Search為例子來講解,輸入一個(gè)關(guān)鍵字cat,然后點(diǎn)search,

    結(jié)果出來了,這個(gè)過程的內(nèi)部是如何運(yùn)作的呢?

    我們用鼠標(biāo)右鍵點(diǎn)擊頁面,然后選擇屬性,我們看到顯示的地址可能是:
    http://localhost:8080/shop/searchProducts.do;jsessionid=E2D01E327B82D068FEE9D073CA33A2A3

    這個(gè)地址就是我們剛才點(diǎn)擊查詢時(shí)提交的地址了,我們看到searchProducts.do這個(gè)字符串,

    我們之前在web.xml里面的設(shè)置大家還記得嗎?
    <servlet-mapping>
       <!--
       <servlet-name>petstore</servlet-name>
       -->
       <servlet-name>action</servlet-name>
       <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    代表著所有以.do為結(jié)尾的請求,都將被名叫action的servlet處理,也就是通過struts-config配置進(jìn)行處理,那我們就去struts-config.xml里面看看,打開struts-config.xml文件,ctrl+F彈出查詢界面,輸入searchProducts,我們就可查到
    <action path="/shop/searchProducts" type="org.springframework.samples.jpetstore.web.
    struts.SearchProductsAction" name="emptyForm" scope="session" validate="false">    
    <forward name="success" path="/WEB-INF/jsp/struts/SearchProducts.jsp"/>    
    </action>
    根據(jù)以上配置,我們可以得知,剛才我們的提交將會(huì)被SearchProductsAction處理,而該action的form是emptyForm,查找emptyForm這個(gè)別名,我們可以找到它指向一個(gè)BaseActionForm,打開這個(gè)form我們可以看到,里面只有兩個(gè)validate方法和一個(gè)addErrorIfStringEmpty方法,沒有任何的屬性,那就是說search這個(gè)提交并沒有把我們輸入的關(guān)鍵字保存在form里面,打開SearchProductsAction,我們看到execute方法里的第一句就是

    String keyword = request.getParameter("keyword");
    也就是說我們輸入的關(guān)鍵字是以參數(shù)的形式傳入到request里面,參數(shù)名字為“keyword”,我們打開IncludeTop.jsp,這個(gè)文件在WEB-INF/jsp/struts目錄下。

    注意了,jsp目錄下分別有spring以及struts兩個(gè)目錄,這兩個(gè)目錄就是分別對應(yīng)兩個(gè)web框架的,我們使用的是struts所以jsp代碼就到struts目錄里面,為什么打開IncludeTop.jsp呢,我們可以看到,無論我們進(jìn)入哪個(gè)頁面,search那個(gè)文本框都存在,也就是說,這個(gè)文本框是被當(dāng)作一個(gè)模板插入到所有頁面當(dāng)中去的,我們隨便打開一個(gè)頁面,就可以看到頁面開頭都是:

    <%@ include file="IncludeTop.jsp" %>
    這句就是把IncludeTop.jsp當(dāng)作頁面頭部包含進(jìn)來,所以凡是包含這個(gè)頭頁面的頁面,他們的頭部都是一樣的,這也是我們在開發(fā)中常用的一種方式,統(tǒng)一界面的一種方式,我們也可以看到在這些文件尾部也有類似的代碼,如:

    <%@ include file="IncludeBottom.jsp" %>

    其作用也是一樣。打開IncludeTop.jsp后,我們看到其中有一段代碼:

    <form action="<c:url value="/shop/searchProducts.do"/>" method="post">
    <input type="hidden" name="search" value="true"/>
    <input name="keyword" size="14"/> <input border="0" src="../images/search.gif"

    type="image" name="search"/>
    </form>
    這段代碼就是我們search文本框以及提交鏈接的代碼,在這里就不做詳細(xì)介紹了。

    好了,接下來我們再看看這個(gè)action的后續(xù)代碼

    if (keyword != null) {  
    if (!StringUtils.hasLength(keyword)) {  
       request.setAttribute("message", "Please enter a keyword to search for,

    then press the search button.");  
       return mapping.findForward("failure");  
       }  
    PagedListHolder productList = new PagedListHolder(getPetStore().

    searchProductList(keyword.toLowerCase()));  
    productList.setPageSize(4);  
    request.getSession().setAttribute("SearchProductsAction_productList", productList);  
    request.setAttribute("productList", productList);  
    return mapping.findForward("success");  
    }

    這里第一句就是判斷keyword是否為空,不為空就執(zhí)行其中的代碼,我們search的時(shí)候這個(gè)keyword肯定是不為空的,

    那就是說這段if包含的代碼就是我們search的處理代碼了,有的人也許會(huì)說,如果我不輸入關(guān)鍵字而直接點(diǎn)search呢,

    這keyword不就是為空了嗎?我想這個(gè)你在此處加個(gè)斷點(diǎn),再運(yùn)行一下就知道了,雖然你沒有輸入,

    但是keyword一樣不是null,它將是一個(gè)空字符串,而不是空對象。我們看到if里面還包含有一個(gè)if,

    這里就是判斷keyword是否為空字符串了,StringUtils.hasLength()方式是一個(gè)工具類,

    用來判斷keyword是否為空字符串,如果是空字符串就返回false,而這句判斷當(dāng)返回false時(shí),

    因?yàn)榍懊嬗袀€(gè)感嘆號(hào),所以值為false就執(zhí)行被if所包含的語句,里面的代碼就是保存一個(gè)錯(cuò)誤信息,然后return mapping.findForward("failure");,這句的意思就不再解釋了。

    現(xiàn)在假設(shè)我們正確輸入keyword,那么程序?qū)⒉粫?huì)執(zhí)行if語句中的代碼,直接向下執(zhí)行,我們看到


    PagedListHolder productList = new PagedListHolder(getPetStore().

    searchProductList(keyword.toLowerCase()));

    這句代碼,PagedListHolder是spring提供的一個(gè)用來保存查詢結(jié)構(gòu)類,通常用來進(jìn)行分頁處理,

    因此我們可以知道

    getPetStore().searchProductList(keyword.toLowerCase())
    這一句就是用來查詢,并返回查詢結(jié)果的。getPetStore()這個(gè)方法是繼承自BaseAction的,它將獲得一個(gè)PetStoreFacade的實(shí)現(xiàn),我們打開BaseAction的代碼,可以看到如下代碼

    public void setServlet(ActionServlet actionServlet) {  
           super.setServlet(actionServlet);  
           if (actionServlet != null) {  
               ServletContext servletContext = actionServlet.getServletContext();  
           WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);  
           this.petStore = (PetStoreFacade) wac.getBean("petStore");  
           }  
    }

    這句代碼里面最重要的一句就是

    WebApplicationContext wac = WebApplicationContextUtils.

    getRequiredWebApplicationContext(servletContext);
    這句代碼的作用就是獲取一個(gè)WebApplicationContext對象wac,在這里我們只需要知道這個(gè)對象的作用,而不對其進(jìn)行深入研究,通過這個(gè)對象,我們可以根據(jù)spring的配置文件,獲得相應(yīng)的Bean,下面這句就是用來獲取相應(yīng)bean的語句:


    this.petStore = (PetStoreFacade) wac.getBean("petStore");
    petStore這個(gè)就是bean的id,這個(gè)petStore的bean具體是哪個(gè)類呢?我們打開applicationContext.xml,可以找到以下配置代碼


    <bean id="petStore" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
       <property name="accountDao" ref="accountDao"/>
       <property name="categoryDao" ref="categoryDao"/>
       <property name="productDao" ref="productDao"/>
       <property name="itemDao" ref="itemDao"/>
       <property name="orderDao" ref="orderDao"/>
    </bean>
    從這里可以看到,petStoreFacade的具體類就是PetStoreImpl,而這個(gè)類當(dāng)中,分別通過spring IOC注入了幾個(gè)DAO的bean,這幾個(gè)DAO的配置可以在dataAccessContext-local.xml文件里面找到,我們打開PetStoreImpl這個(gè)實(shí)現(xiàn)類,我們看到類里有一個(gè)searchProductList方法,這個(gè)方法就是我們在Action當(dāng)中調(diào)用的方法

    return this.productDao.searchProductList(keywords);
    從這句代碼可以看出,這個(gè)方法是通過調(diào)用productDao的searchProductList方法來獲得結(jié)果的,

    productDao這個(gè)DAO從上面的配置文件可以看出,是通過IOC容器進(jìn)行注入的,我們打開dataAccessContext-local.xml文件,可以看到

    <bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis

    .SqlMapProductDao">
       <property name="sqlMapClient" ref="sqlMapClient"/>
    </bean>
    這句配置代表了productDao的實(shí)現(xiàn)類就是SqlMapProductDao,同時(shí)這個(gè)類包含有一個(gè)sqlMapClient的屬性對象,這個(gè)對象也是通過ioc注入的,再在這個(gè)配置文件里,我們可以找到如下一段代碼

    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
       <property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
       <property name="dataSource" ref="dataSource"/>
    </bean>
    這段代碼就是sqlMapClient這個(gè)bean的配置,這里的實(shí)現(xiàn)是SqlMapClientFactoryBean,它是spring專門為ibatis框架提供的一個(gè)支持,通過這個(gè)對象就可以很好的集成ibatis框架,具體的介紹可以通過spring官方文檔或者是其他一些教程獲得,在這里就不多做介紹。

    好了,接下來我們知道了,實(shí)際查詢數(shù)據(jù)是通過DAO的實(shí)現(xiàn)類SqlMapProductDao進(jìn)行的,而SqlMapProductDao當(dāng)中就是通過了ibatis進(jìn)行數(shù)據(jù)的查詢,從而返回結(jié)果,這里也就不多做介紹了,大家可以通過ibatis的教程獲得ibatis的使用方法,非常的簡單,search操作從前臺(tái)到后臺(tái)的大概流程就介紹到這里了。

    在這個(gè)參考文章中,我并沒有對具體技術(shù)做過多的講解,那是因?yàn)楸疚闹皇亲鳛橐粋€(gè)研究jpetstore的參考,提供一個(gè)可供參考的研究流程,主要是為了那些想開始研究jpetstore但是又不知道從哪開始或者是不知道如何進(jìn)行研究的新人朋友們而準(zhǔn)備的,如果具體的講解每一部分,那我想將不僅僅是一篇文章就可以完成的事情,因?yàn)檫@里涉及到struts,spring,ibatis等具體的框架技術(shù),每一個(gè)框架基本都可以寫成一本書,用一篇文章來講就不太實(shí)際了,而且我個(gè)人更傾向于遇到不理解的地方的時(shí)候,多使用google來搜索,這樣能夠進(jìn)一步加深自己對問題的理解。

    好了,關(guān)于jpetstore源碼研究入門的文章就寫到這里結(jié)束了,由于本人技術(shù)和文筆有限,有錯(cuò)漏或者表達(dá)不當(dāng)?shù)牡胤秸埐灰橐?,歡迎各位朋友來指正。

    posted @ 2009-01-06 15:50 Hill 閱讀(3781) | 評論 (0)編輯 收藏
     
    本人剛轉(zhuǎn)到Java技術(shù)方向,希望能在這里與大家一起學(xué)習(xí),進(jìn)步。
    posted @ 2009-01-05 17:24 Hill 閱讀(383) | 評論 (0)編輯 收藏
    僅列出標(biāo)題
    共5頁: 上一頁 1 2 3 4 5 
    CALENDER
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(3)

    隨筆檔案

    文章檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜


    Powered By: 博客園
    模板提供滬江博客

    主站蜘蛛池模板: 午夜免费福利片观看| 成av免费大片黄在线观看| 亚洲毛片免费观看| 亚洲精品V欧洲精品V日韩精品| 日韩电影免费在线观看网址| 又色又污又黄无遮挡的免费视| 国产精品亚洲va在线观看| 亚洲A丁香五香天堂网| jizz免费观看视频| 国产成人综合亚洲AV第一页 | 亚洲视频免费一区| 亚洲成AV人片久久| 午夜毛片不卡高清免费| WWW亚洲色大成网络.COM| 亚洲色偷偷综合亚洲AV伊人| 国产免费高清69式视频在线观看 | 亚洲一区日韩高清中文字幕亚洲 | 亚洲国产激情在线一区| 国产精品无码免费视频二三区| 国产精品亚洲专区一区| 亚洲自偷自偷偷色无码中文| 久久一本岛在免费线观看2020| 亚洲第一页在线播放| 国内自产拍自a免费毛片| 人人公开免费超级碰碰碰视频 | 久久亚洲色一区二区三区| 久草免费福利视频| 亚洲区日韩精品中文字幕| 亚洲精品成人网久久久久久| 亚洲精品免费在线观看| 亚洲中文字幕无码中文字| 亚洲男人的天堂在线va拉文| 久9热免费精品视频在线观看| 亚洲小说图区综合在线| 久久亚洲AV无码西西人体| 免费观看无遮挡www的视频| 美女啪啪网站又黄又免费| 久久夜色精品国产亚洲AV动态图| 国产精品免费观看久久| 一道本不卡免费视频| 亚洲av无码电影网|